diff --git a/boards/hifive1/board.c b/boards/hifive1/board.c index 42d72ad3f9..68352ed51f 100644 --- a/boards/hifive1/board.c +++ b/boards/hifive1/board.c @@ -117,12 +117,6 @@ void board_init(void) cpu_init(); board_init_clock(); - /* Configure pin muxing for UART0 */ - GPIO_REG(GPIO_OUTPUT_VAL) |= IOF0_UART0_MASK; - GPIO_REG(GPIO_OUTPUT_EN) |= IOF0_UART0_MASK; - GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK; - GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK; - /* Configure GPIOs for LEDs */ gpio_init(LED0_PIN, GPIO_OUT); gpio_init(LED1_PIN, GPIO_OUT); diff --git a/boards/hifive1/include/periph_conf.h b/boards/hifive1/include/periph_conf.h index 8bc71e52b8..673184fdda 100644 --- a/boards/hifive1/include/periph_conf.h +++ b/boards/hifive1/include/periph_conf.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2017 Ken Rabold + * 2019 Inria * * This file is subject to the terms and conditions of the GNU Lesser General * Public License v2.1. See the file LICENSE in the top level directory for more @@ -19,6 +20,8 @@ #ifndef PERIPH_CONF_H #define PERIPH_CONF_H +#include "periph_cpu.h" + #ifdef __cplusplus extern "C" { #endif @@ -49,6 +52,28 @@ extern "C" { #define TIMER_NUMOF (1) /** @} */ +/** + * @name UART configuration + * @{ + */ +static const uart_conf_t uart_config[] = { + { + .addr = UART0_CTRL_ADDR, + .rx = GPIO_PIN(0, 16), + .tx = GPIO_PIN(0, 17), + .isr_num = INT_UART0_BASE, + }, + { + .addr = UART1_CTRL_ADDR, + .rx = GPIO_PIN(0, 18), + .tx = GPIO_PIN(0, 23), + .isr_num = INT_UART1_BASE, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +/** @} */ + /** * @name RTT/RTC configuration * @@ -76,16 +101,6 @@ extern "C" { #define PWM_NUMOF (3) /** @} */ -/** - * @name UART configuration - * - * @{ - */ -#define UART_NUMOF (2) -#define UART0_RX_INTR_PRIORITY (2) -#define UART1_RX_INTR_PRIORITY (2) -/** @} */ - #ifdef __cplusplus } #endif diff --git a/boards/hifive1b/board.c b/boards/hifive1b/board.c index 0aaf3471a1..b16b00d7ea 100644 --- a/boards/hifive1b/board.c +++ b/boards/hifive1b/board.c @@ -139,12 +139,6 @@ void board_init(void) board_init_clock(); // board_init_flash(); - /* Configure pin muxing for UART0 */ - GPIO_REG(GPIO_OUTPUT_VAL) |= IOF0_UART0_MASK; - GPIO_REG(GPIO_OUTPUT_EN) |= IOF0_UART0_MASK; - GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK; - GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK; - /* Configure GPIOs for LEDs */ gpio_init(LED0_PIN, GPIO_OUT); gpio_init(LED1_PIN, GPIO_OUT); diff --git a/boards/hifive1b/include/periph_conf.h b/boards/hifive1b/include/periph_conf.h index a38247f808..53986a311a 100644 --- a/boards/hifive1b/include/periph_conf.h +++ b/boards/hifive1b/include/periph_conf.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2019 Ken Rabold + * 2019 Inria * * This file is subject to the terms and conditions of the GNU Lesser General * Public License v2.1. See the file LICENSE in the top level directory for more @@ -14,11 +15,14 @@ * @brief Peripheral specific definitions for the HiFive1b RISC-V board * * @author Ken Rabold + * @author Alexandre Abadie */ #ifndef PERIPH_CONF_H #define PERIPH_CONF_H +#include "periph_cpu.h" + #ifdef __cplusplus extern "C" { #endif @@ -49,6 +53,28 @@ extern "C" { #define TIMER_NUMOF (1) /** @} */ +/** + * @name UART configuration + * @{ + */ +static const uart_conf_t uart_config[] = { + { + .addr = UART0_CTRL_ADDR, + .rx = GPIO_PIN(0, 16), + .tx = GPIO_PIN(0, 17), + .isr_num = INT_UART0_BASE, + }, + { + .addr = UART1_CTRL_ADDR, + .rx = GPIO_PIN(0, 18), + .tx = GPIO_PIN(0, 23), + .isr_num = INT_UART1_BASE, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +/** @} */ + /** * @name RTT/RTC configuration * @@ -76,16 +102,6 @@ extern "C" { #define PWM_NUMOF (3) /** @} */ -/** - * @name UART configuration - * - * @{ - */ -#define UART_NUMOF (2) -#define UART0_RX_INTR_PRIORITY (2) -#define UART1_RX_INTR_PRIORITY (2) -/** @} */ - #ifdef __cplusplus } #endif diff --git a/cpu/fe310/include/cpu.h b/cpu/fe310/include/cpu.h index 2d209c3c9e..cffe0084cb 100644 --- a/cpu/fe310/include/cpu.h +++ b/cpu/fe310/include/cpu.h @@ -25,8 +25,13 @@ #ifndef CPU_H #define CPU_H +#include + #include "thread.h" +#include "vendor/platform.h" +#include "vendor/plic_driver.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/cpu/fe310/include/periph_cpu.h b/cpu/fe310/include/periph_cpu.h index 70b817ed53..9e87c91b25 100644 --- a/cpu/fe310/include/periph_cpu.h +++ b/cpu/fe310/include/periph_cpu.h @@ -19,6 +19,10 @@ #ifndef PERIPH_CPU_H #define PERIPH_CPU_H +#include + +#include "cpu.h" + #ifdef __cplusplus extern "C" { #endif @@ -28,6 +32,39 @@ extern "C" { */ #define CPUID_LEN (12U) +#ifndef DOXYGEN +/** + * @brief Overwrite the default gpio_t type definition + */ +#define HAVE_GPIO_T +typedef uint8_t gpio_t; +#endif + +/** + * @brief Definition of a fitting UNDEF value + */ +#define GPIO_UNDEF (0xff) + +/** + * @brief Define a CPU specific GPIO pin generator macro + */ +#define GPIO_PIN(x, y) (x | y) + +/** + * @brief Structure for UART configuration data + */ +typedef struct { + uint32_t addr; /**< UART control register address */ + gpio_t rx; /**< RX pin */ + gpio_t tx; /**< TX pin */ + plic_source isr_num; /**< ISR source number */ +} uart_conf_t; + +/** + * @brief UART interrupt priority + */ +#define UART_ISR_PRIO (2) + /** * @brief Prevent shared timer functions from being used */ diff --git a/cpu/fe310/periph/uart.c b/cpu/fe310/periph/uart.c index dbc0182d77..3bf54c58c7 100644 --- a/cpu/fe310/periph/uart.c +++ b/cpu/fe310/periph/uart.c @@ -19,11 +19,11 @@ #include #include +#include +#include #include "irq.h" #include "cpu.h" -#include "periph_cpu.h" -#include "periph_conf.h" #include "periph/uart.h" #include "vendor/encoding.h" #include "vendor/platform.h" @@ -35,29 +35,28 @@ */ static uart_isr_ctx_t isr_ctx[UART_NUMOF]; +static inline void _uart_isr(uart_t dev) +{ + uint32_t data = _REG32(uart_config[dev].addr, UART_REG_RXFIFO); + + /* Intr cleared automatically when data is read */ + while ((data & UART_RXFIFO_EMPTY) != (uint32_t)UART_RXFIFO_EMPTY) { + isr_ctx[dev].rx_cb(isr_ctx[dev].arg, (uint8_t)(data & 0xff)); + data = _REG32(uart_config[dev].addr, UART_REG_RXFIFO); + } +} + void uart_isr(int num) { - uint32_t data; - - /* Invoke callback function */ - if (num == INT_UART0_BASE) { - data = UART0_REG(UART_REG_RXFIFO); - - /* Intr cleared automatically when data is read */ - while ((data & UART_RXFIFO_EMPTY) != (uint32_t)UART_RXFIFO_EMPTY) { - isr_ctx[0].rx_cb(isr_ctx[0].arg, (uint8_t) data); - data = UART0_REG(UART_REG_RXFIFO); - } - } - - if (num == INT_UART1_BASE) { - data = UART1_REG(UART_REG_RXFIFO); - - /* Intr cleared automatically when data is read */ - while ((data & UART_RXFIFO_EMPTY) != (uint32_t)UART_RXFIFO_EMPTY) { - isr_ctx[1].rx_cb(isr_ctx[1].arg, (uint8_t) data); - data = UART1_REG(UART_REG_RXFIFO); - } + switch (num) { + case INT_UART0_BASE: + _uart_isr(0); + break; + case INT_UART1_BASE: + _uart_isr(1); + break; + default: + break; } } @@ -66,9 +65,7 @@ int uart_init(uart_t dev, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) uint32_t uartDiv; /* Check for valid UART dev */ - if (dev >= UART_NUMOF) { - return UART_NODEV; - } + assert(dev < UART_NUMOF); /* Save interrupt callback context */ isr_ctx[dev].rx_cb = rx_cb; @@ -77,7 +74,7 @@ int uart_init(uart_t dev, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) /* Power on the device */ uart_poweron(dev); - /* Calculate buadrate divisor given current CPU clk rate + /* Calculate baudrate divisor given current CPU clk rate * Ignore the first run (icache needs to be warm) */ uartDiv = PRCI_measure_mcycle_freq(1000, RTC_FREQ); /* cppcheck-suppress redundantAssignment @@ -86,48 +83,37 @@ int uart_init(uart_t dev, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) uartDiv = uartDiv / baudrate; /* Enable UART 8-N-1 at given baudrate */ - if (dev == 0) { - /* Config UART */ - UART0_REG(UART_REG_DIV) = uartDiv; - UART0_REG(UART_REG_TXCTRL) = UART_TXEN; + _REG32(uart_config[dev].addr, UART_REG_DIV) = uartDiv; - /* Enable RX intr if there is a callback */ - if (rx_cb != NULL) { - /* Disable ext interrupts when setting up */ - clear_csr(mie, MIP_MEIP); + /* Select IOF0 */ + GPIO_REG(GPIO_IOF_SEL) &= ~(1 << uart_config[dev].tx); + /* Enable IOF */ + GPIO_REG(GPIO_IOF_EN) |= (1 << uart_config[dev].tx); - /* Configure UART ISR with PLIC */ - set_external_isr_cb(INT_UART0_BASE, uart_isr); - PLIC_enable_interrupt(INT_UART0_BASE); - PLIC_set_priority(INT_UART0_BASE, UART0_RX_INTR_PRIORITY); - UART0_REG(UART_REG_IE) = UART_IP_RXWM; - UART0_REG(UART_REG_RXCTRL) = UART_RXEN; + /* Enable TX */ + _REG32(uart_config[dev].addr, UART_REG_TXCTRL) = UART_TXEN; - /* Re-eanble ext interrupts */ - set_csr(mie, MIP_MEIP); - } - } + /* Enable RX intr if there is a callback */ + if (rx_cb) { + /* Select IOF0 */ + GPIO_REG(GPIO_IOF_SEL) &= ~(1 << uart_config[dev].rx); + /* Enable IOF */ + GPIO_REG(GPIO_IOF_EN) |= (1 << uart_config[dev].rx); - if (dev == 1) { - /* Config UART */ - UART1_REG(UART_REG_DIV) = uartDiv; - UART1_REG(UART_REG_TXCTRL) = UART_TXEN; + /* Disable ext interrupts when setting up */ + clear_csr(mie, MIP_MEIP); - /* Enable RX intr if there is a callback */ - if (rx_cb != NULL) { - /* Disable ext interrupts when setting up */ - clear_csr(mie, MIP_MEIP); + /* Configure UART ISR with PLIC */ + set_external_isr_cb(uart_config[dev].isr_num, uart_isr); + PLIC_enable_interrupt(uart_config[dev].isr_num); + PLIC_set_priority(uart_config[dev].isr_num, UART_ISR_PRIO); + _REG32(uart_config[dev].addr, UART_REG_IE) = UART_IP_RXWM; - /* Configure UART ISR with PLIC */ - set_external_isr_cb(INT_UART1_BASE, uart_isr); - PLIC_enable_interrupt(INT_UART1_BASE); - PLIC_set_priority(INT_UART1_BASE, UART1_RX_INTR_PRIORITY); - UART1_REG(UART_REG_IE) = UART_IP_RXWM; - UART1_REG(UART_REG_RXCTRL) = UART_RXEN; + /* Enable RX */ + _REG32(uart_config[dev].addr, UART_REG_RXCTRL) = UART_RXEN; - /* Re-eanble ext interrupts */ - set_csr(mie, MIP_MEIP); - } + /* Re-enable ext interrupts */ + set_csr(mie, MIP_MEIP); } return UART_OK; @@ -135,28 +121,13 @@ int uart_init(uart_t dev, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) void uart_write(uart_t dev, const uint8_t *data, size_t len) { - if (dev == 0) { - for (size_t i = 0; i < len; i++) { - /* Wait for FIFO to empty */ - while ((UART0_REG(UART_REG_TXFIFO) & UART_TXFIFO_FULL) - == (uint32_t)UART_TXFIFO_FULL) - ; + for (size_t i = 0; i < len; i++) { + /* Wait for FIFO to empty */ + while ((_REG32(uart_config[dev].addr, UART_REG_TXFIFO) & UART_TXFIFO_FULL) + == (uint32_t)UART_TXFIFO_FULL) {}; - /* Write a byte */ - UART0_REG(UART_REG_TXFIFO) = data[i]; - } - } - - if (dev == 1) { - for (size_t i = 0; i < len; i++) { - /* Wait for FIFO to empty */ - while ((UART1_REG(UART_REG_TXFIFO) & UART_TXFIFO_FULL) - == (uint32_t)UART_TXFIFO_FULL) - ; - - /* Write a byte */ - UART1_REG(UART_REG_TXFIFO) = data[i]; - } + /* Write a byte */ + _REG32(uart_config[dev].addr, UART_REG_TXFIFO) = data[i]; } }