Tutorial: RAM and ROM usage - simonduq/contiki-ng GitHub Wiki
We will use the example hello-world
again here (see tutorial:hello-world), with target zoul
.
Binary file inspection
First, build the example:
$ make
To check the size of the resulting binary, try the standard command size
on the ELF file:
$ size hello-world.zoul
text data bss dec hex filename
38758 412 10880 50050 c382 hello-world.zoul
text
shows the size of the code section in bytes -- this will typically be in ROM. data
and bss
show sections that contain variables, stored in RAM. The Firefly board has 32 KB RAM and 512 KB ROM, so we have some free space here. You can also try other standard commands for ELF file inspection, such as nm
and objdump
.
Contiki-NG provides, in addition, the targets .flashprof
and .ramprof
, which show the list of largest symbols in ROM and RAM, respectively. For instance:
$ make hello-world.ramprof
...
00000248 uip_ds6_if
00000256 received_seqnos
00000256 uip_udp_conns
00000288 _ds6_neighbors_mem
00000352 curr_instance
00000368 frag_info
00000384 events
00000384 nodememb_memb_mem
00001280 uip_aligned_buf
00001356 frag_buf
00001360 buframmem_memb_mem
00002048 stack
Shows you that the pre-allocated runtime stack consumed 2048 bytes, the queuebuf module consumes 1360 bytes (through the memb
array buframmem_memb_mem
), etc.
Now let's take a look at the ROM usage:
$ make hello-world.flashprof
...
00000580 dio_input
00000628 ns_input
00000636 rpl_ext_header_update
00000642 __udivdi3
00000652 vectors
00000700 __divdi3
00001104 uip_process
00001736 format_str_v
00001752 input
00001820 output
This might not seem extremely readable at first, but nm
will help us find where the symbols come from. For instance, the largest functions are output
and input
. Let's look them up as follows:
$ nm -oStd obj_zoul/*.o | grep " output$"
obj_zoul/sicslowpan.o:00000001 00001820 t output
$ nm -oStd obj_zoul/*.o | grep " input$"
obj_zoul/sicslowpan.o:00000001 00001752 t input
These two functions are from the sicslowpan
module. Such troubleshooting can help identify where log levels need to be reduced, or what features should be removed.
Saving RAM and ROM
As you enable more features or edit your configuration files, you might saturate your memory. The linker will then fail to produce a final firmware, and issue a message like:
LD hello-world.elf
/usr/lib/gcc/arm-none-eabi/4.8.2/../../../arm-none-eabi/bin/ld: hello-world.elf section `.bss' will not fit in region `FRSRAM'
/usr/lib/gcc/arm-none-eabi/4.8.2/../../../arm-none-eabi/bin/ld: region `FRSRAM' overflowed by 144 bytes
collect2: error: ld returned 1 exit status
make: *** [hello-world.elf] Error 1
In this case, use viewconf
(see doc:configuration) to inspect your configuration:
$ make viewconf
----------------- Make variables: --------------
##### "TARGET": ________________________________ zoul
##### "BOARD": _________________________________ remote-revb
##### "MAKE_MAC": ______________________________ MAKE_MAC_CSMA
##### "MAKE_NET": ______________________________ MAKE_NET_IPV6
##### "MAKE_ROUTING": __________________________ MAKE_ROUTING_RPL_LITE
----------------- C variables: -----------------
##### "PROJECT_CONF_PATH": _____________________ ><
##### "CONTIKI_VERSION_STRING": ________________ == "Contiki-NG-4.0"
##### "IEEE802154_CONF_PANID":__________________ == 0xabcd
##### "FRAME802154_CONF_VERSION":_______________ == (0x01)
##### "RF_CHANNEL": ____________________________ ><
##### "QUEUEBUF_CONF_NUM": _____________________ == 8
##### "NBR_TABLE_CONF_MAX_NEIGHBORS": __________ == 16
##### "NETSTACK_MAX_ROUTE_ENTRIES": ____________ == 16
##### "UIP_CONF_BUFFER_SIZE": __________________ == 1280
##### "UIP_CONF_UDP": __________________________ == 1
##### "UIP_CONF_UDP_CONNS": ____________________ == 8
##### "UIP_CONF_TCP": __________________________ == 0
##### "UIP_CONF_TCP_CONNS": ____________________ == 0
##### "UIP_CONF_ND6_SEND_RA": __________________ == 0
##### "UIP_CONF_ND6_SEND_NS": __________________ == 0
##### "UIP_CONF_ND6_SEND_NA": __________________ == 1
##### "UIP_CONF_ND6_AUTOFILL_NBR_CACHE": _______ == 1
##### "SICSLOWPAN_CONF_FRAG": __________________ == 1
##### "SICSLOWPAN_CONF_COMPRESSION": ___________ == SICSLOWPAN_COMPRESSION_IPHC
##### "LOG_CONF_LEVEL_RPL": ____________________ == LOG_LEVEL_NONE
##### "LOG_CONF_LEVEL_TCPIP": __________________ == LOG_LEVEL_NONE
##### "LOG_CONF_LEVEL_IPV6": ___________________ == LOG_LEVEL_NONE
##### "LOG_CONF_LEVEL_6LOWPAN": ________________ == LOG_LEVEL_NONE
##### "LOG_CONF_LEVEL_NULLNET": ________________ == LOG_LEVEL_NONE
##### "LOG_CONF_LEVEL_MAC": ____________________ == LOG_LEVEL_NONE
##### "LOG_CONF_LEVEL_FRAMER": _________________ == LOG_LEVEL_NONE
##### "LOG_CONF_LEVEL_6TOP": ___________________ == LOG_LEVEL_NONE
------------------------------------------------
'==' Means the flag is set to a given a value
'->' Means the flag is unset, but will default to a given value
'><' Means the flag is unset and has no default value
To view more Make variables, edit ../../Makefile.include, rule 'viewconf'
To view more C variables, edit ../../tools/viewconf.c
This shows you the current value of many important configuration parameters. To override any of these, simply define them from your project-conf.h
file (see doc:configuration).
If you need to save RAM, you might consider reducing:
QUEUEBUF_CONF_NUM
: the number of packets in the link-layer queue. 4 is probably a lower bound for reasonable operation. As the traffic load increases, e.g. more frequent traffic or larger datagrams, you will need to increase this parameter.NBR_TABLE_CONF_MAX_NEIGHBORS
: the number of entries in the neighbor table. A value greater than the maximum network density is safe. A value lower than that will also work, as the neighbor table will automatically focus on relevant neighbors. But too low values will result in degraded performance.NETSTACK_MAX_ROUTE_ENTRIES
: the number of routing entries, i.e., in RPL non-storing mode, the number of links in the routing graph, and in storing mode, the number of routing table elements. At the network root, this must be set to the maximum network size. In non-storing mode, other nodes can set this parameter to 0. In storing mode, it is recommended for all nodes to also provision enough entries for each node in the network.UIP_CONF_BUFFER_SIZE
: the size of the IPv6 buffer. The minimum value for interoperability is 1280. In closed systems, where no large datagrams are used, lowering this to e.g. 140 may be sensible.SICSLOWPAN_CONF_FRAG
: Enables/disables 6LoWPAN fragmentation. Disable this if all your traffic fits a single link-layer packet. Note that this will also save some significant ROM.
If you need to save ROM, you can consider the following:
UIP_CONF_TCP
: Enables/disables TCP. Make sure this is disabled when TCP is unused.UIP_CONF_UDP
: Enables/disables UDP. Make sure this is disabled when UDP is unused.SICSLOWPAN_CONF_FRAG
: As mentioned above. Disable if no fragmentation is needed.LOG_CONF_LEVEL_*
: Logs consume a large amount of ROM. Reduce log levels to save some more.
There are many other parameters that affect RAM/ROM usage. You can inspect os/contiki-default-conf.h
as well as platform-specific contiki-conf.h
files for inspiration. Or use .flashprof
and .ramprof
to identify the hotspots.