diff --git a/examples/suit_update/Makefile b/examples/suit_update/Makefile index 0f487b68c7..d649e86dc1 100644 --- a/examples/suit_update/Makefile +++ b/examples/suit_update/Makefile @@ -51,6 +51,9 @@ FEATURES_OPTIONAL += periph_gpio_irq # Default COAP manifest resource location when fetched through gpio trigger CFLAGS += -DSUIT_MANIFEST_RESOURCE=\"$(SUIT_COAP_ROOT)/$(SUIT_NOTIFY_MANIFEST)\" +# Enable test_utils_interactive_sync, only used when running automatic test +DEFAULT_MODULE += test_utils_interactive_sync + # Change this to 0 to not use ethos USE_ETHOS ?= 1 diff --git a/examples/suit_update/README.md b/examples/suit_update/README.md index febe9ce1a5..90a8f4a6c3 100644 --- a/examples/suit_update/README.md +++ b/examples/suit_update/README.md @@ -465,22 +465,24 @@ displayed during this step: Once the new image is written, a final validation is performed and, in case of success, the application reboots on the new slot: + Finalizing payload store Verifying image digest - riotboot: verifying digest at 0x1fffbd15 (img at: 0x1000 size: 77448) + Starting digest verification against image + Install correct payload Verifying image digest - riotboot: verifying digest at 0x1fffbd15 (img at: 0x1000 size: 77448) - suit_parse() success - SUIT policy check OK. - suit_coap: finalizing image flash - riotboot_flashwrite: riotboot flashing completed successfully + Starting digest verification against image + Install correct payload Image magic_number: 0x544f4952 - Image Version: 0x5e71f662 - Image start address: 0x00001100 - Header chksum: 0x745a0376 + Image Version: 0x5fa52bcc + Image start address: 0x00201400 + Header chksum: 0x53bb3d33 + suit_coap: rebooting... - main(): This is RIOT! (Version: 2020.04) + main(): This is RIOT! (Version: )) RIOT SUIT update example application - running from slot 1 + Running from slot 1 + ... + The slot number should have changed from after the application reboots. You can do the publish-notify sequence several times to verify this. diff --git a/examples/suit_update/main.c b/examples/suit_update/main.c index d95c5852d7..e8b241914c 100644 --- a/examples/suit_update/main.c +++ b/examples/suit_update/main.c @@ -68,9 +68,10 @@ static void cb(void *arg) } #endif -int main(void) +static int cmd_print_riotboot_hdr(int argc, char **argv) { - puts("RIOT SUIT update example application"); + (void)argc; + (void)argv; int current_slot = riotboot_slot_current(); if (current_slot != -1) { @@ -78,21 +79,48 @@ int main(void) * confuses the test script. As a workaround, just disable interrupts * for a while. */ - irq_disable(); - printf("running from slot %d\n", current_slot); - printf("slot start addr = %p\n", (void *)riotboot_slot_get_hdr(current_slot)); + unsigned state = irq_disable(); riotboot_slot_print_hdr(current_slot); - irq_enable(); + irq_restore(state); } else { printf("[FAILED] You're not running riotboot\n"); } + return 0; +} + +static int cmd_print_current_slot(int argc, char **argv) +{ + (void)argc; + (void)argv; + /* Sometimes, udhcp output messes up the following printfs. That + * confuses the test script. As a workaround, just disable interrupts + * for a while. + */ + unsigned state = irq_disable(); + printf("Running from slot %d\n", riotboot_slot_current()); + irq_restore(state); + return 0; +} + +static const shell_command_t shell_commands[] = { + { "current-slot", "Print current slot number", cmd_print_current_slot }, + { "riotboot-hdr", "Print current slot header", cmd_print_riotboot_hdr }, + { NULL, NULL, NULL } +}; + + +int main(void) +{ + puts("RIOT SUIT update example application"); #if defined(MODULE_PERIPH_GPIO_IRQ) && defined(BTN0_PIN) /* initialize a button to manually trigger an update */ gpio_init_int(BTN0_PIN, BTN0_MODE, GPIO_FALLING, cb, NULL); #endif + cmd_print_current_slot(0, NULL); + cmd_print_riotboot_hdr(0, NULL); /* start suit coap updater thread */ suit_coap_run(); @@ -109,7 +137,7 @@ int main(void) puts("Starting the shell"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/examples/suit_update/tests/01-run.py b/examples/suit_update/tests/01-run.py index b16e1cb846..b56f53d61c 100755 --- a/examples/suit_update/tests/01-run.py +++ b/examples/suit_update/tests/01-run.py @@ -13,6 +13,7 @@ import tempfile import time from testrunner import run +from testrunner import utils # Default test over loopback interface COAP_HOST = "[fd00:dead:beef::1]" @@ -113,10 +114,7 @@ def ping6(client): def get_reachable_addr(child): - # Wait for suit_coap thread to start - child.expect_exact("suit_coap: started.") - child.expect_exact("Starting the shell") - # give some time for the network interface to be configured + # Give some time for the network interface to be configured time.sleep(1) # Get address client_addr = get_ipv6_addr(child) @@ -126,13 +124,25 @@ def get_reachable_addr(child): def app_version(child): + utils.test_utils_interactive_sync_shell(child, 5, 1) # get version of currently running image # "Image Version: 0x00000000" + child.sendline('riotboot-hdr') child.expect(r"Image Version: (?P0x[0-9a-fA-F:]+)\r\n") app_ver = int(child.match.group("app_ver"), 16) return app_ver +def running_slot(child): + utils.test_utils_interactive_sync_shell(child, 5, 1) + # get version of currently running image + # "Image Version: 0x00000000" + child.sendline('current-slot') + child.expect(r"Running from slot (\d+)\r\n") + slot = int(child.match.group(1)) + return slot + + def _test_invalid_version(child, client, app_ver): publish(TMPDIR.name, COAP_HOST, app_ver - 1) notify(COAP_HOST, client, app_ver - 1) @@ -165,9 +175,11 @@ def _test_successful_update(child, client, app_ver): while wait_for_update(child) == 0: pass + # Wait for reboot + child.expect_exact("suit_coap: rebooting...") # Verify running slot - child.expect(r"running from slot (\d+)\r\n") - assert target_slot == int(child.match.group(1)), "BOOTED FROM SAME SLOT" + current_slot = running_slot(child) + assert target_slot == current_slot, "BOOTED FROM SAME SLOT" # Verify client is reachable and get address client = get_reachable_addr(child)