diff --git a/.gitmodules b/.gitmodules index c8500c7..f6b13b4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "firmware/lib/harp.core.rp2040"] path = firmware/lib/harp.core.rp2040 url = git@github.com:AllenNeuralDynamics/harp.core.rp2040.git +[submodule "firmware/lib/pico.async-uart"] + path = firmware/lib/pico.async-uart + url = git@github.com:AllenNeuralDynamics/pico.async-uart.git diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index 2d8762a..b33d240 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -8,6 +8,8 @@ add_definitions(-DGIT_HASH="${COMMIT_ID}") # Usable in source code. #add_definitions(-DDEBUG) # Uncomment for debugging +#set(PICO_PLATFORM rp2040) # rp2040 is the default. + # PICO_SDK_PATH must be defined. include(${PICO_SDK_PATH}/pico_sdk_init.cmake) @@ -23,10 +25,7 @@ project(white_rabbit) pico_sdk_init() add_subdirectory(lib/harp.core.rp2040/firmware) # Path to harp.core.rp2040. - -add_library(uart_nonblocking - src/uart_nonblocking.cpp -) +add_subdirectory(lib/pico.async-uart) # Path to uart_nonblocking and soft_uart add_library(white_rabbit_app src/white_rabbit_app.cpp @@ -38,12 +37,12 @@ add_executable(${PROJECT_NAME} include_directories(inc) -target_link_libraries(uart_nonblocking hardware_dma hardware_timer pico_stdlib) target_link_libraries(white_rabbit_app harp_core harp_c_app harp_sync - hardware_divider pico_stdlib uart_nonblocking hardware_dma) + hardware_divider pico_stdlib uart_nonblocking pio_uart + hardware_pio hardware_dma soft_uart) target_link_libraries(${PROJECT_NAME} harp_core harp_c_app harp_sync pico_stdlib - hardware_dma hardware_timer uart_nonblocking + hardware_dma hardware_timer uart_nonblocking pio_uart white_rabbit_app) pico_add_extra_outputs(${PROJECT_NAME}) diff --git a/firmware/README.md b/firmware/README.md index b5ec611..6e575d2 100644 --- a/firmware/README.md +++ b/firmware/README.md @@ -12,7 +12,7 @@ This project uses the [Pico SDK](https://github.com/raspberrypi/pico-sdk/tree/ma The SDK needs to be downloaded and installed to a known folder on your PC. Note that the PICO SDK also contains submodules (including TinyUSB), so you must ensure that they are also fetched with: ```` -git clone git clone git@github.com:raspberrypi/pico-sdk.git +git clone git@github.com:raspberrypi/pico-sdk.git git submodule update --init --recursive ```` diff --git a/firmware/inc/config.h b/firmware/inc/config.h index 2caa9fe..b8faa54 100644 --- a/firmware/inc/config.h +++ b/firmware/inc/config.h @@ -40,8 +40,7 @@ #define MAX_AUX_SYNC_BAUDRATE (1'000'000UL) // Aux Baud rate should be slower // than this value. #define AUX_PIN (0) -#define AUX_SYNC_START_OFFSET_US (0) // Offset from spec to account for fixed - // delays before transmission starts. +#define AUX_SYNC_START_OFFSET_US (0) #define LED0_PIN (24) #define LED1_PIN (25) diff --git a/firmware/inc/uart_nonblocking.h b/firmware/inc/uart_nonblocking.h deleted file mode 100644 index c0933ef..0000000 --- a/firmware/inc/uart_nonblocking.h +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include -#include -#include - -/** - * \brief nonblocking way to dispatch uart characters. - * \details assumes a global DMA channel has already been assigned. - */ -void __time_critical_func(dispatch_uart_stream)(uint dma_chan, - uart_inst_t* uart, - uint8_t* starting_address, - size_t word_count); diff --git a/firmware/inc/white_rabbit_app.h b/firmware/inc/white_rabbit_app.h index 1f72df8..b65c7cc 100644 --- a/firmware/inc/white_rabbit_app.h +++ b/firmware/inc/white_rabbit_app.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include // for fast hardware division. #ifdef DEBUG diff --git a/firmware/lib/harp.core.rp2040 b/firmware/lib/harp.core.rp2040 index ea1aecb..4173ad6 160000 --- a/firmware/lib/harp.core.rp2040 +++ b/firmware/lib/harp.core.rp2040 @@ -1 +1 @@ -Subproject commit ea1aecbe00b378c3f8e91aaf65f29f45a9c22b5e +Subproject commit 4173ad615e239c3af7c4dd53e89626a8d037ea81 diff --git a/firmware/lib/pico.async-uart b/firmware/lib/pico.async-uart new file mode 160000 index 0000000..d66fa56 --- /dev/null +++ b/firmware/lib/pico.async-uart @@ -0,0 +1 @@ +Subproject commit d66fa561de3ec89ba4b6560ea715ebc14bf1be7e diff --git a/firmware/src/uart_nonblocking.cpp b/firmware/src/uart_nonblocking.cpp deleted file mode 100644 index 91ae1c7..0000000 --- a/firmware/src/uart_nonblocking.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include - - -void __not_in_flash_func(dispatch_uart_stream)(uint dma_chan, uart_inst_t* uart, - uint8_t* starting_address, - size_t word_count) -{ - // DMA channel will write data to the uart, paced by DREQ_TX. - dma_channel_config conf = dma_channel_get_default_config(dma_chan); - - // Setup Sample Channel. - channel_config_set_transfer_data_size(&conf, DMA_SIZE_8); - channel_config_set_read_increment(&conf, true); // read from starting memory address. - channel_config_set_write_increment(&conf, false); // write to fixed uart memory address. - channel_config_set_irq_quiet(&conf, true); - // Pace data according to pio providing data. - uint uart_dreq = (uart == uart0)? DREQ_UART0_TX : DREQ_UART1_TX; - channel_config_set_dreq(&conf, uart_dreq); - channel_config_set_enable(&conf, true); - // Apply samp_chan_ configuration. - dma_channel_configure( - dma_chan, // Channel to be configured - &conf, // corresponding DMA config. - &uart_get_hw(uart)->dr, // write (dst) address. - starting_address, // read (source) address. - word_count, // Number of word transfers i.e: len(string). - true // Do start immediately. - ); -} diff --git a/firmware/src/white_rabbit_app.cpp b/firmware/src/white_rabbit_app.cpp index dbff0ee..a8e92d1 100644 --- a/firmware/src/white_rabbit_app.cpp +++ b/firmware/src/white_rabbit_app.cpp @@ -33,10 +33,14 @@ volatile uint32_t __not_in_flash("double_buffers") aux_clkout_seconds_b; volatile uint32_t __not_in_flash("double_buffers") *dispatch_second; volatile uint32_t __not_in_flash("double_buffers") *load_second; +// AUX CLKout software implementation. +SoftUART soft_uart = SoftUART(AUX_PIN); + // PPS Alarm/IRQ resources int32_t __not_in_flash("double_buffers") pps_output_alarm_num = -1; uint32_t __not_in_flash("double_buffers") pps_output_irq_number; + void setup_harp_clkout() { // Setup DMA. @@ -131,7 +135,6 @@ void __not_in_flash_func(dispatch_and_reschedule_harp_clkout)() timer_hw->inte |= (1u << harp_clkout_alarm_num); // Arm alarm by writing the alarm time. timer_hw->alarm[harp_clkout_alarm_num] = alarm_time_us; - } void setup_aux_clkout() @@ -139,14 +142,9 @@ void setup_aux_clkout() // Setup DMA. if (aux_clkout_dma_chan < 0) // Claim a DMA channel if not yet claimed. aux_clkout_dma_chan = dma_claim_unused_channel(true); - // Setup GPIO Pins. - // Setup UART TX for periodic transmission of the time. - uart_inst_t* aux_uart_id = AUX_SYNC_UART; - uart_init(aux_uart_id, app_regs.AuxBaudRate); - uart_set_hw_flow(aux_uart_id, false, false); - uart_set_fifo_enabled(aux_uart_id, false); // Set FIFO size to 1. - uart_set_format(aux_uart_id, 8, 1, UART_PARITY_NONE); - gpio_set_function(AUX_PIN, GPIO_FUNC_UART); + // Update baud rate (if it has changed). + soft_uart.reset(); + soft_uart.set_baud_rate(app_regs.AuxBaudRate); // Setup AUX CLKOUT periodic outgoing time message. // Setup Outgoing msg double buffer; dispatch_second = &aux_clkout_seconds_a; @@ -169,7 +167,7 @@ void setup_aux_clkout() *dispatch_second = curr_harp_seconds + 1; uint64_t next_msg_harp_time_us = (uint64_t(curr_harp_seconds) * 1'000'000UL) + 1'000'000UL; - // Apply offset if any. + // Apply additional offset if any. next_msg_harp_time_us += AUX_SYNC_START_OFFSET_US; // Schedule next time msg dispatch in system time. // Low-level interface (fast!) to re-schedule this function. @@ -183,8 +181,8 @@ void setup_aux_clkout() void __not_in_flash_func(dispatch_and_reschedule_aux_clkout)() { // Dispatch the previously-configured time. - dispatch_uart_stream(aux_clkout_dma_chan, AUX_SYNC_UART, - (uint8_t*)dispatch_second, sizeof(dispatch_second)); + soft_uart.send((uint8_t*)dispatch_second, sizeof(dispatch_second)); + // Clear the latched hardware interrupt. timer_hw->intr = (1u << aux_clkout_alarm_num); // Compute the *next* whole harp time second. @@ -230,7 +228,7 @@ void cleanup_aux_clkout() irq_set_enabled(aux_clkout_irq_number, false); irq_remove_handler(aux_clkout_irq_number, dispatch_and_reschedule_aux_clkout); - uart_deinit(AUX_SYNC_UART); + soft_uart.cleanup(); gpio_deinit(AUX_PIN); } @@ -415,6 +413,8 @@ void write_aux_baud_rate(msg_t& msg) void update_app_state() { + if (soft_uart.requires_update()) + soft_uart.update(); // Update the state of ConnectedDevices. uint16_t old_port_raw = app_regs.ConnectedDevices; uint32_t port_raw = gpio_get_all(); diff --git a/software/pyharp/enable_aux_uart.py b/software/pyharp/enable_aux_uart.py index 2f16393..a1f6745 100755 --- a/software/pyharp/enable_aux_uart.py +++ b/software/pyharp/enable_aux_uart.py @@ -16,8 +16,8 @@ class Regs(Enum): AuxPortBaudRate = 36 # U32 -#BAUDRATE = 115200 -BAUDRATE = 9600 +BAUDRATE = 115200 +#BAUDRATE = 9600 #BAUDRATE = 1000 # Open the device and print the info on screen