The first challenge we need to tackle with the RED-V board is to have some kind of debugging possibility. Nothing exist so we create code that sends characters to the UART so we can grab debugging states reading the COM port in Linux.
# debug.s
.align 2
.include "./src/include/constants.s"
.section .text
# Function to output a null-terminated string to UART
.globl puts
puts:
li t0, UART_BASE
puts_loop:
lbu t1, (a0)
beqz t1, puts_leave
puts_waits:
lw t2, UART_REG_TXFIFO(t0)
bltz t2, puts_waits
sw t1, UART_REG_TXFIFO(t0)
addi a0, a0, 1
j puts_loop
puts_leave:
ret
.globl uart_init
uart_init:
# Input:
# a0 - baud rate divisor value (e.g., 139 for 115200 baud with 16 MHz clock)
# Configure GPIO pins for UART0
# Enable IOF on GPIO16 (TX) and GPIO17 (RX)
lui t0, %hi(IOF_UART0_MASK) # Load upper 20 bits of IOF_UART0_MASK into t0
ori t0, t0, %lo(IOF_UART0_MASK) # Or lower 12 bits into t0 (t0 = IOF_UART0_MASK)
# Load address of GPIO_IOF_EN into t2
lui t2, %hi(GPIO_IOF_EN) # Load upper 20 bits of GPIO_IOF_EN into t2
addi t2, t2, %lo(GPIO_IOF_EN) # Add lower 12 bits to t2 (t2 = GPIO_IOF_EN)
sw t0, 0(t2) # Store t0 to GPIO_IOF_EN
# Select IOF0 (UART0) for GPIO16 and GPIO17
# Load address of GPIO_IOF_SEL into t3
lui t3, %hi(GPIO_IOF_SEL)
addi t3, t3, %lo(GPIO_IOF_SEL)
lw t1, 0(t3) # Load GPIO_IOF_SEL into t1
not t0, t0 # t0 = ~IOF_UART0_MASK
and t1, t1, t0 # Clear bits for UART0 pins in t1
sw t1, 0(t3) # Store updated t1 back to GPIO_IOF_SEL
# Set baud rate divisor
lui t2, %hi(UART_DIV)
addi t2, t2, %lo(UART_DIV)
sw a0, 0(t2) # Store baud rate divisor to UART_DIV
# Enable transmitter and receiver
li t0, 0x1 # Transmit/Receive enable bit (bit 0)
# Load address of UART_TXCTRL into t3
lui t3, %hi(UART_TXCTRL)
addi t3, t3, %lo(UART_TXCTRL)
sw t0, 0(t3) # Enable transmitter
# Load address of UART_RXCTRL into t3
lui t3, %hi(UART_RXCTRL)
addi t3, t3, %lo(UART_RXCTRL)
sw t0, 0(t3) # Enable receiver
# Disable UART interrupts (optional)
lui t2, %hi(UART_IE)
addi t2, t2, %lo(UART_IE)
sw zero, 0(t2) # Disable UART interrupts
ret
.globl uart_putc
uart_putc:
# Input:
# a0 - byte to send (lower 8 bits)
# Load the address of UART_TXDATA into t2
lui t2, %hi(UART_TXDATA) # Load upper 20 bits of UART_TXDATA
addi t2, t2, %lo(UART_TXDATA) # Add lower 12 bits to t2
# Load the mask into t1 (outside the loop)
li t1, 0x80000000 # Load the 'full' bit mask into t1
uart_putc_wait:
# Check if the TX FIFO is full
lw t0, 0(t2) # Load UART_TXDATA into t0
and t3, t0, t1 # t3 = t0 & 0x80000000
bnez t3, uart_putc_wait # If 'full' bit is set, wait
# Write the character to the TXDATA register
andi t0, a0, 0xFF # Ensure only lower 8 bits are used
sw t0, 0(t2) # Write t0 to UART_TXDATA
ret
.globl uart_writeln
uart_writeln:
# Input:
# a0 - address of the null-terminated string
uart_writeln_loop:
lbu t0, 0(a0) # Load byte from string into t0
beqz t0, uart_writeln_newline # If null terminator, proceed to newline
addi a0, a0, 1 # Increment string pointer
mv a1, t0 # Move character to a1 for uart_putc
jal uart_putc # Call uart_putc to send character
j uart_writeln_loop # Repeat for next character
uart_writeln_newline:
# Send newline character
li a0, '\n' # Load newline character
jal uart_putc # Send newline
ret
In linux we now catch the debug lines through this command:
sudo screen /dev/ttyACM0 or sudo screen /dev/ttyACM0 115200
Kill the monitoring with command Ctrl-a k
Main.s initialization becomes like this.
# main.s
.align 2
.include "./src/include/constants.s"
.include "./src/include/macros.s"
.include "./src/include/string-macros.s"
.include "./src/data/data.s"
.include "./src/data/rodata.s"
.include "./src/data/bss.s"
.section .text
.globl _start
_start:
jal _boot_init # Initialize boot sequence for Sparkfun Red-V board
# Initialize UART
li a0, 139 # Baud rate divisor for 115200 baud
jal uart_init
# Use uart_writeln to send the message
la a0, STRINGS_TEST_START_MSG # Load address of the message into a0
jal uart_writeln # Call uart_writeln to send the string
halt:
j halt
You must press the reset button to see if it captures data..
If nothing shows up then you have some kind of bug ;-)
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.