111 lines
3.1 KiB
Markdown
111 lines
3.1 KiB
Markdown
# ModTOS
|
|
|
|
**Modbus RTU Driver for STM32 + FreeRTOS**
|
|
*Interrupt driven frame handling with RS485 GPIO direction control*
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
**ModTOS** is a lightweight dependency free Modbus RTU slave implementation designed for STM32 microcontrollers running FreeRTOS. It acts as a cooperative background task minimizing CPU load and avoiding interference with timing critical logic.
|
|
|
|
The driver leverages **UART interrupt with idle line detection** to capture Modbus RTU frames without polling. RS485 direction is controlled via GPIO enabling half duplex communication commonly found in industrial systems.
|
|
|
|
ModTOS exposes a flat holding register table accessible through standard Modbus function codes `0x03` Read Holding Registers and `0x10` Write Multiple Holding Registers.
|
|
|
|
---
|
|
|
|
## Features
|
|
|
|
- Modbus RTU Slave one unit ID per UART
|
|
- **Function Code 0x03** Read Holding Registers
|
|
- **Function Code 0x10** Write Multiple Holding Registers
|
|
- CRC 16 Modbus validation on all frames
|
|
- Modbus Exception Handling:
|
|
- `0x01` ILLEGAL_FUNCTION
|
|
- `0x02` ILLEGAL_DATA_ADDRESS
|
|
- `0x03` ILLEGAL_DATA_VALUE
|
|
- Flat register buffer 128 x uint16_t
|
|
- Task based integration with FreeRTOS
|
|
- Zero dynamic memory allocation
|
|
- Uses **UART Receive to Idle** mode no polling
|
|
- Portable to bare metal & polling environments with minimal changes
|
|
|
|
---
|
|
|
|
## High Level Design
|
|
|
|
### 1 Global Modbus Register Table
|
|
- Represents Modbus holding registers starting at address 0
|
|
- Accessible directly by application code or via Modbus transactions
|
|
|
|
### 2 UART RX & TX Buffers
|
|
- `request_frame` holds raw Modbus RTU request bytes
|
|
- `response_frame` used to construct replies
|
|
- Both statically sized for worst case message sizes
|
|
|
|
### 3 RS485 Direction Control
|
|
- DE and RE pin sets transceiver mode:
|
|
- **RX default**
|
|
- **TX only during response transmission**
|
|
|
|
---
|
|
|
|
## Execution Flow
|
|
|
|
### 1 Initialization
|
|
- Clears buffers
|
|
- Sets RS485 to **RX mode**
|
|
- Enables UART in **idle line receive** mode
|
|
|
|
### 2 Receiving a Frame
|
|
- UART receives bytes into `request_frame`
|
|
- Idle line detection triggers reception complete callback
|
|
- Application must implement callback to forward the frame for parsing
|
|
|
|
### 3 Processing the Request
|
|
- Frame validation:
|
|
- Minimum length
|
|
- Slave ID match
|
|
- CRC 16 check
|
|
- Dispatch to appropriate handler:
|
|
- `0x03` Read holding registers
|
|
- `0x10` Write multiple holding registers
|
|
- Others Modbus exception
|
|
|
|
---
|
|
|
|
## Function Code Handlers
|
|
|
|
### FC 0x03 Read Holding Registers
|
|
- Parses `startAddr` and `numRegs`
|
|
- Validates bounds
|
|
- Builds response:
|
|
- Slave ID
|
|
- Function code
|
|
- Byte count
|
|
- Register values High byte Low byte per register
|
|
- CRC
|
|
|
|
### FC 0x10 Write Multiple Holding Registers
|
|
- Parses `startAddr` `numRegs` and `byteCount`
|
|
- Validates range and byte consistency
|
|
- Writes values to register table
|
|
- Responds with echo:
|
|
- Slave ID
|
|
- Function code
|
|
- Start address
|
|
- Quantity
|
|
|
|
---
|
|
|
|
## Response Transmission
|
|
|
|
- Appends CRC to `response_frame`
|
|
- Sets RS485 to **TX mode**
|
|
- Sends frame via **blocking UART**
|
|
- Switches RS485 back to **RX mode**
|
|
- TX timeout currently fixed at **100 ms**
|
|
|
|
---
|