Skip to content

Commit becbef9

Browse files
committed
rebase and add examples/test/app_loader. New app binaries are located in internal/binaries.c.
cleaned up and formatted removed old code removed userspace code from a previous implementation that was giving rise to confusion. added comments to app_loader.h added binaries headers and updated code added binaries in external files to make the app file more readable. Added a new subscribe and callback to support the async setup update readme
1 parent 84edbac commit becbef9

File tree

11 files changed

+1694
-5708
lines changed

11 files changed

+1694
-5708
lines changed

examples/ota_app_wip/Makefile

Lines changed: 0 additions & 13 deletions
This file was deleted.

examples/ota_app_wip/main.c

Lines changed: 0 additions & 5335 deletions
This file was deleted.

examples/tests/app_loader/pre_flashed/Makefile renamed to examples/tests/app_loader/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Makefile for user application
22

33
# Specify this directory relative to the current application.
4-
TOCK_USERLAND_BASE_DIR = ../../../..
4+
TOCK_USERLAND_BASE_DIR = ../../..
55

66
# Which files to compile.
77
C_SRCS := $(wildcard *.c)

examples/tests/app_loader/README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Dynamic App Loader (Helper App)
2+
=================================
3+
4+
This app waits upon the user to press one of two buttons on the device (if supported).
5+
6+
When Button 1 (Default user button on boards) is pressed, the app tried to load in the
7+
`blink` app.
8+
9+
When Button 2 is pressed, the app tries to load in the `adc` app.
10+
11+
There are three stages to this:
12+
13+
1. Setup Phase
14+
2. Flash Phase
15+
3. Load Phase
16+
17+
#### Setup Phase
18+
During the setup phase, the application passes the size of the new app `(blink)/(adc)`'s
19+
binary to the app_loader capsule.
20+
21+
The capsule returns with either a success or failure.
22+
23+
On success, the app requests the app_loader capsule to flash the `blink/adc` app.
24+
25+
On Failure, the app exits logs the reason for failure and exits.
26+
27+
#### Flash Phase
28+
The app sends the binary of the `blink/adc` app 512 bytes (this is the size of the shared
29+
buffer between the app and the capsule) at a time along with the offset.
30+
31+
The capsule checks that these values do not violate the bounds dictated by the kernel
32+
and then requests the kernel to flash the app.
33+
34+
The kernel performs more stringent checking on the request to ensure that memory access
35+
violations do not take place, and flashes the app.
36+
37+
The capsule then returns with either a success or failure.
38+
39+
On success, the app requests the app_loader capsule to load the `blink/adc` app.
40+
41+
On Failure, the app exits logs the reason for failure and exits.
42+
43+
#### Load Phase
44+
The app requests the capsule to load the new app. There are only two outcomes:
45+
46+
1. The `blink/adc` app is loaded successfully and functions without requiring a restart.
47+
2. The load process failed somewhere, and the app is erased.

examples/tests/app_loader/main.c

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
// \file
2+
3+
// This is a helper program to test if the dynamic app loading functionality
4+
// of Tock works. This app has another application's (blink) binary pre-programmed
5+
// into it. When the user presses a button on a supported device, the dynamic
6+
// process loader enables the new app to be written to flash and loaded as a new process.
7+
8+
#include <math.h>
9+
#include <stdio.h>
10+
#include <string.h>
11+
12+
#include <app_binaries.h>
13+
#include <app_loader.h>
14+
#include <button.h>
15+
#include <timer.h>
16+
#include <tock.h>
17+
18+
19+
#define FLASH_BUFFER_SIZE 512
20+
#define RETURNCODE_SUCCESS 0
21+
22+
static bool setup_done = false; // to check if setup is done
23+
static bool write_done = false; // to check if writing to flash is done
24+
25+
/******************************************************************************************************
26+
* Callback functions
27+
*
28+
* 1. Callback to let us know when the capsule is done writing data to flash
29+
* 2. Set button callback to initiate the dynamic app load process on pressing button 1 (on nrf52840dk)
30+
*
31+
******************************************************************************************************/
32+
33+
// static void nop_callback(int a __attribute__((unused)), int b __attribute__((unused)), int c __attribute__((unused)), void *d __attribute__((unused))) {}
34+
35+
static void app_setup_done_callback(__attribute__((unused)) int length,
36+
__attribute__((unused)) int arg1,
37+
__attribute__((unused)) int arg2,
38+
__attribute__((unused)) void *ud)
39+
{
40+
setup_done = true;
41+
}
42+
43+
static void app_write_done_callback(__attribute__((unused)) int length,
44+
__attribute__((unused)) int arg1,
45+
__attribute__((unused)) int arg2,
46+
__attribute__((unused)) void *ud)
47+
{
48+
write_done = true;
49+
}
50+
51+
static void button_callback(int btn_num,
52+
int val,
53+
__attribute__ ((unused)) int arg2,
54+
__attribute__ ((unused)) void *ud)
55+
{
56+
// Callback for button presses.
57+
// val: 1 if pressed, 0 if depressed
58+
59+
// flash and load blink
60+
if (btn_num == BUTTON1 && val == 1) {
61+
62+
delay_ms(100); // debounce
63+
64+
if (val == 1) {
65+
66+
printf("[Event] Button 1 Pressed!\n");
67+
double app_size = sizeof(blink);
68+
int ret = 0;
69+
int ret1 = 0;
70+
int ret2 = 0;
71+
72+
ret = app_loader_command_setup(app_size); // asks the capsule to set up for app flash
73+
if (ret != RETURNCODE_SUCCESS) {
74+
printf("[Error] Setup Failed: %d.\n", ret);
75+
printf("[Log] Exiting Application.\n");
76+
tock_exit(ret); // we failed, so we exit the program.
77+
} else {
78+
yield_for(&setup_done); // wait until the padding app write is done before you send your app, or it will fail during write
79+
setup_done = false;
80+
printf("[Success] Setup successful. Attempting to write app to flash now.\n");
81+
ret1 = write_app(app_size, blink); // writes app data to flash
82+
if (ret1 != RETURNCODE_SUCCESS) {
83+
printf("[Error] App flash write unsuccessful: %d.\n", ret1);
84+
printf("[Log] Exiting Application.\n");
85+
tock_exit(ret1); // we failed, so we exit the program.
86+
} else {
87+
printf("[Success] App flashed successfully. Attempting to create a process now.\n");
88+
ret2 = app_loader_command_load(); // request to load app
89+
if (ret2 != RETURNCODE_SUCCESS) {
90+
printf("[Error] Process creation failed: %d.\n", ret2);
91+
printf("[Log] Exiting Application.\n");
92+
tock_exit(ret2); // we failed, so we exit the program.
93+
} else {
94+
printf("[Success] Process created successfully.\n");
95+
}
96+
}
97+
}
98+
app_size = 0; // reset app_size
99+
}
100+
}
101+
// flash and load adc
102+
else if (btn_num == BUTTON2 && val == 1) {
103+
104+
delay_ms(100); // debounce
105+
106+
if (val == 1) {
107+
printf("[Event] Button 2 Pressed!\n");
108+
double app_size = sizeof(adc);
109+
int ret = 0;
110+
int ret1 = 0;
111+
int ret2 = 0;
112+
113+
ret = app_loader_command_setup(app_size); // asks the capsule to set up for app flash
114+
if (ret != RETURNCODE_SUCCESS) {
115+
printf("[Error] Setup Failed: %d.\n", ret);
116+
printf("[Log] Exiting Application.\n");
117+
tock_exit(ret); // we failed, so we exit the program.
118+
} else {
119+
// yielding for padding write
120+
printf("[Log] yielding for setup done.\n");
121+
yield_for(&setup_done); // wait until the padding app write is done before you send your app, or it will fail during write
122+
setup_done = false;
123+
// padding success
124+
printf("[Success] Setup successful. Attempting to write app to flash now.\n");
125+
ret1 = write_app(app_size, adc); // writes app data to flash
126+
if (ret1 != RETURNCODE_SUCCESS) {
127+
printf("[Error] App flash write unsuccessful: %d.\n", ret1);
128+
printf("[Log] Exiting Application.\n");
129+
tock_exit(ret1); // we failed, so we exit the program.
130+
} else {
131+
printf("[Success] App flashed successfully. Attempting to create a process now.\n");
132+
ret2 = app_loader_command_load(); // request to load app
133+
if (ret2 != RETURNCODE_SUCCESS) {
134+
printf("[Error] Process creation failed: %d.\n", ret2);
135+
printf("[Log] Exiting Application.\n");
136+
tock_exit(ret2); // we failed, so we exit the program.
137+
} else {
138+
printf("[Success] Process created successfully.\n");
139+
}
140+
}
141+
}
142+
app_size = 0; // reset app_size
143+
}
144+
}
145+
}
146+
147+
148+
/******************************************************************************************************
149+
*
150+
* Function to write the app into the flash
151+
*
152+
* Takes app size and the app binary as arguments
153+
******************************************************************************************************/
154+
155+
int write_app(double size, uint8_t binary[]){
156+
157+
int ret;
158+
uint32_t write_count = 0;
159+
uint8_t write_buffer[FLASH_BUFFER_SIZE];
160+
uint32_t flash_offset = 0;
161+
162+
write_count = ceil(size / FLASH_BUFFER_SIZE);
163+
164+
ret = app_loader_write_buffer(write_buffer, FLASH_BUFFER_SIZE); // set the write buffer
165+
if (ret != RETURNCODE_SUCCESS) {
166+
printf("[Error] Failed to set the write buffer: %d.\n", ret);
167+
return -1;
168+
}
169+
170+
for (uint32_t offset = 0; offset < write_count; offset++) {
171+
memcpy(write_buffer, &binary[FLASH_BUFFER_SIZE * offset], FLASH_BUFFER_SIZE); // copy binary to write buffer
172+
flash_offset = (offset * FLASH_BUFFER_SIZE);
173+
ret = app_loader_command_write(flash_offset, FLASH_BUFFER_SIZE);
174+
if (ret != 0) {
175+
printf("[Error] Failed writing data to flash at address: 0x%lx\n", flash_offset);
176+
return -1;
177+
}
178+
yield_for(&write_done); // wait until write done callback
179+
write_done = false;
180+
}
181+
return 0;
182+
}
183+
184+
185+
/******************************************************************************************************
186+
*
187+
* Main
188+
*
189+
******************************************************************************************************/
190+
191+
int main(void) {
192+
printf("[Log] Simple test app to load an app dynamically.\n");
193+
194+
int count;
195+
int err = button_count(&count);
196+
// Ensure there is a button to use.
197+
if (err < 0) return err;
198+
printf("[Log] There are %d buttons on this board.\n", count);
199+
200+
// Enable interrupts on each button.
201+
for (int i = 0; i < count; i++) {
202+
button_enable_interrupt(i);
203+
}
204+
205+
// set up the write done and button press callbacks
206+
int err1 = app_loader_setup_subscribe(app_setup_done_callback, NULL);
207+
if (err1 != 0) {
208+
printf("[Error] Failed to set setup done callback: %d\n", err1);
209+
return err1;
210+
}
211+
212+
// set up the write done and button press callbacks
213+
int err2 = app_loader_write_subscribe(app_write_done_callback, NULL);
214+
if (err2 != 0) {
215+
printf("[Error] Failed to set flash write done callback: %d\n", err2);
216+
return err2;
217+
}
218+
219+
int err3 = button_subscribe(button_callback, NULL);
220+
if (err3 != 0) {
221+
printf("[Error] Failed to set button callback: %d.\n", err3);
222+
return err3;
223+
}
224+
225+
// Check if the app_loader driver exists.
226+
int ret;
227+
ret = app_loader_exists();
228+
if (ret != RETURNCODE_SUCCESS) {
229+
printf("[Error] Dynamic Apploader driver does not exist.\n");
230+
return ret; // the driver does not exist, so we cannot load an app anyway. Let us exit the program.
231+
}
232+
233+
printf("[Log] Waiting for a button press.\n");
234+
235+
while (1) {
236+
yield();
237+
}
238+
}

0 commit comments

Comments
 (0)