This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrf52832 uart tx works only with NRF_UARTE0 read after EndTx

FormerMember
FormerMember

Greetings, There is a bit of strange operation in UARTE peripheral in nrf52832 with the DK. In the simple code below, if both of the if statements with comments 'Check 1' and 'Check 2' are removed the 'hello' prints are not sent and I get some junk value. If either of the two reads to the UARTE registers is made in these if statement, then the 'hello' prints are sent out correctly. What's happening? I don't see any errata related to UARTE peripheral.

Thanks.

Toolchain: GCC 4.9.3q2 on Linux

#include <stdbool.h>
#include <stdint.h>
#include "nrf_delay.h"
#include "nrf52-gpio.h"
#include "nrf52-clock.h"
#include "board.h"
#include "nrf52-uart.h"

int main(void)
{
	nrf_gpio_cfg_output(LED1);
	nrf_gpio_cfg_output(LED2);
	nrf_gpio_cfg_output(LED3);
	nrf_gpio_cfg_output(LED4);

	/* Configure TX and RX pins from board.h */
	nrf_gpio_cfg_output(TX_PIN_NUMBER);
	nrf_gpio_cfg_input(RX_PIN_NUMBER, GPIO_PIN_CNF_PULL_Disabled);
	NRF_UARTE0->PSEL.TXD = TX_PIN_NUMBER;
	NRF_UARTE0->PSEL.RTS = RX_PIN_NUMBER;

	nrf_gpio_cfg_output(RTS_PIN_NUMBER);
	nrf_gpio_cfg_input(CTS_PIN_NUMBER, GPIO_PIN_CNF_PULL_Disabled);
	NRF_UARTE0->PSEL.RTS = RTS_PIN_NUMBER;
	NRF_UARTE0->PSEL.CTS = CTS_PIN_NUMBER;
	NRF_UARTE0->CONFIG = (UARTE_CONFIG_HWFC_Enabled << UARTE_CONFIG_HWFC_Pos);

	/* Configure other UART parameters, BAUD rate is defined in nrf52-uart.h	*/
	NRF_UARTE0->BAUDRATE = (UARTE_BAUDRATE << UARTE_BAUDRATE_BAUDRATE_Pos);
	NRF_UARTE0->ENABLE = (UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos);

    // Toggle LEDs.
    while (true)
    {
    	uint32_t i;
        for (i = 0; i < 2; i++)
        {
        	if(i){
        		NRF_P0->OUTSET = (1<<LED1);
        	} else {
        		NRF_P0->OUTCLR = (1<<LED1);
        	}
        	nrf_delay_ms(500);

            uint8_t str[] = "hello\n";
            uint32_t len = 6;

            NRF_UARTE0->EVENTS_ENDTX = 0;
            NRF_UARTE0->TASKS_STOPTX = 0;

        	NRF_UARTE0->TXD.PTR = (uint32_t)((uint8_t *) str);
        	NRF_UARTE0->TXD.MAXCNT = (uint32_t) len;

        	NRF_UARTE0->TASKS_STARTTX = 1;

        	while((0 == NRF_UARTE0->EVENTS_ENDTX)&&(0 == NRF_UARTE0->EVENTS_TXSTOPPED)){}

            /*****Check 1*****/
        	if(NRF_UARTE0->EVENTS_ENDTX){
        		NRF_P0->OUTSET = (1<<LED3);
        	}

            /*****Check 2*****/    
        	if(6 == NRF_UARTE0->TXD.AMOUNT){
        		NRF_P0->OUTSET = (1<<LED2);
        	}

            NRF_UARTE0->EVENTS_ENDTX = 0;
            NRF_UARTE0->TASKS_STOPTX = 0;
        }
    }
}
Parents
  • Finally, I am answering assuming that you are working on windows. This is GCC bug, if you are using 4_9-2015q2-20150609 There is some issue with it when you enable optimizations.

    NRF_UARTE0->TASKS_STOPTX = 0;
    

    You cannot do this, or more specifically it will have no effect.

    files to analyse main.asm.dump main.no_asm.dump

  • RK, you can probably help me out here I have made this code simple

    #include <stdbool.h>
    #include <stdint.h>
    #include "nrf_delay.h"
    #include "nrf_gpio.h"
    #include "nrf_clock.h"
    #include "boards.h"
    #include "nrf_uart.h"
    
    int main(void)
    {
        /* Configure TX and RX pins from board.h */
        nrf_gpio_cfg_output(TX_PIN_NUMBER);
        nrf_gpio_cfg_input(RX_PIN_NUMBER, GPIO_PIN_CNF_PULL_Disabled);
        NRF_UARTE0->ENABLE = (UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos);
        NRF_UARTE0->PSEL.TXD = TX_PIN_NUMBER;
        NRF_UARTE0->PSEL.RTS = RX_PIN_NUMBER;
    
        nrf_gpio_cfg_output(RTS_PIN_NUMBER);
        nrf_gpio_cfg_input(CTS_PIN_NUMBER, GPIO_PIN_CNF_PULL_Disabled);
        NRF_UARTE0->PSEL.RTS = RTS_PIN_NUMBER;
        NRF_UARTE0->PSEL.CTS = CTS_PIN_NUMBER;
        NRF_UARTE0->CONFIG = (UARTE_CONFIG_HWFC_Enabled << UARTE_CONFIG_HWFC_Pos);
    
        /* Configure other UART parameters, BAUD rate is defined in nrf52-uart.h    */
        NRF_UARTE0->BAUDRATE = (UARTE_BAUDRATE_BAUDRATE_Baud115200 << UARTE_BAUDRATE_BAUDRATE_Pos);
    
        uint8_t str[] = "hello\n";
        uint32_t len = 6;
    
        while(true) 
        {
            NRF_UARTE0->TXD.PTR = (uint32_t)((uint8_t *) str);
            NRF_UARTE0->TXD.MAXCNT = (uint32_t) len;
    
            NRF_UARTE0->TASKS_STARTTX = 1;
            NRF_UARTE0->EVENTS_ENDTX = 0;
            while((0 == NRF_UARTE0->EVENTS_ENDTX));
            register uint32_t delay asm ("r0") = 1;
        __ASM volatile (
              " NOP"
               : "+r" (delay));
        }
    }
    

    With flags -O3, If i remove the ASM in the last, then it writes some garbage. If i add that ASM it does not. The problem does not seem to be write buffer, looking into the generated ASM, it looks like GCC is optimizing away below when no asm is used

    uint8_t str[] = "hello\n"; uint32_t len = 6;

    I am attaching two assembly dump files with and without the ASM code in the last. With ASM, look that there are few extra instructions while assigning str = hello

Reply
  • RK, you can probably help me out here I have made this code simple

    #include <stdbool.h>
    #include <stdint.h>
    #include "nrf_delay.h"
    #include "nrf_gpio.h"
    #include "nrf_clock.h"
    #include "boards.h"
    #include "nrf_uart.h"
    
    int main(void)
    {
        /* Configure TX and RX pins from board.h */
        nrf_gpio_cfg_output(TX_PIN_NUMBER);
        nrf_gpio_cfg_input(RX_PIN_NUMBER, GPIO_PIN_CNF_PULL_Disabled);
        NRF_UARTE0->ENABLE = (UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos);
        NRF_UARTE0->PSEL.TXD = TX_PIN_NUMBER;
        NRF_UARTE0->PSEL.RTS = RX_PIN_NUMBER;
    
        nrf_gpio_cfg_output(RTS_PIN_NUMBER);
        nrf_gpio_cfg_input(CTS_PIN_NUMBER, GPIO_PIN_CNF_PULL_Disabled);
        NRF_UARTE0->PSEL.RTS = RTS_PIN_NUMBER;
        NRF_UARTE0->PSEL.CTS = CTS_PIN_NUMBER;
        NRF_UARTE0->CONFIG = (UARTE_CONFIG_HWFC_Enabled << UARTE_CONFIG_HWFC_Pos);
    
        /* Configure other UART parameters, BAUD rate is defined in nrf52-uart.h    */
        NRF_UARTE0->BAUDRATE = (UARTE_BAUDRATE_BAUDRATE_Baud115200 << UARTE_BAUDRATE_BAUDRATE_Pos);
    
        uint8_t str[] = "hello\n";
        uint32_t len = 6;
    
        while(true) 
        {
            NRF_UARTE0->TXD.PTR = (uint32_t)((uint8_t *) str);
            NRF_UARTE0->TXD.MAXCNT = (uint32_t) len;
    
            NRF_UARTE0->TASKS_STARTTX = 1;
            NRF_UARTE0->EVENTS_ENDTX = 0;
            while((0 == NRF_UARTE0->EVENTS_ENDTX));
            register uint32_t delay asm ("r0") = 1;
        __ASM volatile (
              " NOP"
               : "+r" (delay));
        }
    }
    

    With flags -O3, If i remove the ASM in the last, then it writes some garbage. If i add that ASM it does not. The problem does not seem to be write buffer, looking into the generated ASM, it looks like GCC is optimizing away below when no asm is used

    uint8_t str[] = "hello\n"; uint32_t len = 6;

    I am attaching two assembly dump files with and without the ASM code in the last. With ASM, look that there are few extra instructions while assigning str = hello

Children
No Data
Related