[feat] add uart driver

This commit is contained in:
zhji 2025-03-19 15:59:12 +08:00
parent 40c7bf6258
commit 87e54ba209
6 changed files with 463 additions and 0 deletions

View File

@ -58,6 +58,7 @@ void __attribute__((constructor)) SystemInit (void)
clock_pll_init(CLOCK_PLL_SYSPLL, 1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */ clock_pll_init(CLOCK_PLL_SYSPLL, 1, 100, 3, 2); /* 12MHz / 1 * 100 / 3 / 2 = 200MHz */
clock_sys_set_div(1 << 8); /* 200MHz / 1 = 200MHz */ clock_sys_set_div(1 << 8); /* 200MHz / 1 = 200MHz */
clock_sys_set_src(CLOCK_SYS_SRC_SYSPLL); clock_sys_set_src(CLOCK_SYS_SRC_SYSPLL);
clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL);
SystemCoreClockUpdate(); SystemCoreClockUpdate();

View File

@ -8,6 +8,7 @@ src/gpio.c
src/pio.c src/pio.c
src/timer.c src/timer.c
src/dma.c src/dma.c
src/uart.c
) )
set(TARGET driver) set(TARGET driver)

159
driver/inc/reg/uart_reg.h Normal file
View File

@ -0,0 +1,159 @@
#ifndef __UART_REG_H__
#define __UART_REG_H__
#define UART_UARTDR_OFFSET (0x000)
#define UART_UARTRSR_OFFSET (0x004)
#define UART_UARTFR_OFFSET (0x018)
#define UART_UARTILPR_OFFSET (0x020)
#define UART_UARTIBRD_OFFSET (0x024)
#define UART_UARTFBRD_OFFSET (0x028)
#define UART_UARTLCR_H_OFFSET (0x02C)
#define UART_UARTCR_OFFSET (0x030)
#define UART_UARTIFLS_OFFSET (0x034)
#define UART_UARTIMSC_OFFSET (0x038)
#define UART_UARTRIS_OFFSET (0x03C)
#define UART_UARTMIS_OFFSET (0x040)
#define UART_UARTICR_OFFSET (0x044)
#define UART_UARTDMACR_OFFSET (0x048)
#define UART_UARTPERIPHID0_OFFSET (0xFE0)
#define UART_UARTPERIPHID1_OFFSET (0xFE4)
#define UART_UARTPERIPHID2_OFFSET (0xFE8)
#define UART_UARTPERIPHID3_OFFSET (0xFEC)
#define UART_UARTPCELLID0 (0xFF0)
#define UART_UARTPCELLID1 (0xFF4)
#define UART_UARTPCELLID2 (0xFF8)
#define UART_UARTPCELLID3 (0xFFC)
/* UART_UARTDR_OFFSET @0x000 */
#define UART_UARTDR_DATA_POS (0U)
#define UART_UARTDR_DATA_MASK (0xFF << UART_UARTDR_DATA_POS)
#define UART_UARTDR_FE (1 << 8U)
#define UART_UARTDR_PE (1 << 9U)
#define UART_UARTDR_BE (1 << 10U)
#define UART_UARTDR_OE (1 << 11U)
/* UART_UARTRSR_OFFSET @0x004 */
#define UART_UARTRSR_FE (1 << 0U)
#define UART_UARTRSR_PE (1 << 1U)
#define UART_UARTRSR_BE (1 << 2U)
#define UART_UARTRSR_OE (1 << 3U)
/* UART_UARTFR_OFFSET @0x018 */
#define UART_UARTFR_CTS (1 << 0U)
#define UART_UARTFR_DSR (1 << 1U)
#define UART_UARTFR_DCD (1 << 2U)
#define UART_UARTFR_BUSY (1 << 3U)
#define UART_UARTFR_RXFE (1 << 4U)
#define UART_UARTFR_TXFF (1 << 5U)
#define UART_UARTFR_RXFF (1 << 6U)
#define UART_UARTFR_TXFE (1 << 7U)
#define UART_UARTFR_RI (1 << 8U)
/* UART_UARTILPR_OFFSET @0x020 */
#define UART_UARTILPR_ILPDVSR_POS (0U)
#define UART_UARTILPR_ILPDVSR_MASK (0xFF << UART_UARTILPR_ILPDVSR_POS)
/* UART_UARTIBRD_OFFSET @0x024 */
#define UART_UARTIBRD_BAUD_DIVINT_POS (0U)
#define UART_UARTIBRD_BAUD_DIVINT_MASK (0xFFFF << UART_UARTIBRD_BAUD_DIVINT_POS)
/* UART_UARTFBRD_OFFSET @0x028 */
#define UART_UARTFBRD_BAUD_DIVFRAC_POS (0U)
#define UART_UARTFBRD_BAUD_DIVFRAC_MASK (0x3F << UART_UARTFBRD_BAUD_DIVFRAC_POS)
/* UART_UARTLCR_H_OFFSET @0x02C */
#define UART_UARTLCR_H_BRK (1 << 0U)
#define UART_UARTLCR_H_PEN (1 << 1U)
#define UART_UARTLCR_H_EPS (1 << 2U)
#define UART_UARTLCR_H_STP2 (1 << 3U)
#define UART_UARTLCR_H_FEN (1 << 4U)
#define UART_UARTLCR_H_WLEN_POS (5U)
#define UART_UARTLCR_H_WLEN_MASK (0x3 << UART_UARTLCR_H_WLEN_POS)
#define UART_UARTLCR_H_SPS (1 << 7U)
/* UART_UARTCR_OFFSET @0x030 */
#define UART_UARTCR_UARTEN (1 << 0U)
#define UART_UARTCR_SIREN (1 << 1U)
#define UART_UARTCR_SIRLP (1 << 2U)
#define UART_UARTCR_LBE (1 << 7U)
#define UART_UARTCR_TXE (1 << 8U)
#define UART_UARTCR_RXE (1 << 9U)
#define UART_UARTCR_DTR (1 << 10U)
#define UART_UARTCR_RTS (1 << 11U)
#define UART_UARTCR_OUT1 (1 << 12U)
#define UART_UARTCR_OUT2 (1 << 13U)
#define UART_UARTCR_RTSEN (1 << 14U)
#define UART_UARTCR_CTSEN (1 << 15U)
/* UART_UARTIFLS_OFFSET @0x034 */
#define UART_UARTIFLS_TXIFLSEL_POS (0U)
#define UART_UARTIFLS_TXIFLSEL_MASK (0x7 << UART_UARTIFLS_TXIFLSEL_POS)
#define UART_UARTIFLS_RXIFLSEL_POS (3U)
#define UART_UARTIFLS_RXIFLSEL_MASK (0x7 << UART_UARTIFLS_TXIFLSEL_POS)
/* UART_UARTIMSC_OFFSET @0x038 */
#define UART_UARTIMSC_RIMIM (1 << 0U)
#define UART_UARTIMSC_CTSMIM (1 << 1U)
#define UART_UARTIMSC_DCDMIM (1 << 2U)
#define UART_UARTIMSC_DSRMIM (1 << 3U)
#define UART_UARTIMSC_RXIM (1 << 4U)
#define UART_UARTIMSC_TXIM (1 << 5U)
#define UART_UARTIMSC_RTIM (1 << 6U)
#define UART_UARTIMSC_FEIM (1 << 7U)
#define UART_UARTIMSC_PEIM (1 << 8U)
#define UART_UARTIMSC_BEIM (1 << 9U)
#define UART_UARTIMSC_OEIM (1 << 10U)
/* UART_UARTRIS_OFFSET @0x03C */
#define UART_UARTRIS_RIRMIS (1 << 0U)
#define UART_UARTRIS_CTSRMIS (1 << 1U)
#define UART_UARTRIS_DCDRMIS (1 << 2U)
#define UART_UARTRIS_DSRRMIS (1 << 3U)
#define UART_UARTRIS_RXRIS (1 << 4U)
#define UART_UARTRIS_TXRIS (1 << 5U)
#define UART_UARTRIS_RTRIS (1 << 6U)
#define UART_UARTRIS_FERIS (1 << 7U)
#define UART_UARTRIS_PERIS (1 << 8U)
#define UART_UARTRIS_BERIS (1 << 9U)
#define UART_UARTRIS_OERIS (1 << 10U)
/* UART_UARTMIS_OFFSET @0x040 */
#define UART_UARTMIS_RIMMIS (1 << 0U)
#define UART_UARTMIS_CTSMMIS (1 << 1U)
#define UART_UARTMIS_DCDMMIS (1 << 2U)
#define UART_UARTMIS_DSRMMIS (1 << 3U)
#define UART_UARTMIS_RXMIS (1 << 4U)
#define UART_UARTMIS_TXMIS (1 << 5U)
#define UART_UARTMIS_RTMIS (1 << 6U)
#define UART_UARTMIS_FEMIS (1 << 7U)
#define UART_UARTMIS_PEMIS (1 << 8U)
#define UART_UARTMIS_BEMIS (1 << 9U)
#define UART_UARTMIS_OEMIS (1 << 10U)
/* UART_UARTICR_OFFSET @0x044 */
#define UART_UARTICR_RIMIC (1 << 0U)
#define UART_UARTICR_CTSMIC (1 << 1U)
#define UART_UARTICR_DCDMIC (1 << 2U)
#define UART_UARTICR_DSRMIC (1 << 3U)
#define UART_UARTICR_RXIC (1 << 4U)
#define UART_UARTICR_TXIC (1 << 5U)
#define UART_UARTICR_RTIC (1 << 6U)
#define UART_UARTICR_FEIC (1 << 7U)
#define UART_UARTICR_PEIC (1 << 8U)
#define UART_UARTICR_BEIC (1 << 9U)
#define UART_UARTICR_OEIC (1 << 10U)
/* UART_UARTDMACR_OFFSET @0x048 */
#define UART_UARTDMACR_RXDMAE (1 << 0U)
#define UART_UARTDMACR_TXDMAE (1 << 1U)
#define UART_UARTDMACR_DMAONERR (1 << 2U)
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* __UART_REG_H__ */

88
driver/inc/uart.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef __UART_H__
#define __UART_H__
#include "reg.h"
#include "uart_reg.h"
#define UART_ID_0 (0)
#define UART_ID_1 (1)
#define UART_INT_RI (1 << 0U)
#define UART_INT_CTS (1 << 1U)
#define UART_INT_DCD (1 << 2U)
#define UART_INT_DSR (1 << 3U)
#define UART_INT_RX (1 << 4U)
#define UART_INT_TX (1 << 5U)
#define UART_INT_RTO (1 << 6U)
#define UART_INT_FE (1 << 7U)
#define UART_INT_PE (1 << 8U)
#define UART_INT_BE (1 << 9U)
#define UART_INT_OE (1 << 10U)
#define UART_INT_ALL ((1 << 11U) - 1)
#define UART_MODE_NONE (0)
#define UART_MODE_TX_ONLY (1)
#define UART_MODE_RX_ONLY (2)
#define UART_MODE_TX_RX (3)
#define UART_DATABITS_5 (0)
#define UART_DATABITS_6 (1)
#define UART_DATABITS_7 (2)
#define UART_DATABITS_8 (3)
#define UART_PARITY_NONE (0)
#define UART_PARITY_ODD (1)
#define UART_PARITY_EVEN (2)
#define UART_PARITY_MARK0 (3)
#define UART_PARITY_MARK1 (4)
#define UART_STOPBITS_1 (0)
#define UART_STOPBITS_2 (1)
#define UART_FIFO_LEVEL_1_8 (0)
#define UART_FIFO_LEVEL_1_4 (1)
#define UART_FIFO_LEVEL_1_2 (2)
#define UART_FIFO_LEVEL_3_4 (3)
#define UART_FIFO_LEVEL_7_8 (4)
#define UART_FLAG_CTS (1 << 0U)
#define UART_FLAG_DSR (1 << 1U)
#define UART_FLAG_DCD (1 << 2U)
#define UART_FLAG_BUSY (1 << 3U)
#define UART_FLAG_RXFE (1 << 4U)
#define UART_FLAG_TXFF (1 << 5U)
#define UART_FLAG_RXFF (1 << 6U)
#define UART_FLAG_TXFE (1 << 7U)
#define UART_FLAG_RI (1 << 8U)
struct uart_cfg_s {
uint8_t mode;
uint8_t data_bits;
uint8_t parity;
uint8_t stop_bits;
uint8_t fifo_enable;
uint8_t tx_fifo_level;
uint8_t rx_fifo_level;
};
#ifdef __cplusplus
extern "C" {
#endif
void uart_init(uint8_t uart_id, struct uart_cfg_s *cfg);
void uart_set_baudrate(uint8_t uart_id, uint32_t src_clk, uint32_t baudrate);
uint32_t uart_get_flags(uint8_t uart_id);
void uart_write_block(uint8_t uart_id, uint8_t *data, uint32_t length);
uint32_t uart_int_get_raw_status(uint8_t uart_id);
uint32_t uart_int_get_status(uint8_t uart_id);
void uart_int_clear(uint8_t uart_id, uint32_t int_type);
void uart_int_mask(uint8_t uart_id, uint32_t int_type);
void uart_int_unmask(uint8_t uart_id, uint32_t int_type);
uint32_t uart_int_get_mask_status(uint8_t uart_id);
#ifdef __cplusplus
}
#endif
#endif /* __UART_H__ */

191
driver/src/uart.c Normal file
View File

@ -0,0 +1,191 @@
#include "uart.h"
void uart_init(uint8_t uart_id, struct uart_cfg_s *cfg)
{
uint32_t addr, val;
addr = UART0_BASE + UART_UARTCR_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val &= ~UART_UARTCR_UARTEN;
val &= ~UART_UARTCR_SIREN;
val &= ~UART_UARTCR_SIRLP;
val &= ~UART_UARTCR_LBE;
val &= ~UART_UARTCR_DTR;
val &= ~UART_UARTCR_RTS;
val &= ~UART_UARTCR_OUT1;
val &= ~UART_UARTCR_OUT2;
val &= ~UART_UARTCR_RTSEN;
val &= ~UART_UARTCR_CTSEN;
if (cfg->mode == UART_MODE_NONE) {
val &= ~UART_UARTCR_TXE;
val &= ~UART_UARTCR_RXE;
} else if (cfg->mode == UART_MODE_TX_ONLY) {
val |= UART_UARTCR_TXE;
val &= ~UART_UARTCR_RXE;
} else if (cfg->mode == UART_MODE_RX_ONLY) {
val &= ~UART_UARTCR_TXE;
val |= UART_UARTCR_RXE;
} else {
val |= UART_UARTCR_TXE;
val |= UART_UARTCR_RXE;
}
putreg32(val, addr);
addr = UART0_BASE + UART_UARTLCR_H_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val &= ~UART_UARTLCR_H_BRK;
if (cfg->parity == UART_PARITY_ODD) {
val |= UART_UARTLCR_H_SPS;
val &= ~UART_UARTLCR_H_SPS;
val &= ~UART_UARTLCR_H_EPS;
} else if (cfg->parity == UART_PARITY_EVEN) {
val |= UART_UARTLCR_H_SPS;
val &= ~UART_UARTLCR_H_SPS;
val |= UART_UARTLCR_H_EPS;
} else if (cfg->parity == UART_PARITY_MARK0) {
val |= UART_UARTLCR_H_SPS;
val |= UART_UARTLCR_H_SPS;
val |= UART_UARTLCR_H_EPS;
} else if (cfg->parity == UART_PARITY_MARK1) {
val |= UART_UARTLCR_H_SPS;
val |= UART_UARTLCR_H_SPS;
val &= ~UART_UARTLCR_H_EPS;
} else {
val &= ~UART_UARTLCR_H_PEN;
val &= ~UART_UARTLCR_H_SPS;
val &= ~UART_UARTLCR_H_EPS;
}
if (cfg->stop_bits == UART_STOPBITS_2) {
val |= UART_UARTLCR_H_STP2;
} else {
val &= ~UART_UARTLCR_H_STP2;
}
if (cfg->fifo_enable) {
val |= UART_UARTLCR_H_FEN;
} else {
val &= ~UART_UARTLCR_H_FEN;
}
val &= ~UART_UARTLCR_H_WLEN_MASK;
val |= (cfg->data_bits << UART_UARTLCR_H_WLEN_POS);
putreg32(val, addr);
addr = UART0_BASE + UART_UARTIFLS_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val &= ~UART_UARTIFLS_TXIFLSEL_MASK;
val |= (cfg->tx_fifo_level << UART_UARTIFLS_TXIFLSEL_POS);
val &= ~UART_UARTIFLS_RXIFLSEL_MASK;
val |= (cfg->rx_fifo_level << UART_UARTIFLS_RXIFLSEL_POS);
putreg32(val, addr);
addr = UART0_BASE + UART_UARTCR_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val |= UART_UARTCR_UARTEN;
putreg32(val, addr);
}
void uart_set_baudrate(uint8_t uart_id, uint32_t src_clk, uint32_t baudrate)
{
uint32_t addr, val;
uint32_t baud_rate_div, baud_ibrd, baud_fbrd;
baud_rate_div = 8 * src_clk / baudrate;
baud_ibrd = baud_rate_div >> 7;
if (baud_ibrd == 0) {
baud_ibrd = 1;
baud_fbrd = 0;
} else if (baud_ibrd >= 65535) {
baud_ibrd = 65535;
baud_fbrd = 0;
} else {
baud_fbrd = ((baud_rate_div & 0x7F) + 1) / 2;
}
addr = UART0_BASE + UART_UARTIBRD_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val &= ~UART_UARTIBRD_BAUD_DIVINT_MASK;
val |= (baud_ibrd << UART_UARTIBRD_BAUD_DIVINT_POS);
putreg32(val, addr);
addr = UART0_BASE + UART_UARTFBRD_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val &= ~UART_UARTFBRD_BAUD_DIVFRAC_MASK;
val |= (baud_fbrd << UART_UARTFBRD_BAUD_DIVFRAC_POS);
putreg32(val, addr);
}
uint32_t uart_get_flags(uint8_t uart_id)
{
return getreg32(UART0_BASE + UART_UARTFR_OFFSET + (UART1_BASE - UART0_BASE) * uart_id);
}
void uart_write_block(uint8_t uart_id, uint8_t *data, uint32_t length)
{
uint32_t addr;
uint32_t flag, idx;
idx = 0;
addr = UART0_BASE + UART_UARTDR_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
while (idx < length) {
flag = uart_get_flags(uart_id);
if (!(flag & UART_FLAG_TXFF)) {
putreg32(data[idx++], addr);
}
}
}
uint32_t uart_int_get_raw_status(uint8_t uart_id)
{
uint32_t addr, val;
addr = UART0_BASE + UART_UARTRIS_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val &= UART_INT_ALL;
return val;
}
uint32_t uart_int_get_status(uint8_t uart_id)
{
uint32_t addr, val;
addr = UART0_BASE + UART_UARTMIS_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val &= UART_INT_ALL;
return val;
}
void uart_int_clear(uint8_t uart_id, uint32_t int_type)
{
uint32_t addr, val;
addr = UART0_BASE + UART_UARTICR_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = int_type & UART_INT_ALL;
putreg32(val, addr);
}
void uart_int_mask(uint8_t uart_id, uint32_t int_type)
{
uint32_t addr, val;
addr = UART0_BASE + UART_UARTIMSC_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val |= (int_type & UART_INT_ALL);
putreg32(val, addr);
}
void uart_int_unmask(uint8_t uart_id, uint32_t int_type)
{
uint32_t addr, val;
addr = UART0_BASE + UART_UARTIMSC_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val &= ~(int_type & UART_INT_ALL);
putreg32(val, addr);
}
uint32_t uart_int_get_mask_status(uint8_t uart_id)
{
uint32_t addr, val;
addr = UART0_BASE + UART_UARTIMSC_OFFSET + (UART1_BASE - UART0_BASE) * uart_id;
val = getreg32(addr);
val &= UART_INT_ALL;
return val;
}

23
main.c
View File

@ -4,6 +4,7 @@
#include "sio.h" #include "sio.h"
#include "gpio.h" #include "gpio.h"
#include "dma.h" #include "dma.h"
#include "uart.h"
#include "pio_rmii_tx.h" #include "pio_rmii_tx.h"
#include "RP2040.h" #include "RP2040.h"
#include "main_core0.h" #include "main_core0.h"
@ -126,6 +127,17 @@ struct dma_sniff_cfg_s sniff_cfg = {
.out_inv = ENABLE, .out_inv = ENABLE,
}; };
struct uart_cfg_s uart_cfg = {
.mode = UART_MODE_TX_RX,
.data_bits = UART_DATABITS_8,
.parity = UART_PARITY_NONE,
.stop_bits = UART_STOPBITS_1,
.fifo_enable = ENABLE,
.tx_fifo_level = UART_FIFO_LEVEL_1_2,
.rx_fifo_level = UART_FIFO_LEVEL_1_2,
};
uint8_t uart_data[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
int main(void) int main(void)
{ {
reset_disable(RESET_IO_BANK0 | RESET_PADS_BANK0); reset_disable(RESET_IO_BANK0 | RESET_PADS_BANK0);
@ -135,6 +147,7 @@ int main(void)
gpio_init_simple(rmii.pin + 1, GPIO_FUNC_PIO0, DISABLE, DISABLE); gpio_init_simple(rmii.pin + 1, GPIO_FUNC_PIO0, DISABLE, DISABLE);
gpio_init_simple(rmii.pin + 2, GPIO_FUNC_PIO0, DISABLE, DISABLE); gpio_init_simple(rmii.pin + 2, GPIO_FUNC_PIO0, DISABLE, DISABLE);
gpio_init_simple(rmii.pin + 3, GPIO_FUNC_PIO0, DISABLE, DISABLE); gpio_init_simple(rmii.pin + 3, GPIO_FUNC_PIO0, DISABLE, DISABLE);
gpio_init_simple(0, GPIO_FUNC_UART, DISABLE, ENABLE);
if (udp_create_default(&udp_cfg, &udp_default)) { if (udp_create_default(&udp_cfg, &udp_default)) {
while (1); while (1);
} }
@ -157,9 +170,15 @@ int main(void)
__enable_irq(); __enable_irq();
pio_rmii_tx_init(&rmii); pio_rmii_tx_init(&rmii);
reset_disable(RESET_UART0);
uart_init(UART_ID_0, &uart_cfg);
uart_set_baudrate(UART_ID_0, 200 * 1000 * 1000, 2 * 1000 * 1000);
while (1) { while (1) {
static uint32_t tick_led = 0; static uint32_t tick_led = 0;
static uint32_t tick_rmii = 0; static uint32_t tick_rmii = 0;
static uint32_t tick_uart = 0;
if (tick_1ms > (tick_rmii + 1)) { if (tick_1ms > (tick_rmii + 1)) {
tick_rmii = tick_1ms; tick_rmii = tick_1ms;
pio_rmii_write(&rmii, (uint32_t *)buffer, length); pio_rmii_write(&rmii, (uint32_t *)buffer, length);
@ -168,6 +187,10 @@ int main(void)
tick_led = tick_1ms; tick_led = tick_1ms;
gpio_toggle(gpio_led_cfg.pin); gpio_toggle(gpio_led_cfg.pin);
} }
if (tick_1ms > (tick_uart + 10)) {
tick_uart = tick_1ms;
uart_write_block(UART_ID_0, uart_data, sizeof(uart_data));
}
} }
return 0; return 0;