Skip to content

[feature-nrf528xx] Serial re-implementation for the NRF52 series #6435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 26, 2018
Merged

[feature-nrf528xx] Serial re-implementation for the NRF52 series #6435

merged 1 commit into from
Mar 26, 2018

Conversation

marcuschangarm
Copy link
Contributor

From the README:

Description

Serial

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:

  1. Rx DMA buffer, which EasyDMA is currently writing to.
  2. Rx DMA buffer, pre-loaded in EasyDMA for automatic switchover.
  3. Rx FIFO buffer, for serving data to the application.

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.

Customization

All buffers can be resized to fit the application:

    "name": "nordic",
    "config": {
        "uart-dma-size": {
            "help": "UART DMA buffer. 2 buffers per instance. DMA buffer is filled by UARTE",
            "value": 8
        },
        "uart-0-fifo-size": {
            "help": "UART0 FIFO buffer. FIFO buffer is filled from DMA buffer.",
            "value": 32
        },
        "uart-1-fifo-size": {
            "help": "UART1 FIFO buffer. FIFO buffer is filled from DMA buffer.",
            "value": 32
        }
    }

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.

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.

const PinMapI2C PinMap_UART[] = { 
    {p1, p2, 1},
    {p3, p4, 0},
    {NC, NC, NC}
};

The table must be placed in a C compilation file.

RTC2

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.

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.

Limitations

  • The UARTE hardware only supports 8-bit, None/Even parity, and 1 stop bit.
  • The asynchronous read and write implementation currently only support 255 byte transfers.
  • 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.
  • 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.

Pull request type

[x ] Fix
[ ] Refactor
[ ] New target
[ ] Feature
[ ] Breaking change

@marcuschangarm marcuschangarm changed the title Serial re-implementation for the NRF52 series [feature-nrf528xx] Serial re-implementation for the NRF52 series Mar 22, 2018
@0xc0170
Copy link
Contributor

0xc0170 commented Mar 23, 2018

/morph build

@mbed-ci
Copy link

mbed-ci commented Mar 23, 2018

Build : FAILURE

Build number : 1544
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/6435/

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.
@marcuschangarm
Copy link
Contributor Author

/morph build

@mbed-ci
Copy link

mbed-ci commented Mar 23, 2018

Build : SUCCESS

Build number : 1547
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/6435/

Triggering tests

/morph test
/morph uvisor-test
/morph export-build
/morph mbed2-build

@mbed-ci
Copy link

mbed-ci commented Mar 23, 2018

@mbed-ci
Copy link

mbed-ci commented Mar 24, 2018

@0xc0170
Copy link
Contributor

0xc0170 commented Mar 24, 2018

/morph export-build

@mbed-ci
Copy link

mbed-ci commented Mar 24, 2018

@0xc0170 0xc0170 merged commit fa76b63 into ARMmbed:feature-nrf528xx Mar 26, 2018
@marcuschangarm marcuschangarm deleted the feature-serial branch April 5, 2018 11:31
{
"name": "nordic",
"config": {
"uart-hwfc": {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcuschangarm @0xc0170 Would having uart declared in both mbed_lib.json and targets.json cause any issues when overriding it in custom_targets.json?

I'm using a custom_targets.json which is intended to disable flow control, but the mbed_config.h always ends up containing the following:

#define MBED_CONF_NORDIC_UART_HWFC                        1    // set by target:MCU_NRF52840
#define MBED_CONF_NORDIC_UART_HWFC                        1    // set by library:nordic

Since I'm not using hardware flow control this results in my printf's hanging.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you might have missed my response here: https://os.mbed.com/forum/upcoming-features/topic/29477/?page=1#comment-56395

In any case, targets.json has been cleaned up and a new PR is in the pipeline: #6547

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcuschangarm
I believe the recommendation did not work due to @vergil-SI overriding uart-hwfc and uart_hwfc in custom_targets.json.

#6547 does seems to address this issue by doing target specific target_overrides in mbed_lib.json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants