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

Problems managing a buffer to track events to the ble stack

I am using the following code to manage a buffer to put through data to the ble stack. I think I saw a similar code on the nRFready Desktop 2 v1.0.4 examples:


/**@brief Packet buffering initialization
 */
static void buffer_init(void)
{
    uint32_t err_code;
    
    memset(&s_packet_buffer, 0, sizeof(s_packet_buffer));
	
		err_code = sd_ble_tx_buffer_count_get (&s_packet_buffer.sd_buffers_available);
	
		ASSERT(err_code == NRF_SUCCESS);
	
    err_code =  app_timer_create(&s_packet_buffer_id,
                                  APP_TIMER_MODE_REPEATED,
                                  buffer_send_handler);   
    ASSERT(err_code == NRF_SUCCESS);
}

/**@brief Timeout function used when packet buffer is not empty
 */
static void buffer_send_handler(void* p_context)
{    
    uint32_t err_code;
    // Clear buffer and stop handler if not connected
		if (s_connection_state != state_connected)
    {
				s_packet_buffer.nb_packets = 0;			// Clear buffer
				app_timer_stop(s_packet_buffer_id);		// Stop handler time
        return;
    }
		else if (s_connection_state == state_advertising)
		{
			// Already advertising and waiting for a conenction
			s_packet_buffer.nb_packets = 0;			// Clear buffer
			app_timer_stop(s_packet_buffer_id);		// Stop handler time
			return;
		}
    
		while ((s_packet_buffer.nb_packets))
		{
			#if defined(DEBUG_UART_MAIN) 
				printf("B-L\tB:%u\r\n",s_packet_buffer.sd_buffers_available);
			#endif
			if (s_packet_buffer.sd_buffers_available > MIN_SD_BUFFERS_AVAILABLE)
			{
				memcpy (poster_value, &s_packet_buffer.buffer[s_packet_buffer.index], MIDI_MAX_PACKET_LEN);
				
				err_code = poster_value_meas_handler();
				
				if (err_code == NRF_SUCCESS)
				{
						#if defined(DEBUG_UART_MAIN) 
							printf("B-S\r\n");
						#endif
						s_packet_buffer.nb_packets--;
						s_packet_buffer.sd_buffers_available--;
						s_packet_buffer.index = ((s_packet_buffer.index + 1) % SCHED_QUEUE_SIZE);
				}
				else
				{
						#if defined(DEBUG_UART_MAIN) 
							printf("SE:%u\r\n",err_code);
						#endif
					return;
				}
			}
			if (s_packet_buffer.nb_packets == 0)
			{
					app_timer_stop(s_packet_buffer_id);
					return;
			}
		}
}

/**@brief Utility function to buffer packets that fails to be sent
 */
static void buffer_data(const midi_packet_t* packet)
{
	
	 // The m_coms_btle module should start advertising if data is needed to be send
	if (s_connection_state == state_disconnected)
	{
			// Start advertising if we are not connected
			s_connection_state = state_advertising;
			advertising_start();
			return;
	}
	else if (s_connection_state == state_advertising)
	{
		// Already advertising and waiting for a conenction
		return;
	}
	
	if (s_packet_buffer.nb_packets == SCHED_QUEUE_SIZE)
	{
		 // Buffer is full. Won't overwrite.
		 return;
	}
	else
	{
			uint32_t index;

			index = (s_packet_buffer.index + s_packet_buffer.nb_packets) % 
							(sizeof(s_packet_buffer.buffer) / sizeof(s_packet_buffer.buffer[0]));
			// Put the packet in our circular buffer
			memcpy(&s_packet_buffer.buffer[index], packet, sizeof(midi_packet_t));       
			s_packet_buffer.nb_packets++;

			// Start the timeout handler
			app_timer_start(s_packet_buffer_id, APP_TIMER_TICKS(15 /* [ms] */, APP_TIMER_PRESCALER), 0);
	}
}

This should keep track of the packet buffers in use on the ble stack and only send new ones when there is available room for a new packet. The number of buffers available (s_packet_buffer.sd_buffers_available) is incremented every time a BLE_EVT_TX_COMPLETE event is received as follows:

				
case BLE_EVT_TX_COMPLETE:
						s_packet_buffer.sd_buffers_available += p_ble_evt->evt.common_evt.params.tx_complete.count;
						#if defined(DEBUG_UART_MAIN) 
							printf("M-TXC:%u\r\n",p_ble_evt->evt.common_evt.params.tx_complete.count);
						#endif
						break;

I have add some lines to debug through uart. This is the ouput (BE are bluetooth events)


Modules Initialized
BE: 0x0010
BE: 0x0052
BE: 0x0050
BE: 0x0050
BE: 0x0050
BE: 0x0012
B-L     B:7
B-S
B-L     B:6
B-S
M-TXC:1
BE: 0x0001
B-L     B:6
B-S
B-L     B:5
B-S
M-TXC:2
BE: 0x0001
B-L     B:6
B-S
B-L     B:5
B-S
B-L     B:4
B-S
B-L     B:3
B-S
M-TXC:3
BE: 0x0001
B-L     B:5
B-S
B-L     B:4
B-S
B-L     B:3
B-S
M-TXC:1
BE: 0x0001
M-TXC:1
BE: 0x0001
B-L     B:4
B-S
B-L     B:3
B-S
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2
B-L     B:2

It may be sth basic that I can't see, but it seems that packets are send to the ble stack but not all are cleared through a BLE_EVT_TX_COMPLETE event. Any ideas? Any suggestion?

Thanks in advance

Parents
  • Hi,

    Thanks for your reply.

    This is the poster_value_meas_handle function:

    static uint32_t poster_value_meas_handler(void)
    {
    	uint32_t        err_code;
    
    	err_code = ble_pos_poster_value_measurement_send(m_pos, poster_value);
    	
    	return err_code;
    }
    

    And the ble_pos_poster_value_measurement_send function. It is our own profile and it based on the heart rate profile with some modifications:

    uint32_t ble_pos_poster_value_measurement_send(ble_pos_t * p_pos, uint8_t *poster_value)
    {
        uint32_t err_code;
        
        // Send value if connected and notifying
        if (p_pos->conn_handle != BLE_CONN_HANDLE_INVALID)
        {
            uint16_t               len;
            uint16_t               hvx_len;
            ble_gatts_hvx_params_t hvx_params;
         
    			
    				len = poster_value[0] + 1;	// packet length is poster data size plus length byte
            hvx_len = len;
    
            memset(&hvx_params, 0, sizeof(hvx_params));
     
            hvx_params.handle   = p_pos->pos_handles.value_handle;
            hvx_params.type     = BLE_GATT_HVX_NOTIFICATION;
            hvx_params.offset   = 0;
            hvx_params.p_len    = &hvx_len;
            hvx_params.p_data   = poster_value;
     
            err_code = sd_ble_gatts_hvx(p_pos->conn_handle, &hvx_params);
            if ((err_code == NRF_SUCCESS) && (hvx_len != len))
            {
                err_code = NRF_ERROR_DATA_SIZE;
            }
        }
        else
        {
            err_code = NRF_ERROR_INVALID_STATE;
        }
    
        return err_code;
    }
    

    Yes, I receive all the packets that I am sending on Master Control Panel.

Reply
  • Hi,

    Thanks for your reply.

    This is the poster_value_meas_handle function:

    static uint32_t poster_value_meas_handler(void)
    {
    	uint32_t        err_code;
    
    	err_code = ble_pos_poster_value_measurement_send(m_pos, poster_value);
    	
    	return err_code;
    }
    

    And the ble_pos_poster_value_measurement_send function. It is our own profile and it based on the heart rate profile with some modifications:

    uint32_t ble_pos_poster_value_measurement_send(ble_pos_t * p_pos, uint8_t *poster_value)
    {
        uint32_t err_code;
        
        // Send value if connected and notifying
        if (p_pos->conn_handle != BLE_CONN_HANDLE_INVALID)
        {
            uint16_t               len;
            uint16_t               hvx_len;
            ble_gatts_hvx_params_t hvx_params;
         
    			
    				len = poster_value[0] + 1;	// packet length is poster data size plus length byte
            hvx_len = len;
    
            memset(&hvx_params, 0, sizeof(hvx_params));
     
            hvx_params.handle   = p_pos->pos_handles.value_handle;
            hvx_params.type     = BLE_GATT_HVX_NOTIFICATION;
            hvx_params.offset   = 0;
            hvx_params.p_len    = &hvx_len;
            hvx_params.p_data   = poster_value;
     
            err_code = sd_ble_gatts_hvx(p_pos->conn_handle, &hvx_params);
            if ((err_code == NRF_SUCCESS) && (hvx_len != len))
            {
                err_code = NRF_ERROR_DATA_SIZE;
            }
        }
        else
        {
            err_code = NRF_ERROR_INVALID_STATE;
        }
    
        return err_code;
    }
    

    Yes, I receive all the packets that I am sending on Master Control Panel.

Children
No Data
Related