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

How to change advertising packet in Mesh many time ?

Hi all,

Now, I have a troube. In Mesh 3.0, I want to advertising data. This is my function : 

#define ADVERTISER_BUFFER_SIZE  (128)

void adv_start(uint8_t *data, uint32_t length)
{
    if(length > 31){
        __RESPONSE_UART("LENGTH ADV TOO LONG\n",20);
    }
    else{
        advertiser_enable(&m_advertiser);
        /* Allocate packet */
        adv_packet_t * p_packet = advertiser_packet_alloc(&m_advertiser, length);
        if (p_packet)
        {
            /* Construct packet contents */
            memcpy(p_packet->packet.payload, data, length);
            /* Repeat forever */
            p_packet->config.repeats = ADVERTISER_REPEAT_INFINITE;

            advertiser_packet_send(&m_advertiser, p_packet);
        }
    }
}

And whenever the data changes, I call adv_start function for advertising it. But I only do this 4 times, and from the 5th, data advertising not change. p_packet alway =  NULL .Why?

How to resolve it ? Thank very much.

Parents
  • looking at the implementation of advertiser_packet_alloc() we see that it will return packet_buffer_reserve() return status == NRF_ERROR_NO_MEM

    adv_packet_t * advertiser_packet_alloc(advertiser_t * p_adv, uint32_t adv_payload_size)
    {
        NRF_MESH_ASSERT(p_adv != NULL);
        NRF_MESH_ASSERT(adv_payload_size <= BLE_ADV_PACKET_PAYLOAD_MAX_LENGTH);
    
        packet_buffer_packet_t * p_buf_packet;
        uint32_t status = packet_buffer_reserve(&p_adv->buf, &p_buf_packet, sizeof(adv_packet_t) - BLE_ADV_PACKET_PAYLOAD_MAX_LENGTH + adv_payload_size);
        if (NRF_SUCCESS == status)
        {
            adv_packet_t * p_adv_packet  = (adv_packet_t *) p_buf_packet->packet;
            packet_payload_size_set(&p_adv_packet->packet, adv_payload_size);
            p_adv_packet->packet.header.type = BLE_PACKET_TYPE_ADV_NONCONN_IND;
            set_adv_address(p_adv, &p_adv_packet->packet);
            p_adv_packet->token = NRF_MESH_INITIAL_TOKEN;
            return p_adv_packet;
        }
        else
        {
            NRF_MESH_ASSERT(status == NRF_ERROR_NO_MEM);
            return NULL;
        }
    }

    Looking at the documentation of packet_buffer_reserve

    /**
     * Reserves a packet in the given packet buffer.
     *
     * @param[in, out] p_buffer A packet buffer instance to reserve a packet on.
     * @param[out] pp_packet Reference to the reserved packet.
     * @param[in] length Number of bytes of payload to reserve, not including the
     * static header fields of the packet.
     *
     * @warning This function requires that:
     *               - Pointers supplied are not NULL
     *
     * @retval NRF_SUCCESS The packet is reserved successfully, and pp_packet points to
     * a valid packet pointer instance.
     * @retval NRF_ERROR_NO_MEM The packet buffer does not have enough available memory.
     * @retval NRF_ERROR_INVALID_LENGTH The length of the packet requested cannot be 0 or greater
     * than the maximum available packet size in the given packet buffer. Use @ref
     * packet_buffer_max_packet_len_get to determine the max packet length possible.
     */
    uint32_t packet_buffer_reserve(packet_buffer_t * const p_buffer, packet_buffer_packet_t ** pp_packet, uint16_t length);

    we see that it will return NRF_ERROR_NO_MEM if the packet buffer does not have enough available memory. So you need to look at the size of the buffer that you pass to advertiser_instance_init(), I think defined as ADVERTISER_BUFFER_SIZE  and its set to 

    #define ADVERTISER_BUFFER_SIZE (64)
  • Yes, default set #define ADVERTISER_BUFFER_SIZE (64) and I only change data 2 times, from 3th data not change, I change it to #define ADVERTISER_BUFFER_SIZE (128) and I can change data 4 times, but I can not increase it forever. Seem it not good solution. I try SDK 2.0 , 2.2 ,3.0 , It encounters the same problem. And SDK 1.0 no problem.So I looking for another solution . Thanks.

     

  • It could be that you need to wait for the advertiser_tx_complete_cb_t tx_complete_cb callback, that is registered when calling advertiser_instance_init(), and then free the memory allocated. 

    After advertiser_packet_send() is called and the packet is sent successfully, the @c tx_complete_callback in the @c p_adv * will be called with @c p_packet and @c p_adv as parameters to the callback.

    Use the parameters as input to advertiser_packet_discard(advertiser_t * p_adv, adv_packet_t * p_packet) to free the memory allocated. 

  • Hi,

    I changed code to : 

    static void tx_commplete(advertiser_t * p_adv, nrf_mesh_tx_token_t token, timestamp_t timestamp)
    { 
        // free p_packet pointer for alloc next
        if(p_adv->p_packet!=NULL)
        {
            advertiser_packet_discard(p_adv,p_adv->p_packet);
        }
    }
    
    static void adv_init(void)
    {
        advertiser_instance_init(&m_advertiser, tx_commplete, m_adv_buffer, ADVERTISER_BUFFER_SIZE);
    }

    I get HardFault: 

    And p_packet->packet_state = PACKET_BUFFER_MEM_STATE_FREE

    If I comment NRF_MESH_ASSERT , everything work fine. I can change many time

  • HI Giang, 

    I do not think commenting out NRF_MESH_ASSERT in packet_buffer_free  is a very good idea. As stated in the comment, you cannot call packet_buffer_free  on packets that are not Popped or Reserved. 

Reply Children
No Data
Related