How to run on bare metal platforms

How to run on bare metal platforms

A bare metal platform usually runs a minimal real-time operating system (RTOS) or no conventional operating system at all. Usual services like paging, memory allocation primitives, a file system, etc may not be available at all. There may not even be an interrupt handler, with all code running in a busy polled bit banging loop. There is usually no libc or only parts (often noncompliant) of one.

Duktape has been designed to run on bare metal targets: platform dependencies have been carefully minimized, and all access to platform functions goes through wrapper macros defined in duk_config.h. As such they can be easily replaced with custom providers.

This document discusses the usual issues in compiling and running Duktape on a bare metal target. See also:

Footprint expectations

Duktape configuration options affect the final footprint a great deal. The following configuration compiles to around 160kB on an ARM platform, and can run (very minimally) with 32kB RAM.

It's possible to reduce footprint much below 160kB by dropping Ecmascript built-in bindings:

  • For example, a "stripped" build in Duktape master allows a command line eval tool to compile to less than 80kB on x86 (not including libc etc). However, in a stripped build built-ins like Array.prototype.forEach() are missing. You can customize the bindings more accurately, e.g. remove only specific bindings, using the YAML metadata.

Typical porting steps

Configuration and duk_config.h

  • Use tools/configure.py to create a custom configuration. The low memory configuration in https://github.com/svaarala/duktape/blob/master/config/examples/low_memory.yaml is a reasonable starting point.

  • Use the YAML config format to provide custom tweaks to Duktape configuration.

  • Use a fixup header to redefine platform functions which don't exist or need to be avoided. For example:

    #undef DUK_FLOOR
    #define DUK_FLOOR my_floor_replacement
    
  • Use the fixup header to provide declarations for the custom replacements so that Duktape compilation knows their prototype:

    extern double my_floor_replacement(double x);
    
  • If standard headers are not available, you may need to edit duk_config.h to remove offending #include lines. You can achieve this more cleanly by adding a custom platform to genconfig and creating a duk_config.h for that specific platform.

  • The Date built-in very often needs to be replaced, see:

  • If RAM is very tight, the "ROM built-ins" option allows built-in binding objects (e.g. Math, Math.cos, Array) to be compiled into the read-only code section. This allows Duktape to start up with about 3kB of RAM when packed pointers are also used. Using ROM built-ins increases code footprint however.

Compiling and running

This is obviously compiler specific, but it's important to use options that minimize footprint, remove any unused functions in final linking, etc. See for example:

Enabling "execute in place" is often necessary to allow code to run directly from flash.

Last edited by Sami Vaarala, 2017-03-25 14:43:59