Week 9 Progress Report
BSP-specific Support, Git History Cleanup, and Installed Driver Testing
Overview
This week, I mainly focused on preparing the DCAN driver for upstream review. Separation between the generic driver and the AM335x board-specific support.
I also reorganized the Git history, rebuilt RTEMS, installed the new build into a separate directory, and used the installed RTEMS environment to build my external DCAN test program.
The major work this week included:
- moving AM335x-specific initialization into the Beagle BSP
- keeping the generic DCAN driver independent from the board
- splitting one large commit into two logical commits
- creating a backup branch before changing Git history
- recovering tracked and untracked files from Git stash
- rebuilding and installing RTEMS
- verifying the installed public header and Beagle BSP files
- building the external DCAN register test program with the installed RTEMS
- testing CAN transmit and receive on the BeagleBone Black
1. Separating the Generic Driver and BSP Support
One important task this week was moving AM335x-specific initialization out of the generic DCAN driver.
Before this change, the generic driver directly handled the BeagleBone Black clock and pin configuration.
For example, the driver startup included operations similar to:
dcan1_clock_enable();
dcan1_pinmux();
These functions are specific to the AM335x processor and should not be part of a reusable DCAN controller driver.
After the refactoring, the responsibilities became:
Generic DCAN driver
- controller initialization
- message object access
- interrupt processing
- transmit and receive
- RTEMS CAN framework integration
Beagle BSP support
- AM335x DCAN1 clock setup
- AM335x pin multiplexing
- board startup initialization
The new startup flow is:
RTEMS startup
↓
bbb_drivers_initialize()
↓
rtems_am335x_dcan_initialize()
↓
dcan1_clock_enable()
↓
dcan1_pinmux()
The application still creates the generic DCAN controller later.
chip = rtems_can_dcan_initialize(
SOC_DCAN_1_REGS,
AM335X_INT_DCAN1_INT0,
24000000
);
This design keeps the generic driver independent from the AM335x platform.
2. Files Added and Modified
Generic DCAN Driver
The generic driver files are located under:
bsps/shared/dev/can/dcan/
Main implementation:
bsps/shared/dev/can/dcan/dcan.c
Register definitions:
bsps/shared/dev/can/dcan/dcan_regs.h
Public driver header:
bsps/include/dev/can/dcan.h
AM335x BSP Support
The AM335x-specific implementation was added under the Beagle BSP.
Source file:
bsps/arm/beagle/can/dcan_am335x.c
Header file:
bsps/arm/beagle/include/bsp/dcan_am335x.h
BSP Startup
The Beagle BSP startup file was modified:
bsps/arm/beagle/start/bspstart.c
The BSP now calls:
rtems_am335x_dcan_initialize();
This performs the board-specific DCAN setup during RTEMS startup.
Build System
The generic RTEMS build file was modified:
spec/build/bsps/obj.yml
The Beagle BSP build file was also modified:
spec/build/bsps/arm/beagle/obj.yml
3. Reorganizing the Merge Request
The original merge request contained one large commit:
f2d1931ce9
can/dcan: Add AM335x DCAN controller driver
This commit included both:
- generic DCAN driver code
- AM335x Beagle BSP support
Based on mentor feedback, I split the work into two logical commits.
Commit 1
83df456537
can/dcan: Add generic DCAN controller driver
This commit contains:
- generic driver source
- public driver header
- register definitions
- generic RTEMS build system changes
Files in this commit:
bsps/include/dev/can/dcan.h
bsps/shared/dev/can/dcan/dcan.c
bsps/shared/dev/can/dcan/dcan_regs.h
spec/build/bsps/obj.yml
Commit 2
ca6e1b52a3
bsps/arm/beagle: Add AM335x DCAN board support
This commit contains:
- AM335x clock setup
- pin multiplexing
- Beagle BSP startup integration
- Beagle BSP build configuration
Files in this commit:
bsps/arm/beagle/can/dcan_am335x.c
bsps/arm/beagle/include/bsp/dcan_am335x.h
bsps/arm/beagle/start/bspstart.c
spec/build/bsps/arm/beagle/obj.yml
This structure makes the merge request easier to review because the generic code and board-specific code are clearly separated.
4. Creating a Backup Branch Before Reorganizing the Commits
Before changing the Git history, I created a backup branch.
I checked out the original development branch.
git switch 5440-am335x-dcan
Then I created a new branch for the history cleanup.
git switch -c 5440-am335x-dcan-rebase
The new branch initially pointed to exactly the same commit as the original branch.
This was important because reset and rebase operations can rewrite commit history. If I made a mistake, the backup branch would still point to the original working version of the driver.
Step 1: Check the Current Branch
git branch --show-current
The development branch was:
5440-am335x-dcan-rebase
I also checked the repository status. git status. Before changing the history, I confirmed that the important work was committed or saved.
Step 2: Check the Current Commit
Checked the latest commits.
git log --oneline --decorate -5
The original driver implementation was contained in:
f2d1931ce9 can/dcan: Add AM335x DCAN controller driver
The backup branch needed to point to this commit before I changed the development branch.
Step 3: Create the Backup Branch
While staying on the development branch, I created the backup branch.
git branch backup/5440-am335x-dcan-before-rebase
This command created a new branch without switching to it.
At this point, both branch names pointed to the same commit.
5440-am335x-dcan-rebase
backup/5440-am335x-dcan-before-rebase
↓
f2d1931ce9
This allowed to safely reset and rewrite the development branch.
Step 4: Verify the Backup Branch
I checked the branch list.
git branch -vv
I also checked the latest commit of the backup branch.
git log \
--oneline \
--decorate \
backup/5440-am335x-dcan-before-rebase \
-1
The expected output was similar to:
f2d1931ce9 can/dcan: Add AM335x DCAN controller driver
Step 5: Continue on the Development Branch
The backup branch was only used as a safety reference.
I confirmed that I was still on the development branch.
git switch 5440-am335x-dcan-rebase
Then I continued with:
git stash push -u
and:
git reset --mixed upstream/main
The backup branch remained unchanged.
Why the Backup Branch Was Useful
A Git branch is a name that points to a commit.
The command:
git branch backup/5440-am335x-dcan-before-rebase
did not copy the complete repository. It created another reference to the current commit.
Before the history cleanup:
5440-am335x-dcan-rebase
backup/5440-am335x-dcan-before-rebase
│
└── f2d1931ce9
After the cleanup:
5440-am335x-dcan-rebase
│
└── ca6e1b52a3
│
└── 83df456537
│
└── upstream/main
backup/5440-am335x-dcan-before-rebase
│
└── f2d1931ce9
If the history cleanup failed, I could return to the original code with:
git switch backup/5440-am335x-dcan-before-rebase
I could also restore one file from the backup branch.
git restore \
--source=backup/5440-am335x-dcan-before-rebase \
path/to/file
I kept the backup branch after the cleanup as an additional safety copy.
5. Resetting and Recovering the Changes
After creating the backup branch, I saved the working tree.
git stash push -u
The -u option included untracked files.
Then I reset the development branch to the current upstream main branch.
git reset --mixed upstream/main
The purpose was to remove the original large commit while keeping the driver changes available as local modifications.
However, when I used:
git stash pop
Git reported conflicts because some files restored by the reset were also stored as untracked files in the stash.
To safely recover the work, I first created a temporary commit.
git add -A
git commit -m "WIP: recover DCAN changes"
Then I applied the stash again.
git stash pop
Some untracked files were stored in the third parent of the stash commit. I restored them using:
git restore \
--source='stash@{0}^3' \
--worktree \
bsps/arm/beagle/can/dcan_am335x.c \
bsps/arm/beagle/include/bsp/dcan_am335x.h
I verified the recovered files with:
git diff --exit-code 'stash@{0}^3'
After confirming that the code was recovered, I removed the temporary WIP commit.
git reset --mixed upstream/main
At this point, all driver changes were available as uncommitted changes, and I could split them into two clean commits.
6. Creating the Two New Commits
Generic Driver Commit
I added only the generic files.
git add \
bsps/include/dev/can/dcan.h \
bsps/shared/dev/can/dcan/dcan.c \
bsps/shared/dev/can/dcan/dcan_regs.h \
spec/build/bsps/obj.yml
Then I created the first commit.
git commit -s \
-m "can/dcan: Add generic DCAN controller driver"
The -s option added my Signed-off-by line.
AM335x BSP Commit
Next, I added the board-specific files.
git add \
bsps/arm/beagle/can/dcan_am335x.c \
bsps/arm/beagle/include/bsp/dcan_am335x.h \
bsps/arm/beagle/start/bspstart.c \
spec/build/bsps/arm/beagle/obj.yml
Then I created the second commit.
git commit -s \
-m "bsps/arm/beagle: Add AM335x DCAN board support"
Verify the Commit History
I checked the commits that were ahead of upstream main.
git log --oneline upstream/main..HEAD
The output showed only:
ca6e1b52a3 bsps/arm/beagle: Add AM335x DCAN board support
83df456537 can/dcan: Add generic DCAN controller driver
I also checked the working tree.
git status
The expected result was:
nothing to commit, working tree clean
7. Updating the Existing Merge Request
Because the commit history changed, I needed to update the remote branch with a force push.
I used:
git push --force-with-lease \
origin \
5440-am335x-dcan-rebase:5440-am335x-dcan
I used --force-with-lease instead of --force because it is safer.
It checks whether the remote branch changed unexpectedly before replacing its history.
After pushing, I fetched the remote branch again.
git fetch origin
Then I checked the remote merge request branch.
git log --oneline \
upstream/main..origin/5440-am335x-dcan
The output showed only the two new commits.
I also counted them.
git rev-list --count \
upstream/main..origin/5440-am335x-dcan
The result was:
2
GitLab showed additional upstream commits in the activity log because the branch had been rebased. However, the merge request itself contained only my two driver commits.
8. Building and Installing RTEMS
After finishing the refactoring and commit cleanup, I rebuilt RTEMS to verify that the new driver was correctly integrated into the build system.
First, I configured a clean RTEMS build:
./waf configure \
--prefix=$HOME/development/rtems/7-new \
--rtems-tools=$HOME/development/rtems/7-new \
--rtems-bsps=arm/beagleboneblack
Then I built and installed RTEMS.
./waf build
./waf install
The installation was placed in a separate directory (7-new) so it would not overwrite my existing RTEMS installation.
After installation, I verified that:
- the generic DCAN driver was compiled successfully
- the AM335x BSP support was included
- the public header
dcan.hwas installed - the BeagleBone Black BSP was generated correctly
Finally, I rebuilt my external DCAN test application using the installed RTEMS instead of compiling the driver source files directly. The application linked successfully and the driver worked correctly on the BeagleBone Black.
9. Keeping the DCAN Register Test Program
I kept my original DCAN register test program after the driver refactoring.
The register test is useful because it can test the hardware at a lower level before testing the complete RTEMS CAN framework.
The test program can help verify:
- DCAN clock setup
- pin multiplexing
- controller register access
- initialization mode
- bit timing configuration
- message object configuration
- TX request state
- RX new-data state
- interrupt register values
This test program is especially useful when the full CAN application does not work because it helps separate hardware problems from CAN framework problems.
10. Building the Test Program with the Installed RTEMS
After installing RTEMS under:
$HOME/development/rtems/7-new
I rebuilt the external DCAN test program using the new installation.
The important difference was that the test program no longer compiled the driver source files directly.
It did not compile:
bsps/shared/dev/can/dcan/dcan.c
or:
bsps/arm/beagle/can/dcan_am335x.c
Instead, the application used the driver that was already built into the installed RTEMS BSP libraries.
The test application included the public header:
#include <dev/can/dcan.h>
It also used the Beagle BSP definitions.
#include <bsp.h>
#include <bsp/irq.h>
The controller was created with:
chip = rtems_can_dcan_initialize(
SOC_DCAN_1_REGS,
AM335X_INT_DCAN1_INT0,
24000000
);
The application then started and registered the controller.
chip->chip_ops.start_chip(chip);
rtems_can_bus_register(chip, "dcan1");
The exact application build command depends on the test program build system.
The important point was that the application build used the installed Beagle BSP configuration from:
$HOME/development/rtems/7-new
This verified that:
- the driver was included in the installed BSP libraries
- the public header was installed
- the application could link without adding the driver source files
- the BSP-specific initialization was included automatically
11. Hardware Test Setup
The hardware test setup was:
Linux system
↓
SocketCAN
↓
CANable USB adapter
↓
CAN bus with termination
↓
BeagleBone Black DCAN1
↓
RTEMS DCAN driver
The BeagleBone Black DCAN1 pins were:
P9.24: DCAN1_TX
P9.26: DCAN1_RX
The CAN bus used two 120-ohm termination resistors.
The bitrate was:
125000 bit/s
12. Configuring Linux SocketCAN
Before testing, I configured the Linux CAN interface.
First, I disabled the interface.
sudo ip link set can0 down
Then I enabled it with the correct bitrate.
sudo ip link set can0 up type can bitrate 125000
I checked the interface configuration.
ip -details link show can0
This confirmed:
- CAN state
- bitrate
- sample point
- error counters
- controller status
13. Testing Linux-to-RTEMS Communication
To monitor CAN traffic on Linux, I used:
candump can0
Then I sent a CAN frame from Linux to the BeagleBone Black.
cansend can0 123#1122334455667788
The RTEMS test application received the frame and printed the CAN identifier, DLC, and data.
This verified:
- CANable transmission
- physical CAN bus connection
- DCAN1 receive
- RX message object configuration
- interrupt handling
- RTEMS CAN receive path
14. Testing RTEMS-to-Linux Communication
I kept candump running on Linux.
candump can0
The RTEMS test program transmitted frames through the installed DCAN driver.
Linux displayed the received frame in a format similar to:
can0 123 [8] 11 22 33 44 55 66 77 88
This verified:
- application write path
- RTEMS CAN queue
- DCAN message object write
- TX request
- TX completion interrupt
- physical transmission
- Linux SocketCAN reception
15. Testing the Register Test Program
The register test program was also used to inspect DCAN register values.
The test checked values such as:
DCAN1 base address
clock control register
pin multiplexing registers
control register
bit timing register
error and status register
interrupt register
new data register
message object control registers
The register test allowed me to confirm that BSP initialization happened before the application used the controller.
It was also useful for checking whether:
- the module clock was enabled
- the controller entered initialization mode
- the controller left initialization mode
- the selected message object was valid
- TX and RX state changed as expected
16. Complete Testing Workflow
The complete workflow was:
Modify driver source
↓
Build RTEMS
↓
Install RTEMS to 7-new
↓
Verify installed header and BSP files
↓
Build external DCAN register test
↓
Build external CAN framework test
↓
Copy executable to the BeagleBone Black boot environment
↓
Boot RTEMS
↓
Configure Linux SocketCAN
↓
Test Linux-to-RTEMS CAN frames
↓
Test RTEMS-to-Linux CAN frames
This process verified both the source-tree integration and the installed-driver usage.
17. What I Learned
This week helped me understand that upstream driver development includes more than making the hardware work.
I learned how to:
- separate generic driver code from board-specific support
- organize source files according to RTEMS structure
- update RTEMS build system files
- create a backup branch before changing Git history
- use stash and reset safely
- recover untracked files from a Git stash
- split one large commit into two reviewable commits
- update a merge request using
--force-with-lease - rebuild and install RTEMS into a separate prefix
- verify installed public headers and BSP files
- build an external application using the installed driver
- keep a low-level register test for hardware debugging
The most important result was that the DCAN driver could now be built as part of RTEMS and used by an external application through the installed RTEMS environment.
18. Current Project Status
The current merge request contains two commits:
83df456537
can/dcan: Add generic DCAN controller driver
ca6e1b52a3
bsps/arm/beagle: Add AM335x DCAN board support
The working tree is clean.
git status
Expected output:
nothing to commit, working tree clean
The remote merge request branch contains only these two commits ahead of upstream/main.
git rev-list --count \
upstream/main..origin/5440-am335x-dcan
Expected result:
2
The driver has also been tested through:
- RTEMS source build
- RTEMS installation
- installed public header
- external register test program
- external CAN application
- Linux-to-RTEMS communication
- RTEMS-to-Linux communication
19. Next Week
Next week, I will:
- think of FIFO