Skip to content
Snippets Groups Projects
Unverified Commit cb8c2b75 authored by Alexandre Abadie's avatar Alexandre Abadie
Browse files

cpu/nrf52: use UARTE device type for nrf52840

This requires to implement the use of EasyDMA for this kind of peripheral
parent 190d48c5
No related branches found
No related tags found
No related merge requests found
......@@ -43,9 +43,9 @@ extern "C" {
#define SPI_MOSISEL (dev(bus)->PSEL.MOSI)
#define SPI_MISOSEL (dev(bus)->PSEL.MISO)
#ifndef CPU_MODEL_NRF52840XXAA
#define UART_PIN_RTS GPIO_UNDEF
#define UART_PIN_CTS GPIO_UNDEF
#define UART_HWFLOWCTRL 0
#define UART_PIN_RTS (GPIO_UNDEF)
#define UART_PIN_CTS (GPIO_UNDEF)
#define UART_HWFLOWCTRL (0)
#define UART_IRQN (UARTE0_UART0_IRQn)
#endif
/** @} */
......@@ -165,7 +165,7 @@ typedef struct {
* @brief Structure for UART configuration data
*/
typedef struct {
NRF_UART_Type *dev; /**< UART device base register address */
NRF_UARTE_Type *dev; /**< UART with EasyDMA device base register address */
uint8_t rx_pin; /**< RX pin */
uint8_t tx_pin; /**< TX pin */
uint8_t rts_pin; /**< RTS pin - set to GPIO_UNDEF when not using HW flow control */
......
/*
* Copyright (C) 2014-2017 Freie Universität Berlin
* 2015 Jan Wagner <mail@jwagner.eu>
* 2018 Inria
*
*
* This file is subject to the terms and conditions of the GNU Lesser
......@@ -20,6 +21,7 @@
* @author Timo Ziegler <timo.ziegler@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Jan Wagner <mail@jwagner.eu>
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*
* @}
*/
......@@ -31,56 +33,65 @@
#include "periph/gpio.h"
#ifdef CPU_MODEL_NRF52840XXAA
#define PSEL_RXD dev(uart)->PSEL.RXD
#define PSEL_TXD dev(uart)->PSEL.TXD
#define PSEL_RTS dev(uart)->PSEL.RTS
#define PSEL_CTS dev(uart)->PSEL.CTS
#define UART_IRQN uart_config[uart].irqn
#define UART_PIN_RX uart_config[uart].rx_pin
#define UART_PIN_TX uart_config[uart].tx_pin
#define UART_PIN_RTS uart_config[uart].rts_pin
#define UART_PIN_CTS uart_config[uart].cts_pin
#define UART_HWFLOWCTRL (uart_config[uart].rts_pin != GPIO_UNDEF && \
uart_config[uart].cts_pin != GPIO_UNDEF)
#define PSEL_RXD dev(uart)->PSEL.RXD
#define PSEL_TXD dev(uart)->PSEL.TXD
#define PSEL_RTS dev(uart)->PSEL.RTS
#define PSEL_CTS dev(uart)->PSEL.CTS
#define UART_IRQN uart_config[uart].irqn
#define UART_PIN_RX uart_config[uart].rx_pin
#define UART_PIN_TX uart_config[uart].tx_pin
#define UART_PIN_RTS uart_config[uart].rts_pin
#define UART_PIN_CTS uart_config[uart].cts_pin
#define UART_HWFLOWCTRL (uart_config[uart].rts_pin != GPIO_UNDEF && \
uart_config[uart].cts_pin != GPIO_UNDEF)
#define ISR_CTX isr_ctx[uart]
/**
* @brief Allocate memory for the interrupt context
*/
static uart_isr_ctx_t isr_ctx[UART_NUMOF];
#else
#define PSEL_RXD dev(uart)->PSELRXD
#define PSEL_TXD dev(uart)->PSELTXD
#define PSEL_RTS dev(uart)->PSELRTS
#define PSEL_CTS dev(uart)->PSELCTS
#define UART_0_ISR isr_uart0
#define PSEL_RXD dev(uart)->PSELRXD
#define PSEL_TXD dev(uart)->PSELTXD
#define PSEL_RTS dev(uart)->PSELRTS
#define PSEL_CTS dev(uart)->PSELCTS
#define UART_0_ISR isr_uart0
#ifndef UART_PIN_RTS
#define UART_PIN_RTS GPIO_UNDEF
#define UART_PIN_RTS GPIO_UNDEF
#endif
#ifndef UART_PIN_CTS
#define UART_PIN_CTS GPIO_UNDEF
#define UART_PIN_CTS GPIO_UNDEF
#endif
#ifndef UART_HWFLOWCTRL
#define UART_HWFLOWCTRL 0
#define UART_HWFLOWCTRL 0
#endif
#endif
#define ISR_CTX isr_ctx
/**
* @brief Allocate memory for the interrupt context
*/
static uart_isr_ctx_t isr_ctx;
#endif
static inline NRF_UART_Type *dev(uart_t uart)
{
#ifdef CPU_MODEL_NRF52840XXAA
static inline NRF_UARTE_Type *dev(uart_t uart)
{
return uart_config[uart].dev;
}
static uint8_t rx_buf[UART_NUMOF];
#else
static inline NRF_UART_Type *dev(uart_t uart)
{
(void)uart;
return NRF_UART0;
#endif
return NRF_UART0;
}
#endif
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
{
assert(uart < UART_NUMOF);
/* remember callback addresses and argument */
isr_ctx.rx_cb = rx_cb;
isr_ctx.arg = arg;
ISR_CTX.rx_cb = rx_cb;
ISR_CTX.arg = arg;
#ifdef CPU_FAM_NRF51
/* power on the UART device */
......@@ -166,15 +177,25 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
}
/* enable the UART device */
#ifdef CPU_MODEL_NRF52840XXAA
dev(uart)->ENABLE = UARTE_ENABLE_ENABLE_Enabled;
dev(uart)->RXD.MAXCNT = 1;
dev(uart)->RXD.PTR = (uint32_t)&rx_buf[uart];
#else
dev(uart)->ENABLE = UART_ENABLE_ENABLE_Enabled;
/* enable TX and RX */
/* enable TX and RX*/
dev(uart)->TASKS_STARTTX = 1;
#endif
if (rx_cb) {
dev(uart)->TASKS_STARTRX = 1;
/* enable global and receiving interrupt */
NVIC_EnableIRQ(UART_IRQN);
#ifdef CPU_MODEL_NRF52840XXAA
dev(uart)->INTENSET = UARTE_INTENSET_RXDRDY_Msk;
#else
dev(uart)->INTENSET = UART_INTENSET_RXDRDY_Msk;
#endif
}
return UART_OK;
......@@ -184,6 +205,17 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
{
assert(uart < UART_NUMOF);
#ifdef CPU_MODEL_NRF52840XXAA /* nrf52840 uses EasyDMA to transmit data */
/* reset endtx flag */
dev(uart)->EVENTS_ENDTX = 0;
/* set data to transfer to DMA TX pointer */
dev(uart)->TXD.PTR = (uint32_t)data;
dev(uart)->TXD.MAXCNT = len;
/* start transmission */
dev(uart)->TASKS_STARTTX = 1;
/* wait for the end of transmission */
while (dev(uart)->EVENTS_ENDTX == 0) {}
#else
for (size_t i = 0; i < len; i++) {
/* This section of the function is not thread safe:
- another thread may mess up with the uart at the same time.
......@@ -202,6 +234,7 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
/* wait for any transmission to be done */
while (dev(uart)->EVENTS_TXDRDY == 0) {}
}
#endif
}
void uart_poweron(uart_t uart)
......@@ -216,18 +249,35 @@ void uart_poweroff(uart_t uart)
{
assert(uart < UART_NUMOF);
#ifndef CPU_MODEL_NRF52840XXAA
dev(uart)->TASKS_SUSPEND;
#else
(void)uart;
#endif
}
static inline void irq_handler(uart_t uart)
{
assert(uart < UART_NUMOF);
#ifdef CPU_MODEL_NRF52840XXAA /* nrf52840 uses EasyDMA to receive data */
if (dev(uart)->EVENTS_RXDRDY == 1) {
dev(uart)->EVENTS_RXDRDY = 0;
/* RXRDY doesn't mean that received byte is in RAM
so wait for ENDRX event */
while(dev(uart)->EVENTS_ENDRX == 0) {}
dev(uart)->EVENTS_ENDRX = 0;
/* Process received byte */
ISR_CTX.rx_cb(ISR_CTX.arg, rx_buf[uart]);
/* Restart RX task */
dev(uart)->TASKS_STARTRX = 1;
}
#else
if (dev(uart)->EVENTS_RXDRDY == 1) {
dev(uart)->EVENTS_RXDRDY = 0;
uint8_t byte = (uint8_t)(dev(uart)->RXD & 0xff);
isr_ctx.rx_cb(isr_ctx.arg, byte);
ISR_CTX.rx_cb(ISR_CTX.arg, byte);
}
#endif
cortexm_isr_end();
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment