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

  • s'ok - I can work through this as it is, would be good if I could build it myself. I can see some odd differences already. The TX PTR is loaded from the contents of the SP, however in the asm version that's properly set up beforehand (see address 60: where it's copied from r2) but in the other version it's not set up at all as far as I can tell, so it should have random garbage in it. There's also no link to the string at the end of the assembly (that word at 0x88 in the asm version but missing from the other version), so yes it seems it was optimised out. However the registers are still written so .. currently making no sense at all.

    And why the addition of the r0 asm in there makes a difference is currently also beyond me.

    Will look some more, perhaps I'll see if I can set up a makefile and build it too.

Reply
  • s'ok - I can work through this as it is, would be good if I could build it myself. I can see some odd differences already. The TX PTR is loaded from the contents of the SP, however in the asm version that's properly set up beforehand (see address 60: where it's copied from r2) but in the other version it's not set up at all as far as I can tell, so it should have random garbage in it. There's also no link to the string at the end of the assembly (that word at 0x88 in the asm version but missing from the other version), so yes it seems it was optimised out. However the registers are still written so .. currently making no sense at all.

    And why the addition of the r0 asm in there makes a difference is currently also beyond me.

    Will look some more, perhaps I'll see if I can set up a makefile and build it too.

Children
No Data
Related