一、简介
WSF(wireless software foundation)是对操作系统的一个简单的封装,提供对操作系统的简单编程,提供简单的系统服务
功能简介:
- 事件、消息传递和处理。
- 定时器功能。
- 队列和缓存管理功能。
- 可编程的数据类型。
- 关键部分和任务锁定。
- 调试输出和断言诊断。
- 用于加密和随机数生成的安全接口
WSF不定义任何任务,仅定义了一些给任务的接口。依赖于目标OS去实现任务和事件管理,定时器管理等。也可以在裸机环境中充当一个简单的独立操作系统。
二、组成介绍
数据类型
wsf_types.h
定义了后续软件系统使用的常用数据类型。
/* 嵌入式常用数据类型 */
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed long int32_t;
typedef unsigned long uint32_t;
typedef unsigned long long uint64_t;
内存管理
WSF的内存管理是一个基于内存池的缓存管理方法。
//内存池缓存描述结构
typedef struct
{
uint16_t len; //内存池中单个缓存长度
uint8_t num; //内存池中缓存个数
} wsfBufPoolDesc_t;
//内存池管理结构
typedef struct
{
wsfBufPoolDesc_t desc; //内存池
wsfBufMem_t *pStart; //内存池开始的指针
wsfBufMem_t *pFree; //指向第一个可用的内存位置
#if WSF_BUF_STATS == TRUE //用于控制buf状态信息的输出和调试
uint8_t numAlloc; //当前被申请的内存个数
uint8_t maxAlloc; //使用最大个数
uint16_t maxReqLen; //使用的最长的长度
#endif
} wsfBufPool_t;
//一个内存单位的描述结构,同时作为每个内存块的头部结构,属于复用型结构
//这个地方定义为一个指针的大小,目的可能是为了做内存对齐。
typedef struct wsfBufMem_tag
{
struct wsfBufMem_tag *pNext; //指向下一个内存块的位置
#if WSF_BUF_FREE_CHECK == TRUE
uint32_t free; //表示该内存块单元是否被使用
#endif
} wsfBufMem_t;
内存池分配的结构
内存的初始化
内存的初始化是将传递进来的整块内存,按照上图所示,依次在头部填充N个内存池的管理结构,然后将剩下的内存划分为N个内存池,并根据内存池描述结构将每个内存池划分为M块实际内存。
因此,传递内存的大小应该额外添加N个内存管理结构的大小。否则内存池将厨师胡失败。产生断言。
/*
*bufMemLen:传入的缓冲区大小。
*pBufMem:指向缓冲区的指针。
*numPools:需要创建的内存池个数。
*pDesc:每个内存池的描述结构。
*/
uint16_t WsfBufInit(uint16_t bufMemLen, uint8_t *pBufMem, uint8_t numPools, wsfBufPoolDesc_t *pDesc)
{
wsfBufPool_t *pPool;
wsfBufMem_t *pStart;
uint16_t len;
uint8_t i;
wsfBufMem = (wsfBufMem_t *) pBufMem;
pPool = (wsfBufPool_t *) wsfBufMem;
/* 内存的头部存放内存池管理结构 */
pStart = (wsfBufMem_t *) (pPool + numPools);
wsfBufNumPools = numPools;
/* 循环创建内存池 */
while (TRUE)
{
/* 这里时检测内存是否越限 */
/* 这个位置最好在函数的入口进行总长度的计算,边创建边计算的方式稍微有点不合适 */
if (pStart > &wsfBufMem[bufMemLen / sizeof(wsfBufMem_t)])
{
WSF_ASSERT(FALSE);
return 0;
}
/* 创建完毕退出循环 */
if (numPools-- == 0)
{
break;
}
/* 对内存池进行对齐,这里是以一个指针的大小进行对齐 */
if (pDesc->len < sizeof(wsfBufMem_t))
{
pPool->desc.len = sizeof(wsfBufMem_t);
}
else if ((pDesc->len % sizeof(wsfBufMem_t)) != 0)
{
pPool->desc.len = pDesc->len + sizeof(wsfBufMem_t) - (pDesc->len % sizeof(wsfBufMem_t));
}
else
{
pPool->desc.len = pDesc->len;
}
pPool->desc.num = pDesc->num; //记录内存池中内存块的个数。
pDesc++;
pPool->pStart = pStart; //记录内存其实位置
pPool->pFree = pStart; //记录下一个可用的位置
#if WSF_BUF_STATS == TRUE
pPool->numAlloc = 0;
pPool->maxAlloc = 0;
pPool->maxReqLen = 0;
#endif
WSF_TRACE_INFO2("Creating pool len=%u num=%u", pPool->desc.len, pPool->desc.num);
WSF_TRACE_INFO1(" pStart=0x%x", (uint32_t)pPool->pStart);
/* 循环创建内存块,设置可用链表 */
len = pPool->desc.len / sizeof(wsfBufMem_t);
for (i = pPool->desc.num; i > 1; i--)
{
/* 越界检测,若开始做了检查则此处不在需要检查 */
if (pStart > &wsfBufMem[bufMemLen / sizeof(wsfBufMem_t)])
{
WSF_ASSERT(FALSE);
return 0;
}
/* 记录下一个空闲的位置 */
pStart->pNext = pStart + len;
pStart += len;
}
/* 越界检测,同上 */
if (pStart > &wsfBufMem[bufMemLen / sizeof(wsfBufMem_t)])
{
WSF_ASSERT(FALSE);
return 0;
}
/* 最后一个内存块的下一个指向空 */
pStart->pNext = NULL;
pStart += len;
/* 进行下一个内存池的创建 */
pPool++;
}
wsfBufMemLen = (uint8_t *) pStart - (uint8_t *) wsfBufMem;
WSF_TRACE_INFO1("Created buffer pools; using %u bytes", wsfBufMemLen);
return wsfBufMemLen;
}
内存申请
使用轮询的方式依次检查每个内存池支持的长度以及,是否有剩余空间,然后取其中一个将内存起始地址返回,并重新设置free指针。
/*
*len:申请内存的长度
*/
void *WsfBufAlloc(uint16_t len)
{
wsfBufPool_t *pPool;
wsfBufMem_t *pBuf;
uint8_t i;
WSF_CS_INIT(cs);
WSF_ASSERT(len > 0);
pPool = (wsfBufPool_t *) wsfBufMem;
/* 轮询每个mempool,找到空闲和合适大小的内存池 */
for (i = wsfBufNumPools; i > 0; i--, pPool++)
{
/* 判断当前内存池块大小是否满足需求 */
if (len <= pPool->desc.len)
{
/* enter critical section */
WSF_CS_ENTER(cs);
/* 判断当前内存池是都有空余内存块 */
if (pPool->pFree != NULL)
{
/* pbuf指向可用内存 */
pBuf = pPool->pFree;
/* 将FREE指针指向下一个内存块的位置 */
pPool->pFree = pBuf->pNext;
#if WSF_BUF_FREE_CHECK == TRUE
pBuf->free = 0;
#endif
#if WSF_BUF_STATS_HIST == TRUE
/* increment count for buffers of this length */
if (len < WSF_BUF_STATS_MAX_LEN)
{
wsfBufAllocCount[len]++;
}
else
{
wsfBufAllocCount[0]++;
}
#endif
#if WSF_BUF_STATS == TRUE
if (++pPool->numAlloc > pPool->maxAlloc)
{
pPool->maxAlloc = pPool->numAlloc;
}
pPool->maxReqLen = WSF_MAX(pPool->maxReqLen, len);
#endif
/* exit critical section */
WSF_CS_EXIT(cs);
WSF_TRACE_ALLOC2("WsfBufAlloc len:%u pBuf:%08x", pPool->desc.len, pBuf);
return pBuf;
}
/* exit critical section */
WSF_CS_EXIT(cs);
#if WSF_BUF_ALLOC_BEST_FIT_FAIL_ASSERT == TRUE
WSF_ASSERT(FALSE);
#endif
}
}
/* 申请失败,若使能了回调函数,调用回调通知 */
#if WSF_OS_DIAG == TRUE
if (wsfBufDiagCback != NULL)
{
WsfBufDiag_t info;
info.type = WSF_BUF_ALLOC_FAILED;
info.param.alloc.taskId = WSF_OS_GET_ACTIVE_HANDLER_ID();
info.param.alloc.len = len;
wsfBufDiagCback(&info);
}
else
{
WSF_TRACE_WARN2("WsfBufAlloc failed len:%u - task:%u", len, WSF_OS_GET_ACTIVE_HANDLER_ID());
}
#else
WSF_TRACE_WARN1("WsfBufAlloc failed len:%u", len);
#endif
#if WSF_BUF_ALLOC_FAIL_ASSERT == TRUE
WSF_ASSERT(FALSE);
#endif
return NULL;
}
内存释放
从缓冲区的尾部开始查询,根据每个mempool的起始地址找到被释放内存在内存池中的位置,将内存重新释放到内存池中,并重新定义内存头部信息。
void WsfBufFree(void *pBuf)
{
wsfBufPool_t *pPool;
wsfBufMem_t *p = pBuf;
WSF_CS_INIT(cs);
/* 判断指针范围 */
#if WSF_BUF_FREE_CHECK == TRUE
WSF_ASSERT(p >= ((wsfBufPool_t *) wsfBufMem)->pStart);
WSF_ASSERT(p < (wsfBufMem_t *)(((uint8_t *) wsfBufMem) + wsfBufMemLen));
#endif
/* 从最后一个内存池开始查找 */
pPool = (wsfBufPool_t *) wsfBufMem + (wsfBufNumPools - 1);
while (pPool >= (wsfBufPool_t *) wsfBufMem)
{
/* 如果在当前内存池的范围内 */
if (p >= pPool->pStart)
{
/* enter critical section */
WSF_CS_ENTER(cs);
#if WSF_BUF_FREE_CHECK == TRUE
WSF_ASSERT(p->free != WSF_BUF_FREE_NUM);
p->free = WSF_BUF_FREE_NUM;
#endif
#if WSF_BUF_STATS == TRUE
pPool->numAlloc--;
#endif
/* 重新将内存块放入内存池中,并将free指针指向当前的内存位置 */
p->pNext = pPool->pFree;
pPool->pFree = p;
/* exit critical section */
WSF_CS_EXIT(cs);
WSF_TRACE_FREE2("WsfBufFree len:%u pBuf:%08x", pPool->desc.len, pBuf);
return;
}
/* 不在当前内存池,查找下一个 */
pPool--;
}
/* should never get here */
WSF_ASSERT(FALSE);
return;
}