diff --git a/cmd/load/main.go b/cmd/load/main.go index ac2684d..bde1958 100644 --- a/cmd/load/main.go +++ b/cmd/load/main.go @@ -112,18 +112,6 @@ func run(buildDir string) error { } } - for i := range 2 { - wg.Go(func() { - errs[i] = picotool.WaitForBootsel(serials[i], 10*time.Second) - }) - } - wg.Wait() - for i, err := range errs { - if err != nil { - return fmt.Errorf("wait %s: %w", serials[i], err) - } - } - uf2s := []string{ filepath.Join(buildDir, "picomap.uf2"), filepath.Join(buildDir, "picomap_test.uf2"), @@ -132,7 +120,7 @@ func run(buildDir string) error { fmt.Println("Loading firmware...") for i := range 2 { wg.Go(func() { - errs[i] = picotool.Load(uf2s[i], serials[i]) + errs[i] = picotool.Load(uf2s[i], serials[i], 10*time.Second) }) } wg.Wait() diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index c5a2398..a40aab9 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -10,6 +10,7 @@ set(CMAKE_CXX_STANDARD 23) pico_sdk_init() set(LIB_SOURCES + lib/dispatch.cpp lib/handlers.cpp lib/net.cpp lib/tusb_config.cpp @@ -24,6 +25,7 @@ target_compile_options(picomap PRIVATE -Wall -Wextra -Wno-unused-parameter) pico_generate_pio_header(picomap ${CMAKE_CURRENT_LIST_DIR}/w6300/qspi.pio) pico_enable_stdio_usb(picomap 0) pico_enable_stdio_uart(picomap 0) +pico_set_binary_type(picomap copy_to_ram) pico_add_extra_outputs(picomap) target_link_libraries(picomap ${LIB_DEPS}) @@ -33,5 +35,6 @@ target_compile_options(picomap_test PRIVATE -Wall -Wextra -Wno-unused-parameter) pico_generate_pio_header(picomap_test ${CMAKE_CURRENT_LIST_DIR}/w6300/qspi.pio) pico_enable_stdio_usb(picomap_test 0) pico_enable_stdio_uart(picomap_test 0) +pico_set_binary_type(picomap_test copy_to_ram) pico_add_extra_outputs(picomap_test) target_link_libraries(picomap_test ${LIB_DEPS}) diff --git a/firmware/firmware.cpp b/firmware/firmware.cpp index 800b4dd..be65a5e 100644 --- a/firmware/firmware.cpp +++ b/firmware/firmware.cpp @@ -1,51 +1,11 @@ -#include "pico/stdlib.h" -#include "tusb.h" -#include "wire.h" -#include "usb_cdc.h" -#include "timer_queue.h" +#include "dispatch.h" #include "handlers.h" -#include "net.h" -static usb_cdc usb; -static timer_queue timers; +static constexpr handler_entry handlers[] = { + {RequestPICOBOOT::ext_id, handle_picoboot}, + {RequestInfo::ext_id, handle_info}, +}; int main() { - tusb_init(); - - net_init(); - - static static_vector rx_buf; - - while (true) { - tud_task(); - - usb.drain(); - timers.run(); - - while (tud_cdc_available()) { - uint8_t byte; - if (tud_cdc_read(&byte, 1) != 1) break; - - rx_buf.push_back(byte); - - auto msg = try_decode(rx_buf); - if (!msg) { - if (rx_buf.full()) rx_buf.clear(); - continue; - } - - rx_buf.clear(); - - switch (msg->type_id) { - case RequestPICOBOOT::ext_id: - handle_picoboot(usb, msg->message_id); - break; - case RequestInfo::ext_id: - handle_info(usb, msg->message_id); - break; - } - } - - __wfi(); - } + dispatch(handlers); } diff --git a/firmware/include/dispatch.h b/firmware/include/dispatch.h new file mode 100644 index 0000000..24beddb --- /dev/null +++ b/firmware/include/dispatch.h @@ -0,0 +1,11 @@ +#pragma once +#include +#include +#include "usb_cdc.h" + +struct handler_entry { + int8_t type_id; + void (*handle)(usb_cdc&, uint32_t); +}; + +[[noreturn]] void dispatch(std::span handlers); diff --git a/firmware/lib/dispatch.cpp b/firmware/lib/dispatch.cpp new file mode 100644 index 0000000..6b1a323 --- /dev/null +++ b/firmware/lib/dispatch.cpp @@ -0,0 +1,50 @@ +#include "dispatch.h" +#include +#include "pico/stdlib.h" +#include "tusb.h" +#include "wire.h" +#include "timer_queue.h" +#include "net.h" + +[[noreturn]] void dispatch(std::span handlers) { + std::unordered_map handler_map; + for (auto& entry : handlers) { + handler_map[entry.type_id] = entry.handle; + } + + tusb_init(); + net_init(); + + static usb_cdc usb; + static timer_queue timers; + static static_vector rx_buf; + + while (true) { + tud_task(); + + usb.drain(); + timers.run(); + + while (tud_cdc_available()) { + uint8_t byte; + if (tud_cdc_read(&byte, 1) != 1) break; + + rx_buf.push_back(byte); + + auto msg = try_decode(rx_buf); + if (!msg) { + if (rx_buf.full()) rx_buf.clear(); + continue; + } + + rx_buf.clear(); + + auto it = handler_map.find(msg->type_id); + if (it != handler_map.end()) { + it->second(usb, msg->message_id); + } + } + + __wfi(); + } +} diff --git a/firmware/test.cpp b/firmware/test.cpp index ce064d0..be65a5e 100644 --- a/firmware/test.cpp +++ b/firmware/test.cpp @@ -1,47 +1,11 @@ -#include "pico/stdlib.h" -#include "tusb.h" -#include "wire.h" -#include "usb_cdc.h" +#include "dispatch.h" #include "handlers.h" -#include "net.h" -static usb_cdc usb; +static constexpr handler_entry handlers[] = { + {RequestPICOBOOT::ext_id, handle_picoboot}, + {RequestInfo::ext_id, handle_info}, +}; int main() { - tusb_init(); - net_init(); - - static static_vector rx_buf; - - while (true) { - tud_task(); - - usb.drain(); - - while (tud_cdc_available()) { - uint8_t byte; - if (tud_cdc_read(&byte, 1) != 1) break; - - rx_buf.push_back(byte); - - auto msg = try_decode(rx_buf); - if (!msg) { - if (rx_buf.full()) rx_buf.clear(); - continue; - } - - rx_buf.clear(); - - switch (msg->type_id) { - case RequestPICOBOOT::ext_id: - handle_picoboot(usb, msg->message_id); - break; - case RequestInfo::ext_id: - handle_info(usb, msg->message_id); - break; - } - } - - __wfi(); - } + dispatch(handlers); } diff --git a/lib/picotool/picotool.go b/lib/picotool/picotool.go index 92c98a5..68304f2 100644 --- a/lib/picotool/picotool.go +++ b/lib/picotool/picotool.go @@ -6,25 +6,20 @@ import ( "time" ) -func WaitForBootsel(serial string, timeout time.Duration) error { +func Load(uf2Path string, serial string, timeout time.Duration) error { deadline := time.Now().Add(timeout) - for time.Now().Before(deadline) { - cmd := exec.Command("picotool", "info", "--ser", serial) - if err := cmd.Run(); err == nil { + var out []byte + var err error + for { + cmd := exec.Command("picotool", "load", uf2Path, "-x", "--ser", serial) + out, err = cmd.CombinedOutput() + if err == nil { return nil } - time.Sleep(100 * time.Millisecond) + if time.Now().After(deadline) { + return fmt.Errorf("picotool load: %w\n%s", err, out) + } } - return fmt.Errorf("device %s not found in BOOTSEL after %v", serial, timeout) -} - -func Load(uf2Path string, serial string) error { - cmd := exec.Command("picotool", "load", uf2Path, "-x", "--ser", serial) - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("picotool load: %w\n%s", err, out) - } - return nil } func Reboot(serial string) error {