nimbme–尼姆裸金属环境
nimbme – Nim bare-metal environment

原始链接: https://github.com/mikra01/nimbme

这是一个用于嵌入式开发的裸机Nim环境,专门针对Raspberry Pi 1/Pi Zero(BCM2835)。它侧重于无需特定于供应商的API即可直接访问硬件,为研究和娱乐提供了一个低级游乐场。主要功能包括协作调度器、基于UART的终端、软件中断机制和旨在避免阻塞的异步编程模型。 它具有竞争条件和异常捕获功能,注册快照进行调试,并利用ARM周期计数器进行延迟测量。Stdio被重定向到UART,支持通过CoolTerm等工具上传文件。该构建强调最小的占地面积,避免使用像“printf”这样的大型库来节省空间。 该项目避免了JTAG调试,而是依靠Nim通过UART和GPIO进行监控和调试的灵活性。未来的目标包括支持更多目标,如Cortex-M0和RISC-V、内存应用模式、通用驱动层、以太网/USB小工具支持、SD卡I/O和SPI/I2C示例。

这个Hacker News线程讨论了Nim编程语言及其功能,特别是用于裸机开发和创建内核模块。一个突出的关键优势是Nim编译成C,使其易于移植到不同的平台。用户已经成功地将Nim移植到16位DOS,甚至在CH32V003微控制器上实现了它。 一个有趣的想法是使用Nim编写Linux内核模块,因为它能够生成C代码,从而可能避开Rust面临的集成问题。虽然Nim生成的C语言不可读,但它有助于在任何C语言可以运行的地方进行预编译和运行Nim代码。挑战包括为内部内核API创建绑定和调整构建过程。 该帖子还谈到了Claude等人工智能代码生成工具在编写Nim代码方面的有用性,这些工具产生了令人惊讶的好结果。最后,对话讨论了IDE对Nim的支持、使用“gdb”的调试功能以及安腾名称管理,使函数名称在调试器中更具可读性。一些用户主张使用其他调试方法,例如单元测试和输出到stderr。
相关文章

原文

Nim bare-metal environment for embedded targets. headless mode

Actual implemented target: raspberry pi1 / pi zero (bcm2835)

General target requirements:

  • at least 4KiB ram
  • at least 20KiB flash
  • 1 UART for terminal
  • 1 hardware timer
  • [cycle counter]
  • software interrupt mechanism
  • cooperative scheduler (actual simple round-robin scheme / deadline-scheduler planned)
  • code runs under system-mode (armv6)
  • async programming model (requirement: do not block the event loop)
  • easy portable / most of the stuff is in nim - only a 'few' lines of asm
  • bare-metal playground and research
  • no vendor specific API's - just Nim and direct hardware access
  • having fun
  • GNU-ARM
  • a terminal for uploading files (CoolTerm, yat(supports 3000000baud) , realterm or something else)
  • usb to serial adapter [!!! 3.3Vmax on the line !!!] (ftdi, CH340..)
  • tested with Nim compiler devel / GNU-ARM toolchain 13.3Rel1 with windows11 host
  • older toolchains are also fine but not 14.2Rel1 (actually not investigated)
  • current baudrate is set to 3000000 / highest one for 250mHz core clock - changeable in envconfig.nim [config_uartBaudRate]

Installation (raspberry pi1 or pi zero 1)

whats implemented so far..

  • stdio is retargeted to UART
  • the demo spawns up to 10 'processes' (at the moment no posix api)
  • the complete runtime in cycles (per process) is collected (irq cycles are also collected but at the moment not related to the actual active process)
  • total ram is limited to 64kiB / shared-heap around 24kiB but you can change that in the main linker file subdir 'hal/boardname/boardname.ld'
  • process stacksize is 1kiB (adjustable in envconfig.nim)
  • race conditions are trapped and the cause is printed out to UART (same for uncaught exceptions)
  • you can do snapshots of the entire register set (cpsr/spsr not implemented)
  • in memory image uploadable (the loader is invoked if a race condition occurs or the demo is finished)
  • the ARM is configured to prevent unaligned access

remark on the build size and experiments

the build size is heavily influenced by libraries and functions you are using. For instance printf and friends occupies whooping >20kiB program space. I faced some runtime problems (spurious exceptions) with newlib-nano so it is not used. The default newlib build delivered with the toolchain has reent-support and that stuff needs also much program-space. If you experiment keep in mind that the stack needs to be 8byte aligned in most cases. When you face race conditions this could be the culprit (or your stack is corrupted due to overflows). Experimenting with SBC´s is great because your hardware is not brickable. Unfortunately the provided bcm2835 datasheet is everything but not a datasheet (seriously). If you look at the PI4/PI5 nothing changed. There are other vendors with superior documentation if you like to start with that topic. I simply choosed this target because I recently found one onto my desk ( I remembered Linux was awful slow on this target (10yrs ago) )... and now there is something better :-) --- and yes I was not aware how 'detailed' the BCM-datasheet is.

overclocking (use at your own risk)

I did some overclocking experiments (core-clock 500mHz / arm-clock 1gHz) and I found no issues if you do not utilize the VC. This setup is working fine and the chip temp levels out at around 40 degrees celsius (around 50 degrees celsius for the pi zero). I refer so some community efforts to find the correct settings in config.txt and/or consult config.txt properties

thanks to Nim you literally do not need a jtag debugger (this project was completely done without one). If you like to invest some money go for a scope and utilize gpio for tackling rt problems. If you like to monitor specific code parts use intro and outro procs with exported symbols (to find the codepart of interest) and consult the .lss output. Join state information (print out register- and/or memory snapshots) if needed. For latency measurements take snapshots of the 64bit free running counter (clocked at 1mHz fixed). Unfortunately the free running arm counter option is not implemented (bcm2835) and the prescaler only works with 256 so there is now way to get a better resolution than around 512ns (500mHz core clock divided by 256). Fine granuled measurement is only possible with the arm cycle counter (roundabout 4 seconds max. without prescaler)

  • GPIO handling helper (RP1)
  • more targets (Cortex-M0 / Sitara AM3358 / risc-v /.. planned)
  • in memory-app mode for flash targets with ram > 32kiB (compile and run your prototype in ram without flashing)
  • generic driver layer
  • get ethernet running / usb gadget mode for raspberry pi zero
  • sdcard I/O
  • signal handling
  • spi and i2c examples
  • ...

David Welch´s experiments years ago saved me some time in figuring out 'bcm2835-details' in cases the datasheet lacks some information or was simply wrong (no official erratasheet out there...). If you like to look into the datasheet consult this before: bcm2835 errata

联系我们 contact @ memedata.com