Skip to content

mzaib1012/circular-buffer-serial-parser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚀 Non-Blocking Embedded Architecture Backed by a Lock-Free FIFO Circular Queue & CRC-16 Integrity


📑 Executive Summary

In high-throughput embedded systems (e.g., automotive CAN/UART nodes, telemetry links, industrial Modbus), blocking communication routines introduce catastrophic latency. If a microcontroller stalls inside a busy-wait loop waiting for an entire packet to land, it misses critical tasks like sensor sampling, motor control loops, or actuation sequences.

This repository implements a production-ready, ultra-efficient, non-blocking serial packet parser written in C99. The architecture enforces a strict decoupling of data ingestion from data processing:

  1. Data Ingestion (Background): A simulated Hardware Interrupt Service Routine (ISR) intercepts incoming serial bytes and pushes them onto a thread-safe, power-of-two sized FIFO Circular Buffer (Ring Buffer) with zero processing overhead.
  2. Data Parsing (Foreground): The main application loop calls an asynchronous Finite State Machine (FSM) Parser that dequeues bytes one by one when CPU cycles are available, processes the frame protocol boundaries, and validates payload integrity using a CRC-16-CCITT mathematical checksum.

🛠️ System Architecture & Theory of Operation

1. Lock-Free Thread-Safe Circular Buffer

The core data structure is a fixed-size ring buffer utilizing an array and tracking indices for head and tail.

  • The volatile Safeguard: The tracking indices are declared with the volatile qualifier to prevent compiler registers from caching values, forcing memory re-evaluation because the head changes context asynchronously within an ISR.
  • Lock-Free Concurrency: Because the ISR only writes to the head and increments it, and the main thread only reads from the tail and increments it, the structure remains inherently thread-safe without the use of heavy mutexes or disabling global interrupts, keeping critical sections lightning fast.

2. Finite State Machine (FSM) Packet Processing

The protocol frame format is explicitly defined to guarantee data framing and boundary alignment:

+--------------+------------------+-----------------------+--------------------+--------------+
| SOF (1 Byte) |  Length (1 Byte) |  Payload (N Bytes)    |   CRC-16 (2 Bytes) | EOF (1 Byte) |
|    0x02      |   Length of Data |   Actual Serial Data  |  CCITT Checksum    |    0x03      |
+--------------+------------------+-----------------------+--------------------+--------------+

The parser iterates through a non-blocking execution cycle tracking these states:

  • STATE_WAIT_SOF: Discards all line noise or stray bytes until a valid Start of Frame (0x02) is identified.
  • STATE_GET_LENGTH: Stores the dynamic payload size and checks it against maximum hardware buffer bounds to prevent buffer overflow vulnerabilities.
  • STATE_GET_PAYLOAD: Streams incoming bytes into an internal packet buffer without blocking the runtime engine.
  • STATE_GET_CRC_HIGH / STATE_GET_CRC_LOW: Reconstructs the 16-bit incoming network byte-ordered checksum.
  • STATE_WAIT_EOF: Validates the End of Frame byte boundary (0x03). If validated, it runs the mathematical CRC calculation over the accumulated payload. If the checksum matches, the data packet is dispatched to the system application layer.

💾 Core Logic Code Implementation

Data Structure Blueprint (include/ring_buffer.h)

#ifndef RING_BUFFER_H
#define RING_BUFFER_H

#include <stdint.h>
#include <stdbool.h>

#define RING_BUFFER_SIZE 128 // Must be power of 2 for fast optimization

typedef struct {
    uint8_t buffer[RING_BUFFER_SIZE];
    volatile uint16_t head;  // Handled by incoming Hardware ISR
    volatile uint16_t tail;  // Handled by main foreground parsing loop
} ring_buffer_t;

void ring_buffer_init(ring_buffer_t *rb);
bool ring_buffer_is_full(const ring_buffer_t *rb);
bool ring_buffer_is_empty(const ring_buffer_t *rb);
bool ring_buffer_queue(ring_buffer_t *rb, uint8_t byte);
bool ring_buffer_dequeue(ring_buffer_t *rb, uint8_t *byte);

#endif

Mathematical Frame Validation (src/parser.c snippet)

// Standard CRC-16-CCITT implementation using the 0x1021 generator polynomial
uint16_t crc16_ccitt(const uint8_t *data, uint16_t length) {
    uint16_t crc = 0xFFFF; // Preset initial value
    for (uint16_t i = 0; i < length; i++) {
        crc ^= (uint16_t)data[i] << 8;
        for (uint8_t bit = 0; bit < 8; bit++) {
            if (crc & 0x8000) {
                crc = (crc << 1) ^ 0x1021;
            } else {
                crc <<= 1;
            }
        }
    }
    return crc;
}

📈 Verification Test Suite & Output Results

The system is built alongside a behavioral validation test bench in src/main.c. It injects simulated raw byte arrays mimicking normal operations and transmission interference:

  1. Test Case 1 (Nominal Operation): Transmits a clean packet payload [0x41, 0x42, 0x43] packed with matching boundaries and correct CRC calculations.
  2. Test Case 2 (Line Noise / Data Corruption): Simulates electronic interference over a physical line by altering data contents directly inside the ring buffer memory space before processing.

Cloud Console Execution Logs

When evaluated in a cloud Linux environment via GCC, the runtime execution provides these metrics:

Embedded Serial Parser Simulation Initialized.

--- Simulating Incoming Serial Transmission ---
[PARSER SUCCESS] Valid Packet Received! Length: 3

--- Simulating Incoming Serial Transmission ---
[PARSER ERROR] CRC Mismatch! Expected: 0x4B3A, Got: 0x5A42

The logs prove that the state machine intercepts data corruption errors, drops the invalid frame packet, resets its internal registers instantly, and prepares to read the next transmission string without blocking application performance.


📂 Repository File Tree

circular-buffer-serial-parser/
│
├── src/                      # Implementation source files (.c)
│   ├── main.c                # Behavioral simulation test bench
│   ├── ring_buffer.c         # Circular queue read/write logic
│   └── parser.c              # Finite State Machine & CRC-16 verification
│
├── include/                  # Modular structure interface headers (.h)
│   ├── ring_buffer.h         # Ring buffer configuration macros and type structures
│   └── parser.h              # Parser operational states and protocol tokens
│
├── .gitignore                # Tells git which compiled binaries/junk files to ignore
├── LICENSE                   # Open-source MIT software license
└── README.md                 # Production-grade system documentation

About

An ultra-efficient, interrupt-driven, non-blocking serial frame packet parser utilizing a thread-safe FIFO circular queue and CRC-16 checksums in C.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages