Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Interaction between GPIOTE pin and UART RTS

I have the UART configured using the standard boiler plate code, with flow control enabled, where the RTS output is assigned pin 5.

 I have defined a GPIOTE pin 25 as an output, with its initial state defined as Hi. I then set this output low using nrf_drv_gpiote_out_clear(opPin ); sure enough opPin goes low, however so does RTS.

This is 100% repeatable.

Any ideas?

Parents
  • Hi,

    That's pretty strange. 

    Do you mind posting the code showing how you configure pin 25 as an output, or preferably the whole code? That is the only thing you added to the SDK example right?

    What SDK version do you use? And what is the complete serial number on top of your nRF5 IC?

  • Using on sdk_13.0.0_04a0bfd Based on the UART example.

    Hardware: V1.00

    S/N: 682336494

    I configure the pin 25 thus:

    #define opPin	25
    void io_init( void ) {
        ret_code_t err_code;
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    
        /**
         * Output
         */
    	// Where the true specifies the initial state of the O/P line so in  this case Hi
    	nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE( true );
    	err_code = nrf_drv_gpiote_out_init(opPin, &out_config);
    	APP_ERROR_CHECK(err_code);
    }
    

    configuring the UART (you will notice the desperate attempts to keep RTS Hi !! even this generates a 1.98us low during the execution of APP_UART_FIFO_INIT):

    static void uart_init() {
        uint32_t err_code;
        const app_uart_comm_params_t comm_params =
          {
              RX_PIN_NUMBER,
              TX_PIN_NUMBER,
              RTS_PIN_NUMBER,
              CTS_PIN_NUMBER,
    		  APP_UART_FLOW_CONTROL_ENABLED,//APP_UART_FLOW_CONTROL_DISABLED,//
              false,
    		  UART_BAUDRATE_BAUDRATE_Baud4800 //UART_BAUDRATE_BAUDRATE_Baud115200
          };
    
        NRF_UART0->TASKS_STOPRX = 1;
        APP_UART_FIFO_INIT(&comm_params,
                             UART_RX_BUF_SIZE,
                             UART_TX_BUF_SIZE,
    						 uart_error_handle,
                             APP_IRQ_PRIORITY_LOWEST,
                             err_code);
        NRF_UART0->TASKS_STOPRX = 1;
        APP_ERROR_CHECK(err_code);
    }

    and then to take opPin Low:

    nrf_drv_gpiote_out_clear( opPin );

    The weird thing is I have also see the same effect caused by the execution of this line:

    SEGGER_RTT_WriteString(0, "Exectuing UART Test\n");

    which is called after the initialisation of UART and IO as seen below in main which a bit of a mess, however if you step through from the start, I see RTS go Low when the opPin is cleared, and No opPin is not connected to RTS!

    int main(void)
    {
    	io_init();
        uart_init();
        NRF_UART0->TASKS_STOPRX = 1;
        nrf_drv_gpiote_out_clear( opPin );
        NRF_UART0->TASKS_STOPRX = 1;
        //SEGGER_RTT_WriteString(0, "Exectuing UART Test\n"); // Print message to RTT to the application flow
        //log_init();
    
        //printf("uart_init\r\n");
        //SEGGER_RTT_printf(0, "uart_init\r\n"); // Print service UUID should match definition BLE_UUID_OUR_SERVICE
        //bsp_board_leds_init();
    
        //SEGGER_RTT_WriteString(0,"io_init\r\n");
        //app_uart_flush();
    
        nrf_drv_gpiote_out_clear( opPin );
        NRF_UART0->TASKS_STOPRX = 1;
        //while( !configComplete ){}
    
        while (true) {
        	// do nothing
        }
    }

    I am suspicious of my sdk_config.h

    3755.sdk_config.h

Reply
  • Using on sdk_13.0.0_04a0bfd Based on the UART example.

    Hardware: V1.00

    S/N: 682336494

    I configure the pin 25 thus:

    #define opPin	25
    void io_init( void ) {
        ret_code_t err_code;
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    
        /**
         * Output
         */
    	// Where the true specifies the initial state of the O/P line so in  this case Hi
    	nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE( true );
    	err_code = nrf_drv_gpiote_out_init(opPin, &out_config);
    	APP_ERROR_CHECK(err_code);
    }
    

    configuring the UART (you will notice the desperate attempts to keep RTS Hi !! even this generates a 1.98us low during the execution of APP_UART_FIFO_INIT):

    static void uart_init() {
        uint32_t err_code;
        const app_uart_comm_params_t comm_params =
          {
              RX_PIN_NUMBER,
              TX_PIN_NUMBER,
              RTS_PIN_NUMBER,
              CTS_PIN_NUMBER,
    		  APP_UART_FLOW_CONTROL_ENABLED,//APP_UART_FLOW_CONTROL_DISABLED,//
              false,
    		  UART_BAUDRATE_BAUDRATE_Baud4800 //UART_BAUDRATE_BAUDRATE_Baud115200
          };
    
        NRF_UART0->TASKS_STOPRX = 1;
        APP_UART_FIFO_INIT(&comm_params,
                             UART_RX_BUF_SIZE,
                             UART_TX_BUF_SIZE,
    						 uart_error_handle,
                             APP_IRQ_PRIORITY_LOWEST,
                             err_code);
        NRF_UART0->TASKS_STOPRX = 1;
        APP_ERROR_CHECK(err_code);
    }

    and then to take opPin Low:

    nrf_drv_gpiote_out_clear( opPin );

    The weird thing is I have also see the same effect caused by the execution of this line:

    SEGGER_RTT_WriteString(0, "Exectuing UART Test\n");

    which is called after the initialisation of UART and IO as seen below in main which a bit of a mess, however if you step through from the start, I see RTS go Low when the opPin is cleared, and No opPin is not connected to RTS!

    int main(void)
    {
    	io_init();
        uart_init();
        NRF_UART0->TASKS_STOPRX = 1;
        nrf_drv_gpiote_out_clear( opPin );
        NRF_UART0->TASKS_STOPRX = 1;
        //SEGGER_RTT_WriteString(0, "Exectuing UART Test\n"); // Print message to RTT to the application flow
        //log_init();
    
        //printf("uart_init\r\n");
        //SEGGER_RTT_printf(0, "uart_init\r\n"); // Print service UUID should match definition BLE_UUID_OUR_SERVICE
        //bsp_board_leds_init();
    
        //SEGGER_RTT_WriteString(0,"io_init\r\n");
        //app_uart_flush();
    
        nrf_drv_gpiote_out_clear( opPin );
        NRF_UART0->TASKS_STOPRX = 1;
        //while( !configComplete ){}
    
        while (true) {
        	// do nothing
        }
    }

    I am suspicious of my sdk_config.h

    3755.sdk_config.h

Children
  • Also see this issue when toggling GPIO lines (as opposed to GPIOTE) for example when calling bsp_board_leds_init(); however on this occasion using sdk14 and Segger Embedded Studio. This time changing the settings of the sdk_config.h via app_config.h

    Help!!

  • Hi,

    I have done some more debugging and I have a question for you: Are you sure this is related to the GPIO and/or the RTT? What happens if you don't do anything after initializing the UART?

    In an attempt to narrow it it down I got as far as this:

    #define OUT_PIN	25
    
    int main(void)
    {    
        NRF_UARTE0->PSEL.RTS = RTS_PIN_NUMBER;
        NRF_UARTE0->ENABLE = 8;    
        NRF_UARTE0->TASKS_STARTRX = 1;
        
        while (true) {
        	
        }
    }

    As you can see it wasn't necessary to toggle any GPIO to make the RTS go low. It was only necessary to start the RX and this also happens inside APP_UART_FIFO_INIT().

    So it might be that this is just expected behaviour. 

  • Thanks for pursuing this.

    I am not sure which component is misbehaving GPIO and/or the RTT. [context] I decided to use a completely unrelated custom (as I thought) IO line (Pin 24 (Pin 25 appeared to have some decoupling)) to control the CTS line on my peripheral as I couldn't get the Nordic RTS line to change and block incoming data. The inability to block incoming data resulted in overrun errors.

    [observation] It was while changing my custom GPIO line, stepping through the code, that I saw the Nordic RTS change state. My custom GPIO line and the Nordic RTS line were/are completely disconnected both physically (not connected electrically) and code. I wouldn't consider this expected behaviour which is why I hi-lighted the issue.

    I have recently made progress using the custom GPIO line as I can change its state (exactly when needed) relative to reseting the peripheral on another GPIO line. I would have preferred not to have used this approach and to have pursued a the conventional configuration.

  • Hi,

    I have debugged some more and I think the problem is that the RX task is enabled inside APP_UART_FIFO_INIT(), as I mentioned earlier. Here is the call stack with the path to the instruction.

    After RX is enabled, the UART feels ready to receive and hence activates the RTS signal. I don't think it is related to neither RTT nor any GPIO actions. At least I'm not able to reproduce that. The enabling of RX is embedded quite deep into the app_uart library and I couldn't find a way to cheat it. Hence I think you need to keep doing what you describe above, or drop the app_uart library and use the UART drivers directly.

  • Martin thanks for pursuing this further. I would like to use your (the Nordic) RTS, however given that it changes state when I change the state of an GPIOTE line then I think the likely hood is low - this cannot be correct and must be a bug.

    Currently don't have time to investigate using the UART drivers directly, however it would engender greater understanding so would be an aspiration. Is there any example code and or documentation taking the read from an abstract level down the meet the driver?

Related