Hexabitz communication backend is based on a custom messaging protocol documented here and DMA streams documented here. Each module port is configured by default in messaging mode. Messages are continuously received in circular buffers (UARTRxBuf[i]) via M messaging DMAs where M is number of module ports. Messaging DMAs work continuously on a byte-by-byte basis and if the circular buffer is full, it cycles back to the beginning after raising a flag. Each messaging DMA (msgRxDMA[i]) transfers bytes received at its related UART port to the appropriate circular buffer so that the module can receive messages on all its ports at the same time.
The backend task (BackEndTask()) runs every RTOS cycle and scans through all circular buffers looking for messages or CLI commands. If a valid message delimiter is found, the parser extracts the message and verifies its integrity with the CRC8 checksum. If the message is valid, it is routed to one of the module messaging tasks (PxMessagingTask()). If a CLI delimiter is received (0xD or ENTER key), the CLI task (prvCLITask()) is activated to parse the circular buffer one character at a time.
Each module port has its own messaging task (PxMessagingTask()) that gets activated by the RTOS scheduler when a valid message is received in the backend task. The message is copied to cMessage array to be processed and its location in the circular buffer is cleared. Inside the port messaging task, message header is parsed and if message code is a BOS message, its payload is parsed and processed by the appropriate instructions and then task yields control to the scheduler. If message code is a module message, it is routed to module messaging parser (Module_MessagingTask()) to execute the appropriate instructions and return back to the port messaging task to yield control to the scheduler. Note that although messaging DMAs transfer incoming messages simultaneously, port messaging tasks can only execute serially-one on each RTOS cycle.
- Source module builds a message in the form shown above.
- Source sends the message through the UART port.
- Destination receives the entire message in the receive circular buffer (UARTRxBuf).
- The backend task regularly parses circular buffers and notifies the appropriate messaging task when a message is received correctly. Check out this article for more details on Hexabitz backend.
- Inside the messaging task (PxMessagingTask), messages are parsed to read source, destination and code bytes. Received message length is checked against the Length byte.
- If the message is a transit message, it’ll be forwarded directly. If it’s a broadcast message, it will be broadcasted and then processed.
- Messages are processed according to their message codes. After that buffers are cleared and receive interrupt is activated on this port again.
- Message response and TRACE flags are verified to generate the appropriate response.
- If the message is long, the longMessage flag is activated and can be used to concatenate consecutive payloads before processing them.