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

BLE connection lost after Flash write

Hi: 

I use the SDK 13.0 and nRF52 DK to develop software for the project. Based on BLE UART (NUS), the software do SAADC sample and transfer the data out in real time, The ADC sampling rate is 250 Sa/s. The data is received by a nRF52 dongle board, and transferred to the local PC through UART. The system works fine. 

Now, I try to save the ADC sampling data to the BLE chip flash memory first, and then after triggered, data is read from flash and transferred out through bluetooth. The trigger now is "after finishing the flash write".

For flash write and Read, it's in a packet size of 64 samples. The problem is if I write 4 packets, and read/transfer 4 packets ( total data volume is 64*4 =256 samples), the software works fine. If I write and read/transfer more than 4 packets. the BLE software can be restarted/reset frequently. Double check the data pattern using a terminal software find, the restart/reset happens after/in the last packet write. Because of that, the slave and master device can not build stable connection, and no data transmission can be made.

My thought is the BLE connection parameters (connection interval) are not well tuned. But even tried with different settings on that, it still not work. 

The main function that do the flash write/read and data transfer is attached here. Need some insight to this problem. thanks 

#define MIN_CONNECTION_INTERVAL MSEC_TO_UNITS(180, UNIT_1_25_MS)         /**< Determines minimum connection interval in millisecond. */
#define MAX_CONNECTION_INTERVAL MSEC_TO_UNITS(220, UNIT_1_25_MS)         /**< Determines maximum connection interval in millisecond. */
#define SLAVE_LATENCY           0                                       /**< Determines slave latency in counts of connection events. */
#define SUPERVISION_TIMEOUT     MSEC_TO_UNITS(4000, UNIT_10_MS)  

#define SAADC_SAMPLES_IN_BUFFER         64

static uint16_t FS_WR_DATA_L = 32; 
static uint16_t FS_WR_N = 6; 

int main(void)
{
    uint32_t err_code;
    bool     erase_bonds;
	  int32_t volatile temp;

		///////////////////////
		NRF_POWER->DCDCEN = 1;
		///////////////////////
//		nrf_gpio_cfg_output(13);
//		nrf_gpio_pin_set(13);
//		nrf_gpio_cfg_output(12);
//		nrf_gpio_pin_clear(12);
	
    // Initialize.
		nrf_temp_init(); //////////////////////
		NRF_TEMP->TASKS_START = 1;
		///////////////////////////////////////
    err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);

    uart_init();
    log_init();

    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
	/////////////////////////
	//nrf_ble_gatt_data_length_set(&m_gatt, BLE_CONN_HANDLE_INVALID, 247+4);
	fstorage_init();
    
    saadc_sampling_event_init();
    saadc_init();
    saadc_sampling_event_enable();
		
		//////////////////////////////////20180925 Added
		pwm_setup();
		///////////////////////////////////
    printf("\r\nUART Start1!\r\n");		
    NRF_LOG_INFO("UART Start2!\r\n");
    err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);

		////////////////////////////
		//nrf_gpio_cfg_output(19);
    // Enter main loop.
    for (;;)
    {
			if(fs_write_en == 1)
			{	
					uint16_t cc_r;
					uint8_t bytes_to_send;
					uint32_t value_from_f;
					uint8_t value_to_send[(SAADC_SAMPLES_IN_BUFFER)*2 +2];
					uint8_t value[SAADC_SAMPLES_IN_BUFFER*2 +5];
		
					cc_r = m_adc_evt_counter % FS_WR_N;
					
					printf("%x\r\n", cc_r);
					fstorage_write(cc_r * FS_WR_DATA_L, value_to_f, FS_WR_DATA_L);
//					fstorage_read(0, FS_WR_DATA_L);
					
					if (cc_r == (FS_WR_N - 1))
					{
						
						for (int j=0; j < FS_WR_N; j++)
						{
//							printf("%x\r\n", m_adc_evt_counter);
							printf("Data read from flash address 0x%X: \r\n", (uint32_t)fs_config.p_start_addr + j*32); 
							for(int i=0; i<(SAADC_SAMPLES_IN_BUFFER)/2; i++)
							{
								value_from_f = fstorage_read2(j*32 + i);
//								printf("%X \r\n", value_from_f);   
								value[i*4] 		 = value_from_f;
								value[(i*4)+1] = value_from_f >>  8;
								value[(i*4)+2] = value_from_f >> 16;
								value[(i*4)+3] = value_from_f >> 24;
							}  
								///////////////////////////////
								// read temperature sensor
								int32_t volatile temp;
								int32_t t;
								sd_temp_get(&t);
								temp = t;
					
								value[SAADC_SAMPLES_IN_BUFFER*2] = temp;
								value[SAADC_SAMPLES_IN_BUFFER*2 + 1] = temp >> 8;
								value[SAADC_SAMPLES_IN_BUFFER*2 + 2] = m_adc_evt_counter;
								value[SAADC_SAMPLES_IN_BUFFER*2 + 3] = 0x7A;
								value[SAADC_SAMPLES_IN_BUFFER*2 + 4] = 0x7A;
								// Send data over BLE via NUS service. Makes sure not to send more than 20 bytes.
								if((SAADC_SAMPLES_IN_BUFFER*2) <= NRF_BLE_GATT_MAX_MTU_SIZE - 3) 
								{
										bytes_to_send = (SAADC_SAMPLES_IN_BUFFER*2 + 5);
								}
								else 
								{
										bytes_to_send = 20;
								}
//								if( m_conn_handle != BLE_CONN_HANDLE_INVALID ) 
//								{
									err_code = ble_nus_string_send(&m_nus, value, bytes_to_send);
									if (err_code != NRF_ERROR_INVALID_STATE) 
									{
											APP_ERROR_CHECK(err_code);
									}	
//								}
							}
						}
					m_adc_evt_counter++; 
						
					if ( cc_r == (FS_WR_N - 1))
					{
						fstorage_erase();
					}
					fs_write_en = 0;
					power_manage();
				}
				else
				{
						power_manage();
				}
					// Put SDN# in HIGH mode
				nrf_gpio_cfg_output(8);
				nrf_gpio_pin_set(8);
    }
}

  • Hi Kenneth: 

    Thanks for your kind reply. 

    I follow your instruction and set the breakpoint in the software, and find the error information, as follwoing:

    So, the error happens in main.c, 0x04F1 (1265) line, which is the 108th line in my first attached main function code. 

    This is the error generated after BLE string sending: 

    err_code = ble_nus_string_send(&m_nus, value, bytes_to_send);

    And the error info shows: auto- struct<untagged>.

    Does this is some BLE connection error? How can this happens, and how can I fix it?  Thanks

  • Hi,

    The error code 0x13 means that ble_nus_string_send() return NRF_ERROR_RESOURCES (see nrf_error.h). If you go into the implementation of ble_nus_string_send() you can find that it is the sd_ble_gatts_hvx() call that return this error code, and from the documentation of the softdevice api call you can find:

     * @retval ::NRF_ERROR_RESOURCES Too many notifications queued.
     * Wait for a @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event and retry.

    This is a normal error code that you need to handle as described.

  • Hi Kenneth:

    Thanks for continuously supporting on this case. 

    I did do some search and read many cases online for this error. I tried adding the following or similar code to my project: 

    In on_ble_evt(ble_evt_t * p_ble_evt)

    					case BLE_GATTS_EVT_HVN_TX_COMPLETE:
    					tx_complete = true;
    				//Add by Wei Lu
    					break;

    In main.c, coding like this:

    						
    						while(!tx_complete);
    						err_code = ble_nus_string_send(&m_nus, value, bytes_to_send);
    						if ((err_code != NRF_ERROR_INVALID_STATE)&& (err_code != NRF_ERROR_BUSY))
    							{
    								
    								APP_ERROR_CHECK(err_code);
    							}
    						tx_complete = false;

    Even do this way, the program still not not work. Further check shows the tx_complete not be set back to "True" after the first sending out setting to "False".

    What's the possible reason for this? Do I use the BLE_GATTS_EVT_HVN_TX_COMPLETE correctly?

    Thanks

  • I don't understand the flow here and I don't like infinite while loops, so maybe try something like this instead:

    static volatile bool tx_in_progress;
    
    in on_ble_evt():
    
    case BLE_GATTS_EVT_HVN_TX_COMPLETE:
    	tx_in_progress = false;
    
    in main():
    
    if(tx_in_progress == false)
    	tx_in_progress = true
    	ble_nus_string_send() 
    	if error 
    		tx_in_progress = false

  • Hi Kenneth:

    thanks for the reply. 

    First, I tried your code. But it still not work. 

    My problem is I need read from flash memory, and send the large bulk data out though BLE. The packet size 64 samples, 128 bytes. As I continuously read from flash, and send out. I add the BLE_GATTS_EVT_HVN_TX_COMPLETE to check the transfer complete, like using your code. But in my application, the BLE_GATTS_EVT_HVN_TX_COMPLETE event is not triggered. and the tx_in_progress is always TRUE. 

    What's the possible reason for this? How can I debug it?

    Add new code here. 

    Thanks

    					case BLE_GATTS_EVT_HVN_TX_COMPLETE:
    					tx_complete = true;
    					tx_in_progress = false;
    					break;
    					
    					
    in main.c
    									printf("%x\r\n", tx_in_progress);
    								if(tx_in_progress == false)
    								{
    									tx_in_progress = true;
    									
    									err_code = ble_nus_string_send(&m_nus, value, bytes_to_send);
    									if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_BUSY))
    									{
    										APP_ERROR_CHECK(err_code);
    										tx_in_progress = false;
    									}	
    								}

Related