Skip to content

Commit 3663494

Browse files
author
Marcus Chang
committed
Serial re-implementation for the NRF52 series
Serial implementation uses UARTE instead of UART peripheral: * EasyDMA is used for reading and writing data. * Triple buffering for receiving data. See README for full description.
1 parent 9502011 commit 3663494

File tree

19 files changed

+1854
-492
lines changed

19 files changed

+1854
-492
lines changed

targets/TARGET_NORDIC/TARGET_NRF5x/PeripheralPinsDefault.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,26 @@
2121
* Can be overwritten by user.
2222
*/
2323
MBED_WEAK const PinMapI2C PinMap_I2C[1] = {
24-
{NC, NC, NC}
24+
{ NC, NC, NC }
2525
};
2626

2727
/* Default mapping between SPI pins and SPI instance.
2828
* Can be overwritten by user.
2929
*/
3030
MBED_WEAK const PinMapSPI PinMap_SPI[1] = {
31-
{NC, NC, NC, NC}
31+
{ NC, NC, NC, NC }
3232
};
3333

3434
/* Default mapping between PWM pins and PWM instance.
3535
* Can be overwritten by user.
3636
*/
3737
MBED_WEAK const PinMapPWM PinMap_PWM[1] = {
38-
{NC, NC}
38+
{ NC, NC }
39+
};
40+
41+
/* Default mapping between UART pins and UART instance.
42+
* Can be overwritten by user.
43+
*/
44+
MBED_WEAK const PinMapUART PinMap_UART[1] = {
45+
{ NC, NC, NC }
3946
};

targets/TARGET_NORDIC/TARGET_NRF5x/README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,65 @@ The tables must be placed in a C compilation file.
4040
1. When called from the same thread, it is safe to assign I2C and SPI objects to the same instance.
4141
1. If an instance is being used exclusively for either I2C or SPI, the objects can safely be called from multiple threads.
4242
1. If an instance is being used for both I2C and SPI, the user must provide thread safety between the objects.
43+
44+
45+
### Serial
46+
47+
The serial implementation uses the UARTE module which works exclusively through EasyDMA and RAM buffers. For optimal performance, each configured instance (NRF52832 has 1, NRF52840 has 2) has three buffers statically assigned:
48+
49+
1. Rx DMA buffer, which EasyDMA is currently writing to.
50+
1. Rx DMA buffer, pre-loaded in EasyDMA for automatic switchover.
51+
1. Rx FIFO buffer, for serving data to the application.
52+
53+
When the first DMA buffer is full or flushed the interrupt handler will automatically copy the DMA buffer to the FIFO buffer. This happens in interrupt context to avoid data loss and with UARTE interrupts set at the highest priority. The FIFO buffer is backed by the Nordic atomic fifo, which can be read and written to safely without disabling interrupts.
54+
55+
#### Customization
56+
57+
All buffers can be resized to fit the application:
58+
59+
```
60+
"name": "nordic",
61+
"config": {
62+
"uart-dma-size": {
63+
"help": "UART DMA buffer. 2 buffers per instance. DMA buffer is filled by UARTE",
64+
"value": 8
65+
},
66+
"uart-0-fifo-size": {
67+
"help": "UART0 FIFO buffer. FIFO buffer is filled from DMA buffer.",
68+
"value": 32
69+
},
70+
"uart-1-fifo-size": {
71+
"help": "UART1 FIFO buffer. FIFO buffer is filled from DMA buffer.",
72+
"value": 32
73+
}
74+
}
75+
```
76+
77+
All DMA buffers are the same size and must be at least 5 bytes due to hardware restrictions. DMA buffers should be sized to handle the worst expected interrupt latency. FIFO buffers can be configured per instance and the size should reflect the largest expected burst data. For example, a serial debug port might receive a line of data at a time, so an 80 byte FIFO buffer would be adequate. A serial port connected to a wifi radio should have a FIFO buffer in the kilo byte range.
78+
79+
For the NRF52840, UARTE instances are assigned based on pins and calling order. Serial objects with the same pin configurations will go to the same instance. A custom configuration table can be provided by overriding the weakly defined default empty table. In the example below, serial objects using pins `p1` and `p2` for `Tx` and `Rx` will always be assigned to `Instance 1` and serial objects using pins `p3` and `p4` for `Tx` and `Rx` will be assigned to `Instance 0` regardless of calling order. The custom configuration table must always be terminated with a row of `NC`.
80+
81+
```
82+
const PinMapI2C PinMap_UART[] = {
83+
{p1, p2, 1},
84+
{p3, p4, 0},
85+
{NC, NC, NC}
86+
};
87+
```
88+
89+
The table must be placed in a C compilation file.
90+
91+
92+
#### RTC2
93+
94+
Because each DMA buffer must be at least 5 bytes deep, each buffer is automatically flushed after a certain idle period to ensure low latency and correctness. This idle timeout is implemented using 2 of the 4 channels on RTC instance 2. This leaves RTC0 for the SoftDevice and RTC1 for Mbed tickers.
95+
96+
The RTC2 ISR is set at the lowest interrupt priority to ensure that UARTE interrupts take precedence. The last 2 of the 4 RTC channels are used for decoupling UARTE ISR context from Mbed IRQ events. This ensures that any user code will only delay other user callbacks and idle flushing and puts an upper bound on the interrupt handling time for the UARTE ISR.
97+
98+
#### Limitations
99+
100+
* The UARTE hardware only supports 8-bit, None/Even parity, and 1 stop bit.
101+
* The asynchronous read and write implementation currently only support 255 byte transfers.
102+
* The EasyDMA hardware can only read from RAM, which means all Tx buffers must reside in RAM. If a Tx buffer residing in flash is passed to the asynchronous write function, the function will try to copy the Tx buffer to a temporary internal buffer and transmit the data from there.
103+
* It is not possible to do an asynchronous write from flash and receive non-asynchronously at the same time since the non-asynchronous receive buffer is being used as the temporary transmission buffer.
104+

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PeripheralNames.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@
4545
extern "C" {
4646
#endif
4747

48-
#define STDIO_UART_TX TX_PIN_NUMBER
49-
#define STDIO_UART_RX RX_PIN_NUMBER
50-
#define STDIO_UART UART_0
51-
5248
typedef enum {
5349
UART_0 = (int)NRF_UART0_BASE
5450
} UARTName;

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/PinNames.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ typedef enum {
139139
// mBed interface Pins
140140
USBTX = TX_PIN_NUMBER,
141141
USBRX = RX_PIN_NUMBER,
142+
STDIO_UART_TX = TX_PIN_NUMBER,
143+
STDIO_UART_RX = RX_PIN_NUMBER,
142144

143145
SPI_PSELMOSI0 = p23,
144146
SPI_PSELMISO0 = p24,

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_UBLOX_NINA_B1/PinNames.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ typedef enum {
119119
TX_PIN_NUMBER = p6,
120120
CTS_PIN_NUMBER = p7,
121121
RTS_PIN_NUMBER = p31,
122+
STDIO_UART_TX = TX_PIN_NUMBER,
123+
STDIO_UART_RX = RX_PIN_NUMBER,
122124

123125
I2C_SDA = p2,
124126
I2C_SCL = p3,

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_NRF52_DK/PinNames.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ typedef enum {
140140
// mBed interface Pins
141141
USBTX = TX_PIN_NUMBER,
142142
USBRX = RX_PIN_NUMBER,
143+
STDIO_UART_TX = TX_PIN_NUMBER,
144+
STDIO_UART_RX = RX_PIN_NUMBER,
143145

144146
SPI_PSELMOSI0 = p23,
145147
SPI_PSELMISO0 = p24,

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_RBLAB_BLENANO2/PinNames.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ typedef enum {
130130
TX_PIN_NUMBER = p29,
131131
CTS_PIN_NUMBER = p28,
132132
RTS_PIN_NUMBER = p2,
133+
STDIO_UART_TX = TX_PIN_NUMBER,
134+
STDIO_UART_RX = RX_PIN_NUMBER,
133135

134136
// mBed interface Pins
135137
USBTX = TX_PIN_NUMBER,

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVA_NINA/PinNames.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ typedef enum {
8484
TX_PIN_NUMBER = p6,
8585
CTS_PIN_NUMBER = p7,
8686
RTS_PIN_NUMBER = p31,
87+
STDIO_UART_TX = TX_PIN_NUMBER,
88+
STDIO_UART_RX = RX_PIN_NUMBER,
89+
8790
I2C_SDA0 = p2,
8891
I2C_SCL0 = p3,
8992

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVK_NINA_B1/PinNames.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ typedef enum {
107107
TX_PIN_NUMBER = p6,
108108
CTS_PIN_NUMBER = p7,
109109
RTS_PIN_NUMBER = p31,
110+
STDIO_UART_TX = TX_PIN_NUMBER,
111+
STDIO_UART_RX = RX_PIN_NUMBER,
110112
I2C_SDA0 = p2,
111113
I2C_SCL0 = p3,
112114
// mBed interface pins

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_VBLUNO52/PinNames.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ typedef enum {
141141
TX_PIN_NUMBER = p6,
142142
CTS_PIN_NUMBER = p7, //not on Header
143143
RTS_PIN_NUMBER = p5, //not on Header
144+
STDIO_UART_TX = TX_PIN_NUMBER,
145+
STDIO_UART_RX = RX_PIN_NUMBER,
144146

145147
// mBed interface Pins
146148
USBTX = TX_PIN_NUMBER,

0 commit comments

Comments
 (0)