This project demonstrates a robust embedded architecture using FreeRTOS and the Active Object pattern. The core focus was to create a "crash-proof" sensor driver that can recover from I2C bus lockups caused by DC motor electrical noise (EMI) without resetting the entire microcontroller.
It serves as a study in concurrency, hardware abstraction, and fault-tolerance on the RISC-V architecture.
- MCU: Sipeed Longan Nano (GD32VF103CBT6 - RISC-V)
- Sensor: LIS2DW12 3-Axis Accelerometer
- Actuator: Standard DC Motor via DRV8833 H-Bridge
- Wiring: No custom PCB was used; modules are connected via breadboard for prototyping.
| Module | Pin | Function |
|---|---|---|
| I2C sensor | PB6 | SCL |
| PB7 | SDA | |
| Motor Driver | PB0 | PWM (Timer 2 CH2) |
| PB1 | PWM (Timer 2 CH3) | |
| Debug | PC13 | Status LED |
The system runs on FreeRTOS with two primary Active Objects (Tasks) communicating via a thread-safe Queue:
- Sensor Actor: Polls the accelerometer every 20ms and converts raw tilt vectors into velocity commands.
- Motor Actor: Receives commands and updates the PWM duty cycle. It implements a failsafe timeout: if no new data arrives for >100ms (due to sensor failure), the motor performs an emergency stop.
The LIS2DW12 driver was written from scratch to handle I2C Bus Lockups. Standard drivers often hang in infinite while loops if a motor spark corrupts the clock line. This driver uses macro-based timeouts to detect these hangs and trigger a peripheral reset.
Key Implementation Details:
#define I2C_TIMEOUT_CYCLES 100000
/* Robust Wait Macro: Returns error (-1) instead of hanging forever */
#define I2C_WAIT_FLAG(instance, flag) \
{ \
volatile int32_t timeout = I2C_TIMEOUT_CYCLES; \
while (!i2c_flag_get(instance, flag)) { \
if (--timeout <= 0) return -1; /* ABORT TRANSACTION */ \
} \
}If I2C_WAIT_FLAG returns -1, the Sensor Actor initiates a Software Reset sequence on the I2C peripheral to clear the bus and resume operation automatically.
This project uses the GD32V Linux toolchain.
- Clone repository into your projects folder.
- Put the Longan Nano into DFU Bootloader mode.
- Compile and flash:
make dfucompressed-out-tilt-motor.mp4
This video demonstrates real-time motor velocity control based on accelerometer tilt vectors.
Key Feature Showcase: Fault Injection & Recovery The video specifically highlights the system's robustness against connection failures:
- Signal Loss: The I2C lines (green wires) are physically disconnected while the motor is running.
- Failsafe Activation: The system detects the timeout immediately, triggering an Emergency Stop (Motor Speed = 0) and entering an error state (Blinking LED).
- Automatic Recovery: Upon reconnection, the driver detects the restored bus, re-initializes the sensor, and resumes normal operation without requiring a hard reset.
- Based on the open-source GD32V Examples by Linus Remahl.