The BLE host stack, Packetcraft(Cordio formerly,) adopted by AmbiqSuite equips with its own buffer management service, wsf_buf, serving the application and the host stack. The implementation of wsf_buf is available in the following files:
<ambiqsuite_root>/third_party/cordio/wsf/include/wsf_buf.h
<ambiqsuite_root>/third_party/cordio/wsf/sources/port/freertos/wsf_buf.c
wsf_buf implements an intuitive method for buffer management. Application provides a RAM space as a buffer to wsf_buf at initialization when calling to the API WsfBufInit(). The initialization exists in the source file radio_task.c of every BLE example.
Pool Descriptor and Buffer Management
wsf_buf divides the given buffer into one section for wsf_buf internal control structure and memory pools of various block sizes based on the settings provided by the 4th input argument to the API WsfBufInit(). Each memory pool is further divided into memory blocks of the length specified in a pool descriptor. Take the following pool descriptor as an example. The buffer has four memory pools. The first pool consists of 8 blocks of 16 bytes in length, 4x 32-byte blocks in the second, 6x 64-byte blocks in the third and 14x 280-byte blocks in the fourth.
static wsfBufPoolDesc_t g_psPoolDescriptors[4] =
{
{16, 8},
{32, 4},
{64, 6},
{280, 14}
};
When WsfBufAlloc() is called, the pointer to one block picked from the pool, with available blocks, of the block size the least sufficient to the requested size is returned. Otherwise, NULL is returned. For example in the process of a request of 20 bytes, the 1st pool of 16-byte blocks is checked not fit. One block will be selected from the 2nd pool if there is at least one block available. If no available blocks exist, next memory pool is checked and so on until all memory pools are visited.
How to Fix Buffer Allocation Failure?
When the message “WsfBufAlloc failed len: XX”, where XX is the requested size, is printed in SWO log(most of the BLE examples in Ambiqsuite have this log enabled by default on SWO), a buffer allocation failure occurs. Two cases could lead to the failure.
Case A: No blocks of any size fit the requested size. For example, no blocks is able to accommodate a requested size of 281 byte. Two possible solutions:
- Increase the block size of one of the existing pools. And modify the variable g_pui32BufMem accordingly.
- Add one more pool with sufficient block size. It's a good practice to have the block size 4-byte aligned. And modify the variable g_pui32BufMem and the macro WSF_BUF_POOLS accordingly.
Case B: The requested size is servable but no blocks available at the time the request is made. In this case, it is recommended to review:
- If memory leakages exist in application. That is, WsfBufAlloc() is called but no calls to WsfBufFree() to free up allocated memory. These two APIs need to be used in pair.
- If application makes massive allocation requests in a short period of time. Massive requests could run the pools out of available blocks. Avoid this kind of usage as much as possible. Or increase the number of blocks in certain memory pool.
Appendix
wsf_buf provides several utility functions to check the pool status. Set WSF_BUF_STATS true to let the API WsfBufGetPoolStats() return the statistic of a given buffer pool.
Comments
0 comments
Please sign in to leave a comment.