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

UART close breakes whole communication

Hello 

I am writing low-power application where NRF is called from the other chip by interrupt, performs bluetooth scan and sends data back over UART. Of course, I want to close and reopen UART on every interrupt to decrease power consumption. On NRF52832 I am using SDK 15.2.0 and S132

So the problem is that after the uart initialization in main thread I am receiving interrupt, going to BLE scan and on the timeout event making app_uart_put() and app_uart_close(). In case app_uart_close() is not there - data is sent well. But when it is there I am receiving just several random (0xFE or 0xFF) bytes on other side and that is it. 

I was googling a lot and searched the forum. So here is what I already tried: 

1. Rewrite uart_init() from APP_UART_FIFO_INIT to app_uart_init(). Here is how my initialisation looks like right now 

	uint32_t					 err_code;
	app_uart_comm_params_t const comm_params =
	{
		.rx_pin_no	= RX_PIN_NUMBER,
		.tx_pin_no	= TX_PIN_NUMBER,
		.flow_control = APP_UART_FLOW_CONTROL_DISABLED,
		.use_parity = false,
		.baud_rate	= NRF_UART_BAUDRATE_115200
	};

	app_uart_buffers_t buffers;
	static uint8_t     rx_buf[UART_RX_BUF_SIZE];
	static uint8_t     tx_buf[UART_TX_BUF_SIZE];
	buffers.rx_buf      = rx_buf;
	buffers.rx_buf_size = sizeof (rx_buf);
	buffers.tx_buf      = tx_buf;
	buffers.tx_buf_size = sizeof (tx_buf);
	err_code = app_uart_init(&comm_params, &buffers, uart_event_handle, APP_IRQ_PRIORITY_HIGH);

2. Next few steps were taken from this thread. Increased UART interrupt priority to APP_IRQ_PRIORITY_HIGH.

3. Call uart_init() and app_uart_close() from main thread, there is now function in while(1) loop which checks flag status and does it from there, not from the event handler. 

4. Disable debug logs to RTT completely because apparently there is some issue with LOG and UART modules working together. 

None of those steps helped. Looking forward to hear your thoughts on this topic, for me it is quite crucial right now. Any links for the example/tutorial of UART in low-power mode would be much appreciated. Thanks!

Parents Reply Children
  • Hello Jorgen, 

    DEBUG_ON flag is undefined, here is the example when it doesn't work (uart_init is initialized in main()). When you comment out app_uart_close() it works. If uart_init is moved to the timeout event right before sending it still works without app_uart_close() and doesn't work with it. 

    /**@brief Function for handling Scanning Module events.
     */
    static void scan_evt_handler(scan_evt_t const * p_scan_evt)
    {
    	switch(p_scan_evt->scan_evt_id)
    	{
    		case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
    		{
                //doing some Math here .....
                
    			//fill in final beacon_scan_result packet with 5 closest beacons
    			for (uint16_t i = 0; i < SAMPLES_UART_NUM; i++)
    			{
    				ui32ToByteArray((uint32_t)((maj_result[i] << 16) | min_result[i]), &beacon_scan_result[i * SAMPLES_PACKET_SIZE]);
    				floatToByteArray(rssi_result[i], &beacon_scan_result[i * SAMPLES_PACKET_SIZE + 4]);
    			}
    
    			//uart_flag = 1;
    			for (uint16_t i = 0; i < SAMPLES_UART_NUM * SAMPLES_PACKET_SIZE; i++)
    			{
    				while(app_uart_put(beacon_scan_result[i]) != NRF_SUCCESS){};
    			}
    
    			app_uart_close();
    			//uart_flag = 0;
    
    			#ifdef DEBUG_ON
    				SEGGER_RTT_printf(0, "\nUART data sent and port closed\n");
    				SEGGER_RTT_printf(0, "___________________________\n");
    			#endif
    		} break;
    
    		default:
    		  break;
    	}
    }

    Commented out uart_flag was used to test point #3 and I didn't notice any difference there. My example is based on the ble_app_uart example. 

    Error codes of what functions? app_uart_close doesn't have any meaningful error codes as for me. 

    Kind regards,

    Max

  • I'm not sure I understand the purpose of the app_uart_close call. You are transferring data with app_uart_put inside the handler and the transfers will most likely not start because you close the UART right after queuing the data for transfer. Note that app_uart_put is a non-blocking function that will only put the data into the transfer queue before returning, the actual transfer will happen asynchronously.

  • The purpose is to decrease power consumption. 

    I've tried to configure UART in blocking mode (without UART handler). Even though it wasn't working 
    How to close UART after the transmission has been finished in smart way? Simple delay for a second doesn't work. 

  • You should wait until you get the APP_UART_TX_EMPTY event in the handler. And I recommend that you exit the scan_evt_handler before doing any delayin, it might run at a higher priority that will block your transfer from starting.

Related