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

Timeslot bluetooth TX causes freeze when not in data handler

I have encountered this issue while trying to trigger a ble_nus_string_send() - function from anywhere else than in the ble_rx_handler.

I use Softdevice S110 on the NRF52832 and SDK12.3.0_d7731ad.

The system uses shockburst and BLE in a timeslot configuration, as described here.

---------------------------------

What I am trying to do is make the transmit of data being triggered by some event other than bluetooth RX-event, for example from button push.

So when button is pushed, it should store bool push=true; 

And then it should do a send_variable function within timeslot that would just send the variable push let's say every second.

Inside main.c I have my Bluetooth RX handler; 

// snippet from MAIN_C

static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length)
{
	NRF_LOG_INFO("Received data from BLE NUS. Writing data on UART.");
    NRF_LOG_HEXDUMP_INFO(p_data, length);
	
	switch(p_data[0]){
		
		case 0xBB: // fedback test
			*point = 0xCC;
			len = 1;
			ble_nus_string_send(&m_nus, point, len);
			break;
	}
	// one part of the switch-case, the rest have been exluded here, but all the cases works.
}

I have tried making a common variable, and letting it be set by some other process, the variable is correct.

Now, I want to transmit that variable without first being prompted by nus_data_handler().

Like so;

void unit_event_tx(void){ // Function to send unprompted information to app from the Wiral units.
	
	uint8_t buttonVar = 0;
	buttonvar = externalButtonvar;
	
	ble_nus_string_send(&m_nus,&buttonVar,1); // send the button variable
}

And I have tried to trigger it from the button push, which obviously did not work since it was not inside the timeslot.

I have also tried to trigger it on static nrf_radio_signal_callback_return_param_t * radio_callback(uint8_t signal_type).

Like so; 

static nrf_radio_signal_callback_return_param_t * radio_callback(uint8_t signal_type)
{
    switch(signal_type)
    {
        default:
		{
            //No implementation needed
            break;
		}
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
		{	/* Start of the timeslot - set up timer interrupt */
            signal_callback_return_param.params.request.p_next = NULL;
            signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
            
            NRF_TIMER0->TASKS_STOP          = 1;
            NRF_TIMER0->TASKS_CLEAR         = 1;
            NRF_TIMER0->MODE                = (TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos);
            NRF_TIMER0->EVENTS_COMPARE[0]   = 0;
            NRF_TIMER0->EVENTS_COMPARE[1]   = 0;
            NRF_TIMER0->INTENSET            = TIMER_INTENSET_COMPARE0_Msk | TIMER_INTENSET_COMPARE1_Msk ;
            NRF_TIMER0->CC[0]               = TS_LEN_US - TS_SAFETY_MARGIN_US;
            NRF_TIMER0->CC[1]               = (TS_LEN_US - TS_EXTEND_MARGIN_US);
            NRF_TIMER0->BITMODE             = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
            NRF_TIMER0->TASKS_START         = 1;
            NRF_RADIO->POWER                = (RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos);

            NVIC_EnableIRQ(TIMER0_IRQn); 
						TIMESLOT_DEBUG_PIN_SET(TIMESLOT_DBG_PIN_RADIO_TIMESLOT);
			
						// send information to app
						unit_event_tx(); // <--- This is the function-call

						if(m_timeslot.begin)
						{
							m_timeslot.begin();
						}
						
			break;
		}
		
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:
		{
		.
		.
		.
		}
	}
}
	

Whenever the function unit_event_tx is being called, the unit freeze. And when the function is called outside of here, like on button push, nothing happens.

When the function ble_nus_string_send() is being triggered from the nus_data_handler everything works as expected. (e.g. when sending 0xBB, it responds with 0xCC)

The unit works fine until I accept uart in the NRF connect app, at which point the nrf52 start to transmit, and it quickly crashes. (freezes)

I suspect one of two things, either the function gets called continiously, and it goes into an infinite loop, or I just messed up either the send data function or the place to trigger the function.

All help would be highly appreciated! 

I would rather not share full code since it is confidential.

Parents
  • HI Jonathan, 

    I use Softdevice S110 on the NRF52832 and SDK12.3.0_d7731ad.

     I assume that S110 is a typo since the S110 is not supported on the nRF52832 ,see SDKs and SoftDevices

    Whenever the function unit_event_tx is being called, the unit freeze. And when the function is called outside of here, like on button push, nothing happens.

    You are trying to call ble_nus_string_send, which triggers a Bluetooth Handle Value Notification using sd_ble_gatts_hvx() , see the definition of ble_nus_string_send below:

    uint32_t ble_nus_string_send(ble_nus_t * p_nus, uint8_t * p_string, uint16_t length)
    {
        ble_gatts_hvx_params_t hvx_params;
    
        VERIFY_PARAM_NOT_NULL(p_nus);
    
        if ((p_nus->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_nus->is_notification_enabled))
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (length > BLE_NUS_MAX_DATA_LEN)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = p_nus->rx_handles.value_handle;
        hvx_params.p_data = p_string;
        hvx_params.p_len  = &length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(p_nus->conn_handle, &hvx_params);
    }

    In a RADIO timeslot, the SoftDevice is temporarily disabled so that the RADIO can be freely used for another purpose, in your case ESB. So while the timeslot is open, you cannot call any functions from the SoftDevice API and sd_ble_gatts_hvx() is one of them, as it has the sd_-prefix.

    However, calling ble_nus_string_send() outside the timeslot and outside the nus_data_handler should work just fine. Can you run your code in a debug session and check the return value of sd_ble_gatts_hvx() inside ble_nus_string_send() when you call it  outside a timeslot and outside the nus_data_handler? 

    Alternatively, you can set a breakpoint in app_error_handler_bare() and/or app_error_handler ( if you have DEBUG set in your Preprocessor Definitions). If you enter this error handler it means that a APP_ERROR_CHECK() macro has caught a non-zero return code from a function. Looking at the call stack should point you to which function that is the culprit. 

    Best regards

    Bjørn

Reply
  • HI Jonathan, 

    I use Softdevice S110 on the NRF52832 and SDK12.3.0_d7731ad.

     I assume that S110 is a typo since the S110 is not supported on the nRF52832 ,see SDKs and SoftDevices

    Whenever the function unit_event_tx is being called, the unit freeze. And when the function is called outside of here, like on button push, nothing happens.

    You are trying to call ble_nus_string_send, which triggers a Bluetooth Handle Value Notification using sd_ble_gatts_hvx() , see the definition of ble_nus_string_send below:

    uint32_t ble_nus_string_send(ble_nus_t * p_nus, uint8_t * p_string, uint16_t length)
    {
        ble_gatts_hvx_params_t hvx_params;
    
        VERIFY_PARAM_NOT_NULL(p_nus);
    
        if ((p_nus->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_nus->is_notification_enabled))
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (length > BLE_NUS_MAX_DATA_LEN)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = p_nus->rx_handles.value_handle;
        hvx_params.p_data = p_string;
        hvx_params.p_len  = &length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(p_nus->conn_handle, &hvx_params);
    }

    In a RADIO timeslot, the SoftDevice is temporarily disabled so that the RADIO can be freely used for another purpose, in your case ESB. So while the timeslot is open, you cannot call any functions from the SoftDevice API and sd_ble_gatts_hvx() is one of them, as it has the sd_-prefix.

    However, calling ble_nus_string_send() outside the timeslot and outside the nus_data_handler should work just fine. Can you run your code in a debug session and check the return value of sd_ble_gatts_hvx() inside ble_nus_string_send() when you call it  outside a timeslot and outside the nus_data_handler? 

    Alternatively, you can set a breakpoint in app_error_handler_bare() and/or app_error_handler ( if you have DEBUG set in your Preprocessor Definitions). If you enter this error handler it means that a APP_ERROR_CHECK() macro has caught a non-zero return code from a function. Looking at the call stack should point you to which function that is the culprit. 

    Best regards

    Bjørn

Children
No Data
Related