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);
    }
}

  • I was thinking more like this, in main.c:

    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) && (err_code != NRF_ERROR_RESOURCES))
        {
        	APP_ERROR_CHECK(err_code);
        }
        if (err_code != NRF_SUCCESS)
        {
            tx_in_progress = false;
        }
    }

  • Hi Kenneth:

    thanks for continuously support on this topic.

    In my application, I need transfer out bulk data in one time. Like in the tested application,  it need transfer out 6 packets of 128 bytes in one time. 

    I tried your code, it can connect with the master without break, but it only transfer 1 packet, while lost the other 5 packets. 

    I happen to try this code:

    									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) && (err_code != NRF_ERROR_RESOURCES))
    										{
    											APP_ERROR_CHECK(err_code);
    										} 
    										if (err_code != NRF_SUCCESS)
    										{
    												tx_in_progress = false;
    										}
    This code can transfer 4 packets, while lost the other 2 packets. 

    In my previous code, 4 packets is the maximum number I can get for the one time transfer.

    thanks

    Wei

  • It's only when you receive err_code = NRF_SUCCESS that the packet is queued to be sent as notification. Do you take into account that when you receive the BLE_GATTS_EVT_HVN_TX_COMPLETE event you also need to check the counter value to know how many packets were sent? 

    p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count


  • No, I did not do that. 

    What's that, and should I do that? See some example codes, do not see they do this. Or do you more information about this?

    Wei

  • I think it is easier to help you if you can describe what you want to do.

    Most just send notification by calling sd_ble_gatts_hvx() until NRF_ERROR_RESOURCES, wait for BLE_GATTS_EVT_HVN_TX_COMPLETE event, and then call sd_ble_gatts_hvx() until NRF_ERROR_RESOURCES again. This can be repeated indefinitely. 

    Just be aware that you will get one BLE_GATTS_EVT_HVN_TX_COMPLETE for many sd_ble_gatts_hvx() calls.

    If you want to know how many notifications that was actually sent you need to check p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count on BLE_GATTS_EVT_HVN_TX_COMPLETE event.

Related