Skip to content

Commit f3a0cee

Browse files
committed
test: add uart receive check via loopback mode
1 parent becb40d commit f3a0cee

File tree

6 files changed

+44
-9
lines changed

6 files changed

+44
-9
lines changed

.github/scripts/check_sim.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ expected_lines=(
1212
"\[JTAG\] Halting hart 0"
1313
"\[JTAG\] Resumed hart 0"
1414
"\[UART\] Hello World!"
15+
"\[UART\] Loopback received: internal msg"
1516
"\[UART\] Result: 0x8940, Cycles: 0xBD"
1617
"\[UART\] Tick"
1718
"\[UART\] Tock"

sw/helloworld.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ uint32_t isqrt(uint32_t n) {
3131
return res;
3232
}
3333

34+
char receive_buff[16] = {0};
35+
3436
int main() {
3537
uart_init(); // setup the uart peripheral
3638

@@ -39,6 +41,22 @@ int main() {
3941
// wait until uart has finished sending
4042
uart_write_flush();
4143

44+
// uart loopback
45+
uart_loopback_enable();
46+
printf("internal msg\n");
47+
sleep_ms(1);
48+
for(uint8_t idx = 0; idx<15; idx++) {
49+
receive_buff[idx] = uart_read();
50+
if(receive_buff[idx] == '\n') {
51+
break;
52+
}
53+
}
54+
uart_loopback_disable();
55+
56+
printf("Loopback received: ");
57+
printf(receive_buff);
58+
uart_write_flush();
59+
4260
// toggling some GPIOs
4361
gpio_set_direction(0xFFFF, 0x000F); // lowest four as outputs
4462
gpio_write(0x0A); // ready output pattern

sw/lib/inc/print.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@
1111
extern void putchar(char);
1212

1313
// simple printf with support for %x formatter but no others
14-
void printf(const char *fmt, ...);
14+
void printf(char *fmt, ...);

sw/lib/inc/uart.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@
3030

3131
// Register fields
3232
#define UART_LINE_STATUS_DATA_READY_BIT 0
33-
#define UART_LINE_STATUS_THR_EMPTY_BIT 5
33+
#define UART_LINE_STATUS_THR_EMPTY_BIT 5
3434
#define UART_LINE_STATUS_TMIT_EMPTY_BIT 6
3535

3636
void uart_init();
3737

38+
void uart_loopback_enable();
39+
40+
void uart_loopback_disable();
41+
3842
int uart_read_ready();
3943

4044
void uart_write(uint8_t byte);

sw/lib/src/print.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ uint8_t format_hex32(char *buffer, uint32_t num) {
2727
return idx;
2828
}
2929

30-
void printf(const char *fmt, ...) {
30+
void printf(char *fmt, ...) {
3131
va_list args;
3232
va_start(args, fmt);
3333
char buffer[12]; // holds string while assembling

sw/lib/src/uart.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,27 @@ void uart_init() {
1515
const uint16_t divisor = UART_DIVISOR(UART_FREQ, UART_BAUD); // Calculate from provided config
1616
uint8_t dlo = (uint8_t)(divisor);
1717
uint8_t dhi = (uint8_t)(divisor >> 8);
18-
*reg8(UART_BASE_ADDR, UART_INTR_ENABLE_REG_OFFSET) = 0x00; // Disable all interrupts
19-
*reg8(UART_BASE_ADDR, UART_LINE_CONTROL_REG_OFFSET) = 0x80; // Enable DLAB (set baud rate divisor)
20-
*reg8(UART_BASE_ADDR, UART_DLAB_LSB_REG_OFFSET) = dlo; // divisor (lo byte)
21-
*reg8(UART_BASE_ADDR, UART_DLAB_MSB_REG_OFFSET) = dhi; // divisor (hi byte)
22-
*reg8(UART_BASE_ADDR, UART_LINE_CONTROL_REG_OFFSET) = 0x03; // 8 bits, no parity, one stop bit
23-
*reg8(UART_BASE_ADDR, UART_FIFO_CONTROL_REG_OFFSET) = 0xC7; // Enable & clear FIFO, 14B threshold
18+
*reg8(UART_BASE_ADDR, UART_INTR_ENABLE_REG_OFFSET) = 0x00; // Disable all interrupts
19+
*reg8(UART_BASE_ADDR, UART_LINE_CONTROL_REG_OFFSET) = 0x80; // Enable DLAB (set baud rate divisor)
20+
*reg8(UART_BASE_ADDR, UART_DLAB_LSB_REG_OFFSET) = dlo; // divisor (lo byte)
21+
*reg8(UART_BASE_ADDR, UART_DLAB_MSB_REG_OFFSET) = dhi; // divisor (hi byte)
22+
*reg8(UART_BASE_ADDR, UART_LINE_CONTROL_REG_OFFSET) = 0x03; // 8 bits, no parity, one stop bit
23+
*reg8(UART_BASE_ADDR, UART_FIFO_CONTROL_REG_OFFSET) = 0xC7; // Enable & clear FIFO, 14B threshold
2424
*reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET) = 0x20; // Autoflow mode
2525
}
2626

27+
void uart_loopback_enable() {
28+
uart_write_flush();
29+
uint8_t mcr = *reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET);
30+
*reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET) = mcr | (1 << 4);
31+
}
32+
33+
void uart_loopback_disable() {
34+
uart_write_flush();
35+
uint8_t mcr = *reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET);
36+
*reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET) = mcr & ~(1 << 4);
37+
}
38+
2739
int uart_read_ready() {
2840
return *reg8(UART_BASE_ADDR, UART_LINE_STATUS_REG_OFFSET) & (1 << UART_LINE_STATUS_DATA_READY_BIT);
2941
}

0 commit comments

Comments
 (0)