Build epoch in info, flash-status command, cmake version embedding

This commit is contained in:
Ian Gulliver
2026-04-12 09:02:31 +09:00
parent 21c7900444
commit a41ee70a3c
9 changed files with 85 additions and 5 deletions

View File

@@ -113,7 +113,7 @@ func closeTargets(targets []target) {
func main() { func main() {
if len(os.Args) < 2 { if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "usage: picomap <command> [args...]\n\ncommands:\n info\n load\n log\n reboot\n picoboot\n test\n") fmt.Fprintf(os.Stderr, "usage: picomap <command> [args...]\n\ncommands:\n info\n flash-status\n load\n log\n reboot\n picoboot\n test\n")
os.Exit(1) os.Exit(1)
} }
cmd := os.Args[1] cmd := os.Args[1]
@@ -123,6 +123,8 @@ func main() {
switch cmd { switch cmd {
case "info": case "info":
err = cmdInfo(args) err = cmdInfo(args)
case "flash-status":
err = cmdFlashStatus(args)
case "load": case "load":
err = cmdLoad(args) err = cmdLoad(args)
case "log": case "log":
@@ -134,7 +136,7 @@ func main() {
case "test": case "test":
err = cmdTestGroup(args) err = cmdTestGroup(args)
default: default:
fmt.Fprintf(os.Stderr, "usage: picomap <command> [args...]\n\ncommands:\n info\n load\n log\n reboot\n picoboot\n test\n") fmt.Fprintf(os.Stderr, "usage: picomap <command> [args...]\n\ncommands:\n info\n flash-status\n load\n log\n reboot\n picoboot\n test\n")
os.Exit(1) os.Exit(1)
} }
if err != nil { if err != nil {
@@ -150,7 +152,8 @@ func printInfo(via string, info *client.ResponseInfo) {
"mac", net.HardwareAddr(info.MAC[:]).String(), "mac", net.HardwareAddr(info.MAC[:]).String(),
"ip", net.IP(info.IP[:]).String(), "ip", net.IP(info.IP[:]).String(),
"firmware", info.FirmwareName, "firmware", info.FirmwareName,
"boot", info.Boot.String()) "boot", info.Boot.String(),
"build_epoch", info.BuildEpoch)
} }
func cmdInfo(args []string) error { func cmdInfo(args []string) error {
@@ -204,6 +207,31 @@ func cmdLog(args []string) error {
return nil return nil
} }
func cmdFlashStatus(args []string) error {
fs := flag.NewFlagSet("flash-status", flag.ExitOnError)
tf := addTargetFlags(fs)
fs.Parse(args)
targets, err := tf.connect(500 * time.Millisecond)
if err != nil {
return err
}
defer closeTargets(targets)
for _, t := range targets {
status, err := t.client.FlashStatus()
if err != nil {
slog.Error("flash-status error", "via", t.name, "err", err)
continue
}
slog.Info("flash-status",
"via", t.name,
"boot_partition", status.BootPartition,
"boot_type", status.BootType)
}
return nil
}
func cmdReboot(args []string) error { func cmdReboot(args []string) error {
fs := flag.NewFlagSet("reboot", flag.ExitOnError) fs := flag.NewFlagSet("reboot", flag.ExitOnError)
tf := addTargetFlags(fs) tf := addTargetFlags(fs)

View File

@@ -30,6 +30,11 @@ pico_generate_pio_header(picomap ${CMAKE_CURRENT_LIST_DIR}/w6300/qspi.pio)
pico_enable_stdio_usb(picomap 0) pico_enable_stdio_usb(picomap 0)
pico_enable_stdio_uart(picomap 0) pico_enable_stdio_uart(picomap 0)
pico_set_binary_type(picomap copy_to_ram) pico_set_binary_type(picomap copy_to_ram)
string(TIMESTAMP BUILD_EPOCH "%s" UTC)
math(EXPR VERSION_MAJOR "${BUILD_EPOCH} >> 16")
math(EXPR VERSION_MINOR "${BUILD_EPOCH} & 65535")
pico_set_binary_version(picomap MAJOR ${VERSION_MAJOR} MINOR ${VERSION_MINOR})
target_compile_definitions(picomap PRIVATE BUILD_EPOCH=${BUILD_EPOCH})
pico_add_extra_outputs(picomap) pico_add_extra_outputs(picomap)
target_link_libraries(picomap ${LIB_DEPS}) target_link_libraries(picomap ${LIB_DEPS})
@@ -40,5 +45,7 @@ pico_generate_pio_header(picomap_test ${CMAKE_CURRENT_LIST_DIR}/w6300/qspi.pio)
pico_enable_stdio_usb(picomap_test 0) pico_enable_stdio_usb(picomap_test 0)
pico_enable_stdio_uart(picomap_test 0) pico_enable_stdio_uart(picomap_test 0)
pico_set_binary_type(picomap_test copy_to_ram) pico_set_binary_type(picomap_test copy_to_ram)
pico_set_binary_version(picomap_test MAJOR ${VERSION_MAJOR} MINOR ${VERSION_MINOR})
target_compile_definitions(picomap_test PRIVATE BUILD_EPOCH=${BUILD_EPOCH})
pico_add_extra_outputs(picomap_test) pico_add_extra_outputs(picomap_test)
target_link_libraries(picomap_test ${LIB_DEPS}) target_link_libraries(picomap_test ${LIB_DEPS})

View File

@@ -10,6 +10,7 @@ static constexpr handler_entry handlers[] = {
{RequestFlashErase::ext_id, typed_handler<RequestFlashErase, handle_flash_erase>}, {RequestFlashErase::ext_id, typed_handler<RequestFlashErase, handle_flash_erase>},
{RequestFlashWrite::ext_id, typed_handler<RequestFlashWrite, handle_flash_write>}, {RequestFlashWrite::ext_id, typed_handler<RequestFlashWrite, handle_flash_write>},
{RequestReboot::ext_id, typed_handler<RequestReboot, handle_reboot>}, {RequestReboot::ext_id, typed_handler<RequestReboot, handle_reboot>},
{RequestFlashStatus::ext_id, typed_handler<RequestFlashStatus, handle_flash_status>},
}; };
int main() { int main() {

View File

@@ -14,3 +14,4 @@ std::optional<ResponseLog> handle_log(const responder& resp, const RequestLog&);
std::optional<ResponseFlashErase> handle_flash_erase(const responder& resp, const RequestFlashErase&); std::optional<ResponseFlashErase> handle_flash_erase(const responder& resp, const RequestFlashErase&);
std::optional<ResponseFlashWrite> handle_flash_write(const responder& resp, const RequestFlashWrite&); std::optional<ResponseFlashWrite> handle_flash_write(const responder& resp, const RequestFlashWrite&);
std::optional<ResponseReboot> handle_reboot(const responder& resp, const RequestReboot&); std::optional<ResponseReboot> handle_reboot(const responder& resp, const RequestReboot&);
std::optional<ResponseFlashStatus> handle_flash_status(const responder& resp, const RequestFlashStatus&);

View File

@@ -57,8 +57,9 @@ struct ResponseInfo {
std::array<uint8_t, 4> ip; std::array<uint8_t, 4> ip;
std::string firmware_name; std::string firmware_name;
boot_reason boot; boot_reason boot;
auto as_tuple() const { return std::tie(board_id, mac, ip, firmware_name, boot); } uint32_t build_epoch;
auto as_tuple() { return std::tie(board_id, mac, ip, firmware_name, boot); } auto as_tuple() const { return std::tie(board_id, mac, ip, firmware_name, boot, build_epoch); }
auto as_tuple() { return std::tie(board_id, mac, ip, firmware_name, boot, build_epoch); }
}; };
struct RequestLog { struct RequestLog {
@@ -121,6 +122,20 @@ struct ResponseReboot {
auto as_tuple() { return std::tie(); } auto as_tuple() { return std::tie(); }
}; };
struct RequestFlashStatus {
static constexpr int8_t ext_id = 14;
auto as_tuple() const { return std::tie(); }
auto as_tuple() { return std::tie(); }
};
struct ResponseFlashStatus {
static constexpr int8_t ext_id = 15;
int8_t boot_partition;
uint8_t boot_type;
auto as_tuple() const { return std::tie(boot_partition, boot_type); }
auto as_tuple() { return std::tie(boot_partition, boot_type); }
};
struct RequestListTests { struct RequestListTests {
static constexpr int8_t ext_id = 125; static constexpr int8_t ext_id = 125;
auto as_tuple() const { return std::tie(); } auto as_tuple() const { return std::tie(); }

View File

@@ -45,6 +45,7 @@ std::optional<ResponseInfo> handle_info(const responder&, const RequestInfo&) {
resp.ip = ns.ip; resp.ip = ns.ip;
resp.firmware_name = firmware_name; resp.firmware_name = firmware_name;
resp.boot = detected_boot_reason; resp.boot = detected_boot_reason;
resp.build_epoch = BUILD_EPOCH;
return resp; return resp;
} }
@@ -87,6 +88,19 @@ std::optional<ResponseFlashWrite> handle_flash_write(const responder&, const Req
return ResponseFlashWrite{}; return ResponseFlashWrite{};
} }
std::optional<ResponseFlashStatus> handle_flash_status(const responder&, const RequestFlashStatus&) {
ResponseFlashStatus resp;
boot_info_t bi;
if (rom_get_boot_info(&bi)) {
resp.boot_partition = bi.partition;
resp.boot_type = bi.boot_type;
} else {
resp.boot_partition = -1;
resp.boot_type = 0;
}
return resp;
}
std::optional<ResponseReboot> handle_reboot(const responder&, const RequestReboot&) { std::optional<ResponseReboot> handle_reboot(const responder&, const RequestReboot&) {
dispatch_schedule_ms(100, []{ dispatch_schedule_ms(100, []{
watchdog_hw->scratch[0] = static_cast<uint32_t>(boot_reason::request_reboot); watchdog_hw->scratch[0] = static_cast<uint32_t>(boot_reason::request_reboot);

View File

@@ -20,6 +20,7 @@ static constexpr handler_entry handlers[] = {
{RequestFlashErase::ext_id, typed_handler<RequestFlashErase, handle_flash_erase>}, {RequestFlashErase::ext_id, typed_handler<RequestFlashErase, handle_flash_erase>},
{RequestFlashWrite::ext_id, typed_handler<RequestFlashWrite, handle_flash_write>}, {RequestFlashWrite::ext_id, typed_handler<RequestFlashWrite, handle_flash_write>},
{RequestReboot::ext_id, typed_handler<RequestReboot, handle_reboot>}, {RequestReboot::ext_id, typed_handler<RequestReboot, handle_reboot>},
{RequestFlashStatus::ext_id, typed_handler<RequestFlashStatus, handle_flash_status>},
{RequestListTests::ext_id, typed_handler<RequestListTests, handle_list_tests>}, {RequestListTests::ext_id, typed_handler<RequestListTests, handle_list_tests>},
{RequestTest::ext_id, typed_handler<RequestTest, handle_test>}, {RequestTest::ext_id, typed_handler<RequestTest, handle_test>},
}; };

View File

@@ -132,6 +132,10 @@ func (c *Client) Reboot() error {
return err return err
} }
func (c *Client) FlashStatus() (*ResponseFlashStatus, error) {
return first(roundTrip[ResponseFlashStatus](c, &RequestFlashStatus{}))
}
func (c *Client) ListTests() (*ResponseListTests, error) { func (c *Client) ListTests() (*ResponseListTests, error) {
return first(roundTrip[ResponseListTests](c, &RequestListTests{})) return first(roundTrip[ResponseListTests](c, &RequestListTests{}))
} }

View File

@@ -33,6 +33,7 @@ type ResponseInfo struct {
IP [4]byte IP [4]byte
FirmwareName string FirmwareName string
Boot BootReason Boot BootReason
BuildEpoch uint32
} }
type RequestLog struct{} type RequestLog struct{}
@@ -61,6 +62,12 @@ type ResponseFlashWrite struct{}
type RequestReboot struct{} type RequestReboot struct{}
type ResponseReboot struct{} type ResponseReboot struct{}
type RequestFlashStatus struct{}
type ResponseFlashStatus struct {
BootPartition int8
BootType uint8
}
type RequestListTests struct{} type RequestListTests struct{}
type ResponseListTests struct { type ResponseListTests struct {
Names []string Names []string
@@ -105,6 +112,8 @@ func init() {
msgpack.RegisterExt(11, (*ResponseFlashWrite)(nil)) msgpack.RegisterExt(11, (*ResponseFlashWrite)(nil))
msgpack.RegisterExt(12, (*RequestReboot)(nil)) msgpack.RegisterExt(12, (*RequestReboot)(nil))
msgpack.RegisterExt(13, (*ResponseReboot)(nil)) msgpack.RegisterExt(13, (*ResponseReboot)(nil))
msgpack.RegisterExt(14, (*RequestFlashStatus)(nil))
msgpack.RegisterExt(15, (*ResponseFlashStatus)(nil))
msgpack.RegisterExt(125, (*RequestListTests)(nil)) msgpack.RegisterExt(125, (*RequestListTests)(nil))
msgpack.RegisterExt(124, (*ResponseListTests)(nil)) msgpack.RegisterExt(124, (*ResponseListTests)(nil))
msgpack.RegisterExt(127, (*RequestTest)(nil)) msgpack.RegisterExt(127, (*RequestTest)(nil))