Recent Changes - Search:

edit SideBar

MaximPegasusDuktapeProblems

Below 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 Creation

I attempted to create a makefile by hand, but it seems easier to use the mbed command to create a makefile and add to that.

  1. In /ptII/org/terraswarm/accessor/accessors/web/hosts/duktape:
      mbed new mbed-duktape2
      cd mbed-duktape2/
      mbed export -i GCC_ARM -m MAX32630FTHR
  2. Add the following to duktape/mbed-duktape2/Makefile:
    CFLAGS += -DDUK_F_32BIT_PTRS -DDUK_USE_DEBUG -DDUK_USE_DEBUG_LEVEL=0
    CXX_FLAGS += -DEDUK_RUN_RAMPJSDISPLAY $(CFLAGS)

    #       ../duktape2/examples/cmdline/duk_cmdline.c                                                                                                      
    C_SRCS = \
            ../duktape2/src/duktape.c \
            ../eduk2/duk_stack.c \
            ../eduk2/nofileio.c \
            ../eduk2/c_eventloop.c \
            ../eduk2/modSearch.c \
            ../duktape2/extras/print-alert/duk_print_alert.c \
            ../duktape2/extras/console/duk_console.c \
            ../duktape2/extras/logging/duk_logging.c \
            ../duktape2/extras/module-duktape/duk_module_duktape.c

    CPP_SRCS = \
            ../eduk2.cpp

    OBJECTS = $(C_SRCS:%.c=%.o)
    OBJECTS += $(CPP_SRCS:%.cpp=%.o)

    INCLUDE_PATHS += -I../../duktape2
    INCLUDE_PATHS += -I../../duktape2/src
    INCLUDE_PATHS += -I../../eduk2
    FIXME why can't we put the above in a separate duktape.mk file and include it in the Makefile?
  3. Copy the eduk2.cpp file:
    cp BUILD/mbed-duktape2.bin /Volumes/DAPLINK/
  4. The red LED will blink, indicating that the file is being uploaded
  5. Wait for the message about "Disk Not Ejected Properly", which indicates that the processor has rebooted.
  6. Start up CoolTerm, find the port, set it for 9600-8-None-1
  7. Messages should appear.

Duktape Size

The 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 duktape2/duk_config.j:

/* __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 problem

Under 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, continued

The 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 [Ss]tack symbols.

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

mbed-os/targets/TARGET_Maxim/TARGET_MAX32630/device/TOOLCHAIN_GCC_ARM/startup_max3263x.S contains:

#ifdef __STACK_SIZE
.equ Stack_Size, __STACK_SIZE
#else
.equ Stack_Size, 0x00005000
#endif

So, let's define __STACK_SIZE! Editing the Makefile:

  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 ASM_FLAGS in the Makefile, then do

  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 Usage

https://github.com/nuket/mbed-memory-status looks promising

  1. Added two lines to mbed-os/targets/T>ARGET_Maxim/TARGET_MAX32630/device/TOOLCHAIN_GCC_ARM/startup_max3263x.S
    .SKIPRAMINIT:

    /* Perform system initialization after RAM initialization */
    ldr r0, =SystemInit
    blx r0

    /* https://github.com/nuket/mbed-memory-status */
    LDR R0, =fill_isr_stack_with_canary
    BLX R0

    /* This must be called to walk the constructor array for static C++ objects */
    /* Note: The linker file must have .data symbols for __X_array_start and __X_array_end */
    /* where X is {preinit, init, fini} */
    ldr r0, =_start
    blx r0

Editing eduk2.cpp:

    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 Thread

https://developer.mbed.org/blog/entry/Tracing-stack-and-heap-overflow-errors/ indicates that we can create a thread and specify the stack size.

  1. In eduk2.cpp, move the bulk of main() into a method called inner_main(). Remove the return statements.
  2. In main():
    #include "mbed.h"
    #include "rtos.h"


    DigitalOut led1(LED1);
    DigitalOut led2(LED2);
    Thread thread;

    void led2_thread() {
      while (true) {
        led2 = !led2;
        Thread::wait(1000);
      }
    }

    int main(int argc, char *argv[]) {
      fprintf(stderr, "eduk2.cpp main() start\n");
      Thread t(osPriorityNormal, 200 * 1024);

      thread.start(led2_thread);


      fprintf(stderr, "eduk2.cpp main() Thread t: max_stack:%ld\n", t.max_stack());
      print_all_thread_info();
      print_heap_and_isr_stack_info();
      fprintf(stderr, "eduk2.cpp main() after print thread info\n");

      t.start(&inner_main);
      fprintf(stderr, "eduk2.cpp main() started duktape thread\n");

      while (true) {
        led1 = !led1;
        Thread::wait(500);
      }

    }

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.

  1. The first thread is entry: 0001ED71
  2. Use nm on the *.elf binary:
    bash-3.2$ nm ./BUILD/mbed-duktape2.elf | grep -i 1ED70
    0001ed70 T osTimerThread
    bash-3.2$

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 entry: 0001DEB9 appears twice in the output.

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 mbed-os/targets/TARGET_Maxim/TARGET_MAX32630/device/TOOLCHAIN_GCC_ARM/startup_max3263x.S (see above)

ReferenceError: 4

To 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

  • Makefile
    • Added ../duktape2/extras/module-duktape/duk_module_duktape.c to the C_SRCS
    • Added INCLUDE_PATHS += -I../../duktape2/extras/module-duktape
  • eduk.cpp
    • Added
      // See Duktape 1.x compatible module loading framework at                                                                
      // https://github.com/svaarala/duktape/tree/master/extras/module-duktape                                                
      extern "C" {
      #include "duk_module_duktape.h"
      }
    • After setting ctx, added
        // Duktape 1.x compatible module loading framework.                                                                    
        // https://github.com/svaarala/duktape/tree/master/extras/module-duktape                                              
        duk_module_duktape_init(ctx);
      (:source:)

      Got further!

      !![[#deterministicTemporalSemantics]] deterministicTemporalSemantics.js missing
      (:source lang=javascript:)
      duk2.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:85: About to load C version of c_eventloop.
      ../eduk2.cpp: Loading C version of c_eventloop worked
      ../../eduk2/nofileio.c:190 Could not find common/modules/deterministicTemporalSemantics.js
      ../eduk2.cpp:106: Loading C version of duktapeHost failed.  Error was:
      ReferenceError: identifier 'FileIo' undefined

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.

gettimeofday

The 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 _gettimeofday, but that is now ifdef'd out for mbed.

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 -Wl,-v,-t to the $(LD) line shows that gettimeofday is being found here:

  (/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 /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 shows the following:

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 gettimeofday_r is a reentrant version of gettimeofday.

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. gettimeofday() returns 0 if everything is ok. Correcting c_eventloop.h and eduk2.cpp results in:

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 ./src/newlib/libgloss/libnosys/gettod.c:

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 Bad file number, which is why perror() displays that.

So, gettimeofday is not implemented!

See MaximPegasus gettimeofday

Edit - History - Print - Recent Changes - Search
Page last modified on March 17, 2017, at 11:47 PM