Notes /
MaximPegasusDuktapeProblemsBelow are various problems I had building Duktape 2.1 for the Maxim Pegasus. See Maxim Pegasus for instructions about how to build from the accessors repo. See below for possibly useful information. Makefile CreationI attempted to create a makefile by hand, but it seems easier to use the
Duktape SizeThe issue is that the Accessor host starts up and echoes to the port, but we never see the numbers. We get: eduk: About to run test/auto/RampJSDisplay.js With the default Duktape2.0.1 settings, the size is: text data bss dec hex filename 437688 15364 8316 461368 70a38 BUILD/mbed-duktape2.elf With the following changes to /* __OVERRIDE_DEFINES__ */ #define DUK_USE_DEBUG #define DUK_USE_DEBUG_LEVEL 2 #define DUK_USE_DEBUG_WRITE(level,file,line,func,msg) do { \ fprintf(stderr, "D%ld %s:%ld (%s): %s\n", \ (long) (level), (file), (long) (line), (func), (msg)); \ } while (0) /* #define DUK_OPT_NO_JSON_STRINGIFY_FASTPATH #undef DUK_USE_REFERENCE_COUNTING #define DUK_USE_REFCOUNT16 #define DUK_USE_STRHASH16 #define DUK_USE_STRLEN16 #define DUK_USE_OBJSIZES16 */ #undef DUK_USE_AUGMENT_ERRORS #undef DUK_USE_TRACEBACKS /*#undef DUK_USE_VERBOSE_ERRORS*/ #undef DUK_USE_VERBOSE_EXECUTOR_ERRORS #undef DUK_USE_PC2LINE #undef DUK_USE_LEXER_SLIDING_WINDOW #undef DUK_USE_JSON_STRINGIFY_FASTPATH #undef DUK_USE_JSON_QUOTESTRING_FASTPATH #undef DUK_USE_JSON_DECSTRING_FASTPATH #undef DUK_USE_JSON_DECNUMBER_FASTPATH #undef DUK_USE_JSON_EATWHITE_FASTPATH #undef DUK_USE_JX #undef DUK_USE_JC #undef DUK_USE_ES6_OBJECT_SETPROTOTYPEOF #undef DUK_USE_ES6_OBJECT_PROTO_PROPERTY /* #undef DUK_USE_ES6_PROXY */ #undef DUK_USE_BYTECODE_DUMP_SUPPORT #define DUK_USE_DEBUG_BUFSIZE 2048 #define DUK_USE_LIGHTFUNC_BUILTINS #undef DUK_USE_REFERENCE_COUNTING #undef DUK_USE_DOUBLE_LINKED_LIST #define DUK_USE_REFCOUNT16 #define DUK_USE_STRHASH16 #define DUK_USE_STRLEN16 #define DUK_USE_BUFLEN16 #define DUK_USE_OBJSIZES16 #undef DUK_USE_HSTRING_CLEN #define DUK_USE_EXTERNAL_STRINGS Sizes: text data bss dec hex filename 531736 16388 8316 556440 87d98 BUILD/mbed-duktape2.elf Then I get quite a bit of output in the terminal and it eventually fails with: D2 duk_alloc_default.c:30 (duk_default_free_function): default free function: 0x20006be0 D0 duk_heap_alloc.c:329 (duk_heap_free): freeing heap structure: 0x20006288 D2 duk_alloc_default.c:30 (duk_default_free_function): default free function: 0x20006288 D1 duk_error_throw.c:34 (duk_err_create_and_throw): duk_err_create_and_throw(): code=3, msg=cannot push beyond allocated stack, filename=duk_api_stack.c, line=3445 D0 duk_error_throw.c:74 (duk_err_create_and_throw): double fault detected -> push built-in fixed 'double error' instance D1 duk_error_throw.c:34 (duk_err_create_and_throw): duk_err_create_and_throw(): code=3, msg=cannot push beyond allocated stack, filename=duk_api_stack.c, line=3445 Interestingly, it appears that enabling the debugging means that we never get to the first println in eduk.cpp. Presumably we are consuming too much memory with the debugging. So, it appears there is a stack problem. This could be because we are running with the mbed RTOS, instead we should try to compile without it. limits problemUnder the Maxim Pegasus (Cortex Arm 4), adding debugging fails: D0 duk_heap_alloc.c:621 (duk__dump_type_sizes): duk_re_compiler_ctx=196 D0 duk_heap_alloc.c:624 (duk__dump_type_limits): limits See Maxim Pegasus Limits Problem Size, continuedThe Makefile contains LINKER_SCRIPT ?= .././mbed-os/targets/TARGET_Maxim/TARGET_MAX32630/device/TOOLCHAIN_GCC_ARM/max3263x.ld Looking at the max3263x.ld file shows various Running nm shows that Stack_Size is 0x5000 or 20480 decimal bash-3.2$ nm */*.elf | grep -i stack | head 00005000 a Stack_Size 00000025 a TCB_STACKF 0000002c a TCB_TSTACK 2007b000 A __StackLimit 20080000 B __StackTop 20080000 A __stack
#ifdef __STACK_SIZE .equ Stack_Size, __STACK_SIZE #else .equ Stack_Size, 0x00005000 #endif So, let's define ASM_FLAGS += -D__STACK_SIZE=0x00050000 The mbed RTOS presumably defines a stack size per thread. Changing this globally could be bad. There is a web page somewhere about how to change this on a per thread basis. If you change the value of rm ./BUILD/mbed-os/targets/TARGET_Maxim/TARGET_MAX32630/device/TOOLCHAIN_GCC_ARM/startup_max3263x.o With ASM_FLAGS += -D__STACK_SIZE=0x00068000 and #define DUK_USE_DEBUG_LEVEL 1 The failure occurs later: D1 duk_heap_markandsweep.c:802 (duk__sweep_heap): keep object: {__extensible:true,__thread:true,__strict:0,__state:1,__unused1:0,__unused2:0,__valstack\ _max:1000000,__callstack_max:10000,__catchstack_max:10000,__valstack:0x200082e8,__valstack_end:0x20008ae8/256,__valstack_bottom:0x200082e8/0,__valstack\ _top:0x20008548/76,__catchstack:0x20008290,__catchstack_size:4,__catchstack_top:0,__resumer:NULL,__class:18,__heapptr:0x20007ba0} D0 duk_heap_markandsweep.c:875 (duk__sweep_heap): mark-and-sweep sweep objects (non-string): 0 freed, 78 kept, 0 rescued, 0 queued for finalization D1 duk_heap_markandsweep.c:664 (duk__sweep_stringtable_probe): duk__sweep_stringtable: 0x20006288 D0 duk_heap_markandsweep.c:716 (duk__sweep_stringtable_probe): mark-and-sweep sweep stringtable: 0 freed, 247 kept D1 duk_heap_markandsweep.c:525 (duk__clear_finalize_list_flags): duk__clear_finalize_list_flags: 0x20006288 D1 duk_heap_markandsweep.c:1351 (duk_heap_mark_and_sweep): resize stringtable: 0x20006288 D0 duk_heap_memory.c:80 (duk_heap_mem_alloc): first alloc attempt failed, attempt to gc and retry D0 duk_heap_memory.c:89 (duk_heap_mem_alloc): duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size 2084 D0 duk_heap_markandsweep.c:1403 (duk_heap_mark_and_sweep): finalizer run skipped because DUK_MS_FLAG_NO_FINALIZERS is set D0 duk_heap_markandsweep.c:1442 (duk_heap_mark_and_sweep): garbage collect (mark-and-sweep) finished: 78 objects kept, 247 strings kept, trigger reset \ to 1280 D0 duk_heap_memory.c:118 (duk_heap_mem_alloc): duk_heap_mem_alloc() failed even after gc, alloc size 328 D1 duk_hbuffer_alloc.c:120 (duk_hbuffer_alloc): hbuffer allocation failed D1 duk_error_throw.c:34 (duk_err_create_and_throw): duk_err_create_and_throw(): code=1, msg=alloc failed, filename=duk_api_stack.c, line=4564 D1 duk_hobject_props.c:911 (duk_hobject_realloc_props): resized hobject 0x20007608 props (0 -> 28 bytes), from {p=NULL,e_size=0,e_next=0,a_size=0,h_siz\ e=0} to {p=0x20009ae8,e_size=2,e_next=0,a_size=0,h_size=0}, abandon_array=0, unadjusted new_e_size=2 D1 duk_hobject_props.c:911 (duk_hobject_realloc_props): resized hobject 0x20007608 props (28 -> 52 bytes), from {p=0x20009ae8,e_size=2, Memory Usagehttps://github.com/nuket/mbed-memory-status looks promising
Editing print_all_thread_info(); print_heap_and_isr_stack_info(); stack ( start: 20005AF0 end: 20005E10 size: 00000320 used: 00000000 ) thread ( id: 20005E1C entry: 0003D089 )^M stack ( start: 2000447C end: 2000547C size: 00001000 used: 00000000 ) thread ( id: 20005E5C entry: 0003C3FD )^M stack ( start: 20005828 end: 20005A28 size: 00000200 used: 00000000 ) thread ( id: 20006234 entry: 0003C37D )^M heap ( start: 20006280 end: 2007FC00 size: 00079980 used: 00000000 ) alloc ( ok: 00000000 fail: 00000000 )^M isr_stack ( start: 2007FC00 end: 20080000 size: 00000400 used: 000000E4 )^M Create A Threadhttps://developer.mbed.org/blog/entry/Tracing-stack-and-heap-overflow-errors/ indicates that we can create a thread and specify the stack size.
When this runs, it creates two threads, one for Duktape, one to blink the LEDs. eduk2.cpp main() start eduk2.cpp main() Thread t: max_stack:0 stack ( start: 200054F0 end: 20005810 size: 00000320 used: 00000000 ) thread ( id: 2000581C entry: 0001ED71 ) stack ( start: 20003EF4 end: 20004EF4 size: 00001000 used: 00000000 ) thread ( id: 2000585C entry: 0001E185 ) stack ( start: 20005C88 end: 20006488 size: 00000800 used: 00000000 ) thread ( id: 2000589C entry: 0001DEB9 ) stack ( start: 20005228 end: 20005428 size: 00000200 used: 00000000 ) thread ( id: 20005C34 entry: 0001E1CD ) heap ( start: 20005C80 end: 2007FC00 size: 00079F80 used: 00000000 ) alloc ( ok: 00000000 fail: 00000000 ) isr_stack ( start: 2007FC00 end: 20080000 size: 00000400 used: 00000090 ) eduk2.cpp main() after print thread info eduk2.cppeduk2 main.cpp () stmain(arted) abo duktut toape t callhread duk_ create_heap_default() It fails while loading duktape.js: eduk2.cpp main() done with duk_create_heap_default() eduk2.cpp main() about to call eventloop_register() eduk2.cpp main() done with eventloop_register() eduk: About to run test/auto/RampJSDisplay.js ../eduk2.cpp:66: About to load C version of c_eventloop. ../eduk2.cpp: Loading C version of c_eventloop worked D0 duk_js_executor.c:1358 (duk__handle_longjmp): -> throw propagated up to entry level, rethrow and exit bytecode executor ../eduk2.cpp:87: Loading C version of duktapeHost failed. Error was: ReferenceError: 4 ../eduk2.cpp:275: about to print thread info stack ( start: 200054F0 end: 20005810 size: 00000320 used: 00000000 ) thread ( id: 2000581C entry: 0001ED71 ) stack ( start: 20003EF4 end: 20004EF4 size: 00001000 used: 00000000 ) thread ( id: 2000585C entry: 0001E185 ) stack ( start: 20005C88 end: 20006488 size: 00000800 used: 00000000 ) thread ( id: 2000589C entry: 0001DEB9 ) stack ( start: 20006490 end: 20038490 size: 00032000 used: 00000000 ) thread ( id: 200058DC entry: 0001DEB9 ) stack ( start: 20005228 end: 20005428 size: 00000200 used: 00000000 ) thread ( id: 20005C34 entry: 0001E1CD ) heap ( start: 20005C80 end: 2007FC00 size: 00079F80 used: 00000000 ) alloc ( ok: 00000000 fail: 00000000 ) isr_stack ( start: 2007FC00 end: 20080000 size: 00000400 used: 00000090 ) BTW - to identify the threads, subtract 1 from the entry and use nm.
Here are the other threads. bash-3.2$ nm ./BUILD/mbed-duktape2.elf | grep -i 1E184 0001e184 T pre_main bash-3.2$ nm ./BUILD/mbed-duktape2.elf | grep -i 1DEB8 0001deb8 T _ZN4rtos6Thread6_thunkEPKv bash-3.2$ nm ./BUILD/mbed-duktape2.elf | grep -i 1E1CC 0001e1cc T os_idle_demon bash-3.2$ I'm not sure why BTW - Here are the sizes: text data bss dec hex filename 286720 15184 8316 310220 4bbcc BUILD/mbed-duktape2.elf In the output, the used values are 00000 because we did not update ReferenceError: 4To deal with ReferenceError: 4 Edit duk_config.h: /* #undef DUK_USE_VERBOSE_ERRORS */ Run make, cp and press the reset. Now: ReferenceError: identifier 'require' undefined See Duktape 1.x compatible module loading framework
The solution to the above was to add detrministicTemporalSemantics.js to the list of files for which we generate .h files and modify eduk2/nofileio.c to use it. gettimeofdayThe problem now is that the swarmlet loads but fails to produce output. Compiling the code under x86_64 on the mac works properly. See the instructions at the top of eduk2.cpp for how to do this. The makefile is too messed up to easily add this there, so the commands are run by hand. Adding fprintfs to c_eventloop.c shows that we get output like: eduk2.cpp main() done with duk_create_heap_default() eduk2.cpp main() about to call eventloop_register() eduk2.cpp main() done with eventloop_register() eduk2: About to run test/auto/RampJSDisplay.js ../eduk2.cpp:94: About to load C version of c_eventloop. ../eduk2.cpp: Loading C version of c_eventloop worked duktapeHost.js done ../eduk2.cpp: Loading C version of duktapeHost worked ../eduk2.cpp: Loading C version of deterministicTemporalSemantics worked ../../eduk2/c_eventloop.c:105: get_now() returning 0? This is bad. ../../eduk2/c_eventloop.c:105: get_now() returning 0? This is bad. ../eduk2.cpp:193: test/auto/RampJSDisplay.js: About to invoke eventloop_run() ../../eduk2/c_eventloop.c:356: expire_timers() ../../eduk2/c_eventloop.c:105: get_now() returning 0? This is bad. ../../eduk2/c_eventloop.c:105: get_now() returning 0? This is bad. going to poll, timeout 1000 ms, pollfd count 0 timeout -> 1000 ../../eduk2/c_eventloop.c:416: busy_delay_us() ../../eduk2/c_eventloop.c:445: RC -> 0 ../../eduk2/c_eventloop.c:356: expire_timers() ../../eduk2/c_eventloop.c:105: get_now() returning 0? This is bad. ../../eduk2/c_eventloop.c:105: get_now() returning 0? This is bad. going to poll, timeout 1000 ms, pollfd count 0 timeout -> 1000 In particular, it looks like gettimeofday() always returns 0! The binary has three definitions of gettimeofday bash-3.2$ nm BUILD/*.elf | grep gettimeofday 00031ae0 T _gettimeofday 0002d54c T _gettimeofday_r 0002a574 T gettimeofday bash-3.2$ eduk2.cpp defines a Running nm $(filter %.o, $^) | grep gettimeofday returns U gettimeofday which indicates that we are looking for the gettimeofday() definition and that it is not defined in the .o files Adding (/usr/local/Cellar/arm-none-eabi-gcc/5-2016-q3-update/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/lib/armv7e-m/softfp/libc.a)lib_a-gettimeofdayr.o Running nm on lib_a-gettimeofdayr.o: U _gettimeofday 00000000 T _gettimeofday_r U errno ... lib_a-sysgettod.o: U _gettimeofday_r U _impure_ptr 00000000 T gettimeofday ... lib_a-time.o: U _gettimeofday_r U _impure_ptr 00000000 T time So, it appears that lib_a-sysgettod.o defines a gettimeofday() that calls _gettimeofday_r(), which is also defined. It is not clear why the addresses are 00000000. It looks like It could be that the gettimeofday() that is defined in the library returns 0, but there is no documentation about that. See
https://github.com/ARMmbed/mbed-time defines a version, we could try that. Whoops. eduk2: About to run test/auto/RampJSDisplay.js ../eduk2.cpp:94: About to load C version of c_eventloop. ../eduk2.cpp: Loading C version of c_eventloop worked duktapeHost.js done ../eduk2.cpp: Loading C version of duktapeHost worked ../eduk2.cpp: Loading C version of deterministicTemporalSemantics worked ../../eduk2/c_eventloop.c:105: WARNING: gettimeofday() returned -1!! get_now will return 0.0? This is bad. ../../eduk2/c_eventloop.c:105: WARNING: gettimeofday() returned -1!! get_now will return 0.0? This is bad. ../eduk2.cpp:193: test/auto/RampJSDisplay.js: About to invoke eventloop_run() ../../eduk2/c_eventloop.c:358: expire_timers() ../../eduk2/c_eventloop.c:105: WARNING: gettimeofday() returned -1!! get_now will return 0.0? This is bad. ../../eduk2/c_eventloop.c:105: WARNING: gettimeofday() returned -1!! get_now will return 0.0? This is bad. going to poll, timeout 1000 ms, pollfd count 0 timeout -> 1000 ../../eduk2/c_eventloop.c:418: busy_delay_us() ../../eduk2/c_eventloop.c:447: RC -> 0 ../../eduk2/c_eventloop.c:358: expire_timers() ../../eduk2/c_eventloop.c:105: WARNING: gettimeofday() returned -1!! get_now will return 0.0? This is bad. ../../eduk2/c_eventloop.c:105: WARNING: gettimeofday() returned -1!! get_now will return 0.0? This is bad. going to poll, timeout 1000 ms, pollfd count 0 timeout -> 1000 Added perror(): /* Get Javascript compatible 'now' timestamp (millisecs since 1970). */ static double get_now(void) { struct timeval tv; int rc; rc = gettimeofday(&tv, NULL); if (rc != 0) { fprintf(stderr, "%s:%d: WARNING: gettimeofday() returned %d!! get_now will return 0.0? This is bad.\n", __FIL\ E__, __LINE__, rc); perror("gettimeofday() failed"); /* Should never happen, so return whatever. */ return 0.0; } double returnValue = ((double) tv.tv_sec) * 1000.0 + ((double) tv.tv_usec) / 1000.0; fprintf(stderr, "%s:%d: get_now() returning %g.\n", __FILE__, __LINE__, returnValue); return returnValue; } results in timeout -> 1000 ../../eduk2/c_eventloop.c:419: busy_delay_us() ../../eduk2/c_eventloop.c:448: RC -> 0 ../../eduk2/c_eventloop.c:359: expire_timers() ../../eduk2/c_eventloop.c:105: WARNING: gettimeofday() returned -1!! get_now will return 0.0? This is bad. gettimeofday() failed: Bad file number ../../eduk2/c_eventloop.c:105: WARNING: gettimeofday() returned -1!! get_now will return 0.0? This is bad. gettimeofday() failed: Bad file number going to poll, timeout 1000 ms, pollfd count 0 timeout -> 1000 It looks like gcc-arm-none-eabi-5_4-2016q3-20160926/src/newlib/newlib/libc/sys/arm/syscalls.c contains the definition: int _gettimeofday (struct timeval * tp, void * tzvp) { struct timezone *tzp = tzvp; if (tp) { /* Ask the host for the seconds since the Unix epoch. */ #ifdef ARM_RDI_MONITOR tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL); #else { int value; asm ("swi %a1; mov %0, r0" : "=r" (value): "i" (SWI_Time) : "r0"); tp->tv_sec = value; } #endif tp->tv_usec = 0; } /* Return fixed data for the timezone. */ if (tzp) { tzp->tz_minuteswest = 0; tzp->tz_dsttime = 0; } return 0; } Interestingly at the end of the verbose output of ld, we have (/usr/local/Cellar/arm-none-eabi-gcc/5-2016-q3-update/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/lib/armv7e-m/softfp/libnosys.a)gettod.o Going to https://launchpad.net/gcc-arm-embedded/+download and downloading https://launchpad.net/gcc-arm-embedded/5.0/5-2016-q3-update/+download/gcc-arm-none-eabi-5_4-2016q3-20160926-src.tar.bz2 and looking for gettod finds int _DEFUN (_gettimeofday, (ptimeval, ptimezone), struct timeval *ptimeval _AND void *ptimezone) { errno = ENOSYS; return -1; } Revisiting the code and printing errno: extern int errno; /* Get Javascript compatible 'now' timestamp (millisecs since 1970). */ static double get_now(void) { struct timeval tv; int rc; rc = gettimeofday(&tv, NULL); if (rc != 0) { fprintf(stderr, "%s:%d: WARNING: gettimeofday() returned %d!! get_now will return 0.0? This is bad. errno = %\ d\n", __FILE__, __LINE__, rc, errno); perror("gettimeofday() failed"); /* Should never happen, so return whatever. */ return 0.0; } double returnValue = ((double) tv.tv_sec) * 1000.0 + ((double) tv.tv_usec) / 1000.0; fprintf(stderr, "%s:%d: get_now() returning %g.\n", __FILE__, __LINE__, returnValue); return returnValue; } Now, we get ../../eduk2/c_eventloop.c:107: WARNING: gettimeofday() returned -1!! get_now will return 0.0? This is bad. errno = 88 gettimeofday() failed: Bad file number /src/newlib/newlib/libc/include/sys/errno.h has #define ENOSYS 88 /* Function not implemented */ So, what is happening here is that we get the errno = 88 and then the fprintf fails with a So, gettimeofday is not implemented! |