From 535dd672787344c05a885a429147f1fc2b4f77ec Mon Sep 17 00:00:00 2001 From: Lucas Dietrich Date: Wed, 14 Aug 2024 22:34:03 +0200 Subject: [PATCH] Experimental support for rust * Update readme.md about intentions about rust support * Generate bindings * Create simple examples * Highlights compilation issues * Fix warnings --- .cargo/config.toml | 12 + .gitignore | 2 + .vscode/launch.template.json | 42 +- .vscode/settings.json | 70 +- Cargo.lock | 600 +++++ Cargo.toml | 19 + Makefile | 15 +- avr-atmega2560.json | 25 + readme.md | 162 +- rust-avrtos-core/Cargo.toml | 13 + rust-avrtos-core/src/lib.rs | 3 + rust-avrtos-examples/Cargo.toml | 23 + rust-avrtos-examples/build.rs | 6 + .../src/loop_invalid_assembly.rs | 26 + rust-avrtos-examples/src/serial_demo.rs | 41 + rust-avrtos-examples/src/sleep_demo.rs | 59 + rust-avrtos-sys/Cargo.toml | 21 + rust-avrtos-sys/build.rs | 291 +++ rust-avrtos-sys/scripts/bindgen-help | 231 ++ rust-avrtos-sys/scripts/gen.sh | 138 ++ rust-avrtos-sys/src/bindings.rs | 2128 +++++++++++++++++ rust-avrtos-sys/src/lib.rs | 26 + rust-avrtos-sys/src/main.rs | 1 + rust-toolchain.toml | 10 + scripts/piodis.py | 3 +- scripts/qemu-runner.sh | 6 + scripts/rustdis.py | 11 + src/avrtos/avrtos.h | 1 + src/avrtos/avrtos_conf.h | 19 + src/avrtos/avrtos_rust_conf.h | 29 + src/avrtos/drivers/i2c.c | 2 + src/avrtos/drivers/timer.c | 4 + src/avrtos/idle.c | 2 + src/avrtos/init.c | 2 +- src/avrtos/ring.c | 2 + src/avrtos/rust_helpers.c | 49 + src/avrtos/rust_helpers.h | 20 + src/avrtos_all.h | 13 + 38 files changed, 4048 insertions(+), 79 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 avr-atmega2560.json create mode 100644 rust-avrtos-core/Cargo.toml create mode 100644 rust-avrtos-core/src/lib.rs create mode 100644 rust-avrtos-examples/Cargo.toml create mode 100644 rust-avrtos-examples/build.rs create mode 100644 rust-avrtos-examples/src/loop_invalid_assembly.rs create mode 100644 rust-avrtos-examples/src/serial_demo.rs create mode 100644 rust-avrtos-examples/src/sleep_demo.rs create mode 100644 rust-avrtos-sys/Cargo.toml create mode 100644 rust-avrtos-sys/build.rs create mode 100644 rust-avrtos-sys/scripts/bindgen-help create mode 100755 rust-avrtos-sys/scripts/gen.sh create mode 100644 rust-avrtos-sys/src/bindings.rs create mode 100644 rust-avrtos-sys/src/lib.rs create mode 100644 rust-avrtos-sys/src/main.rs create mode 100644 rust-toolchain.toml create mode 100755 scripts/qemu-runner.sh create mode 100644 scripts/rustdis.py create mode 100644 src/avrtos/avrtos_rust_conf.h create mode 100644 src/avrtos/rust_helpers.c create mode 100644 src/avrtos/rust_helpers.h create mode 100644 src/avrtos_all.h diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..88463420 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,12 @@ +[build] +target = "avr-atmega2560.json" # architecture/avr/ + +[unstable] +build-std = ["core"] + +[target.'cfg(target_arch = "avr")'] +# runner = "./scripts/qemu-runner.sh" +runner = "ravedude -cb 115200 mega2560" + +# runner = "ravedude -cb 57600 mega2560 -P /dev/ttyACM0" + diff --git a/.gitignore b/.gitignore index 438ef889..3980f2c4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ *.dump /scripts/misra-rules.txt /misra.json + +/target \ No newline at end of file diff --git a/.vscode/launch.template.json b/.vscode/launch.template.json index 7a70b6ba..2181f698 100644 --- a/.vscode/launch.template.json +++ b/.vscode/launch.template.json @@ -1,20 +1,34 @@ { "version": "0.2.0", "configurations": [ - { - "name": "(gdb) QEMU", - "type": "cppdbg", - "request": "launch", - "miDebuggerServerAddress": "127.0.0.1:1234", - "program": "${workspaceFolder}/.pio/build/Sysclock-qemu-ATmega2560/firmware.elf", - "args": [], - "stopAtEntry": true, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false, - "miDebuggerPath": "avr-gdb", - "MIMode": "gdb" - }, + { + "name": "(gdb) QEMU", + "type": "cppdbg", + "request": "launch", + "miDebuggerServerAddress": "127.0.0.1:1234", + "program": "${workspaceFolder}/.pio/build/Sysclock-qemu-ATmega2560/firmware.elf", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "miDebuggerPath": "avr-gdb", + "MIMode": "gdb" + }, + { + "name": "rust QEMU (avr)", + "type": "cppdbg", + "request": "launch", + "miDebuggerServerAddress": "127.0.0.1:1234", + "program": "target/avr-atmega2560/release/rust-avrtos-examples.elf", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "miDebuggerPath": "avr-gdb", + "MIMode": "gdb" + }, { "name": "(gdb) remote QEMU WSL", "type": "cppdbg", diff --git a/.vscode/settings.json b/.vscode/settings.json index 93dd75ec..fb0577fc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,7 @@ "CMAKE_GENERATOR": "Unix Makefiles", "CMAKE_TOOLCHAIN_FILE": "${workspaceFolder}/cmake/avr6-atmega2560.cmake", }, + "rust-analyzer.cargo.buildScripts.enable": false, "editor.tabSize": 4, "editor.rulers": [80], "files.associations": { @@ -13,67 +14,16 @@ "*.bb": "shellscript", "*.bbclass": "shellscript", "*.inc": "shellscript", - "multithreading_debug.h": "c", - "serial.h": "c", - "multithreading_defines.h": "c", - "schedules_items.h": "c", - "xqueue.h": "c", - "mutex.h": "c", - "pgmspace.h": "c", - "io.h": "c", - "interrupt.h": "c", - "kernel.h": "c", + "rust.h": "c", "defines.h": "c", - "sys.h": "c", - "debug.h": "c", - "fifo.h": "c", - "assert.h": "c", - "idle.h": "c", - "canaries.h": "c", - "queue.h": "c", - "workqueue.h": "c", - "dlist.h": "c", - "stddef.h": "c", - "mem_slab.h": "c", "avrtos.h": "c", - "tqueue.h": "c", - "slist.h": "c", - "led.h": "c", - "delay.h": "c", - "cpufunc.h": "c", - "stdint.h": "c", - "avrtos_conf.h": "c", - "time.h": "c", - "event.h": "c", - "atomic.h": "c", - "timer.h": "c", - "stack_sentinel.h": "c", - "fault.h": "c", - "iom328p.h": "c", - "stdbool.h": "c", - "usart.h": "c", - "semaphore.h": "c", - "kernel_private.h": "c", - "drivers.h": "c", - "gpio.h": "c", - "flags.h": "c", - "logging.h": "c", - "iom2560.h": "c", - "iomxx0_1.h": "c", - "typeinfo": "c", - "exti.h": "c", - "spi.h": "c", - "sleep.h": "c", - "cmath": "c", - "types.h": "c", - "errno.h": "c", - "init.h": "c", - "ring.h": "c", - "string.h": "c", - "crc16.h": "c", - "delay_basic.h": "c", - "twi.h": "c", - "i2c.h": "c", - "i2c_defs.h": "c" + "rust_helpers.h": "c", + "system_error": "c", + "array": "c", + "functional": "c", + "tuple": "c", + "type_traits": "c", + "utility": "c", + "kernel.h": "c" }, } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..da648a9c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,600 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "arduino-hal" +version = "0.1.0" +source = "git+https://github.com/rahix/avr-hal?rev=ravedude-0.1.6#06ad11ffdbc64b1e0e43c4910be4110d488662e1" +dependencies = [ + "atmega-hal", + "avr-device", + "avr-hal-generic", + "cfg-if 1.0.0", + "embedded-hal", + "ufmt 0.1.2", + "void", +] + +[[package]] +name = "atmega-hal" +version = "0.1.0" +source = "git+https://github.com/rahix/avr-hal?rev=ravedude-0.1.6#06ad11ffdbc64b1e0e43c4910be4110d488662e1" +dependencies = [ + "avr-device", + "avr-hal-generic", +] + +[[package]] +name = "avr-device" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546b09da5e933d18b790ccb5aae351371c6c4f8094a7b011dcd7c7e7fb69cc94" +dependencies = [ + "avr-device-macros", + "bare-metal", + "cfg-if 1.0.0", + "vcell", +] + +[[package]] +name = "avr-device-macros" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b108541dc1ea060dfa9b824acbded94f658f8daecca549144d05a4d01e65b6f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "avr-hal-generic" +version = "0.1.0" +source = "git+https://github.com/rahix/avr-hal?rev=ravedude-0.1.6#06ad11ffdbc64b1e0e43c4910be4110d488662e1" +dependencies = [ + "avr-device", + "cfg-if 0.1.10", + "embedded-hal", + "embedded-storage", + "nb 0.1.3", + "paste", + "rustversion", + "ufmt 0.1.2", + "void", +] + +[[package]] +name = "avrtos-core" +version = "0.1.0" +dependencies = [ + "avrtos-sys", +] + +[[package]] +name = "avrtos-sys" +version = "0.1.0" +dependencies = [ + "arduino-hal", + "bindgen", + "cc", + "nb 1.1.0", + "panic-halt", + "ufmt 0.2.0", +] + +[[package]] +name = "bare-metal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.74", + "which", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "cc" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fb8dd288a69fc53a1996d7ecfbf4a20d59065bff137ce7e56bbd620de191189" +dependencies = [ + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-storage" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723dce4e9f25b6e6c5f35628e144794e5b459216ed7da97b7c4b66cdb3fa82ca" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if 1.0.0", + "windows-targets", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "panic-halt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.74", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rust-avrtos-examples" +version = "0.1.0" +dependencies = [ + "arduino-hal", + "avrtos-sys", + "nb 1.1.0", + "panic-halt", + "ufmt 0.2.0", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "ufmt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d3c0c63312dfc9d8e5c71114d617018a19f6058674003c0da29ee8d8036cdd" +dependencies = [ + "proc-macro-hack", + "ufmt-macros 0.2.0", + "ufmt-write", +] + +[[package]] +name = "ufmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a64846ec02b57e9108d6469d98d1648782ad6bb150a95a9baac26900bbeab9d" +dependencies = [ + "ufmt-macros 0.3.0", + "ufmt-write", +] + +[[package]] +name = "ufmt-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ab6c92f30c996394a8bd525aef9f03ce01d0d7ac82d81902968057e37dd7d9" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ufmt-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d337d3be617449165cb4633c8dece429afd83f84051024079f97ad32a9663716" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ufmt-write" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..551fce83 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[workspace] +resolver = "2" +members = [ + "rust-avrtos-sys", + "rust-avrtos-core", + "rust-avrtos-examples", +] + +[profile.dev] +panic = "abort" +lto = true +opt-level = "s" + +[profile.release] +panic = "abort" +codegen-units = 1 +debug = true +lto = true +opt-level = "s" \ No newline at end of file diff --git a/Makefile b/Makefile index ff6b3b33..fa09ca85 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ endif all: single -.PHONY: single cmake multiple upload monitor qemu run_qemu format clean piogen arduino_gen gen flash +.PHONY: single cmake multiple upload monitor qemu run_qemu format clean piogen arduino_gen gen flash rust rust_build rust_bindgen cmake: cmake -S . -B build \ @@ -101,6 +101,7 @@ format: clean: rm -rf build + rm -rf target piogen: python3 ./scripts/piogen.py @@ -115,4 +116,14 @@ metrics: scripts/metrics-build-examples-default.sh # Prepare for release -publish: piogen arduino_gen format clean multiple metrics arduino_lint \ No newline at end of file +publish: piogen arduino_gen format clean multiple metrics arduino_lint + +rust_bindgen: + ./rust-avrtos-sys/scripts/gen.sh + +rust_build: + cargo build --package rust-avrtos-examples --release --bin loop_invalid_assembly + python3 scripts/rustdis.py + +rust: + cargo run --package rust-avrtos-examples --release --bin loop_invalid_assembly \ No newline at end of file diff --git a/avr-atmega2560.json b/avr-atmega2560.json new file mode 100644 index 00000000..49106546 --- /dev/null +++ b/avr-atmega2560.json @@ -0,0 +1,25 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega2560", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gcc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "no-default-libraries": false, + "pre-link-args": { + "gcc": [ + "-mmcu=atmega2560" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} \ No newline at end of file diff --git a/readme.md b/readme.md index 54aa9e95..9426ee80 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,7 @@ # AVRTOS: An RTOS for 8-bit AVR Microcontrollers +**[Note about rust support in the project](#rust-support)** + ## Introduction AVRTOS is a real-time operating system (RTOS) crafted for 8-bit AVR microcontrollers. @@ -436,4 +438,162 @@ Run the sample in QEMU: A [Jenkinsfile](./Jenkinsfile) is provided to build the project in a Jenkins (multibranch) pipeline. -It is based on the previous Docker container: `devops/fedora-avr-toolchain` \ No newline at end of file +It is based on the previous Docker container: `devops/fedora-avr-toolchain` + +## Rust support + +Rust support is currently in development, the goal is to provide a Rust API to +compile rust programs using AVRTOS. + +Major steps are: + +- Generate rust bindings for the C API using `bindgen`. +- Compile the kernel sources as a static library to link with the rust program, this will take place in the `avrtos-sys` crate. +- Provide an rust idiomatic API to use AVRTOS, this will take place in the `avrtos-core` crate. +- Provide examples to demonstrate the usage of AVRTOS in Rust using a real board and QEMU, this will take place in the `avrtos-examples` crate. +- Extend the support to other boards (e.g. ATmega328p). + +External resources: + +- [avr-hal-template](https://github.com/Rahix/avr-hal-template/tree/main) +- [avr-hal](https://github.com/Rahix/avr-hal/blob/main/rust-toolchain.toml) + +Note about current development: + +- Sysclock is configured with 100000us period +- Scheduler debug is active +- Only `atmega2560` is supported +- [src/avrtos/rust_helpers.c](src/avrtos/rust_helpers.c) servers development purposes but should behave as a bridge between C and avrtos-core in the future. + +### Generate Rust bindings + +Script [rust-avrtos-sys/scripts/gen.sh](rust-avrtos-sys/scripts/gen.sh) generates the Rust bindings for the C API. It takes care only `avrtos` API is generated (mainly structures and functions). +The bindgen targets the `atmega2560` cpu variant only, bingen relies on clang which +has a *experimental* support for AVR. Default configuration constants are provided, +most of the constants are not used by the headers, only constants which enable/disable +a feature are used. + +Bindings will end up in [rust-avrtos-sys/src/bindings.rs](rust-avrtos-sys/src/bindings.rs). + +TODOs: + +- The path to the `avr` headers must be updated to find the system headers automatically. +Maybe the script can be transformed into a CMakelist to generate the bindings during the build process. +- Move default configuration constants to a dedicated header file: [](./src/avrtos/avrtos_rust_conf.h). + +### Compile the kernel as a static library + +The build script [rust-avrtos-sys/build.rs](rust-avrtos-sys/build.rs) compiles the kernel sources as a static library. It uses the `cc` crate to compile the sources. + +Configuration constants must be correct at this stage, as the sources are compiled. + +Linker script is provided in [architecture/avr/avrtos-avr6.xn](architecture/avr/avrtos-avr6.xn). + +### Provide an idiomatic API + +The `avrtos-core` crate will provide an idiomatic API to use AVRTOS in Rust. +The goal is to be to able most of the avrtos features with a fully safe rust API. + +### Provide examples + +Build current examples with: + +- `cargo run --package rust-avrtos-examples --release --bin loop_invalid_assembly` +- `cargo run --package rust-avrtos-examples --release --bin sleep_demo` + +Feel free to test the binary by configuring the `runner` in the [.cargo/config.toml](.cargo/config.toml) file: + +- The `atmega2560` with `runner = "ravedude -cb 115200 mega2560"` +- QEMU with `runner = "./scripts/qemu-runner.sh"`, also start debugging with `F5`, + see [.vscode/launch.json](.vscode/launch.json) + +### Current issues + +Below are the current issues I'm facing with the Rust support: + +#### Compiler + +I'm unable to find a correct version for the compiler (see [rust-toolchain.toml](rust-toolchain.toml)): + +- `nightly` seems to work but cannot be reproduced. +- `nightly-2024-03-22` which was tested with [avr-hal](https://github.com/Rahix/avr-hal/blob/main/rust-toolchain.toml), doesn't work with `cc` or `bindgen`. + - Error is exactly described in this [issue (avr-hal: 537)](https://github.com/Rahix/avr-hal/issues/537) + +#### Invalid assembly generated + +Following example generates invalid assembly: + +```rust +#![no_std] +#![no_main] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +use core::ffi::c_char; + +use avrtos_sys::{ + serial_init_baud, serial_print +}; +use panic_halt as _; + +const boot: &'static str = "avrtos starting\n\x00"; + +#[arduino_hal::entry] +fn main() -> ! { + unsafe { + serial_init_baud(115200); + serial_print(boot.as_ptr() as *const c_char); + } + + loop { + } +} +``` + +The generated assembly of the `main` function is invalid: + +```s + +000001b2
: + +#[arduino_hal::entry] + 1b2: 0e 94 db 00 call 0x1b6 ; 0x1b6 <_ZN21loop_invalid_assembly20__avr_device_rt_main17h75ecf0a9a15b5945E> + +000001b6 <_ZN21loop_invalid_assembly20__avr_device_rt_main17h75ecf0a9a15b5945E>: +fn main() -> ! { + 1b6: 60 e0 ldi r22, 0x00 ; 0 + 1b8: 72 ec ldi r23, 0xC2 ; 194 + 1ba: 81 e0 ldi r24, 0x01 ; 1 + 1bc: 90 e0 ldi r25, 0x00 ; 0 + unsafe { + serial_init_baud(115200); + 1be: 0e 94 95 00 call 0x12a ; 0x12a + serial_print(boot.as_ptr() as *const c_char); + 1c2: 80 e0 ldi r24, 0x00 ; 0 + 1c4: 92 e0 ldi r25, 0x02 ; 2 + 1c6: 0e 94 c6 00 call 0x18c ; 0x18c + } + + loop { + 1ca: 00 c0 rjmp .+0 ; 0x1cc <__udivmodsi4> + +000001cc <__udivmodsi4>: + 1cc: a1 e2 ldi r26, 0x21 ; 33 + 1ce: 1a 2e mov r1, r26 + 1d0: aa 1b sub r26, r26 + 1d2: bb 1b sub r27, r27 + 1d4: fd 01 movw r30, r26 + 1d6: 0d c0 rjmp .+26 ; 0x1f2 <__udivmodsi4_ep> +``` + +Loop consists of a `rjmp .+0` instruction, which actually refers to the instruction +at the address following the `rjmp` instruction which is the start of the `__udivmodsi4` function. + +This issue appears in most of infinite `loop` I've experienced. + +#### Float conversion or arguments passing ? + +I'm not sure, but float calculations seems to be an issue, any use of the +macro `K_MSEC` or even calling directly `k_sleep` generates issues. \ No newline at end of file diff --git a/rust-avrtos-core/Cargo.toml b/rust-avrtos-core/Cargo.toml new file mode 100644 index 00000000..60d831ba --- /dev/null +++ b/rust-avrtos-core/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "avrtos-core" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] + +[dependencies] +avrtos-sys = { path = "../rust-avrtos-sys" } + +[build-dependencies] diff --git a/rust-avrtos-core/src/lib.rs b/rust-avrtos-core/src/lib.rs new file mode 100644 index 00000000..3f4fa68a --- /dev/null +++ b/rust-avrtos-core/src/lib.rs @@ -0,0 +1,3 @@ +#![no_std] + +pub use avrtos_sys::*; diff --git a/rust-avrtos-examples/Cargo.toml b/rust-avrtos-examples/Cargo.toml new file mode 100644 index 00000000..d1a104a4 --- /dev/null +++ b/rust-avrtos-examples/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "rust-avrtos-examples" +version = "0.1.0" +edition = "2021" + +[dependencies] +panic-halt = "0.2.0" +ufmt = "0.2.0" +nb = "1.1.0" +arduino-hal ={ git = "https://github.com/rahix/avr-hal", rev = "ravedude-0.1.6", features = ["arduino-mega2560"] } +avrtos-sys = { path = "../rust-avrtos-sys" } + +[[bin]] +name = "loop_invalid_assembly" +path = "src/loop_invalid_assembly.rs" + +[[bin]] +name = "sleep_demo" +path = "src/sleep_demo.rs" + +[[bin]] +name = "serial_demo" +path = "src/serial_demo.rs" \ No newline at end of file diff --git a/rust-avrtos-examples/build.rs b/rust-avrtos-examples/build.rs new file mode 100644 index 00000000..15c5c9db --- /dev/null +++ b/rust-avrtos-examples/build.rs @@ -0,0 +1,6 @@ +const LINKER_SCRIPT: &'static str = "architecture/avr/avrtos-avr6.xn"; + +fn main() { + println!("cargo:rustc-link-arg=-T{}", LINKER_SCRIPT); + println!("cargo:rustc-link-lib=static=avrtos"); +} diff --git a/rust-avrtos-examples/src/loop_invalid_assembly.rs b/rust-avrtos-examples/src/loop_invalid_assembly.rs new file mode 100644 index 00000000..54f77f39 --- /dev/null +++ b/rust-avrtos-examples/src/loop_invalid_assembly.rs @@ -0,0 +1,26 @@ +#![no_std] +#![no_main] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +use core::ffi::c_char; + +use avrtos_sys::{ + serial_init_baud, serial_print +}; +use panic_halt as _; + +const boot: &'static str = "avrtos starting\n\x00"; + +#[arduino_hal::entry] +fn main() -> ! { + unsafe { + serial_init_baud(115200); + serial_print(boot.as_ptr() as *const c_char); + } + + loop { + } +} diff --git a/rust-avrtos-examples/src/serial_demo.rs b/rust-avrtos-examples/src/serial_demo.rs new file mode 100644 index 00000000..6a7a7bf1 --- /dev/null +++ b/rust-avrtos-examples/src/serial_demo.rs @@ -0,0 +1,41 @@ +#![no_std] +#![no_main] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +use core::ffi::c_char; + +use avrtos_sys::{ + k_sleep, k_timeout_t, led_init, led_off, led_on, led_toggle, my_yield, serial_hex16, serial_init_baud, serial_print, sleep, sleep_1s, z_avrtos_init, z_rust_sys, z_yield +}; +use panic_halt as _; + +const boot: &'static str = "avrtos starting\n\x00"; +const msg: &'static str = "\n\x00"; + +#[arduino_hal::entry] +fn main() -> ! { + unsafe { + z_avrtos_init(); + serial_init_baud(115200); + serial_print(boot.as_ptr() as *const c_char); + led_init(); + } + + let mut counter = 0; + + loop { + counter += 1; + + unsafe { + led_toggle(); + serial_hex16(counter); + serial_print(msg.as_ptr() as *const c_char); + } + + sleep_1s(); + } + +} diff --git a/rust-avrtos-examples/src/sleep_demo.rs b/rust-avrtos-examples/src/sleep_demo.rs new file mode 100644 index 00000000..55367062 --- /dev/null +++ b/rust-avrtos-examples/src/sleep_demo.rs @@ -0,0 +1,59 @@ +#![no_std] +#![no_main] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +use core::ffi::c_char; + +use avrtos_sys::{ + k_sleep, k_timeout_t, led_init, led_off, led_on, led_toggle, my_yield, serial_hex16, serial_init_baud, serial_print, sleep, sleep_1s, z_avrtos_init, z_rust_sys, z_yield +}; +use panic_halt as _; + +const boot: &'static str = "avrtos starting\n\x00"; +const msg: &'static str = "\n\x00"; + +#[arduino_hal::entry] +fn main() -> ! { + unsafe { + z_avrtos_init(); + serial_init_baud(115200); + serial_print(boot.as_ptr() as *const c_char); + led_init(); + } + + sleep_1s(); + unsafe { + led_toggle(); + } + sleep_1s(); + unsafe { + led_toggle(); + } + sleep_1s(); + unsafe { + led_toggle(); + } + sleep_1s(); + unsafe { + led_toggle(); + } + sleep_1s(); + unsafe { + led_toggle(); + } + sleep_1s(); + unsafe { + led_toggle(); + } + sleep_1s(); + unsafe { + led_toggle(); + } + + loop { + } + +} diff --git a/rust-avrtos-sys/Cargo.toml b/rust-avrtos-sys/Cargo.toml new file mode 100644 index 00000000..eb6fe1c7 --- /dev/null +++ b/rust-avrtos-sys/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "avrtos-sys" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +default = ["avrtos-linker-script", "qemu"] +avrtos-linker-script = [] +qemu = [] + +[dependencies] +panic-halt = "0.2.0" +ufmt = "0.2.0" +nb = "1.1.0" +arduino-hal ={ git = "https://github.com/rahix/avr-hal", rev = "ravedude-0.1.6", features = ["arduino-mega2560"] } + +[build-dependencies] +cc = "1.1" +bindgen = "0.69" \ No newline at end of file diff --git a/rust-avrtos-sys/build.rs b/rust-avrtos-sys/build.rs new file mode 100644 index 00000000..9b4439cb --- /dev/null +++ b/rust-avrtos-sys/build.rs @@ -0,0 +1,291 @@ +const LINKER_SCRIPT: &'static str = "architecture/avr/avrtos-avr6.xn"; + +const SOURCES: &[&str] = &[ + "../src/avrtos/arch/arch_atomic.S", + "../src/avrtos/arch/arch_utils.S", + "../src/avrtos/arch/debug_utils.S", + "../src/avrtos/arch/init_sections.S", + "../src/avrtos/arch/thread_switch_preempt.S", + "../src/avrtos/assert.c", + "../src/avrtos/atomic.c", + "../src/avrtos/canaries.c", + "../src/avrtos/debug.c", + "../src/avrtos/devices/tcn75.c", + "../src/avrtos/drivers/exti.c", + "../src/avrtos/drivers/gpio.c", + "../src/avrtos/drivers/i2c.c", + "../src/avrtos/drivers/spi.c", + "../src/avrtos/drivers/timer.c", + "../src/avrtos/drivers/usart.c", + "../src/avrtos/dstruct/debug.c", + "../src/avrtos/dstruct/dlist.c", + "../src/avrtos/dstruct/slist.c", + "../src/avrtos/dstruct/tqueue.c", + "../src/avrtos/event.c", + "../src/avrtos/fault.c", + "../src/avrtos/fifo.c", + "../src/avrtos/flags.c", + "../src/avrtos/idle.c", + "../src/avrtos/init.c", + "../src/avrtos/io.c", + "../src/avrtos/kernel.c", + "../src/avrtos/mem_slab.c", + "../src/avrtos/misc/led.c", + "../src/avrtos/misc/serial.c", + "../src/avrtos/msgq.c", + "../src/avrtos/mutex.c", + "../src/avrtos/prng.c", + "../src/avrtos/ring.c", + "../src/avrtos/semaphore.c", + "../src/avrtos/signal.c", + "../src/avrtos/stack_sentinel.c", + "../src/avrtos/sysclock.c", + "../src/avrtos/time.c", + "../src/avrtos/timer.c", + "../src/avrtos/workqueue.c", + "../src/avrtos/rust_helpers.c", +]; + +const HEADERS: &[&str] = &[ + "../src/avrtos.h", + "../src/avrtos/assert.h", + "../src/avrtos/atomic.h", + "../src/avrtos/avrtos.h", + "../src/avrtos/avrtos_arduinoide_conf.h", + "../src/avrtos/avrtos_conf.h", + "../src/avrtos/canaries.h", + "../src/avrtos/debug.h", + "../src/avrtos/defines.h", + "../src/avrtos/devices/tcn75.h", + "../src/avrtos/drivers.h", + "../src/avrtos/drivers/exti.h", + "../src/avrtos/drivers/gpio.h", + "../src/avrtos/drivers/i2c.h", + "../src/avrtos/drivers/i2c_defs.h", + "../src/avrtos/drivers/spi.h", + "../src/avrtos/drivers/timer.h", + "../src/avrtos/drivers/timer_defs.h", + "../src/avrtos/drivers/usart.h", + "../src/avrtos/dstruct/debug.h", + "../src/avrtos/dstruct/dlist.h", + "../src/avrtos/dstruct/slist.h", + "../src/avrtos/dstruct/tqueue.h", + "../src/avrtos/errno.h", + "../src/avrtos/event.h", + "../src/avrtos/fault.h", + "../src/avrtos/fifo.h", + "../src/avrtos/flags.h", + "../src/avrtos/idle.h", + "../src/avrtos/init.h", + "../src/avrtos/io.h", + "../src/avrtos/kernel.h", + "../src/avrtos/kernel_private.h", + "../src/avrtos/logging.h", + "../src/avrtos/mem_slab.h", + "../src/avrtos/misc/led.h", + "../src/avrtos/misc/serial.h", + "../src/avrtos/msgq.h", + "../src/avrtos/mutex.h", + "../src/avrtos/prng.h", + "../src/avrtos/ring.h", + "../src/avrtos/semaphore.h", + "../src/avrtos/signal.h", + "../src/avrtos/stack_sentinel.h", + "../src/avrtos/sys.h", + "../src/avrtos/time.h", + "../src/avrtos/timer.h", + "../src/avrtos/types.h", + "../src/avrtos/workqueue.h", + "../src/avrtos/rust_helpers.h", +]; + +const INCLUDES: &[&str] = &[ + "../src/", + "../src/avrtos", + "../src/avrtos/arch", + "../src/avrtos/devices", + "../src/avrtos/drivers", + "../src/avrtos/dstruct", + "../src/avrtos/misc", +]; + +const FEATURE_KERNEL_DEBUG: bool = true; + +// TODO reset to default value (1000us) +const FEATURE_KERNEL_SYSCLOCK_PERIOD_US: u32 = 100000; + +fn compile_avrtos_sources() { + let mut build = cc::Build::new(); + + let linker_script; + #[cfg(feature = "avrtos-linker-script")] + { + linker_script = "1"; + println!("cargo:rustc-link-arg=-T{}", LINKER_SCRIPT); + } + + #[cfg(not(feature = "avrtos-linker-script"))] + { + linker_script = "0"; + } + + build + .compiler("avr-gcc") + .files(SOURCES.iter()) + .includes(INCLUDES.iter()) + .static_flag(true) + .debug(true) + .no_default_flags(true) + // mcu + .flag("-mmcu=atmega2560") + // standard flags + .flag("-Wall") + .flag("-fno-fat-lto-objects") + .flag("-funsigned-char") + .flag("-funsigned-bitfields") + .flag("-fpack-struct") + .flag("-fshort-enums") + .flag("-fdata-sections") + .flag("-ffunction-sections") + .flag("-fno-split-wide-types") + .flag("-fno-tree-scev-cprop") + .flag("-flto") + .flag("-Wstrict-prototypes") + .flag("-std=gnu11") + + // debug infos + .flag("-g") + // .flag("-Og") + // .flag("-gdwarf-3") + // .flag("-gstrict-dwarf") + .flag("-Os") + + + + // disable strict warnings + .flag("-Wno-expansion-to-defined") + .flag("-Wno-implicit-fallthrough") + .flag("-Wno-sign-compare") + .flag("-Wno-type-limits") + + // target config flags + .flag("-DF_CPU=16000000UL") + + // Default config (must match what is in the bindgen script avrtos-sys/scripts/gen.sh at any cost) + .flag("-DCONFIG_RUST=1") + .flag(format!("-DCONFIG_AVRTOS_LINKER_SCRIPT={}", linker_script)) + .flag("-DCONFIG_ARDUINO_FRAMEWORK=0") + .flag("-DCONFIG_PLATFORMIO_IDE=0") + .flag("-DCONFIG_THREAD_MAIN_COOPERATIVE=1") + .flag("-DCONFIG_INTERRUPT_POLICY=1") + .flag("-DCONFIG_THREAD_EXPLICIT_MAIN_STACK=0") + .flag("-DCONFIG_THREAD_MAIN_STACK_SIZE=0x200") + .flag("-DCONFIG_USE_STDLIB_HEAP_MALLOC_MAIN=0") + .flag("-DCONFIG_USE_STDLIB_HEAP_MALLOC_THREAD=0") + .flag("-DCONFIG_THREAD_DEFAULT_SREG=128") + .flag("-DCONFIG_KERNEL_THREAD_TERMINATION_TYPE=0") + .flag("-DCONFIG_KERNEL_SCHEDULER_COMPARE_THREADS_BEFORE_SWITCH=1") + .flag("-DCONFIG_KERNEL_COOPERATIVE_THREADS=1") + .flag(format!("-DCONFIG_KERNEL_SYSCLOCK_PERIOD_US={}llu", FEATURE_KERNEL_SYSCLOCK_PERIOD_US)) + .flag(format!("-DCONFIG_KERNEL_TIME_SLICE_US={}llu", FEATURE_KERNEL_SYSCLOCK_PERIOD_US)) + .flag("-DCONFIG_KERNEL_SYSLOCK_HW_TIMER=1") + .flag("-DCONFIG_CONFIG_KERNEL_TICKS_COUNTER_40BITS=1") + .flag("-DCONFIG_KERNEL_DELAY_OBJECT_U32=1") + .flag("-DCONFIG_KERNEL_AUTO_INIT=0") + .flag("-DCONFIG_KERNEL_MINICORE_SAVE_RESET_CAUSE=0") + .flag("-DCONFIG_KERNEL_CLEAR_WDT_ON_INIT=0") + .flag("-DCONFIG_KERNEL_THREAD_IDLE=1") + .flag("-DCONFIG_KERNEL_THREAD_IDLE_ADD_STACK=0x50") + .flag("-DCONFIG_THREAD_IDLE_COOPERATIVE=0") + .flag("-DCONFIG_IDLE_HOOK=0") + .flag("-DCONFIG_THREAD_CANARIES=0") + .flag("-DCONFIG_THREAD_CANARIES_SYMBOL=0xAA") + .flag("-DCONFIG_THREAD_STACK_SENTINEL=0") + .flag("-DCONFIG_THREAD_STACK_SENTINEL_SIZE=1") + .flag("-DCONFIG_THREAD_STACK_SENTINEL_SYMBOL=0x55") + .flag("-DCONFIG_THREAD_MONITOR=0") + .flag("-DCONFIG_THREAD_MAIN_MONITOR=0") + .flag("-DCONFIG_SYSTEM_WORKQUEUE_ENABLE=0") + .flag("-DCONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=0x200") + .flag("-DCONFIG_SYSTEM_WORKQUEUE_COOPERATIVE=0") + .flag("-DCONFIG_WORKQUEUE_DELAYABLE=0") + .flag("-DCONFIG_KERNEL_ASSERT=0") + .flag("-DCONFIG_KERNEL_ARGS_CHECKS=0") + .flag("-DCONFIG_KERNEL_TIMERS=0") + .flag("-DCONFIG_KERNEL_EVENTS=0") + .flag("-DCONFIG_KERNEL_EVENTS_ALLOW_NO_WAIT=1") + .flag("-DCONFIG_THREAD_ERRNO=0") + .flag("-DCONFIG_SERIAL_AUTO_INIT=0u") + .flag("-DCONFIG_SERIAL_USART_BAUDRATE=500000lu") + .flag("-DCONFIG_STDIO_PRINTF_TO_USART=-1") + .flag("-DCONFIG_LOGGING_SUBSYSTEM=1") + .flag("-DCONFIG_KERNEL_UPTIME=0") + .flag("-DCONFIG_KERNEL_TIME_API=0") + .flag("-DCONFIG_KERNEL_TIME_API_MS_PRECISION=0") + .flag("-DCONFIG_KERNEL_ATOMIC_API=1") + .flag("-DCONFIG_KERNEL_DEBUG_PREEMPT_UART=0") + .flag("-DCONFIG_KERNEL_API_NOINLINE=0") + .flag(format!("-DCONFIG_KERNEL_DEBUG={}", FEATURE_KERNEL_DEBUG as u8)) + .flag(format!("-DCONFIG_KERNEL_SCHEDULER_DEBUG={}", FEATURE_KERNEL_DEBUG as u8)) + .flag("-DCONFIG_FD_MAX_COUNT=0") + .flag("-DCONFIG_KERNEL_REENTRANCY=0") + .flag("-DCONFIG_DRIVERS_USART0_ASYNC=0") + .flag("-DCONFIG_DRIVERS_USART1_ASYNC=0") + .flag("-DCONFIG_DRIVERS_USART2_ASYNC=0") + .flag("-DCONFIG_DRIVERS_USART3_ASYNC=0") + .flag("-DCONFIG_DRIVERS_TIMER0_API=0") + .flag("-DCONFIG_DRIVERS_TIMER1_API=0") + .flag("-DCONFIG_DRIVERS_TIMER2_API=0") + .flag("-DCONFIG_DRIVERS_TIMER3_API=0") + .flag("-DCONFIG_DRIVERS_TIMER4_API=0") + .flag("-DCONFIG_DRIVERS_TIMER5_API=0") + .flag("-DCONFIG_KERNEL_SYSTICK_GPIOB_DEBUG=0") + .flag("-DCONFIG_KERNEL_STATS=0") + .flag("-DCONFIG_KERNEL_FAULT_VERBOSITY=1") + .flag("-DCONFIG_KERNEL_DEBUG_GPIO=0") + .flag("-DCONFIG_KERNEL_DEBUG_GPIO_SYSTICK=1") + .flag("-DCONFIG_SPI_ASYNC=0") + .flag("-DCONFIG_AVRTOS_BANNER_ENABLE=0") + .flag("-DCONFIG_AVRTOS_BANNER=\"*** AVRTOS ***\\n\"") + .flag("-DCONFIG_I2C_DRIVER_ENABLE=1") + .flag("-DCONFIG_I2C0_ENABLED=1") + .flag("-DCONFIG_I2C1_ENABLED=0") + .flag("-DCONFIG_I2C_INTERRUPT_DRIVEN=0") + .flag("-DCONFIG_I2C_FREQ=400000") + .flag("-DCONFIG_I2C_BLOCKING=1") + .flag("-DCONFIG_I2C_MAX_BUF_LEN_BITS=3u") + .flag("-DCONFIG_I2C_LAST_ERROR=1") + .flag("-DCONFIG_I2C_DEBUG"); + + // build + // .flag("-Wl,--gc-sections") + // .flag("-Wl,-Map,map.out"); + + #[cfg(feature = "qemu")] + { + build.flag("-D__QEMU__"); + } + + build.ar_flag("v"); + + build.compile("avrtos"); + + for source in SOURCES { + println!("cargo:rerun-if-changed={}", source); + } + + for header in HEADERS { + println!("cargo:rerun-if-changed={}", header); + } + + // add link args + // println!("cargo:rustc-flag=-Wl,--gc-sections"); + // println!("cargo:rustc-flag=-Wl,-Map,map.out"); + // println!("link-arg=-Wl,--verbose"); + + println!("cargo:rustc-link-lib=static=avrtos"); +} + +fn main() { + compile_avrtos_sources() +} diff --git a/rust-avrtos-sys/scripts/bindgen-help b/rust-avrtos-sys/scripts/bindgen-help new file mode 100644 index 00000000..5265497c --- /dev/null +++ b/rust-avrtos-sys/scripts/bindgen-help @@ -0,0 +1,231 @@ +Generates Rust bindings from C/C++ headers. + +Usage: bindgen
-- ... + +Arguments: + [HEADER] C or C++ header file + [CLANG_ARGS]... Arguments to be passed straight through to clang + +Options: + --depfile + Path to write depfile to + --default-enum-style