Skip to content

Repository files navigation

UART Driver Development (RISC-V Processor)

Project Overview

This project focuses on the development of a bare-metal UART driver in Embedded C for a RISC-V processor using register-level programming and Memory-Mapped I/O (MMIO).

The driver provides UART initialization, register-level access, polling-based transmit and receive services, software queue management, interrupt support, error monitoring, and driver status management.

The implementation was validated using UART loopback testing and host-side test cases.


Objectives

  • Develop a UART driver using Embedded C
  • Implement register-level programming using Memory-Mapped I/O
  • Configure and initialize UART hardware registers
  • Implement transmit and receive functionality
  • Implement polling-based UART communication
  • Implement software TX/RX queue management
  • Support UART interrupt configuration and handling
  • Monitor UART error conditions
  • Validate driver functionality using loopback and test cases

Technologies Used

  • Embedded C
  • C Programming
  • RISC-V Processor
  • UART
  • Memory-Mapped I/O (MMIO)
  • Register-Level Programming
  • FIFO
  • Polling
  • Interrupts
  • Bare-Metal Programming
  • GCC
  • Linux / Ubuntu

Key Features

1. UART Initialization

The driver initializes the UART device by:

  • Mapping the UART register space
  • Configuring the device base address
  • Resetting TX and RX FIFOs
  • Clearing and checking UART status
  • Initializing software TX/RX queues
  • Verifying the post-reset state
  • Enabling interrupts when required
  • Marking the driver as ready

2. Memory-Mapped I/O

The driver accesses UART hardware registers directly through memory-mapped addresses using volatile register read/write operations.

*(volatile uint32_t *)(base + offset)

This provides low-level communication between the software driver and UART hardware.

3. UART Transmit

The transmit service:

  • Checks UART status
  • Checks TX FIFO availability
  • Writes data to the TX FIFO
  • Monitors FIFO status
  • Returns the number of transmitted bytes

4. UART Receive

The receive service:

  • Monitors RX data availability
  • Reads received bytes from the RX FIFO
  • Transfers received data into the software RX queue
  • Tracks received byte statistics

5. Polling-Based Communication

The driver uses status-register polling to monitor UART TX/RX FIFO conditions and perform data transfer.

6. Interrupt Support

The driver also provides interrupt-related functionality including:

  • TX interrupt enable
  • RX interrupt enable
  • Interrupt service handling
  • TX queue service
  • RX queue service

7. Error Monitoring

The driver monitors UART error conditions including:

  • Overrun errors
  • Frame errors
  • Parity errors

Error statistics are maintained by the driver.

8. FIFO Management

The driver provides:

  • TX FIFO reset
  • RX FIFO reset
  • FIFO status monitoring
  • FIFO recovery
  • FIFO-based transmit and receive services

UART Register Map

The driver uses a memory-mapped UART register interface:

Offset Register Description
0x00 RX_FIFO Receive data register
0x04 TX_FIFO Transmit data register
0x08 STAT_REG UART status register
0x0C CTRL_REG UART control register

The register map and bit definitions are implemented according to the custom UART core used in this project.


Working Principle

              Application / Test Program
                         │
                         ▼
                 UART Driver API
                         │
                         ▼
              Memory-Mapped I/O
                         │
                         ▼
                UART Registers
                  │          │
                  ▼          ▼
               TX FIFO    RX FIFO
                  │          │
                  ▼          ▼
               UART TX    UART RX
                  │          │
                  └────┬─────┘
                       ▼
                 Serial Communication
                       │
                       ▼
                 Loopback / Testing

Testing and Validation

The driver was tested using:

  • UART loopback testing
  • Transmit and receive validation
  • FIFO boundary testing
  • NULL argument testing
  • Zero-length input testing
  • Software queue overflow testing
  • UART error-condition testing
  • Driver ready/not-ready state testing
  • Corner-case and boundary-condition testing

The test suite reports PASS / FAIL results and uses the process exit status to indicate test success.


Output

UART Driver Output

UART Driver Output

UART Loopback Test Output

UART Loopback Test Output


UART Loopback Test

The loopback test validates the transmit and receive path.

Test Data
   │
   ▼
UART TX FIFO
   │
   ▼
UART TX
   │
   ▼
TX → RX Loopback
   │
   ▼
UART RX
   │
   ▼
UART RX FIFO
   │
   ▼
Received Data
   │
   ▼
Compare TX and RX
   │
   ▼
PASS / FAIL

The loopback test transmits test bytes, receives them back through the RX path, compares transmitted and received data, and reports the result.


Host-Side Driver Testing

The driver includes a host-side simulated hardware model for testing without physical UART hardware.

The test environment models UART register behavior and FIFO operations to validate driver functionality.

Example build command:

gcc -Wall -Wextra -std=c11 \
axi_uart_lite.c test_axi_uart_lite.c \
-o test_axi_uart_lite

Run:

./test_axi_uart_lite

The test suite checks boundary conditions, invalid arguments, FIFO limits, software queue behavior, error states, and other corner cases.


Project Structure

UART-Driver-Development-RISC-V-Processor/
│
├── axi_uart_lite.c
├── axi_uart_lite.h
├── loopback_test.c
├── test_axi_uart_lite.c
├── test_corner_cases (1).c
├── README.md
└── LICENSE

File Description

File Description
axi_uart_lite.c UART driver implementation
axi_uart_lite.h UART driver declarations, register definitions, structures and APIs
loopback_test.c UART TX/RX loopback test
test_axi_uart_lite.c Driver functionality and corner-case test suite
test_corner_cases (1).c Additional boundary and corner-case tests
README.md Project documentation
LICENSE Apache License 2.0

Key Learning Outcomes

  • UART driver development
  • Embedded C programming
  • RISC-V processor concepts
  • Memory-Mapped I/O
  • Register-level programming
  • FIFO-based communication
  • Polling-based communication
  • Interrupt handling
  • Device driver architecture
  • Error monitoring
  • Software queue management
  • Driver testing and debugging
  • UART loopback validation

Future Improvements

  • Add configurable baud-rate support if supported by the target UART hardware
  • Add hardware-specific RISC-V build and deployment configuration
  • Integrate with a complete RISC-V embedded platform
  • Add automated test execution
  • Improve timeout handling for polling operations

📄 License

This project is licensed under the Apache License 2.0.

About

UART driver development in Embedded C for a RISC-V processor using register-level programming, Memory-Mapped I/O, and loopback testing.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages