week_4 from bringup to RTEMS Driver framework
Overview
This week, I continued developing the AM335x D-CAN driver on BeagleBone Black. The focus was to move from a simple register-level test toward a cleaner RTEMS CAN framework driver. Significant progress was made in initialization, bit timing support, register abstraction, interrupt handling, and worker task design.
Driver Initialization Improvements
Several improvements were made to the initialization flow:
-
Created and initialized the basic RTEMS CAN structures:
chipinternalqends_dev
-
Added worker task creation during initialization.
-
Installed the DCAN interrupt handler.
-
Cleaned up the startup sequence.
-
Improved the overall driver structure to better follow existing RTEMS CAN drivers.
RTEMS CAN Bit Timing Support
Previously, the bit timing parameters were hard-coded.
This week, the driver was converted to use the RTEMS CAN framework:
bitrate
↓
rtems_can_bitrate2bittiming()
↓
bittiming structure
↓
dcan_set_bittiming()
↓
DCAN BTR register
Completed
- Added
dcan_calc_and_set_bittiming(). - Used
rtems_can_bitrate2bittiming()to calculate CAN timing parameters. - Programmed the BTR register based on the calculated values.
- Removed hard-coded timing values.
This makes the driver more flexible and consistent with other RTEMS CAN drivers.
Register Access Cleanup
Previously, many registers were accessed directly through:
REG32(...)
These accesses were replaced with:
dcan_read_reg()
dcan_write_reg()
Benefits
- Cleaner code.
- Better encapsulation.
- Easier debugging.
- Less hardware-specific code scattered throughout the driver.
Removing Global Variables
Private driver information is now stored inside:
chip->internal
instead of using global variables.
Benefits
- Better modularity.
- Easier future expansion.
- Similar structure to SJA1000 and CTU CAN FD drivers.
Header and Register File Cleanup
Several code organization improvements were made:
- Reorganized register definitions.
- Cleaned up
dcan_regs.h. - Reduced dependency on legacy TI header files.
- Removed unnecessary include files.
- Began moving AM335x-specific definitions into local driver files.
- Simplified the code structure.
Interrupt Handling
Following the mentor's recommendation, I studied the CTU CAN FD driver instead of SJA1000 because its interrupt architecture is simpler and closer to D-CAN.
Interrupt Flow
Hardware Interrupt
↓
ISR
↓
Disable interrupt
↓
Post worker semaphore
↓
Return immediately
The interrupt service routine remains short and avoids heavy processing.
Worker Flow
Worker wakes up
↓
Process interrupt source
↓
Read message object
↓
Deliver frame
↓
Re-enable interrupt
This design separates interrupt handling from frame processing and follows the CTU CAN FD style.
Worker Task Skeleton
A real RTEMS worker task was implemented.
Worker Responsibilities
- Wait on a binary semaphore.
- Process pending interrupts.
- Read received message objects.
- Deliver frames to the RTEMS CAN queue.
- Re-enable interrupts.
This replaces the earlier polling-based "worker-like" implementation.
Receive Path Validation
Successfully verified the complete receive path:
Linux SocketCAN
↓
CAN bus
↓
BBB DCAN1
↓
Hardware interrupt
↓
ISR
↓
Worker task
↓
Read RX message object
↓
RTEMS CAN queue
↓
RX callback
Multiple CAN frames were successfully received.
Example:
RX ID=0x123 DLC=8 DATA=00 99 88 77 66 55 44 33
This confirms that the interrupt-driven receive mechanism is functioning correctly.
Current Status
Completed
- Driver initialization skeleton
- RTEMS CAN bit timing support
- Register read/write abstraction
- Remove global variables
- Register file cleanup
- Worker task skeleton
- Interrupt handler installation
- Interrupt-driven receive mechanism
- Multiple-frame reception
- Frame delivery to RTEMS CAN queue
- Debug callback verification
Architecture After This Week
Linux SocketCAN
↓
CAN bus
↓
DCAN Controller
↓
Hardware Interrupt
↓
ISR
(disable interrupt + post semaphore)
↓
Worker Task
↓
dcan_process_interrupts()
↓
Read RX message object
↓
RTEMS CAN Queue
↓
Application / Callback
Next Steps
Code Cleanup
- Remove the old polling-based
worker_like()implementation. - Continue separating AM335x-specific definitions.
- Further simplify interrupt helper functions.
RTEMS CAN Queue Study
- Study
can-queue.c. - Understand queue edges and queue slots.
- Learn how applications read frames from the queue.
Application-Level Integration
Implement a queue-based application read path:
Hardware
↓
Interrupt
↓
Worker
↓
RTEMS CAN Queue
↓
Application read()
Transmit Path
Begin TX queue integration:
Application
↓
RTEMS CAN Queue
↓
TX buffer
↓
DCAN Message Object
↓
CAN bus
Long-Term Goal
Continue refining the driver toward full RTEMS CAN framework support and eventual upstream submission.