In-app flash write, UF2 parser, remove picotool dependency, reboot command
This commit is contained in:
@@ -7,6 +7,9 @@ static constexpr handler_entry handlers[] = {
|
||||
{RequestPICOBOOT::ext_id, typed_handler<RequestPICOBOOT, handle_picoboot>},
|
||||
{RequestInfo::ext_id, typed_handler<RequestInfo, handle_info>},
|
||||
{RequestLog::ext_id, typed_handler<RequestLog, handle_log>},
|
||||
{RequestFlashErase::ext_id, typed_handler<RequestFlashErase, handle_flash_erase>},
|
||||
{RequestFlashWrite::ext_id, typed_handler<RequestFlashWrite, handle_flash_write>},
|
||||
{RequestReboot::ext_id, typed_handler<RequestReboot, handle_reboot>},
|
||||
};
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -9,3 +9,6 @@ extern std::string_view firmware_name;
|
||||
std::optional<ResponsePICOBOOT> handle_picoboot(const responder& resp, const RequestPICOBOOT&);
|
||||
std::optional<ResponseInfo> handle_info(const responder& resp, const RequestInfo&);
|
||||
std::optional<ResponseLog> handle_log(const responder& resp, const RequestLog&);
|
||||
std::optional<ResponseFlashErase> handle_flash_erase(const responder& resp, const RequestFlashErase&);
|
||||
std::optional<ResponseFlashWrite> handle_flash_write(const responder& resp, const RequestFlashWrite&);
|
||||
std::optional<ResponseReboot> handle_reboot(const responder& resp, const RequestReboot&);
|
||||
|
||||
@@ -74,6 +74,46 @@ struct ResponseLog {
|
||||
auto as_tuple() { return std::tie(entries); }
|
||||
};
|
||||
|
||||
struct RequestFlashErase {
|
||||
static constexpr int8_t ext_id = 8;
|
||||
uint32_t addr;
|
||||
uint32_t len;
|
||||
auto as_tuple() const { return std::tie(addr, len); }
|
||||
auto as_tuple() { return std::tie(addr, len); }
|
||||
};
|
||||
|
||||
struct ResponseFlashErase {
|
||||
static constexpr int8_t ext_id = 9;
|
||||
auto as_tuple() const { return std::tie(); }
|
||||
auto as_tuple() { return std::tie(); }
|
||||
};
|
||||
|
||||
struct RequestFlashWrite {
|
||||
static constexpr int8_t ext_id = 10;
|
||||
uint32_t addr;
|
||||
std::span<const uint8_t> data;
|
||||
auto as_tuple() const { return std::tie(addr, data); }
|
||||
auto as_tuple() { return std::tie(addr, data); }
|
||||
};
|
||||
|
||||
struct ResponseFlashWrite {
|
||||
static constexpr int8_t ext_id = 11;
|
||||
auto as_tuple() const { return std::tie(); }
|
||||
auto as_tuple() { return std::tie(); }
|
||||
};
|
||||
|
||||
struct RequestReboot {
|
||||
static constexpr int8_t ext_id = 12;
|
||||
auto as_tuple() const { return std::tie(); }
|
||||
auto as_tuple() { return std::tie(); }
|
||||
};
|
||||
|
||||
struct ResponseReboot {
|
||||
static constexpr int8_t ext_id = 13;
|
||||
auto as_tuple() const { return std::tie(); }
|
||||
auto as_tuple() { return std::tie(); }
|
||||
};
|
||||
|
||||
struct RequestListTests {
|
||||
static constexpr int8_t ext_id = 125;
|
||||
auto as_tuple() const { return std::tie(); }
|
||||
|
||||
@@ -42,8 +42,8 @@ bool dispatch_cancel_timer(timer_handle h) {
|
||||
}
|
||||
|
||||
static usb_cdc usb;
|
||||
static static_vector<uint8_t, 256> usb_rx_buf;
|
||||
static std::array<uint8_t, 1514> tx_buf;
|
||||
static static_vector<uint8_t, 4096> usb_rx_buf;
|
||||
static std::array<uint8_t, 4096> tx_buf;
|
||||
|
||||
auto dispatch_msg = [&](const DecodedMessage& msg, std::function<void(std::span<const uint8_t>)> send) {
|
||||
auto it = handler_map.find(msg.type_id);
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#include "handlers.h"
|
||||
#include "pico/unique_id.h"
|
||||
#include "pico/bootrom.h"
|
||||
#include "hardware/flash.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "dispatch.h"
|
||||
#include "net.h"
|
||||
#include "debug_log.h"
|
||||
|
||||
static constexpr uint32_t XIP_BASE_ADDR = 0x10000000;
|
||||
static constexpr uint32_t FLASH_SIZE = 2 * 1024 * 1024;
|
||||
|
||||
std::optional<ResponsePICOBOOT> handle_picoboot(const responder&, const RequestPICOBOOT&) {
|
||||
dispatch_schedule_ms(100, []{ reset_usb_boot(0, 1); });
|
||||
return ResponsePICOBOOT{};
|
||||
@@ -28,3 +33,41 @@ std::optional<ResponseLog> handle_log(const responder&, const RequestLog&) {
|
||||
resp.entries.push_back(LogEntry{e.timestamp_us, std::move(e.message)});
|
||||
return resp;
|
||||
}
|
||||
|
||||
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&) {
|
||||
dispatch_schedule_ms(100, []{ watchdog_reboot(0, 0, 0); });
|
||||
return ResponseReboot{};
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ static constexpr handler_entry handlers[] = {
|
||||
{RequestPICOBOOT::ext_id, typed_handler<RequestPICOBOOT, handle_picoboot>},
|
||||
{RequestInfo::ext_id, typed_handler<RequestInfo, handle_info>},
|
||||
{RequestLog::ext_id, typed_handler<RequestLog, handle_log>},
|
||||
{RequestFlashErase::ext_id, typed_handler<RequestFlashErase, handle_flash_erase>},
|
||||
{RequestFlashWrite::ext_id, typed_handler<RequestFlashWrite, handle_flash_write>},
|
||||
{RequestReboot::ext_id, typed_handler<RequestReboot, handle_reboot>},
|
||||
{RequestListTests::ext_id, typed_handler<RequestListTests, handle_list_tests>},
|
||||
{RequestTest::ext_id, typed_handler<RequestTest, handle_test>},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user