NXFLAT>>> Under Construction <<<Last Updated: June 26, 2009 |
Table of Contents |
1.0 Overview |
NXFLAT is a customized and simplified version of binary format implemented a few years ago called XFLAT With the NXFLAT binary format you will be able to do the following:
This allows you to extend the NuttX base code after it has been written into FLASH. One motivation for implementing NXFLAT is support clean CGI under an HTTPD server.
This feature is especially attractive when combined with the NuttX ROMFS support: ROMFS allows you to execute programs in place (XIP) in flash without copying anything other than the .data section to RAM. In fact, the initial NXFLAT release will work only on ROMFS.
This NuttX feature includes:
NXFLAT is derived from XFLAT. XFLAT is a toolchain add that provides full shared library and XIP executable support for processors that have no Memory Management Unit (MMU). NXFLAT is greatly simplified for the deeply embedded environment targeted by Nuttx:
Rather, the NXFLAT module only imports symbol values. In the NXFLAT model, the (PIC1) NXFLAT module resides in a FLASH file system and when it is loaded at run time, it is dynamically linked only to the (non-PIC) base NuttX code: The base NuttX exports a symbol table; the NXFLAT module imports those symbol value to dynamically bind the module to the base code.
1"Position Independent Code"
mmap()
the code segment.
NUTTX does not provide any general kind of file mapping capability.
In fact, true file mapping is only possible with RTOSs and MCUs that provide an MMU1
and only ROMFS supports that kind of XIP execution from FLASH.
It is possible to simulate file mapping by allocating memory and copy the file into memory.
NXFLAT would work that kind of file mapping to and that feature could easily be added to NuttX.
.rodata
).
Embedded firmware developers normally like to keep .rodata
in FLASH with the code sections.
But because all data is referenced with the PIC base register, all of that data must lie in RAM.
A NXFLAT change to work around this is under investigation3.
qsort()
must be avoided in an NXFLAT module.
1"Memory Management Unit"
2"Position Independent Code"
3A work around is under consideration:
At run time, the .rodata
offsets will be indexed by a RAM address.
If the dynamic loader were to offset those .rodata
offsets properly, it
still might be possible to reference .rodata
in ROM.
That work around is still a top of investigation at this time.
As mentioned above, the NXFLAT toolchain is only available for ARM and Cortex-M3 (thumb2) targets. Furthermore, NXFLAT has only been tested on the Eagle-100 LMS6918 Cortex-M3 board.
The initial release of NXFLAT was made in NuttX version 0.4.9.
Testing is limited to the tests found under examples/nxflat
in the source tree.
Some known problems exist
(see the TODO list).
As such, NXFLAT is currently in an early alpha phase.
2.0 NXFLAT Toolchain |
In order to use NXFLAT, you must use special NXFLAT tools to create the binary module in FLASH. To do this, you will need to download the buildroot package and build it on your Linux or Cygwin machine. The buildroot can be downloaded from Sourceforge. You will need version 0.1.7 or later.
Here are some general build instructions:
<some-dir>/nuttx
buildroot-0.x.y
into <some-dir>
<some-dir>/buildroot-0.x.y.tar.gz
using a command like tar zxf buildroot-0.x.y
.
This will result in a new directory like <some-dir>/misc/buildroot-0.x.y
mv <some-dir>/misc/buildroot-0.x.y <some-dir>/buildroot
cd <some-dir>/buildroot
cp configs/abc-defconfig-x.y.z .config
.
make menuconfig
.
Select to build the NXFLAT toolchain with GCC (you can also select omit building GCC with and only build the
NXFLAT toolchain for use with your own GCC toolchain).
make
.
When the make completes, the tool binaries will be available under
<some-dir>/buildroot/build_abc/staging_dir/bin
mknxflat
is used to build a thunk file.
See below for usage.
Usage: mknxflat [options] <bfd-filename> Where options are one or more of the following. Note that a space is always required between the option and any following arguments. -d Use dynamic symbol table. [symtab] -f <cmd-filename> Take next commands from <cmd-filename> [cmd-line] -o <out-filename> Output to[stdout] -v Verbose output [no output] -w Import weakly declared functions, i.e., weakly declared functions are expected to be provided at load-time [not imported]
ldnxflat
is use to link your object files along with the thunk file
generated by mknxflat
to produce the NXFLAT binary module.
See below for usage.
Usage: ldnxflat [options] <bfd-filename> Where options are one or more of the following. Note that a space is always required between the option and any following arguments. -d Use dynamic symbol table [Default: symtab] -e <entry-point> Entry point to module [Default: _start] -o <out-filename> Output to <out-filename> [Default: <bfd-filename>.nxf] -s <stack-size> Set stack size to <stack-size> [Default: 4096] -v Verbose output. If -v is applied twice, additional debug output is enabled [Default: no verbose output].
Below is a snippet from an NXFLAT make file (simplified from NuttX Hello, World! example.
Target 1 | hello.r1: |
hello.o |
---|---|---|
abc-elf-ld -r -d -warn-common -o $@ $^ |
||
Target 2 | hello-thunk.S: |
hello.r1 |
mknxflat -o $@ $^ |
||
Target 3 | hello.r2: |
hello-thunk.S |
abc-elf-ld -r -d -warn-common -T binfmt/libnxflat/gnu-nxflat.ld -no-check-sections -o $@ hello.o hello-thunk.o
|
||
Target 4 | hello: |
hello.r2 |
ldnxflat -e main -s 2048 -o $@ $^ |
||
Target 1.
This target links all of the object files together into one relocation object.
In this case, there is only a single object file, hello.o
, and it is linked to produce hello.r1
.
Target 2.
Given hello.r1
, this target will invoke mknxflat
to make the thunk file, hello-thunk.S
.
This thunk contains all of the information needed to create the imported function list.
Target 3
This this target is similar to Target 1.
In this case, it will link together the object file, hello.o
along with the assembled thunk file,
hello-thunk.o
to create another, single relocatable object, hello.r2
.
The linker script, gnu-nxflat.ld
is required at this point to correctly position the sections.
Target 4.
Finally, this target will use the hello.r2
relocatable object to create the final, NXFLAT module
hello
by calling ldnxflat
.
Appendix A. No GOT Operation |
When GCC generate position independent code, new code sections will appear in your programs. One of these the the GOT (Global Offset Table) and, in ELF environments, the PLT (Procedure Lookup Table. For example, if your C code generated (ARM) assembly language like this without PIC:
ldr r1, .L0 <-- Fetch the offset to 'x' ldr r0, [r10, r1] <-- Load the value of 'x' with PIC offset ... .L0: .word x <-- Offset to 'x'
Then when PIC is enabled (say with the -fpic compiler option), it will generate code like this:
ldr r1, .L0 <-- Fetch the offset to the GOT entry ldr r1, [r10,r1] <-- Fetch the (relocated) address of 'x' from the GOT ldr r0, [r1, #0] <-- Fetch the value of 'x' ... .L1 .word x(GOT) <-- Offset to entry in the GOT
See reference
Notice that the generates an extra level of indirection through the GOT. This indirection is not needed by NXFLAT and only adds more RAM usage and execution time.
NXFLAT (like XFLAT) can work even better with the GOT. Patches again older version of GCC exist to eliminate the GOT indirections. Several are available here if you are inspired to port them to a new GCC version.
Appendix B. PIC Text Workaround |
There is a problem with the memory model in GCC that prevents it from being used as you need to use it in the NXFLAT context. The problem is that GCC PIC model assumes that the executable lies in a flat, contiguous (virtual) address space like:
Virtual |
---|
.text |
.got |
.data |
.bss |
It assumes that the PIC base register (usually r10 for ARM) points to the base of .text
so that any address in .text
, .got
, .data
, .bss
can be found with an offset from the same base address.
But that is not the memory arrangement that we need in the XIP embedded environment.
We need two memory regions, one in FLASH containing shared code and on per task in RAM containing task-specific data:
Flash | RAM |
---|---|
.text |
.got |
.data |
|
.bss |
The PIC base register needs to point to the base of the .got
and only
addresses in the .got
, .data
, and .bss
sections can be accessed as an offset from the PIC base register.
See also this
XFLAT discussion.
Patches again older version of GCC exist to correct this GCC behavior. Several are available here if you are inspired to port them to a new GCC version.