Skip to content

modm: a barebone embedded library generator

modm (pronounced like dial-up "modem") is a toolbox for building custom C++17 libraries tailored to your embedded device. modm generates startup code, HALs and their implementations, communication protocols, drivers for external devices, BSPs, etc… in a modular, customizable process that you can fine-tune to your needs.

This project also has a technical blog to document larger design concepts.

modm is optimized for the harsh requirements of the Eurobot competition, where our robots need to run reliably and completely autonomously for the game's 100 second duration. Our robots contain a lot of different microcontrollers, some without a lot of resources, so modm needs to fulfill a diverse set of objectives, like small code size with small memory consumption, predictable program flow, extreme portability.

The library source code is licensed as MPLv2 with any external source code under compatible licenses (BSD, Apache2, MIT). So feel free to fork this project and adapt it to your needs. The only thing we ask of you is to contribute your changes back so everyone can benefit.

Please clone modm recursively, you need all the submodules:

git clone --recurse-submodules https://github.com/modm-io/modm.git

Features

  • Efficient and fast object-oriented C++17 API.
  • Support for hundreds of AVR and ARM Cortex-M microcontrollers from Atmel and ST.
  • Build system agnostic: Choose SCons, CMake or use your own.
  • Data-driven, target-specific HAL generation using the lbuild engine.
  • No memory allocations in HAL with very low overall RAM consumption.
  • Highly-configurable modules with sensible defaults and lots of documentation.
  • Cross platform peripheral interfaces incl. bit banging:
    • GPIO and GPIO expanders.
    • ADC and Analog.
    • UART, I2C, SPI, CAN.
  • Interfaces and drivers for many external I2C and SPI sensors and devices.
  • Debug/logging system with IOStream and printf interface.
  • Lightweight, stackless threads and resumable functions using cooperative multitasking.
  • Functional (partial) libstdc++ implementation for AVRs.
  • Integration of useful third-party software: FreeRTOS, ROSserial, CMSIS-DSP.
  • Useful filter, interpolation and geometric algorithms.
  • Lightweight unit testing system (suitable for AVRs).
  • Hundreds of tests to ensure correct functionality.

Targets

modm can generate code for 78 AVR and 958 STM32 devices, however, there are different levels of support and testing.

Device Family Support Device Family Support Device Family Support
AVR ★★★ STM32F2 ★★★ STM32F7 ★★★★
STM32F0 ★★★★ STM32F3 ★★★★★ STM32L4 ★★★★
STM32F1 ★★★★ STM32F4 ★★★★★ STM32G0 ★★★★

All of these targets are compiling and booting correctly (★) and have GPIO and UART working (★★). Most targets have support for basic peripherals, like I2C, SPI and ADC (★★★) as well as complicated peripherals, like Timers, CAN and external memory (★★★★). We also use a few targets in everyday development, which are very well tested (★★★★★).

We are only a small team of developers and are limited in the amount of targets we can support and test in hardware. We have prepared, but currently not finished support for STM32F2, STM32L0 and STM32L1. Open an issue to ask if your specific target is supported out-of-the-box and what you can do if it's not.

Boards

We have out-of-box support for several development boards including documentation.

AL-AVREB-CAN Arduino NANO Arduino UNO Black Pill
Blue Pill DISCO-F051R8 DISCO-F072RB DISCO-F100RB
DISCO-F303VC DISCO-F407VG DISCO-F429ZI DISCO-F469NI
DISCO-F746NG DISCO-F769NI DISCO-L476VG NUCLEO-F031K6
NUCLEO-F042K6 NUCLEO-F103RB NUCLEO-F303K8 NUCLEO-F401RE
NUCLEO-F411RE NUCLEO-F429ZI NUCLEO-F446RE NUCLEO-G071RB
NUCLEO-L432KC NUCLEO-L476RG OLIMEXINO-STM32 STM32F030F4P6-DEMO

Drivers

We also have a number of completely target-independent drivers for external devices connected via I2C, SPI, UART, BitBang, etc. Most of these also give you access to the entire device so you can easily configure them for you specific needs.

AD7280A AD7928 ADNS9800 ADS7843 AMS5915 APA102
SPI-FLASH BME280 BMP085 BNO055 DRV832X DS1302
DS1631 DS18B20 EA-DOG FT245 FT6X06 HCLAx
HD44780 HMC58x HMC6343 I2C-EEPROM ITG3200 L3GD20
LAWICEL LIS302DL LIS3DSH LM75 LSM303A LTC2984
MAX6966 MAX7219 MCP23X17 MCP2515 NOKIA5110 NRF24
TFT-DISPLAY PAT9125EL PCA8574 PCA9535 PCA9548A PCA9685
SIEMENS-S65 SIEMENS-S75 SK6812 SSD1306 TCS3414 TCS3472
TLC594X TMP102 TMP175 VL53L0 VL6180 WS2812

Examples

We have a huge number of examples which are always up-to-date and compilable as enforced by our CI.

AVR: 1-wire/ds18b20 AVR: adc/basic
AVR: adc/oversample AVR: app_can2usb
AVR: assert AVR: block_device_mirror
AVR: can/mcp2515 AVR: can/mcp2515_uart
AVR: display/dogm128/benchmark AVR: display/dogm128/caged_ball
AVR: display/dogm128/draw AVR: display/dogm128/image
AVR: display/dogm128/text AVR: display/dogm128/touch
AVR: display/dogm132 AVR: display/dogm163
AVR: display/hd44780 AVR: display/siemens_s65
AVR: flash AVR: gpio/basic
AVR: gpio/blinking AVR: gpio/button_group
AVR: logger AVR: ports
AVR: protothread AVR: pwm/pca9685
AVR: sab/master AVR: sab/slave
AVR: timeout AVR: uart/basic
AVR: uart/basic_mega8 AVR: uart/extended
AVR: xpcc/receiver AVR: xpcc/sender
Arduino UNO: basic/analog_read_serial Arduino UNO: basic/blink
Arduino UNO: basic/digital_read_serial Arduino UNO: basic/read_analog_voltage
Generic: blinky Generic: i2c_multiplex
Generic: resumable Generic: ros/can_bridge
Generic: ros/environment Generic: ros/sub_pub
Generic: rtc_ds1302 Linux: assert
Linux: block_device/file Linux: block_device/mirror
Linux: block_device/ram Linux: build_info
Linux: can_debugger Linux: git
Linux: logger Linux: printf
Linux: serial_interface Linux: static_serial_interface
Linux: threads Linux: xpcc/basic
NUCLEO-F031K6: blink NUCLEO-F031K6: sk6812
NUCLEO-F042K6: adc NUCLEO-F042K6: blink
NUCLEO-F103RB: blink NUCLEO-F103RB: hard_fault
NUCLEO-F103RB: itm NUCLEO-F103RB: rtos
NUCLEO-F103RB: undefined_irq NUCLEO-F303K8: blink
NUCLEO-F303K8: rtos NUCLEO-F401RE: blink
NUCLEO-F401RE: distance_vl53l0 NUCLEO-F411RE: blink
NUCLEO-F411RE: imu_bno055 NUCLEO-F411RE: radio/nrf24-basic-comm
NUCLEO-F411RE: radio/nrf24-data NUCLEO-F411RE: radio/nrf24-phy-test
NUCLEO-F411RE: radio/nrf24-scanner NUCLEO-F411RE: rtos
NUCLEO-F411RE: ws2812b NUCLEO-F429ZI: blink
NUCLEO-F429ZI: cmsis_dsp/class_marks NUCLEO-F429ZI: cmsis_dsp/convolution
NUCLEO-F429ZI: cmsis_dsp/dotproduct NUCLEO-F429ZI: cmsis_dsp/fft_bin
NUCLEO-F429ZI: cmsis_dsp/fir NUCLEO-F429ZI: cmsis_dsp/graphic_equalizer
NUCLEO-F429ZI: cmsis_dsp/linear_interp NUCLEO-F429ZI: cmsis_dsp/matrix
NUCLEO-F429ZI: cmsis_dsp/signal_converge NUCLEO-F429ZI: cmsis_dsp/sin_cos
NUCLEO-F429ZI: cmsis_dsp/variance NUCLEO-F429ZI: pat9125el
NUCLEO-F429ZI: spi_flash NUCLEO-F446RE: blink
NUCLEO-G071RB: apa102 NUCLEO-G071RB: blink
NUCLEO-G071RB: rtos NUCLEO-L432KC: blink
NUCLEO-L432KC: comp NUCLEO-L432KC: gyroscope
NUCLEO-L432KC: pwm NUCLEO-L432KC: pwm_advanced
NUCLEO-L432KC: uart_spi NUCLEO-L476RG: adc
NUCLEO-L476RG: blink NUCLEO-L476RG: i2c_test
OLIMEXINO-STM32: blink STM32F0-DISCOVERY: blink
STM32F0-DISCOVERY: logger STM32F030F4P6-DEMO-BOARD: blink
STM32F072-DISCOVERY: blink STM32F072-DISCOVERY: can
STM32F072-DISCOVERY: hard_fault STM32F072-DISCOVERY: rotation
STM32F072-DISCOVERY: tmp102 STM32F072-DISCOVERY: uart
STM32F072-DISCOVERY: unaligned_access STM32F1-DISCOVERY: blink
STM32F1-DISCOVERY: logger STM32F103C8T6-Black Pill: blink
STM32F103C8T6-Blue Pill: adns_9800 STM32F103C8T6-Blue Pill: blink
STM32F103C8T6-Blue Pill: can STM32F103C8T6-Blue Pill: environment
STM32F103C8T6-Blue Pill: logger STM32F103C8T6-Blue Pill: tlc594x
STM32F3-DISCOVERY: accelerometer STM32F3-DISCOVERY: adc/continous
STM32F3-DISCOVERY: adc/interrupt STM32F3-DISCOVERY: adc/simple
STM32F3-DISCOVERY: blink STM32F3-DISCOVERY: can
STM32F3-DISCOVERY: comp STM32F3-DISCOVERY: ft245
STM32F3-DISCOVERY: gdb STM32F3-DISCOVERY: rotation
STM32F3-DISCOVERY: timer/basic STM32F3-DISCOVERY: uart/hal
STM32F3-DISCOVERY: uart/logger STM32F4-DISCOVERY: accelerometer
STM32F4-DISCOVERY: adc/interrupt STM32F4-DISCOVERY: adc/oversample
STM32F4-DISCOVERY: adc/simple STM32F4-DISCOVERY: app_uart_sniffer
STM32F4-DISCOVERY: barometer_bmp085_bmp180 STM32F4-DISCOVERY: blink
STM32F4-DISCOVERY: can STM32F4-DISCOVERY: can2
STM32F4-DISCOVERY: colour_tcs3414 STM32F4-DISCOVERY: display/hd44780
STM32F4-DISCOVERY: display/nokia_5110 STM32F4-DISCOVERY: display/ssd1306
STM32F4-DISCOVERY: distance_vl6180 STM32F4-DISCOVERY: exti
STM32F4-DISCOVERY: fpu STM32F4-DISCOVERY: fsmc
STM32F4-DISCOVERY: led_matrix_display STM32F4-DISCOVERY: open407v-d/gui
STM32F4-DISCOVERY: open407v-d/touchscreen STM32F4-DISCOVERY: pressure_ams5915
STM32F4-DISCOVERY: protothreads STM32F4-DISCOVERY: sab2
STM32F4-DISCOVERY: spi STM32F4-DISCOVERY: temperature_ltc2984
STM32F4-DISCOVERY: timer STM32F4-DISCOVERY: timer_test
STM32F4-DISCOVERY: uart STM32F4-DISCOVERY: uart_spi
STM32F429-DISCOVERY: blink STM32F429-DISCOVERY: logger
STM32F469-DISCOVERY: assert STM32F469-DISCOVERY: blink
STM32F469-DISCOVERY: can STM32F469-DISCOVERY: display
STM32F469-DISCOVERY: game_of_life STM32F469-DISCOVERY: hard_fault
STM32F469-DISCOVERY: ports STM32F469-DISCOVERY: tlsf-allocator
STM32F469-DISCOVERY: touchscreen STM32F746G-DISCOVERY: adc_ad7928
STM32F746G-DISCOVERY: blink STM32F746G-DISCOVERY: rtos
STM32F746G-DISCOVERY: tmp102 STM32F769I-DISCOVERY: blink
STM32L476-DISCOVERY: blink Windows: build_info
ZMQ: 1_stm32 ZMQ: 2_zmq_gateway
ZMQ: 3_zmq_app ZMQ: 4_zmq_backtoback