Repository navigation
Releases: mikroverk/cooja-ng
Release list
Cooja-NG v0.4.0
This release makes Cooja-NG usable without building it from source. cngsim takes you from the download to a running simulation in three commands, with commented examples, layouts that place many nodes at once, and a web UI that edits the running network and saves it as YAML. Cooja-NG now also runs in the browser: the same C code, compiled to WebAssembly, runs the original firmware and gives byte-for-byte the same output as the native build. That build is what runs the site's live demos.
New features include two TI SimpleLink LaunchPads join (CC1352R1 and CC1312R7, checked against hardware), Contiki-NG talks to Zephyr and to RIOT in two interop demos, and four boards without a radio model leave. Configs are checked harder: an image whose board cannot be told, a duplicate id, too many mote types or a plugin that is not there is an error now rather than a quiet surprise, so read Changed before upgrading. The plugin API (version 3) and the files Contiki-NG's CI uses are unchanged; plugins that read radio_medium_t fields directly must be rebuilt (Changed).
Contributors to this release: @nfi (warnings as errors, and reviews of the CC13x2 boards, cngsim, the browser build, the engine timing fixes and the board removal), and @nvt (reviews of cngsim and the browser build).
Changed — check these before upgrading
- An unknown or missing firmware extension is an error, in
cngsimandtest_runneralike: exit 2 before anything starts, naming the file. It used to boot as a Tmote Sky, so an ARM image named.elfran silently as an MSP430 and did nothing. Name the board withboard:on the mote type instead (below). A node added at run time (shelladd, JSaddMote, a timed config action) is refused the same way, and a removed board's extension says that its board was removed. test_runnerwith no arguments, or an unknown mode, exits 2 with its usage on stderr. An unknown mode used to run nothing and exit 0.--helpprints the usage, now listing every mode and option.- More than 16 mote types, or more nodes than the limit (128), is a load error. Mote types beyond 8 used to be dropped without a word. A v1 config is held to it too, counting each distinct firmware image as a type: one with 17 images loaded, and the file Save wrote from it did not. On the command line
-nover 128, or more than 128 firmware images, is refused the same way; it used to run 128 nodes under a banner naming more. - Durations outside 1 ms to 24.8 days are refused (exit 2):
-t,--duration, a config'stimeout_msand a test step's.-ttookatoi's word, soabcwas 0 and3000000000wrapped to a negative run that ended at once, andcngsim run --duration 720hreported DONE at 0 s; a config'stimeout_msof 3000000000 was cut to 24.8 days and 1.5 to 1 without a word.-ttakes whole milliseconds only. - A plugin that cannot be loaded, or a medium no plugin provides, is an error (exit 2, before the run starts), from
--plugin, a config'spluginslist or itsmedium. A misspelt built-in name (energist) used to print one line and run without it, and an unknown medium ran on the default UDGM.cngsim checkreports an unknown built-in name and an unreadable plugin path too. - With
--ui, a test verdict no longer ends the run. It is printed when it is decided and the run continues until the UI ends it (or--wall-timeout); the full report still comes at the end. A script that relied on--uiexiting at the verdict now runs until it is stopped. Headless and--ui-recordruns are unchanged (Fixed has the details). - Firmware paths are looked up next to the config first (Added): a name that exists both there and in the current directory now gives the file next to the config.
- libcsim: changed signatures and layouts.
sim_board_for_pathreturns NULL for an unknown extension instead of the Sky board;sim_config_write_yamltakes the directory to write paths relative to, thesim_controlops'save_configafor_pageflag andaddthe mote type's name (sim_control_add_typednames it apart from the images);msp430_config_find,msp430f149_configandcc430f5137_configare gone with their boards.sim_normalized_config_t(16 mote types, nodename,metaand relative paths),arm_cpu_t(96 IO windows,io_width) andradio_medium_t(the frame tracker'stail) changed layout, so code built against them, including a medium plugin that readsradio_medium_tfields rather than calling its accessors, must be rebuilt. The plugin headers (csim_plugin.h,sim_service.h,sim_observer.h) are unchanged andCSIM_PLUGIN_API_VERSIONstays 3. - Two nodes with the same id is a load error, including an explicit id equal to the one an unnumbered node is given. They used to share an address and a console label.
- Warnings are errors. The build is warning-free on gcc 13–15 and clang, and
-Werroris on by default;make WERROR=0drops it for a compiler that reports something new. The vendored QuickJS header is a system include (-isystem), so its function-pointer cast no longer warns in every file that includesjs_node.h. - A PR that moves a simulation on purpose says which workloads. A
baseline-moves: shell54line in its description lets thebyte-identity vs mainjob pass when exactly those workloads differ; any other difference, or a named workload that does not move, still fails it.tools/check-baseline.shtakes the list asMOVED. - Simulation output moves relative to 0.3.0 where a model was fixed (Fixed below), so a baseline recorded with 0.3.0 differs in these places; of the nine
check-baselineworkloads only shell54 moves:- a timed config action applies at its time: shell54's
sendlands at 2000 ms instead of 2007 ms; - console input to an idle ARM node runs at the time it arrives, and wakes the node;
- nRF52840 UARTE input keeps the first byte of a line, which arrives one byte time after the ENDRX acknowledgement;
- an ARM core in WFI with no event queued sleeps to the slice horizon;
- radio-bus frames too long for the old 160-byte queue entry (a CC1200 frame over about 150 bytes) reach a busy receiver whole, and a frame whose length cannot be read no longer holds up the queue;
- the 802.15.4g frame tracker takes each frame's own channel and counts the CC1200's trailing CRC bytes with it.
- a timed config action applies at its time: shell54's
Added
cngsim, the command for people (docs/quick-start.md).cngsim run sim.yamlruns a simulation and prints the node consoles, the checks and a one-line verdict, without the radio traces and chip counters (--traceor-vbring them back);--uiopens the browser, paused at real time.cngsim newwrites a commented setup from a template,checkvalidates one,examplesandboardslist what there is, andconverttakes a Cooja.csc. It runs the same simulation astest_runner test(CI compares their console lines and exit codes), which stays the developer and CI binary. Its durations take a unit (--duration 60s,500ms), and Ctrl-C ends a run withINTERRUPTED, how far it got, and exit 130.newplaces every node within radio reach of node 1 and gives an RPL network time for its depth; the bundledudp-serveranswers 15 clients (Contiki-NG's 16-route table), sonew rpl-udptakes up to 16 nodes.- Edit a running simulation in the web UI: add nodes of the setup's mote types, remove and reboot nodes, send a line to a node's console, and save the setup as YAML. On by default on a loopback UI; a UI bound to another address with
--ui-bindneeds--ui-editfor these (anyone who reaches it can still pause, play, change the speed, restart and move nodes). The browser never names a file. - Layouts: a node entry with
countandlayout(grid,line,circle,random) places many nodes, as Cooja's Add-motes dialog does. board:on a mote type names the board, so Contiki-NG's.nrf,.simplelinkand.zoulimages, or any.elf, run without renaming; on a.nrf52840image it picks the board variant (nrf52840-dongle).--board NAMEdoes the same for images given on the command line.- Firmware paths are relative to the config file (falling back to the current directory, as before), so a setup and its firmware can live anywhere.
--save-configwrites those paths relative to the file it saves, and the browser's Save relative to the config; other paths are written as the config gave them.cngsimlooks a path up last among its bundled examples, so a copied example still finds its firmware. - The web UI page is built into the binary:
--uiworks from any directory and from an installed binary. Aui/index.htmlin the current directory still wins, andCSIM_UI_PAGEnames another. - Twelve commented example simulations (
examples/), runnable by name. - The quick start is a test (
tools/check-quick-start.sh): every command indocs/quick-start.mdruns as written, from an empty directory against a package laid out as the release tarball, and the output it shows must be what the package prints. It runs on every PR and on each release's unpacked tarball, beside a check that the README's platform table matchescngsim boards.test-format.mdlists the run options,--pcap,--pluginand-damong them. - A sanitizer job in CI (ASan + UBSan, interpreter build) runs the malformed-firmware images, failed reboots (
tools/check-lifecycle.sh), live saves (tools/check-save.sh) and the config loader's refusals on every PR; the two new checks also run in the normal jobs. make install(PREFIX,DESTDIR), and release tarballs that carrycngsim, the examples, their firmware, the guides and the setups the guides run, beside thebuild/test_runnerandtools/the Contiki-NG suite uses.- Cooja-NG in the browser (
wasm/): the whole runner compiled to WebAssembly with Emscripten, running in a Web Worker behind the existing we...
Cooja-NG v0.3.0
Cooja-NG becomes something you can drive, embed and watch: a command shell
and script engine for testing firmware through its own console, the simulator
as a library, Renode as a co-simulation clock master, and recorded runs that
replay in the browser. The nRF54L15's TrustZone-M is enforced the way a Seeed
XIAO nRF54L15 enforces it; three CPU architectures share one RPL network; and
the kernel's wakeup path no longer scales with the node count (in networks
without native motes). Release binaries for linux-x86_64, macos-x64 and
macos-arm64 produce byte-identical simulation output: builds no longer fuse
multiply-adds on arm64 (#72), and the release workflow checks the identity on
real firmware with every JIT on and off.
Contributors to this release: @nfi (the shell, the nRF54L15 console, radio and
TrustZone-M enforcement), and @nvt (hardening, native-mote CCA, the firmware
cache, FreeBSD, the JIT divide-trap fix, and reviews of the kernel,
performance, library, UI-replay, Firefly and release work).
Changed — check these before upgrading
- The web UI listens on loopback only.
--ui PORTbinds 127.0.0.1;
--ui-bind ADDRexposes it deliberately. Cross-origin WebSocket handshakes
and DNS-rebindingHostheaders are refused, and a slow or hostile client
can no longer hold up the run (#53). - The MSP430 PC-trace counters are opt-in. The end-of-run
FW cc2420_transmit=… eb_process=… queue_add=…line appears only with
CSIM_PC_TRACE=1; the per-instruction hook it needed is gone from every
other run (#61). - Off-SoC chip drivers moved to
src/chips/andinclude/chips/(CC2420,
CC1200, MX25R6435F, ENC28J60): they are not architecture-specific.
Out-of-tree code that includes their headers needs-I include/chips(#33). - Simulation output moves relative to 0.2.3 where a model was fixed, so a
regression baseline recorded with 0.2.3 differs in these places:- nRF54L15
node_idis the configured mote id (it was a hash, 8251 / 16758
for motes 1 / 2), so link-layer addresses change (#30); - nRF54L15 radio DISABLE→DISABLED latency is 3 µs instead of 8 µs
(NRF54L_DISABLED_DEFER_NSoverrides; the working window is 2.5–4 µs),
and the DK firmware images were rebuilt for the hardware-ACK path (#34); - native-mote CCA follows on-air time: a duty-cycled sixteen-node rpl-udp
network went from 33–89 % of round trips delivered to 99.9–100 % (#56); - CC1200 (Zolertia Firefly sub-GHz) frame timing (#67);
- ARM output with the JIT on, wherever firmware calls the 64-bit divide
helpers (nRF52840 TSCH among them) — it now equals JIT-off output (#69).
- nRF54L15
- Refusals that used to pass silently: an ELF whose segments place no
bytes fails at init instead of running a zero-filled image to exit 0 (#50);
a GDB client must answer within 5 s and an external-node peer must advance
its clock within 10000 exchanges, or it is dropped (#52); a web-UI client
that stops reading for 200 ms is dropped (#53). - Firmware cache names include the source directory (relative to the
Contiki-NG root), so existing local builds are rebuilt once;--clean
removes only untracked builds, never shipped firmware (#57).
Added — interactive shell and command scripts (#43, #45, #47, #54)
--shellgives a live simulation a command line (line editing,
history, completion; plain lines from a pipe).--script FILEruns the
same commands with blockingexpect/sleep/wait-until,at/every
/onqueues and a pass/fail verdict, so one Contiki-NG shell firmware can
serve many tests: the shell types into a node's console and asserts on what
it prints. The exit code says what failed: 0 pass, 1 assertion, 2 invalid
request, 6 wall timeout, 7 cancelled.- Node commands (
cmd: send a line, wait for the prompt, check the output),
per-node console masks and log files, environment control, breakpoints and
watchpoints, register and MSP430 memory access, GPIO, and fault injection —
a SecureFault injected withreg pc =and caught withexpect-fault. --wall-timeout DURbounds a run in wall-clock time without touching
the simulation. Seedocs/shell.md.
Added — web UI recording and replay, and a project site (#65, #66)
--ui-record FILE.jsonwrites the stream the web UI would receive as a
replay file. Without--uithe run stays headless and unpaced, and stdout
is byte-identical with and without the flag (tools/check-ui-record.sh, in
CI).ui/index.html?replay=FILE.jsonplays it from a static file: pause,
speed, a scrubber. Seedocs/ui-replay.md.- https://mikroverk.github.io/cooja-ng/: recorded runs to watch in the
browser, recorded by CI from the commit the site is built from, each
published only if it shows what its card says.
Added — the simulator as a library (#63)
make libbuildsbuild/libcsim.awithouttest/;make lib-link-check
(in CI) links it with amainof its own, so a kernel, chip or service
object that needs a symbol only the runner defines fails the build. Three
such dependencies on runner-only symbols were removed to get there.
Added — Renode co-simulation: csim as a clock slave (#36, #39, #41)
- Renode can drive csim's simulation clock. New
src/services/renode_cosim_service.cspeaks Renode'sCoSimulationPlugin
protocol — the 24-byte binary message over two TCP sockets, the handshake,
the fixed-quantumtickClock, bus reads and writes, and the asynchronous
interruptandlogMessagechannel. EverytickClockbecomes the runner's
next horizon, so Renode's virtual time and csim's advance together. From
Renode's side this needs no Renode-side code: one
CoSimulated.CoSimulatedPeripheralline in a.repl
(examples/renode/csim.repl). Everywhere else in csim, csim owns the clock;
this is the one inversion. See
docs/design/renode-cosim-plan.md. - csim's whole 802.15.4 network as a memory-mapped device. New
src/native/renode_dev.cis the register window behind that peripheral:
transmit a frame into csim's medium, read received frames back with their
sender, channel, per-receiver RSSI and on-air start time, bridge one
csim node's console, and take a level interrupt when something arrives. The
guest-side mirror of the map isexamples/renode/csim_dev.h. - New mote kind
renode-cosim, selected by a.renodefirmware
extension the way.pyselects an external node (the path is never opened).
It has no CPU and no clock of its own: it is the device's place in csim's
medium. Without a master attached it is inert, so a config containing one
still runs as a plain regression. - New runner flags
--renode ADDR:MAIN:ASYNCand--renode-freq HZ
(--renode-freqmust match the peripheral'sfrequency; thetickClock
message carries only a tick count). Also reachable asplugins: ["renode"]
with the connection inCSIM_RENODE.tools/csim-renode-launch.shmaps
Renode's positional spawn arguments onto the flag. - Tests:
./build/test_runner renode-cosimcovers the wire codec against
a hand-written byte vector, the register window and its FIFOs, and the real
protocol loop driven by a scripted mock master over asocketpair.
tools/renode-mock-master.pyplustools/check-renode-cosim.shgate it end
to end: exact clock coupling, frames crossing in both directions, console
lines forwarded, determinism across identical runs, and a clean exit when
the master dies mid-run. - The runner's loop is touched in exactly two gated places, so with no
--renodethe default path stays byte-identical.
Added — Renode as the RPL root, and three emulators on one network (#37)
- Renode's own CC2538 as the RPL root of a csim network
(configs/test-renode-root-rpl.yaml): csim's Sky and nRF52840 clients join
its DAG and complete UDP round trips through it, with
examples/renode/bridge/CsimBridge.csjoining Renode's medium to csim's.
With esp32sim as well, three emulators and three ISAs share one network
(configs/test-threeway-cosim.yaml). Examples, not CI gates: they need
Renode (and esp32sim).
Added — nRF54L15 (#30, #31, #32, #34, #38, #42, #44, #46, #51, #58, #59)
- TrustZone-M under the simulation kernel, on a new board,
nrf54l15-xiao(Seeed Studio XIAO nRF54L15). A node can carry a
Secure-world ELF (secure_firmware) beside its Non-secure one; boot starts
in the Secure world, and the end-of-run report adds SG / BXNS /
secure-exception counters. - Attribution and peripheral permissions enforced as on silicon. The
per-SoC attribution hook is new: before it, every address answered
Non-secure, so nothing was refused. The SPU's
per-peripheral permissions refuse Non-secure accesses with a precise
BusFault taken by the Secure world, and SecureFault AUVIOL is precise too
(the frame names the access, and a refused load or store changes nothing).
The security unit's behaviour was measured on a Seeed XIAO nRF54L15
(devices/nrf54l15-xiao/HARDWARE-COMPARISON.md).
New configs: TrustZone boot, a watchdog the Secure world owns (verified line
for line against a XIAO), a peripheral-permission violation, and two-node
RPL-UDP over TrustZone with the radio driven through SG veneers. - Two-node RPL-UDP on the nRF54L15: timer deadlines, interconnect channel
groups, and the Nordic 802.15.4 driver's own hardware ACK path, which
Contiki-NG's port now relies on (#34). - Console receive through UARTE20 EasyDMA, paced at the baud rate (#31);
SPIM with the DK's MX25R6435F flash and an ENC28J60 (#32); FICR.DEVICEID
seeded sonode_idequals the configured mote id (#30).
Added — platforms, tests and tools
- FreeBSD (tested by hand on 15.1, amd64; not in CI): build with
gmake;
the scripts under `tools/...
Cooja-NG v0.3.0-rc1
Cooja-NG becomes something you can drive, embed and watch: a command shell
and script engine for testing firmware through its own console, the simulator
as a library, Renode as a co-simulation clock master, and recorded runs that
replay in the browser. The nRF54L15's TrustZone-M is enforced the way a Seeed
XIAO nRF54L15 enforces it; three CPU architectures share one RPL network; and
the kernel's wakeup path no longer scales with the node count (in networks
without native motes). Release binaries for linux-x86_64, macos-x64 and
macos-arm64 produce byte-identical simulation output: builds no longer fuse
multiply-adds on arm64 (#72), and the release workflow checks the identity on
real firmware with every JIT on and off.
Contributors to this release: @nfi (the shell, the nRF54L15 console, radio and
TrustZone-M enforcement), and @nvt (hardening, native-mote CCA, the firmware
cache, FreeBSD, the JIT divide-trap fix, and reviews of the kernel,
performance, library, UI-replay, Firefly and release work).
Changed — check these before upgrading
- The web UI listens on loopback only.
--ui PORTbinds 127.0.0.1;
--ui-bind ADDRexposes it deliberately. Cross-origin WebSocket handshakes
and DNS-rebindingHostheaders are refused, and a slow or hostile client
can no longer hold up the run (#53). - The MSP430 PC-trace counters are opt-in. The end-of-run
FW cc2420_transmit=… eb_process=… queue_add=…line appears only with
CSIM_PC_TRACE=1; the per-instruction hook it needed is gone from every
other run (#61). - Off-SoC chip drivers moved to
src/chips/andinclude/chips/(CC2420,
CC1200, MX25R6435F, ENC28J60): they are not architecture-specific.
Out-of-tree code that includes their headers needs-I include/chips(#33). - Simulation output moves relative to 0.2.3 where a model was fixed, so a
regression baseline recorded with 0.2.3 differs in these places:- nRF54L15
node_idis the configured mote id (it was a hash, 8251 / 16758
for motes 1 / 2), so link-layer addresses change (#30); - nRF54L15 radio DISABLE→DISABLED latency is 3 µs instead of 8 µs
(NRF54L_DISABLED_DEFER_NSoverrides; the working window is 2.5–4 µs),
and the DK firmware images were rebuilt for the hardware-ACK path (#34); - native-mote CCA follows on-air time: a duty-cycled sixteen-node rpl-udp
network went from 33–89 % of round trips delivered to 99.9–100 % (#56); - CC1200 (Zolertia Firefly sub-GHz) frame timing (#67);
- ARM output with the JIT on, wherever firmware calls the 64-bit divide
helpers (nRF52840 TSCH among them) — it now equals JIT-off output (#69).
- nRF54L15
- Refusals that used to pass silently: an ELF whose segments place no
bytes fails at init instead of running a zero-filled image to exit 0 (#50);
a GDB client must answer within 5 s and an external-node peer must advance
its clock within 10000 exchanges, or it is dropped (#52); a web-UI client
that stops reading for 200 ms is dropped (#53). - Firmware cache names include the source directory (relative to the
Contiki-NG root), so existing local builds are rebuilt once;--clean
removes only untracked builds, never shipped firmware (#57).
Added — interactive shell and command scripts (#43, #45, #47, #54)
--shellgives a live simulation a command line (line editing,
history, completion; plain lines from a pipe).--script FILEruns the
same commands with blockingexpect/sleep/wait-until,at/every
/onqueues and a pass/fail verdict, so one Contiki-NG shell firmware can
serve many tests: the shell types into a node's console and asserts on what
it prints. The exit code says what failed: 0 pass, 1 assertion, 2 invalid
request, 6 wall timeout, 7 cancelled.- Node commands (
cmd: send a line, wait for the prompt, check the output),
per-node console masks and log files, environment control, breakpoints and
watchpoints, register and MSP430 memory access, GPIO, and fault injection —
a SecureFault injected withreg pc =and caught withexpect-fault. --wall-timeout DURbounds a run in wall-clock time without touching
the simulation. Seedocs/shell.md.
Added — web UI recording and replay, and a project site (#65, #66)
--ui-record FILE.jsonwrites the stream the web UI would receive as a
replay file. Without--uithe run stays headless and unpaced, and stdout
is byte-identical with and without the flag (tools/check-ui-record.sh, in
CI).ui/index.html?replay=FILE.jsonplays it from a static file: pause,
speed, a scrubber. Seedocs/ui-replay.md.- https://mikroverk.github.io/cooja-ng/: recorded runs to watch in the
browser, recorded by CI from the commit the site is built from, each
published only if it shows what its card says.
Added — the simulator as a library (#63)
make libbuildsbuild/libcsim.awithouttest/;make lib-link-check
(in CI) links it with amainof its own, so a kernel, chip or service
object that needs a symbol only the runner defines fails the build. Three
such dependencies on runner-only symbols were removed to get there.
Added — Renode co-simulation: csim as a clock slave (#36, #39, #41)
- Renode can drive csim's simulation clock. New
src/services/renode_cosim_service.cspeaks Renode'sCoSimulationPlugin
protocol — the 24-byte binary message over two TCP sockets, the handshake,
the fixed-quantumtickClock, bus reads and writes, and the asynchronous
interruptandlogMessagechannel. EverytickClockbecomes the runner's
next horizon, so Renode's virtual time and csim's advance together. From
Renode's side this needs no Renode-side code: one
CoSimulated.CoSimulatedPeripheralline in a.repl
(examples/renode/csim.repl). Everywhere else in csim, csim owns the clock;
this is the one inversion. See
docs/design/renode-cosim-plan.md. - csim's whole 802.15.4 network as a memory-mapped device. New
src/native/renode_dev.cis the register window behind that peripheral:
transmit a frame into csim's medium, read received frames back with their
sender, channel, per-receiver RSSI and on-air start time, bridge one
csim node's console, and take a level interrupt when something arrives. The
guest-side mirror of the map isexamples/renode/csim_dev.h. - New mote kind
renode-cosim, selected by a.renodefirmware
extension the way.pyselects an external node (the path is never opened).
It has no CPU and no clock of its own: it is the device's place in csim's
medium. Without a master attached it is inert, so a config containing one
still runs as a plain regression. - New runner flags
--renode ADDR:MAIN:ASYNCand--renode-freq HZ
(--renode-freqmust match the peripheral'sfrequency; thetickClock
message carries only a tick count). Also reachable asplugins: ["renode"]
with the connection inCSIM_RENODE.tools/csim-renode-launch.shmaps
Renode's positional spawn arguments onto the flag. - Tests:
./build/test_runner renode-cosimcovers the wire codec against
a hand-written byte vector, the register window and its FIFOs, and the real
protocol loop driven by a scripted mock master over asocketpair.
tools/renode-mock-master.pyplustools/check-renode-cosim.shgate it end
to end: exact clock coupling, frames crossing in both directions, console
lines forwarded, determinism across identical runs, and a clean exit when
the master dies mid-run. - The runner's loop is touched in exactly two gated places, so with no
--renodethe default path stays byte-identical.
Added — Renode as the RPL root, and three emulators on one network (#37)
- Renode's own CC2538 as the RPL root of a csim network
(configs/test-renode-root-rpl.yaml): csim's Sky and nRF52840 clients join
its DAG and complete UDP round trips through it, with
examples/renode/bridge/CsimBridge.csjoining Renode's medium to csim's.
With esp32sim as well, three emulators and three ISAs share one network
(configs/test-threeway-cosim.yaml). Examples, not CI gates: they need
Renode (and esp32sim).
Added — nRF54L15 (#30, #31, #32, #34, #38, #42, #44, #46, #51, #58, #59)
- TrustZone-M under the simulation kernel, on a new board,
nrf54l15-xiao(Seeed Studio XIAO nRF54L15). A node can carry a
Secure-world ELF (secure_firmware) beside its Non-secure one; boot starts
in the Secure world, and the end-of-run report adds SG / BXNS /
secure-exception counters. - Attribution and peripheral permissions enforced as on silicon. The
per-SoC attribution hook is new: before it, every address answered
Non-secure, so nothing was refused. The SPU's
per-peripheral permissions refuse Non-secure accesses with a precise
BusFault taken by the Secure world, and SecureFault AUVIOL is precise too
(the frame names the access, and a refused load or store changes nothing).
The security unit's behaviour was measured on a Seeed XIAO nRF54L15
(devices/nrf54l15-xiao/HARDWARE-COMPARISON.md).
New configs: TrustZone boot, a watchdog the Secure world owns (verified line
for line against a XIAO), a peripheral-permission violation, and two-node
RPL-UDP over TrustZone with the radio driven through SG veneers. - Two-node RPL-UDP on the nRF54L15: timer deadlines, interconnect channel
groups, and the Nordic 802.15.4 driver's own hardware ACK path, which
Contiki-NG's port now relies on (#34). - Console receive through UARTE20 EasyDMA, paced at the baud rate (#31);
SPIM with the DK's MX25R6435F flash and an ENC28J60 (#32); FICR.DEVICEID
seeded sonode_idequals the configured mote id (#30).
Added — platforms, tests and tools
- FreeBSD (tested by hand on 15.1, amd64; not in CI): build with
gmake;
the scripts under `tools/...
Cooja-NG v0.2.3
What's Changed
- docs: plan for external data-driven nodes (+ a worked disturber example) by @joakimeriksson in #22
- ext_node: emulator peers lag the kernel; run the ESP32-C6 (esp32sim) as an external mote by @joakimeriksson in #24
- ext motes: put a peer's tx on the air at its stamp, and measure the ACK gap by @joakimeriksson in #25
- docs: correct the E6 stage-2 findings — the ACK is not late, and the slice model is not the cause by @joakimeriksson in #26
- config: YAML as the primary format, one strict schema, and --save-config by @joakimeriksson in #27
- native motes: wake serially-injected motes at the kernel clock; kernel refuses wakeups in the past by @joakimeriksson in #29
- version: 0.2.3 — YAML configs, ESP32-C6 external motes, ext ACK timing by @joakimeriksson in #28
Full Changelog: v0.2.2...v0.2.3
Cooja-NG v0.2.2
What's Changed
- ci: verified, mirrored GNU Lightning fetch (curl | tar failed silently) by @joakimeriksson in #13
- release: ship tools/test-border-router.sh in the tarball by @joakimeriksson in #14
- test: fail loudly — unknown .csc features and missing verdicts are failures, never green by @joakimeriksson in #15
- version: 0.2.1 — fail-loudly suite + complete tarball by @joakimeriksson in #16
- MSP430: enforce slice cycle budget, apply RPT to single-op instructions, fix CC2420 footer RSSI by @joakimeriksson in #17
- run-cooja-tests: default the suite firmware target to cooja (no silent cc2538dk fallback on fresh checkouts) by @joakimeriksson in #18
- native motes: boot at the scheduled start and receive frames the way COOJA's ContikiRadio does by @joakimeriksson in #19
- suite: --seed and --logdir, so Contiki-NG's BASESEED/RUNCOUNT loop is faithful by @joakimeriksson in #20
- version: 0.2.2 — suite --seed/--logdir, fail-loudly, Contiki-NG guide by @joakimeriksson in #21
Full Changelog: v0.2.0...v0.2.2
Cooja-NG v0.2.0
Cooja-NG 0.2.0
First release shipped as prebuilt binaries: cooja-ng-v0.2.0-{linux-x86_64,macos-x64,macos-arm64}.tar.gz + SHA256SUMS. Each tarball holds build/test_runner and the Contiki-NG suite runner scripts (tools/run-cooja-tests.sh, csc2json.py, build-test-firmware.sh) — no JVM, no build step. GNU Lightning is statically linked; the JIT is cycle-exact, so results are byte-identical with or without it.
tar xzf cooja-ng-v0.2.0-linux-x86_64.tar.gz && cd cooja-ng-v0.2.0-linux-x86_64
CONTIKI_DIR=/path/to/contiki-ng tools/run-cooja-tests.sh # 85 Cooja tests
CONTIKI_DIR=/path/to/contiki-ng tools/run-cooja-tests.sh --with-tun # all 93 (needs sudo/TUN)Passes the complete Contiki-NG 5.2 Cooja simulation suite: 93/93, 0 skipped, on Linux/x86-64 and macOS/arm64.
ARM performance: interpreter + JIT (#9)
- Interpreter: 34% faster on the ARM runner workload (inlined condition evaluation, gated debug facilities, flash-window / GDB / ROM-trap hoists, page-indexed MMIO lookup — 1.07x on TSCH, 1.16x on Contiki-NG/nRF52840 from the trap hoist alone).
- GNU Lightning JIT for Cortex-M (
src/arm/arm_decode.c,src/arm/arm_jit.c): hot Thumb-16 blocks — ALU, shifts, branches, guarded SRAM loads/stores, native self-loops. On by default when Lightning is present.zephyr-synchronization60 s sim: 2.05 s → 0.58 s (3.5x) on Apple Silicon, 5.9x MIPS on x86-64. Contiki-NG protocol firmware is ~1.0–1.2x — the plan document explains why, with measurements. - Cycle-exact by gate:
CSIM_ARM_JIT=0and=1produce byte-identical simulation output on every multinode config. - New test suites, both in CI on both hosts:
arm-decode(307,800 differential comparisons of the decoder + reference model vs the interpreter) andarm-jit(410,400 comparisons of the generated machine code vs the interpreter). The latter exists becausejit_andi(dst, src, 0x80000000)returns 0 on x86-64 Lightning 2.2.3 — every N-reading condition silently took the wrong branch there while all other tests stayed green. Fixed and regression-gated. make pgorepaired and trained on ARM workloads (1.55x clang / 1.18x gcc);arm-benchbenchmark mode added.- Everything tried and rejected is recorded in
docs/design/arm-performance-plan.md, including the negative results.
ARMv8-M TrustZone-M on the nRF54L15 (#8)
- Security attribution engine (
src/arm/arm_trustzone.c): SAU + SPU-as-IDAU, memory-mapped SAU registers, hot-path access enforcement feeding SecureFault/SFSR. - Banked SP/CONTROL,
SG/BXNS/BLXNS/FNC_RETURN,TT*, secure exception entry/return with integrity signature,NVIC_ITNSbanking. - Per-node SG / BXNS / secure-exception counters — TEE transition cost is measurable network-wide.
test_runner tz-boot <secure.elf> <normal.elf>boots the real Contiki-NG split image. 71 new tests;arm-correctnessis now 230.- The JIT never runs Non-secure code (interpreter-only there), verified byte-identical on the TZ split image.
CC2538 and nRF radio fixes (#7, by @highlunder)
- cc2538 SYS_CTRL:
CLOCK_STA.OSCmirrorsCLOCK_CTRL.OSC;SYNC_32Kclear-then-set sequence modelled — fixes the RCOSC frequency downshift that broke TSCH slot timing and the PM1/2 wedge. New fix-sensitive regression testconfigs/test-tsch-lpm-cc2538dk.json. - nRF52840/nRF54L15: clear
psdu_being_receivedon aborted RX — multi-hop RPL chains now pass (chain-4node-nrf52840-dk,chain-4node-nrf52840-dongle,chain-3node-nrf54l15-dkleave the known-failing list).
Radio media (#6, by @highlunder)
- Gilbert-Elliott two-state burst-loss radio medium plugin (
CSIM_GE_*knobs,make test-gestatistical validation).
CI
- GNU Lightning installed on both runners (source-built on Linux with the vendored upstream
mprotectfix — vanilla 2.2.3 SIGBUSes on Apple Silicon);arm-jitfails on SKIP. - New PR gates: JIT on/off byte-identity, lockstep verification on real cc2538 firmware, TSCH association + sync canary, and a no-Lightning rebuild so the optional path keeps coverage.
- Per-tag release workflow (#10) producing the tarballs above.
Full Changelog: v0.1.0...v0.2.0
v0.1.0: Cooja-NG (csim) 0.1.0 — first public release
Cooja-NG (csim) 0.1.0 — first public release
A fast, multi-architecture C re-implementation of Cooja and MSPSim: run the
upstream Contiki-NG test suite headlessly, with an emphasis on simulation
speed, deterministic timing, and faithful peripheral behaviour.
Emulation
- MSP430 / MSP430X (interpreter + optional GNU Lightning JIT): F149, F1611,
F2617, F5437, CC430F5137, FR5969, with the CC2420 radio. - ARM Cortex-M3/M4F/M33: CC2538, Zolertia Firefly (+ CC1200 sub-GHz), Nordic
nRF52840 and nRF54L15 with on-chip 802.15.4. - RISC-V RV32EMC via the nRF54L15 FLPR coprocessor — unmodified Contiki-NG
running dual-core with the M33 over shared SRAM. - Native Cooja motes (dlopen) and JS app motes (QuickJS).
- Also boots stock Zephyr OS and RIOT OS on the nRF52840 (experimental).
Simulation
- Single-threaded event-driven kernel, ns-precise clock, per-radio
multi-channel medium, per-byte RF delivery. - Ports-and-adapters architecture; static registry plus a dlopen plugin ABI
(v1 service, v2 radio medium, v3 live web-UI panel).
Tests
- Contiki-NG Cooja suite: 93/93, zero failed and zero skipped — all 85
headless tests plus all 8 TUN/border-router cases against a real tun0. - Instruction, firmware, radio-medium/bus, chip-driver and plugin suites;
determinism and config-equivalence guards. Verified on macOS/arm64 and
Linux/x86-64.
Includes a full pre-release subsystem audit — memory-safety fixes (WebSocket
frame parser, ELF loader bounds, native-mote clamps), CPU/peripheral
correctness fixes (MSP430 DADD/RRCM/timer/JIT, ARM NVIC, CC2538 GPTimer,
RISC-V WFI), end-to-end nRF 802.15.4 routing for 2-node and multi-hop chains
on both nRF radios, and host-link latency on the serial socket so the native
border router drains correctly (the last failing suite test).
Known limitations: SVC is a no-op; MSP430 CS HFXT returns the DCO frequency;
the serial socket carries a deliberate 40 ms host-link latency pending a
flow-controlled link. See CHANGELOG.md.