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

Timeslot API: BLE + ESB, slower transmissions when no advertising or no connection

Good morning everyone,

I am facing an apparently common problem (reported with some variations HereHere or here ) which is driving me crazy. In the linked discussions no working solution was given, so this is

why I open a new topic.

In my application, I have a NRF52832 development kit which should receive periodic packets from a custom board (later there will be n custom board, n = 5 more or less).

The DK is programmed with the ESB protocol in PRX mode, while the custom boards are programmed with the S132 and the timeslot API with ESB protocol in PTX mode.

Once a second, the custom board should transmit a message to the DK using the timeslot API (thus, the ESB protocol).

The problem I have is that when the custom board is advertising OR connected to a smartphone, all works perfectly fine: I receive all the data both on the smartphone and the DK with

the expected timings. When the custom board is disconnected AND/OR not advertising, then I receive on the DK only 1 packet every 10 seconds. For the record, I am on SDK 15.0.0.

If I do not start advertising, all my code (I have some periodical sensors sampling) runs perfectly fine and all the timings are well respected. The only issue is with the ESB transmissions, 

which are performed only once every 10 seconds.

From the look of it, it seems a configuration problem somewhere, but I was not able to find until now a solution. 

Can someone help me with this?

Thanks a lot!

Lorenzo

Parents
  • Hi,

     

    Is there any logic in your application that enters system off mode?

    Could you share a bit of code regarding the logic of the timeslot, and the handling in the application?

    When you enter debug mode, do you observe any unwanted/unexpected behavior?

     

    Kind regards,

    Håkon

  • Hi,

    thanks for your answer.

    Concerning the timeslot library, it was almost entirely taken from one of Nordic's examples in the github.

    Here it is

    #include "esb_timeslot.h"
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "nrf.h"
    #include "app_error.h"
    #include "nrf_gpio.h"
    #include "nrf_sdh.h"
    #include "boards.h"
    #include "sdk_common.h"
    #include "app_util_platform.h"
    #include "fifo.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #define TIMESLOT_BEGIN_IRQn        LPCOMP_IRQn
    #define TIMESLOT_BEGIN_IRQHandler  LPCOMP_IRQHandler
    #define TIMESLOT_BEGIN_IRQPriority 1
    #define TIMESLOT_END_IRQn          QDEC_IRQn
    #define TIMESLOT_END_IRQHandler    QDEC_IRQHandler
    #define TIMESLOT_END_IRQPriority   1
    #define ESB_RX_HANDLE_IRQn        WDT_IRQn
    #define ESB_RX_HANDLE_IRQHandler  WDT_IRQHandler
    #define ESB_RX_HANDLE_IRQPriority 3
    //Maximum attempt before discarding the packet (the number of trial = MAX_TX_ATTEMPTS x retransmit_count, if timeslot is large enough)
    #define MAX_TX_ATTEMPTS 10
    #define TS_LEN_US                          		(5000UL)
    #define TX_LEN_EXTENSION_US                 	(5000UL)
    #define TS_SAFETY_MARGIN_US                  	(700UL)    /**< The timeslot activity should be finished with this much to spare. */
    #define TS_EXTEND_MARGIN_US                     (2000UL)
    
    static volatile enum
    {
        STATE_IDLE, /* Default state */
        STATE_RX,   /* Waiting for packets */
        STATE_TX    /* Trying to transmit packet */
    } m_state = STATE_IDLE;
    
    // Variables for timeslot API
    static nrf_radio_request_t m_timeslot_request;
    
    static nrf_esb_config_t nrf_esb_config;
    static esb_data_handler_t m_evt_handler = 0;
    static fifo_t m_transmit_fifo;
    
    static nrf_radio_signal_callback_return_param_t signal_callback_return_param;
    static uint32_t         m_total_timeslot_length = 0;
    static uint32_t         m_tx_attempts = 0; 
    void RADIO_IRQHandler(void);
    
    
    /** Address. */
    static const uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};     /**< Base address part #0. */
    static const uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};     /**< Base address part #1. */
    static const uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8 };    /**< Address prefix. */
    
    
    /**@brief Request next timeslot event in earliest configuration
     */
    uint32_t request_next_event_earliest(void)
    {
        m_timeslot_request.request_type                = NRF_RADIO_REQ_TYPE_EARLIEST;
        m_timeslot_request.params.earliest.hfclk       = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
        m_timeslot_request.params.earliest.priority    = NRF_RADIO_PRIORITY_HIGH;
        m_timeslot_request.params.earliest.length_us   = TS_LEN_US;
        m_timeslot_request.params.earliest.timeout_us  = 1000000;
        return sd_radio_request(&m_timeslot_request);
    }
    
    
    
    /**@brief Configure next timeslot event in earliest configuration
     */
    void configure_next_event_earliest(void)
    {
        m_timeslot_request.request_type                = NRF_RADIO_REQ_TYPE_EARLIEST;
        m_timeslot_request.params.earliest.hfclk       = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
        m_timeslot_request.params.earliest.priority    = NRF_RADIO_PRIORITY_HIGH;
        m_timeslot_request.params.earliest.length_us   = TS_LEN_US;
        m_timeslot_request.params.earliest.timeout_us  = 1000000;
    }
    
    
    /**@brief Configure next timeslot event in normal configuration
     */
    void configure_next_event_normal(void)
    {
        m_timeslot_request.request_type               = NRF_RADIO_REQ_TYPE_NORMAL;
        m_timeslot_request.params.normal.hfclk        = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
        m_timeslot_request.params.normal.priority     = NRF_RADIO_PRIORITY_HIGH;
        m_timeslot_request.params.normal.length_us    = TS_LEN_US;
        m_timeslot_request.params.normal.distance_us  = 100000;
    }
    
    
    /**@brief Timeslot signal handler
     */
    void nrf_evt_signal_handler(uint32_t evt_id)
    {
        uint32_t err_code;
    
        switch (evt_id)
        {
            case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
                //No implementation needed
                break;
            case NRF_EVT_RADIO_SESSION_IDLE:
                err_code = sd_radio_session_close();
                APP_ERROR_CHECK(err_code);
                break;
            case NRF_EVT_RADIO_SESSION_CLOSED:
                //No implementation needed, session ended
                break;
            case NRF_EVT_RADIO_BLOCKED:
                //Fall through
            case NRF_EVT_RADIO_CANCELED:
    		{
                err_code = request_next_event_earliest();
                APP_ERROR_CHECK(err_code);
                break;
    		}
    		default:
                break;					
        }
    }
    
    
    /**@brief Timeslot event handler
     */
    nrf_radio_signal_callback_return_param_t * timeslot_callback(uint8_t signal_type)
    {
        switch(signal_type)
        {
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
    	
            	NRF_LOG_INFO(" NRF_RADIO_CALLBACK_SIGNAL_TYPE_START\r\n");
                //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); 
                NVIC_SetPendingIRQ(TIMESLOT_BEGIN_IRQn);
    				
                break;
    
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:  //2
    
                signal_callback_return_param.params.request.p_next = NULL;
                signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
    
                ESB_TIMESLOT_DEBUG_PIN_SET(ESB_TIMESLOT_DBG_PIN_RADIO_IRQHANDLER);
                RADIO_IRQHandler();
                ESB_TIMESLOT_DEBUG_PIN_CLEAR(ESB_TIMESLOT_DBG_PIN_RADIO_IRQHANDLER);
    
                break;
    
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0: //1
    					
                NRF_LOG_INFO(" NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0\r\n");
                if (NRF_TIMER0->EVENTS_COMPARE[0] &&
                     (NRF_TIMER0->INTENSET & (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENCLR_COMPARE0_Pos)))
                {
                    NRF_TIMER0->TASKS_STOP        = 1;
                    NRF_TIMER0->EVENTS_COMPARE[0] = 0;
    
                    /* This is the "timeslot is about to end" timeout. */
                    if (!nrf_esb_is_idle())
                    {
                        NRF_RADIO->INTENCLR      = 0xFFFFFFFF;
                        NRF_RADIO->TASKS_DISABLE = 1;
                    }
    
                    /* Schedule next timeslot. */
                    configure_next_event_earliest();
                    signal_callback_return_param.params.request.p_next = &m_timeslot_request;
                    signal_callback_return_param.callback_action       = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
                }
    
                if (NRF_TIMER0->EVENTS_COMPARE[1] &&
                     (NRF_TIMER0->INTENSET & (TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENCLR_COMPARE1_Pos)))
                {
                    NRF_TIMER0->EVENTS_COMPARE[1] = 0;
                    if (m_total_timeslot_length < (128000000UL - 1UL - TX_LEN_EXTENSION_US))
                    {
                            // Request timeslot extension if total length does not exceed 128 seconds
                        signal_callback_return_param.params.extend.length_us = TX_LEN_EXTENSION_US;
                        signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND;
                    }
                    else
                    {
                        // Return with no action request
                        signal_callback_return_param.params.request.p_next = NULL;
                        signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
                    }
                }
                break;
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:   //4
            	// NRF_LOG("  NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED\r\n");
                NRF_TIMER0->TASKS_STOP          = 1;
                NRF_TIMER0->EVENTS_COMPARE[0]   = 0;
                NRF_TIMER0->EVENTS_COMPARE[1]   = 0;
                NRF_TIMER0->CC[0]               += (TX_LEN_EXTENSION_US - 25);
                NRF_TIMER0->CC[1]               += (TX_LEN_EXTENSION_US - 25);
                NRF_TIMER0->TASKS_START         = 1;
                m_total_timeslot_length += TX_LEN_EXTENSION_US;
                NVIC_SetPendingIRQ(TIMESLOT_BEGIN_IRQn);
                break;
            
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED:
                //NRF_LOG(" NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED\r\n");
                //Try scheduling a new timeslot
                // Disabling ESB is done in a lower interrupt priority
                NVIC_SetPendingIRQ(TIMESLOT_END_IRQn);
    
                signal_callback_return_param.params.request.p_next = NULL;
                signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
                break;
            default:
    			//No implementation needed
    			break;
        }
        return (&signal_callback_return_param);
    }
    
    //!
    //! @brief Function for initializing the timeslot API.
    //!
    //!
    uint32_t timeslot_sd_start(void)
    {
        uint32_t err_code;
    
        err_code = sd_radio_session_open(timeslot_callback);
        if (err_code != NRF_SUCCESS)
        {
           NRF_LOG_INFO("Err: %d\n", err_code);
            return err_code;
        }
        err_code = request_next_event_earliest();
                NRF_LOG_INFO("Err: %d\n", err_code);
    
        if (err_code != NRF_SUCCESS)
        {
            (void)sd_radio_session_close();
            return err_code;
        }
        return NRF_SUCCESS;
    }
    
    /**@brief IRQHandler used for execution context management. 
      *        Any available handler can be used as we're not using the associated hardware.
      *        This handler is used to stop and disable UESB
      */
    void TIMESLOT_END_IRQHandler(void)
    {
        uint32_t err_code;
    
        ESB_TIMESLOT_DEBUG_PIN_SET(ESB_TIMESLOT_DBG_PIN_DISABLE);
    	//NRF_LOG("TIMESLOT_END_IRQHandler\r\n");
        // Timeslot is about to end: stop UESB
        if (m_state == STATE_RX)
        {  
    		err_code= nrf_esb_stop_rx();
        }
    	err_code= nrf_esb_flush_tx();
    //	APP_ERROR_CHECK(err_code);
    	err_code= nrf_esb_flush_rx();
    //	APP_ERROR_CHECK(err_code);
        err_code= nrf_esb_disable();
    //    APP_ERROR_CHECK(err_code);
        m_total_timeslot_length = 0;
        m_state = STATE_IDLE;
    
    
        ESB_TIMESLOT_DEBUG_PIN_CLEAR(ESB_TIMESLOT_DBG_PIN_DISABLE);
        ESB_TIMESLOT_DEBUG_PIN_CLEAR(ESB_TIMESLOT_DBG_PIN_RADIO_TIMESLOT);
    }
    
    /**@brief IRQHandler used for execution context management. 
     *        Any available handler can be used as we're not using the associated hardware.
     *        This handler is used to initiate ESB RX/TX
     */
    void TIMESLOT_BEGIN_IRQHandler(void)
    {
        uint32_t err_code;
    	nrf_esb_payload_t     tx_payload ;
    	uint32_t       tx_payload_len;
        bool can_continue = true;
    	//NRF_LOG("TIMESLOT_BEGIN_IRQHandler\r\n");
    
    	ESB_TIMESLOT_DEBUG_PIN_SET(ESB_TIMESLOT_DBG_PIN_RADIO_TIMESLOT);
    
    	if (m_state == STATE_IDLE)
        {
    			
    		err_code = nrf_esb_init(&nrf_esb_config);
            if (err_code != NRF_SUCCESS)
            {
                can_continue = false;
            }
    		err_code = nrf_esb_set_base_address_0(base_addr_0);
            if (err_code != NRF_SUCCESS)
            {
                can_continue = false;
            }
    		err_code = nrf_esb_set_base_address_1(base_addr_1);
            if (err_code != NRF_SUCCESS)
            {
                can_continue = false;
            }		err_code = nrf_esb_set_prefixes(addr_prefix, 8);
    
            if (err_code != NRF_SUCCESS)
            {
                can_continue = false;
            }    
        }
        if (can_continue)
        {
            CRITICAL_REGION_ENTER();
            if (m_transmit_fifo.free_items < sizeof(m_transmit_fifo.buf) && m_state != STATE_TX)
            {				
                // There are packets in the FIFO: Start transmitting
                tx_payload_len  = sizeof(tx_payload);
                // Copy packet from FIFO. Packet isn't removed until transmissions succeeds or max retries has been exceeded
                if (m_tx_attempts < MAX_TX_ATTEMPTS)
                {        
                    fifo_peek_pkt(&m_transmit_fifo, (uint8_t *) &tx_payload, &tx_payload_len);
                    APP_ERROR_CHECK_BOOL(tx_payload_len == sizeof(tx_payload));
                }
                else
                {	
                    //max attempts reached, remove packet
                    NRF_LOG_ERROR("FAILED TO SEND, NO ACK\r\n");
                    fifo_get_pkt(&m_transmit_fifo, (uint8_t *) &tx_payload, &tx_payload_len);
                    APP_ERROR_CHECK_BOOL(tx_payload_len == sizeof(tx_payload));
                
                    m_tx_attempts = 0;
                }
            
                if (m_state == STATE_RX)
                {
                    nrf_esb_stop_rx(); 
                }
         
                err_code = nrf_esb_write_payload(&tx_payload);
                APP_ERROR_CHECK(err_code);
            
                m_state = STATE_TX;
            }
            else
            {
                // No packets in the FIFO: start reception
                err_code = nrf_esb_start_rx();
                APP_ERROR_CHECK(err_code);
                m_state = STATE_RX;
    
            }
            CRITICAL_REGION_EXIT();
        }
    }
    
    uint32_t esb_timeslot_send_str(uint8_t * p_str, uint32_t length)
    {
    	static nrf_esb_payload_t tx_payload;
        bool success;
        memset(&tx_payload, 0, sizeof(tx_payload));
        memcpy(tx_payload.data, p_str, length);
        tx_payload.length = length;
        tx_payload.pipe = 0;
        CRITICAL_REGION_ENTER();
        success = fifo_put_pkt(&m_transmit_fifo, (uint8_t *)&tx_payload, sizeof(tx_payload));
        CRITICAL_REGION_EXIT();
        return success ? NRF_SUCCESS : NRF_ERROR_NO_MEM;
    }
    
    uint32_t esb_timeslot_send_buffer(uint8_t *dataToSend, uint32_t length, uint32_t hw_addr)
    {
        static nrf_esb_payload_t tx_payload;
        bool success;
        memset(&tx_payload, 0, sizeof(tx_payload));
        memcpy(tx_payload.data, dataToSend, length);
        tx_payload.data[19] = (hw_addr >> 24);
        tx_payload.data[20] = (hw_addr >> 16);
        tx_payload.data[21] = (hw_addr >> 8);
        tx_payload.data[22] = hw_addr;
        tx_payload.length = length + 4;
        tx_payload.pipe = 0;
        CRITICAL_REGION_ENTER();
        success = fifo_put_pkt(&m_transmit_fifo, (uint8_t *)&tx_payload, sizeof(tx_payload));
        CRITICAL_REGION_EXIT();
        return success ? NRF_SUCCESS : NRF_ERROR_NO_MEM;
    
    
    }
    
    void nrf_esb_event_handler(nrf_esb_evt_t const * p_event)
    {
    	//NRF_LOG("NRF ESB EVENT HANDLERr\r\n");
    	if(p_event->evt_id == NRF_ESB_EVENT_TX_FAILED)
        { 
    		nrf_esb_flush_tx();
            // Data reception is handled in a lower priority interrupt
            m_tx_attempts += 1;
            m_state = STATE_RX;
    			
        }
    	if (p_event->evt_id == NRF_ESB_EVENT_TX_SUCCESS)
        {		
            nrf_esb_payload_t payload;
            uint32_t       payload_len;
            
            // Successful transmission. Can now remove packet from our FIFO
            payload_len = sizeof(payload);
    
            fifo_get_pkt(&m_transmit_fifo, (uint8_t *) &payload, &payload_len);
            APP_ERROR_CHECK_BOOL(payload_len == sizeof(payload));
            
            m_tx_attempts = 0;
        }
    		
        if(p_event->evt_id & NRF_ESB_EVENT_RX_RECEIVED)
        {
            // Data reception is handled in a lower priority interrupt
            NVIC_SetPendingIRQ(ESB_RX_HANDLE_IRQn);
        }
    }
    
    uint32_t esb_init(esb_data_handler_t evt_handler)
    {
    
        nrf_esb_config_t tmp_config  = NRF_ESB_DEFAULT_CONFIG;
    		
    		
    	m_evt_handler = evt_handler;
        memcpy(&nrf_esb_config, &tmp_config, sizeof(nrf_esb_config_t));
        nrf_esb_config.payload_length     = 32;
        nrf_esb_config.protocol           = NRF_ESB_PROTOCOL_ESB_DPL;
        nrf_esb_config.bitrate            = NRF_ESB_BITRATE_2MBPS;
        nrf_esb_config.mode               = NRF_ESB_MODE_PTX;
        nrf_esb_config.event_handler      = nrf_esb_event_handler;
        nrf_esb_config.selective_auto_ack = false;
    	nrf_esb_config.radio_irq_priority = 0;
        fifo_init(&m_transmit_fifo);
    
        // Using three avilable interrupt handlers for interrupt level management
        // These can be any available IRQ as we're not using any of the hardware,
        // simply triggering them through software
        NVIC_ClearPendingIRQ(TIMESLOT_END_IRQn);
        NVIC_SetPriority(TIMESLOT_END_IRQn, 1);
        NVIC_EnableIRQ(TIMESLOT_END_IRQn);
        
        NVIC_ClearPendingIRQ(TIMESLOT_BEGIN_IRQn);
        NVIC_SetPriority(TIMESLOT_BEGIN_IRQn, 1);
        NVIC_EnableIRQ(TIMESLOT_BEGIN_IRQn);
        
        NVIC_ClearPendingIRQ(ESB_RX_HANDLE_IRQn);
        NVIC_SetPriority(ESB_RX_HANDLE_IRQn, 1);
        NVIC_EnableIRQ(ESB_RX_HANDLE_IRQn);
    
        return NRF_SUCCESS;
    }
    
    
    void ESB_RX_HANDLE_IRQHandler(void)
    {
        nrf_esb_payload_t rx_payload;
        uint32_t err_code;
    		
    	//NRF_LOG("UESB_RX_HANDLE_IRQHandler \r\n");
        // Get packet from UESB buffer
        err_code = nrf_esb_read_rx_payload(&rx_payload);
        APP_ERROR_CHECK(err_code);
    	
        // Give packet to main application 
        // app_scheduler can be used instead to send the event in main context
        m_evt_handler(rx_payload.data, rx_payload.length);
    }
    
    

    As for the main, I simply have a timer which once a second invokes the esb send function as below

             err_code = esb_timeslot_send_buffer(to_send, 19, hw_addr);       
    

    Actually this function simply puts the data in the tx_fifo, and the fifo is emptied when a timeslot is available.

    Of course, the esb_init function is properly called in the initialization phase of my main class.

    When in debug mode, I see that the event 

    nrf_radio_signal_callback_return_param_t * timeslot_callback(uint8_t signal_type)
    {
        switch(signal_type)
        {
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
    	
            	NRF_LOG_INFO(" NRF_RADIO_CALLBACK_SIGNAL_TYPE_START\r\n");

    is correctly called once per second when advertising.

    When no advertising, the event is called once every 10 seconds as I said in the initial post. I don't see any strange behavior, as I said also when not advertising all the operations happens normally. The enqueueing in the ESB fifo works as well, but after some time I got a "fifo full" error message, because obviously the fifo is not emptied quick enough.

    In the main while cycle, I had inface the idle_state_handle() function call, but even if I try to disable it I still got the same behaviour.

    I am honestly out of ideas....I definitely need a solution to this problem because in the envisaged application I need to have x boards active at the same time, sending their packets to the ESB board and they MUST NOT advertise.

    Hope you can help, and thanks in advance for the support!

  • lbe said:
    yes, the END_IRQHandler is called regularly, both after a NRF_RADIO_CALLBACK_SIGNAL_TYPE_START and after a NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO

     The only way you can get a _END_IRQHandler called, based on the sources that you have attached here, is if the timeslot fails to extend. Could you see if this is the case when the softdevice is "inactive"?

  • No, I don't get the EXTEND_FAILED case.....Just as before, all the code seems to run correctly, but the event NRF_RADIO_CALLBACK_SIGNAL_TYPE_START does not seem to be signaled regularly if the advertising is inactive.....I tried to modify the code to use normal timeslots instead of earliest, but things got worse....only a first timeslot is allocated, then I don't get any transmission, not even once every 10 seconds.

    I tried to update the softdevice to the latest available version, but this did not make any difference.

    As for your reply, I was wrong....the END_IRQHandler is in fact called only when there was a previous SIGNAL_TYPE_START event....my mistake.

  • You'll need to add some debug signals to your timeslot handling to find out why you're not getting the slot extended. Do you have several GPIOs available, so that you can toggle these in each of the respective events? Also check your nrf_evt_signal_handler(), to see if anything pops up there as well.

    Could you post more code regarding your handling of this in main?

     

    Kind regards,

    Håkon

  • Hi again,

    I don't have easy access to GPIOs. I checked the nrf_evt_signal_handler() in debug mode and it is never called, neither with advertising, nor without advertising.

    There is nothing more concerning the handling of this in the main.....the main only calls 

    err_code = esb_timeslot_send_buffer(to_send, 19, hw_addr);

    in a timer callback once a second. 

    All the other code related to timeslot management is the one I posted above.

    Just a question: is it possible that if the advertising is not started at all, the soft device does not start the HF crystal and/or the radio? So that it cannot allocate any slot, because the needed hardware is not running? Maybe the no-advertising mode is a corner case......

  • lbe said:
    I don't have easy access to GPIOs. I checked the nrf_evt_signal_handler() in debug mode and it is never called, neither with advertising, nor without advertising.

    You need to call this from the system event handler from the SoftDevice, as described here (step 8): https://devzone.nordicsemi.com/nordic/short-range-guides/b/software-development-kit/posts/setting-up-the-timeslot-api

     

    Since you are using a newer SDK, you can do something like this to register a system observer (include nrf_sdh_soc.h as well):

    NRF_SDH_SOC_OBSERVER(m_timeslot_sys_obs, 0, nrf_evt_signal_handler, NULL);

     

    Kind regards,

    Håkon

Reply Children
No Data
Related