diff --git a/CMSIS/Device/RaspberryPi/RP2040/Source/system_RP2040.c b/CMSIS/Device/RaspberryPi/RP2040/Source/system_RP2040.c index 4b9b073..6177b5d 100644 --- a/CMSIS/Device/RaspberryPi/RP2040/Source/system_RP2040.c +++ b/CMSIS/Device/RaspberryPi/RP2040/Source/system_RP2040.c @@ -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_sys_set_div(1 << 8); /* 200MHz / 1 = 200MHz */ clock_sys_set_src(CLOCK_SYS_SRC_SYSPLL); + clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL); SystemCoreClockUpdate(); diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt index 5b686c2..6cb8c13 100644 --- a/driver/CMakeLists.txt +++ b/driver/CMakeLists.txt @@ -8,6 +8,7 @@ src/gpio.c src/pio.c src/timer.c src/dma.c +src/uart.c ) set(TARGET driver) diff --git a/driver/inc/reg/uart_reg.h b/driver/inc/reg/uart_reg.h new file mode 100644 index 0000000..d9cffd6 --- /dev/null +++ b/driver/inc/reg/uart_reg.h @@ -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__ */ diff --git a/driver/inc/uart.h b/driver/inc/uart.h new file mode 100644 index 0000000..d6b787e --- /dev/null +++ b/driver/inc/uart.h @@ -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__ */ diff --git a/driver/src/uart.c b/driver/src/uart.c new file mode 100644 index 0000000..7a7e58e --- /dev/null +++ b/driver/src/uart.c @@ -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; +} diff --git a/main.c b/main.c index a0f37de..ff3c741 100644 --- a/main.c +++ b/main.c @@ -4,6 +4,7 @@ #include "sio.h" #include "gpio.h" #include "dma.h" +#include "uart.h" #include "pio_rmii_tx.h" #include "RP2040.h" #include "main_core0.h" @@ -126,6 +127,17 @@ struct dma_sniff_cfg_s sniff_cfg = { .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) { 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 + 2, 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)) { while (1); } @@ -157,9 +170,15 @@ int main(void) __enable_irq(); 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) { static uint32_t tick_led = 0; static uint32_t tick_rmii = 0; + static uint32_t tick_uart = 0; if (tick_1ms > (tick_rmii + 1)) { tick_rmii = tick_1ms; pio_rmii_write(&rmii, (uint32_t *)buffer, length); @@ -168,6 +187,10 @@ int main(void) tick_led = tick_1ms; 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;