TockOS /
Duktape2InitialCompilationBelow are notes about the steps taken to compile Duktape2 under TockOS for the Hail board. See Duktape2 for how to use Duktape 2.x. The notes below are of historical interest only. Disable the MPUThe program fails, we turn off the MPU, see Hail Size -> Disable MPU bash-3.2$ git diff boards/hail/src/main.rs diff --git a/boards/hail/src/main.rs b/boards/hail/src/main.rs index 29b56ad..16104ff 100644 --- a/boards/hail/src/main.rs +++ b/boards/hail/src/main.rs @@ -369,7 +369,8 @@ pub unsafe fn reset_handler() { hail.nrf51822.initialize(); let mut chip = sam4l::chip::Sam4l::new(); - chip.mpu().enable_mpu(); + // duktape Disable the MPU, see {$ACCESSORS_HOME}/wiki/TockOS/HailSize#DisableMPU + //chip.mpu().enable_mpu(); kernel::main(&hail, &mut chip, load_processes(), &hail.ipc); } bash-3.2$ Then reinstall the OS: cd boards/hail make TOCK_BOARD=hail program Second Compilationcd ../../userland/examples/duktape/ make TOCK_BOARD=hail program We got further: bash-3.2$ tockloader listen No serial port specified. Discovering attached serial devices... Using "/dev/cu.usbserial-00001014 - Hail IoT Module - TockOS - Hail IoT Module - TockOS" duktape/main.c: start duktape/main.c: after heap create duktapduktape/main.c: start duktape/main.c: after heap create duktape/main.c: before pushing native_print Why does the output appear twice? In int main(int argc, char *argv[]) { putstr("duktape/main.c: start\n"); duk_context *ctx = duk_create_heap_default(); putstr("duktape/main.c: after heap create\n"); (void) argc; (void) argv; /* suppress warning */ putstr("duktape/main.c: before pushing native_print\n"); duk_push_c_function(ctx, native_print, DUK_VARARGS); putstr("duktape/main.c: after pushing native_print\n"); Interestingly, bash-3.2$ tockloader list No serial port specified. Discovering attached serial devices... Using "/dev/cu.usbserial-00001014 - Hail IoT Module - TockOS - Hail IoT Module - TockOS" [App 0] Name: duktape Total Size in Flash: 262144 bytes [WARNING] App is misaligned for the MPU bash-3.2$ Here are the sizes: text data bss dec hex filename 182656 6705 64 189425 2e3f1 build/cortex-m4/app.elf Adding some more putstr() calls shows that in duktape.c, the top of the stack is past the end. DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t fl\ ags) { duk_hthread *thr = (duk_hthread *) ctx; duk_hnatfunc *obj; duk_idx_t ret; duk_tval *tv_slot; duk_int16_t func_nargs; putstr("duktape.c: duk__push_c_function_raw() start 5\n"); DUK_ASSERT_CTX_VALID(ctx); putstr("duktape.c: duk__push_c_function_raw() after CTX_VALID\n"); /* check stack first */ if (thr->valstack_top >= thr->valstack_end) { putstr("duktape.c: duk__push_c_function_raw() check stack\n"); DUK_ERROR_RANGE_PUSH_BEYOND(thr); } putstr("duktape.c: duk__push_c_function_raw() func null?\n"); Debugging shows that
DebuggingIt would be nice if we could get the error messages Following the Duktape2.x steps in http://wiki.duktape.org/HowtoDebugPrints.html, edit
Unfortunately, this causes a fault: bash-3.2$ tockloader listen No serial port specified. Discovering attached serial devices... Using "/dev/cu.usbserial-00001014 - Hail IoT Module - TockOS - Hail IoT Module - TockOS" duktape/main.c: star�Kernel panic at /Users/cxh/src/hail/tock/kernel/src/process.rs:272: "Process duktape had a fault" ---| Fault Status |--- Imprecise Data Bus Error: true Bus Stacking Fault: true Forced Hard Fault: true Fault Status Register (CFSR): 0x00001400 Hard Fault Status Register (HFSR): 0x40000000 ---| App Status |--- Kernel panic at /Users/cxh/src/hail/tock/chips/sam4l/src/lib.rs:239: "Kernel HardFault. r0 0x1d1d1duktape/main.c: star�Kernel panic at /Users/cxh/src/hail/tock/kernel/src/process.rs:272: "Process duktape had a fault" ---| Fault Status |--- Imprecise Data Bus Error: true Bus Stacking Fault: true Forced Hard Fault: true Fault Status Register (CFSR): 0x00001400 Hard Fault Status Register (HFSR): 0x40000000 ---| App Status |--- Kernel panic at /Users/cxh/src/hail/tock/chips/sam4l/src/lib.rs:239: "Kernel HardFault. r0 0x1d1d1d1d r1 0x0 r2 0x0 r3 0x0 r12 0x0 lr 0x0 pc 0x0 prs 0x0 sp 0x200021f8 SHCSR 0x0 CFSR 0x9600 HSFR 0x40000000 " ---| Fault Status |--- Imprecise Data Bus Error: true Bus Stacking Fault: true Forced Hard Fault: true Fault Status Register (CFSR): 0x00001400 Hard Fault Status Register (HFSR): 0x40000000 ---| App Status |--- The sizes are still probably OK: text data bss dec hex filename 216080 9453 64 225597 3713d build/cortex-m4/app.elf SizeLikely running in to size issues here
LowMemConfigured using low_memory.yml See http://wiki.duktape.org/Configuring2x.html python tools/configure.py \ --output-directory /tmp/output \ --source-directory src-input \ --config-metadata config \ --option-file config/examples/low_memory.yaml \ -DDUK_USE_FASTINT \ --rom-support Copied /tmp/output/* to duktape/ In duktape/main.c: int main(int argc, char *argv[]) { putstr("duktape/main.c: start\n"); duk_context *ctx = duk_create_heap_default(); putstr("duktape/main.c: after heap create\n"); The second putstr() after creating the heap does not occur. I'm able to build with debugging levels 0 and 1.
text data bss dec hex filename 137040 18929 64 156033 26181 build/cortex-m4/app.elf
text data bss dec hex filename 170088 21617 64 191769 2ed19 build/cortex-m4/app.elf
text data bss dec hex filename 184216 22281 64 206561 326e1 build/cortex-m4/app.elf
text data bss dec hex filename 263984 26205 64 290253 46dcd build/cortex-m4/app.elf Fails to flash: Flashing binar(y|ies) to board... Error: Expected return type 15, got return 12 Error: Error when flashing page Error: RESPONSE_BADADDR: Invalid address for page to write (address: 0x80000 Could not flash the binaries. make: *** [program] Error 1 panic()Really, what we want is to get a nice TockOS crash dump. To do this, we can dereference a null pointer. In addition, we want to print out the error message before we crash. Enabling debugging messages consumes too much memory. So, we add one printf() and then dereference a null pointer in duktape.c: #if defined(DUK_USE_VERBOSE_ERRORS) DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) { #else DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) { #endif duk_context *ctx = (duk_context *) thr; duk_bool_t double_error = thr->heap->handling_error; printf("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld\n", (long) code, (const char *) msg, (const char *) filename, (long) line); int * crash = NULL; *crash = 1; duk_config.h gets #define DUK_USE_VERBOSE_ERRORS Now, when we run, we get duktape/main.c: start duk_err_create_and_throw(): code=1, msg=alloc failed, filename=duktape.c, line=24771�Kernel panic at /Users/cxh/sr\ c/hail/tock/kernel/src/process.rs:272: "Process duktape had a fault" and | ▲ Heap 21896 | 8192 EXCEEDED! So, we need to allocate more Heap. Partial SuccessWith these changes:
CFLAGS += -Os -DSTACK_SIZE=1024 -DAPP_HEAP_SIZE=28000
- SRAM (RWX) : ORIGIN = 0x00000000, LENGTH = 0x00004000 + /*SRAM (RWX) : ORIGIN = 0x00000000, LENGTH = 0x00004000 */ + SRAM (RWX) : ORIGIN = 0x00000000, LENGTH = 0x0000B000
/* MPU_MIN_ALIGN = 8K; */ MPU_MIN_ALIGN = 32K;
- static mut APP_MEMORY: [u8; 16384] = [0; 16384]; + static mut APP_MEMORY: [u8; 32768] = [0; 32768]; ... - chip.mpu().enable_mpu(); + // duktape Disable the MPU, see https://ptolemy.berkeley.edu/accessors/wiki/TockOS/HailSize#DisableMPU + //chip.mpu().enable_mpu();
-CPPFLAGS += -DSTACK_SIZE=2048 +#CPPFLAGS += -DSTACK_SIZE=2048 bash-3.2$ tockloader listen No serial port specified. Discovering attached serial devices... Using "/dev/cu.usbserial-00001014 - Hail IoT Module - TockOS - Hail IoT Module - TockOS" duktape/main.c: start duktape/main.c: after heap create duktape/main.c: before pushing native_print 2 duktape/main.c: after pushing native_print duktape/main.c: after put_global print duktape/main.c: after pushing native_adder duktape/main.c: after put_global print Kernel panic at /Users/cxh/src/hail/tock/kernel/src/process.rs:272: "Process duktape had a fault" ---| Fault Status |--- Precise Data Bus Error: true Forced Hard Fault: true Bus Fault Address: 0x1046C0C1 Fault Status Register (CFSR): 0x00008200 Hard Fault Status Register (HFSR): 0x40000000 --| App Status |--- App: duktape [Fault] - Events Queued: 0 Syscall Count: 406 build/ Address │ Region Name Used | Allocated (bytes) 0x20010000 │ v Grant 320 | 1024 0x2000FEC0 - │ Unused 0x2000FB48 - │ ^ Heap 28872 | 28000 EXCEEDED! S 0x20008A80 - R │ v Stack 1160 | 1024 EXCEEDED! A 0x200085F8 - M │ Unused 0x20008680 - │ Data 1664 | 1664 0x20008000 - ..... 0x00070000 - │ Unused 0x00052F4C - F │ Data 1600 L 0x0005290C - A │ Text 140288 S 0x0003050C - H │ Header 1292 0x00030000 - R0 : 0x20008574 R6 : 0x0000000C R1 : 0x20009E00 R7 : 0x20008574 R2 : 0x1046C0BD R8 : 0xC514EB28 R3 : 0x1046C0BD R10: 0x20008B40 R4 : 0x004B1348 R11: 0x00000000 R5 : 0x20008000 R12: 0x1046C0BD R9 : 0x20008000 (Static Base Register) SP : 0x200085F8 (Process Stack Pointer) LR : 0x00049105 [0x80018BF8 in lst file] PC : 0x00047C86 [0x8001777A in lst file] YPC : 0x0004A480 [0x80028080 in lst file] Reducing the size againDUKtapeImplementationinARM suggests setting a number of *16* defines. Updating duk_config.h with the following worked better -#undef DUK_USE_BUFLEN16 +#define DUK_USE_BUFLEN16 ... -#undef DUK_USE_OBJSIZES16 +#define DUK_USE_OBJSIZES16 ... -#undef DUK_USE_STRHASH16 +#define DUK_USE_STRHASH16 ... -#undef DUK_USE_STRLEN16 +#define DUK_USE_STRLEN16 For details, see Duktape low-memory.rst Invalid State Usage FaultNow, we get "Invalid State Usage Fault" bash-3.2$ tockloader listen tockloader listen No serial port specified. Discovering attached serial devices... Using "/dev/cu.usbserial-00001014 - Hail IoT Module - TockOS - Hail IoT Module - TockOS" duktape/main.c: start duktape/main.c: after heap create duktape/main.c: before pushing native_print 2 duktape/main.c: after pushing native_print duktape/main.c: after put_global print Kernel panic at /Users/cxh/src/hail/tock/kernel/src/process.rs:272: "Process duktape had a fault" ---| Fault Status |--- Invalid State Usage Fault: true Forced Hard Fault: true Fault Status Register (CFSR): 0x00020000 Hard Fault Status Register (HFSR): 0x40000000 ---| App Status |--- App: duktape [Fault] - Events Queued: 0 Syscall Count: 395 Address │ Region Name Used | Allocated (bytes) 0x20010000 │ ▼ Grant 320 | 1024 0x2000FEC0 - │ Unused 0x2000F1D0 - │ ▲ Heap 25448 | 27000 S 0x20008E68 - R │ ▼ Stack 1200 | 2048 A 0x200089B8 - M │ Unused 0x20008668 - │ Data 1640 | 1640 0x20008000 --------- ..... 0x00070000 ------- │ Unused 0x00052E80 - F │ Data 1580 L 0x00052854 - A │ Text 140104 S 0x0003050C - H │ Header 1292 0x00030000 ------- R0 : 0x20008EA8 R6 : 0x00000000 R1 : 0x2000E678 R7 : 0x20008018 R2 : 0x2000E678 R8 : 0x2000E678 R3 : 0x000034EE R10: 0x00000000 R4 : 0x20008EA8 R11: 0xFFFFFFFF R5 : 0x00030E2B R12: 0x000034EE R9 : 0x20008000 (Static Base Register) LR : 0x00037BE7 [0x800076DA in lst file] PC : 0x20008018 [0x9FFD7B0C in lst file] YPC : 0x0004A430 [0x800280E8 in lst file] Amit wrote: It's a hardware fault (4.3.11 in the Cortex-M4 user guide) that results from an invalid attempt to access the EPSR core memory register (2.1.3), which determines the thumb-state bit and if-then conditional result.
Usually, a fault means that you tried to execute in non-Thumb mode by loading a PC value with the lowest bit set to zero.
From the error attached, it looks like the PC that caused the fault is somewhere in the process GOT, which seems unintentional... The stacked
LR also does not correspond to a BLX instruction or anything else that should result in the LR being there, so this seems like it might be the result of some incorrect jump a few stack frames earlier or something. Increase MemoryDiscussion about process.rs suggests that modifying it to not round up to the next power of 2 might work diff --git a/boards/hail/layout.ld b/boards/hail/layout.ld index 6db637d..0532c4a 100644 --- a/boards/hail/layout.ld +++ b/boards/hail/layout.ld @@ -8,6 +8,7 @@ RAM_ORIGIN = 0x20000000; RAM_LENGTH = 0x00010000; /* MPU_MIN_ALIGN = 8K; */ -MPU_MIN_ALIGN = 32K; +/* MPU_MIN_ALIGN = 32K;*/ +MPU_MIN_ALIGN = 44K; INCLUDE ../kernel_layout.ld diff --git a/boards/hail/src/main.rs b/boards/hail/src/main.rs index 3bca9c1..30cdbe5 100644 --- a/boards/hail/src/main.rs +++ b/boards/hail/src/main.rs @@ -40,8 +40,9 @@ unsafe fn load_processes() -> &'static mut [Option<kernel::process::Process<'sta #[link_section = ".app_memory"] //static mut APP_MEMORY: [u8; 16384] = [0; 16384]; - static mut APP_MEMORY: [u8; 32768] = [0; 32768]; - //static mut APP_MEMORY: [u8; 45056] = [0; 45056]; + //static mut APP_MEMORY: [u8; 32768] = [0; 32768]; + static mut APP_MEMORY: [u8; 45056] = [0; 45056]; + static mut processes: [Option<kernel::process::Process<'static>>; NUM_PROCS] = [None, None]; diff --git a/kernel/src/process.rs b/kernel/src/process.rs index e1d2748..d7f6290 100644 --- a/kernel/src/process.rs +++ b/kernel/src/process.rs @@ -386,8 +386,11 @@ impl<'a> Process<'a> { let app_heap_len = align8!(load_info.min_app_heap_len); let kernel_heap_len = align8!(load_info.min_kernel_heap_len); + //let app_slice_size = + // closest_power_of_two(load_result.data_len + stack_len + app_heap_len + + // kernel_heap_len) as usize; let app_slice_size = - closest_power_of_two(load_result.data_len + stack_len + app_heap_len + + (load_result.data_len + stack_len + app_heap_len + kernel_heap_len) as usize; // TODO round app_slice_size up to a closer MPU unit. // This is a very conservative approach that rounds up to power of diff --git a/userland/linker.ld b/userland/linker.ld index c038f92..6b09930 100644 --- a/userland/linker.ld +++ b/userland/linker.ld @@ -3,7 +3,7 @@ ENTRY(_start) MEMORY { FLASH (rx) : ORIGIN = 0x80000000, LENGTH = 0x00080000 /*SRAM (RWX) : ORIGIN = 0x00000000, LENGTH = 0x00004000 */ - SRAM (RWX) : ORIGIN = 0x00000000, LENGTH = 0x0000B000 + SRAM (RWX) : ORIGIN = 0x00000000, LENGTH = 0x0000C000 } SECTIONS { The sizes in CFLAGS += -Os -DSTACK_SIZE=6134 -DAPP_HEAP_SIZE=32768 Success! After the above changes and recompiling the kernel and Duktape, it was possible to run a few commands. See Duktape2 Simple |