2026-04-06 17:24:34 +09:00
|
|
|
#include "handlers.h"
|
|
|
|
|
#include "pico/unique_id.h"
|
2026-04-10 22:04:38 +09:00
|
|
|
#include "pico/bootrom.h"
|
2026-04-11 22:26:54 +09:00
|
|
|
#include "hardware/flash.h"
|
|
|
|
|
#include "hardware/watchdog.h"
|
2026-04-10 22:04:38 +09:00
|
|
|
#include "dispatch.h"
|
2026-04-07 07:34:24 +09:00
|
|
|
#include "net.h"
|
2026-04-07 09:18:43 +09:00
|
|
|
#include "debug_log.h"
|
2026-04-06 17:24:34 +09:00
|
|
|
|
2026-04-11 22:26:54 +09:00
|
|
|
static constexpr uint32_t XIP_BASE_ADDR = 0x10000000;
|
|
|
|
|
static constexpr uint32_t FLASH_SIZE = 2 * 1024 * 1024;
|
2026-04-12 08:17:22 +09:00
|
|
|
static constexpr uint32_t REBOOT_MAGIC = 0x504D5242;
|
|
|
|
|
|
|
|
|
|
static boot_reason detected_boot_reason;
|
|
|
|
|
|
|
|
|
|
void handlers_init() {
|
|
|
|
|
if (watchdog_hw->scratch[0] == REBOOT_MAGIC)
|
|
|
|
|
detected_boot_reason = boot_reason::request_reboot;
|
|
|
|
|
else
|
|
|
|
|
detected_boot_reason = boot_reason::cold_boot;
|
|
|
|
|
watchdog_hw->scratch[0] = 0;
|
|
|
|
|
}
|
2026-04-11 22:26:54 +09:00
|
|
|
|
2026-04-11 08:15:41 +09:00
|
|
|
std::optional<ResponsePICOBOOT> handle_picoboot(const responder&, const RequestPICOBOOT&) {
|
2026-04-10 22:04:38 +09:00
|
|
|
dispatch_schedule_ms(100, []{ reset_usb_boot(0, 1); });
|
2026-04-11 08:15:41 +09:00
|
|
|
return ResponsePICOBOOT{};
|
2026-04-06 17:24:34 +09:00
|
|
|
}
|
|
|
|
|
|
2026-04-11 08:15:41 +09:00
|
|
|
std::optional<ResponseInfo> handle_info(const responder&, const RequestInfo&) {
|
2026-04-06 17:24:34 +09:00
|
|
|
ResponseInfo resp;
|
|
|
|
|
pico_unique_board_id_t uid;
|
|
|
|
|
pico_get_unique_board_id(&uid);
|
|
|
|
|
std::copy(uid.id, uid.id + 8, resp.board_id.begin());
|
2026-04-07 07:34:24 +09:00
|
|
|
auto& ns = net_get_state();
|
|
|
|
|
resp.mac = ns.mac;
|
|
|
|
|
resp.ip = ns.ip;
|
2026-04-06 20:09:30 +09:00
|
|
|
resp.firmware_name = firmware_name;
|
2026-04-12 08:17:22 +09:00
|
|
|
resp.boot = detected_boot_reason;
|
2026-04-10 22:21:31 +09:00
|
|
|
return resp;
|
2026-04-06 17:24:34 +09:00
|
|
|
}
|
2026-04-07 09:18:43 +09:00
|
|
|
|
2026-04-11 08:15:41 +09:00
|
|
|
std::optional<ResponseLog> handle_log(const responder&, const RequestLog&) {
|
2026-04-07 09:18:43 +09:00
|
|
|
ResponseLog resp;
|
|
|
|
|
for (auto& e : dlog_drain())
|
|
|
|
|
resp.entries.push_back(LogEntry{e.timestamp_us, std::move(e.message)});
|
2026-04-10 22:21:31 +09:00
|
|
|
return resp;
|
2026-04-07 09:18:43 +09:00
|
|
|
}
|
2026-04-11 22:26:54 +09:00
|
|
|
|
|
|
|
|
std::optional<ResponseFlashErase> handle_flash_erase(const responder&, const RequestFlashErase& req) {
|
|
|
|
|
if (req.addr < XIP_BASE_ADDR || req.addr + req.len > XIP_BASE_ADDR + FLASH_SIZE) {
|
|
|
|
|
dlogf("flash erase: out of range %08lx+%lu",
|
|
|
|
|
static_cast<unsigned long>(req.addr), static_cast<unsigned long>(req.len));
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
uint32_t offset = req.addr - XIP_BASE_ADDR;
|
|
|
|
|
if (offset % FLASH_SECTOR_SIZE != 0 || req.len % FLASH_SECTOR_SIZE != 0 || req.len == 0) {
|
|
|
|
|
dlogf("flash erase: bad alignment %08lx+%lu",
|
|
|
|
|
static_cast<unsigned long>(req.addr), static_cast<unsigned long>(req.len));
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
flash_range_erase(offset, req.len);
|
|
|
|
|
return ResponseFlashErase{};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::optional<ResponseFlashWrite> handle_flash_write(const responder&, const RequestFlashWrite& req) {
|
|
|
|
|
if (req.addr < XIP_BASE_ADDR || req.addr + req.data.size() > XIP_BASE_ADDR + FLASH_SIZE) {
|
|
|
|
|
dlogf("flash write: out of range %08lx+%zu",
|
|
|
|
|
static_cast<unsigned long>(req.addr), req.data.size());
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
uint32_t offset = req.addr - XIP_BASE_ADDR;
|
|
|
|
|
if (offset % FLASH_PAGE_SIZE != 0 || req.data.size() % FLASH_PAGE_SIZE != 0 || req.data.empty()) {
|
|
|
|
|
dlogf("flash write: bad alignment %08lx+%zu",
|
|
|
|
|
static_cast<unsigned long>(req.addr), req.data.size());
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
flash_range_program(offset, req.data.data(), req.data.size());
|
|
|
|
|
return ResponseFlashWrite{};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::optional<ResponseReboot> handle_reboot(const responder&, const RequestReboot&) {
|
2026-04-12 08:17:22 +09:00
|
|
|
dispatch_schedule_ms(100, []{
|
|
|
|
|
watchdog_hw->scratch[0] = REBOOT_MAGIC;
|
|
|
|
|
watchdog_reboot(0, 0, 0);
|
|
|
|
|
});
|
2026-04-11 22:26:54 +09:00
|
|
|
return ResponseReboot{};
|
|
|
|
|
}
|
|
|
|
|
|