1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/mips_pic32_common/periph/uart.c
Francois Berder 8775254755 cpu: mips_pic32_common: Refactor UART
Signed-off-by: Francois Berder <18538310+francois-berder@users.noreply.github.com>
2020-03-25 19:10:01 +00:00

194 lines
4.4 KiB
C

/*
* Copyright(C) 2016,2017 Imagination Technologies Limited and/or its
* affiliated group companies.
*
* 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 details.
*
*/
/**
* @ingroup cpu_mips_pic32_common
* @ingroup drivers_periph_uart
* @{
*
* @file
* @brief Peripheral UART driver implementation
*
* @}
*/
#include "cpu.h"
#include "eic.h"
#include "sched.h"
#include "thread.h"
#include "assert.h"
#include "periph/uart.h"
#include "periph/gpio.h"
#define UxMODE(U) ((U)[0x00/4])
#define UxMODECLR(U) ((U)[0x04/4])
#define UxMODESET(U) ((U)[0x08/4])
#define UxSTA(U) ((U)[0x10/4])
#define UxSTACLR(U) ((U)[0x14/4])
#define UxSTASET(U) ((U)[0x18/4])
#define UxTXREG(U) ((U)[0x20/4])
#define UxRXREG(U) ((U)[0x30/4])
#define UxBRG(U) ((U)[0x40/4])
/**
* @brief Allocate memory to store the callback functions.
*/
static uart_isr_ctx_t uart_ctx[UART_NUMOF];
static void irq_handler(uart_t uart)
{
uint32_t status = UxSTA(uart_config[uart].base);
if (status & _U1STA_URXDA_MASK) {
uart_ctx[uart].rx_cb(uart_ctx[uart].arg, UxRXREG(uart_config[uart].base));
}
if (status & _U1STA_OERR_MASK) {
UxSTA(uart_config[uart].base) &= ~_U1STA_OERR_MASK;
}
#ifdef CPU_FAM_PIC32MX
eic_clear_flag(uart_config[uart].irq);
#else
eic_clear_flag(uart_config[uart].vector);
#endif
mips32r2_isr_end();
}
#ifdef UART_0_ISR
void UART_0_ISR(void)
{
irq_handler(UART_DEV(0));
}
#endif
#ifdef UART_1_ISR
void UART_1_ISR(void)
{
irq_handler(UART_DEV(1));
}
#endif
#ifdef UART_2_ISR
void UART_2_ISR(void)
{
irq_handler(UART_DEV(2));
}
#endif
#ifdef UART_3_ISR
void UART_3_ISR(void)
{
irq_handler(UART_DEV(3));
}
#endif
#ifdef UART_4_ISR
void UART_4_ISR(void)
{
irq_handler(UART_DEV(4));
}
#endif
#ifdef UART_5_ISR
void UART_5_ISR(void)
{
irq_handler(UART_DEV(5));
}
#endif
static void uart_init_pins(uart_t uart, uart_rx_cb_t rx_cb)
{
/* configure TX pin */
gpio_init(uart_config[uart].tx_pin, GPIO_OUT);
/* set TX pin high to avoid garbage during further initialization */
gpio_set(uart_config[uart].tx_pin);
*(uart_config[uart].tx_mux_reg) = uart_config[uart].tx_af;
/* configure RX pin */
if (rx_cb) {
gpio_init(uart_config[uart].rx_pin, GPIO_IN_PU);
*(uart_config[uart].rx_mux_reg) = uart_config[uart].rx_af;
}
}
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
{
assert(uart < UART_NUMOF);
uart_init_pins(uart, rx_cb);
UxBRG(uart_config[uart].base) = (uart_config[uart].clock / (16 * baudrate)) - 1;
UxSTA(uart_config[uart].base) = 0;
if (rx_cb) {
/* register callbacks */
uart_ctx[uart].rx_cb = rx_cb;
uart_ctx[uart].arg = arg;
UxSTASET(uart_config[uart].base) = _U1STA_URXEN_MASK;
switch (uart) {
#ifdef UART_0_ISR
case UART_DEV(0): set_external_isr_cb(uart_config[uart].vector, UART_0_ISR); break;
#endif
#ifdef UART_1_ISR
case UART_DEV(1): set_external_isr_cb(uart_config[uart].vector, UART_1_ISR); break;
#endif
#ifdef UART_2_ISR
case UART_DEV(2): set_external_isr_cb(uart_config[uart].vector, UART_2_ISR); break;
#endif
#ifdef UART_3_ISR
case UART_DEV(3): set_external_isr_cb(uart_config[uart].vector, UART_3_ISR); break;
#endif
#ifdef UART_4_ISR
case UART_DEV(4): set_external_isr_cb(uart_config[uart].vector, UART_4_ISR); break;
#endif
#ifdef UART_5_ISR
case UART_DEV(5): set_external_isr_cb(uart_config[uart].vector, UART_5_ISR); break;
#endif
}
eic_configure_priority(uart_config[uart].vector, 1, 0);
#ifdef CPU_FAM_PIC32MX
eic_enable(uart_config[uart].irq);
#else
eic_enable(uart_config[uart].vector);
#endif
}
UxSTASET(uart_config[uart].base) = _U1STA_UTXEN_MASK;
UxMODE(uart_config[uart].base) = _U1MODE_ON_MASK;
return 0;
}
void uart_write(uart_t uart, const uint8_t *data, size_t len)
{
assert(uart < UART_NUMOF);
while(len--) {
while(UxSTA(uart_config[uart].base)& _U1STA_UTXBF_MASK) {}
UxTXREG(uart_config[uart].base) = *data++;
}
}
void uart_poweron(uart_t uart)
{
assert(uart < UART_NUMOF);
UxMODESET(uart_config[uart].base)= _U1MODE_ON_MASK;
}
void uart_poweroff(uart_t uart)
{
assert(uart < UART_NUMOF);
UxMODECLR(uart_config[uart].base)= _U1MODE_ON_MASK;
}