Building a Scalable PRU Processing Chain | Stage 1: Real-Time PRU Ingestion Baseline

This post outlines Stage 1 of a scalable, clock-driven 8-bit parallel data transport platform designed to establish high-throughput, multi-device processing pipelines using PRU subsystem nodes.

Instead of building a rigid, board-specific deployment, this architecture abstracts the data source entirely. Because data ingestion is strictly driven by an external hardware clock line (CLK), the transport layer handles raw data streams identically, whether interfacing a test transmitter node, an OV5640 camera, or an upstream processing unit.

The primary objective of this stage is to validate the underlying synchronous 8-bit parallel bus mechanics, firmware loop limits, and driver ring-buffer synchronization under a continuous, real-time workload.

Hardware Implementation:
The physical test bench routes the parallel bus pins across the expansion headers of two independent BeagleBoard hardware nodes:

  • Transmitter Node: BeagleBone Black (BBB) exporting pre-selected, pre-encoded reference payload blocks over designated P8/P9 expansion headers.
  • Receiver Node: PocketBeagle 2 (PB2) sampling the bus over matching P1/P2 expansion headers.
  • Attenuation Matrix: A pin-correct breadboard circuit coupling the nodes via a series of 110-Ohm protection resistors. [1]

Signal timing evaluation using a ZOYI ZT703 handheld oscilloscope shows expected edge attenuation at 30 MHz. Rather than square waves, the clock line presents consistent high-frequency spikes. The receiver core relies on these sharp rising edges for precise state tracking.

Workload Partitioning and Firmware Design:
To guarantee a reliable 35ns per byte capture window without data corruption or loss of clock synchronization, the system split separates critical timing logic from OS memory management:

  • Bare-Metal PRU Firmware: Written entirely in optimized C using the TI PRU optimizing compiler structures. The execution loop handles strict, cycle-accurate polling of the external clock line to sample input registers (R31 tracking) instantly on the rising edge. Loop unrolling and minimal variable overhead prevent compiler anomalies, achieving strict deterministic timing boundaries.
  • Linux Kernel Driver: A native kernel module executing on the host core to manage a shared-memory ring buffer. The driver utilizes atomic context tracking structures (CTX) to synchronize memory read windows with the active PRU write pointers. This kernel-space abstraction completely bypasses user-space filesystem latencies and scheduling overhead, eliminating context-switch delays and cache misses.

Payload Integrity and Verification:
System performance is mathematically verified through a complete cryptographic loop. A unique SHA-256 checksum is calculated across the baseline payload on the BeagleBone Black. The PocketBeagle 2 captures the 29 MHz hardware stream silently to protect timing margins, flushes the raw binary bytes to local storage, and parses unaligned asynchronous frame boundaries using a host-side Python script to drop partial leading or trailing data fragments. Generating an identical SHA-256 hash on the recovered data proves a 100% bit-perfect transmission with zero dropped clock pulses.

Platform Roadmap Trajectory:
This layout operates as a functional stepping stone for modular processing chains:

  • Stage 2: Direct 8-Bit Camera Ingestion (Integrating an OV5640 camera module directly into the clock-driven PB2 PRU receiver interface).
  • Stage 3: Piped Multi-Node Processing Chains (Expanding the firmware and kernel driver framework across multi-core industrial SoCs like the AM62x, AM65x, or AM67x platforms to pipe, process, and transmit data sequentially via NEON and PRU coprocessors). [1, 2]

A detailed overview video documenting the physical wiring layouts, driver execution logs, and side-by-side verification baselines has been uploaded to YouTube.

Video Link: https://www.youtube.com/watch?v=xOOTbS9ZcHo&t=7s

The project repository is currently in a private deployment phase. However, access to the low-level C codebase, custom kernel driver modules, and schematic layouts can be shared with community members, developers, or engineering teams upon request for technical review.

Feedback on optimizing the PRU C loop structure further or handling higher frequency bus attenuation on the expansion headers is highly welcome.

The SHA check is a nice sanity check, though the real fun starts once frame boundaries and camera blanking get mixed into that raw clock stream. 29 MHz on a breadboard is already plenty spicy :slight_smile:

Thanks for the comment! I was honestly a little surprised myself that ~29 MHz worked over that breadboard setup. :slight_smile: Some credit definitely goes to the TI engineers for making the PRU I/O quite forgiving.

You are absolutely right about the camera framing problem. The broader goal of this project is to build a data-processing pipeline between PRU-capable nodes. The BBB now, and the camera in the next stage, are primarily ways of providing real, verifiable data that can be ingested, processed, and eventually passed to another node.

For the OV5640 I’m considering two approaches. The straightforward one is to capture D[7:0] together with HREF (HS on my camera module) and VSYNC (VS on the module), synchronized by PCLK — effectively 10 input bits plus the clock.

The alternative is to use the OV5640’s JPEG output, ingest the 8-bit + PCLK stream, using existing code and recover individual images after transferring the data to DDR. That keeps the acquisition layer more payload-agnostic, but requires additional parsing. I’d rather spend those processing resources on something more interesting — AI/OCR, face or gesture recognition, or perhaps a stepper-motor control algorithm. I haven’t decided yet.

I’ve already drawn up the next OV5640 setup — and yes, another breadboard. :slight_smile: PB2 exposes the signals through its expansion headers rather than a dedicated camera connector, so a breadboard is the practical option for this prototype.

Right now I’m stuck on something much less exciting that appears to be a Device Tree/pinmux issue. I put PT and RT on P1.03 and P2.03 respectively. P2.03 shows up in gpioinfo, but P1.03 doesn’t, so that’s what I’m banging my head against at the moment. :slight_smile:

P.S. Written with some help from AI — my English isn’t quite this polished yet. :slightly_smiling_face: