2024-07-23 19:18:42 +00:00
|
|
|
#include "uart.h"
|
|
|
|
|
|
|
|
|
|
|
|
void write_reg_u8(uintptr_t addr, uint8_t value)
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
volatile uint8_t *loc_addr = (volatile uint8_t *)addr;
|
|
|
|
*loc_addr = value;
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t read_reg_u8(uintptr_t addr)
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
return *(volatile uint8_t *)addr;
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int is_transmit_empty()
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
return read_reg_u8(UART_LSR) & 0x20;
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int is_receive_empty()
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
return !(read_reg_u8(UART_LSR) & 0x1);
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void write_serial(char a)
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
while (is_transmit_empty() == 0) {};
|
2024-07-23 19:18:42 +00:00
|
|
|
|
2024-07-25 18:04:27 +00:00
|
|
|
write_reg_u8(UART_THR, a);
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void init_uart(uint32_t freq, uint32_t baud)
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
// Alternative divisor calculation. From OpenSBI code.
|
|
|
|
// Reduces error for every possible frequency.
|
|
|
|
uint32_t divisor = (freq + 8 * baud) /(baud << 4);
|
2024-07-23 19:18:42 +00:00
|
|
|
|
2024-07-25 18:04:27 +00:00
|
|
|
write_reg_u8(UART_IER, 0x00); // Disable all interrupts
|
|
|
|
write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor)
|
|
|
|
write_reg_u8(UART_DLL, divisor & 0xFF); // divisor (lo byte)
|
|
|
|
write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte)
|
|
|
|
write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit
|
|
|
|
write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_uart(const char *str)
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
const char *cur = &str[0];
|
|
|
|
while (*cur != '\0') {
|
|
|
|
write_serial((uint8_t)*cur);
|
|
|
|
++cur;
|
|
|
|
}
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t bin_to_hex_table[16] = {
|
2024-07-25 18:04:27 +00:00
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
2024-07-23 19:18:42 +00:00
|
|
|
|
|
|
|
void bin_to_hex(uint8_t inp, uint8_t res[2])
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
res[1] = bin_to_hex_table[inp & 0xf];
|
|
|
|
res[0] = bin_to_hex_table[(inp >> 4) & 0xf];
|
|
|
|
return;
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_uart_int(uint32_t addr)
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
int i;
|
|
|
|
for (i = 3; i > -1; i--) {
|
|
|
|
uint8_t cur = (addr >> (i * 8)) & 0xff;
|
|
|
|
uint8_t hex[2];
|
|
|
|
bin_to_hex(cur, hex);
|
|
|
|
write_serial(hex[0]);
|
|
|
|
write_serial(hex[1]);
|
|
|
|
}
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_uart_addr(uint64_t addr)
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
int i;
|
|
|
|
for (i = 7; i > -1; i--) {
|
|
|
|
uint8_t cur = (addr >> (i * 8)) & 0xff;
|
|
|
|
uint8_t hex[2];
|
|
|
|
bin_to_hex(cur, hex);
|
|
|
|
write_serial(hex[0]);
|
|
|
|
write_serial(hex[1]);
|
|
|
|
}
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_uart_byte(uint8_t byte)
|
|
|
|
{
|
2024-07-25 18:04:27 +00:00
|
|
|
uint8_t hex[2];
|
|
|
|
bin_to_hex(byte, hex);
|
|
|
|
write_serial(hex[0]);
|
|
|
|
write_serial(hex[1]);
|
2024-07-23 19:18:42 +00:00
|
|
|
}
|