BabyOS V8.3.0更新介绍
BabyOS V8.3.0版本首先是修复了队列等模块的bug,然后HAL层增加中断接口,Modules增加select功能模块。
以下对新增的两个模块进行介绍。
HAL层中断接口
BabyOS V8.3.0 之前,MCU发生中断没有接口通知BabyOS,导致编写驱动程序时无法使用中断。
例如:ST的三轴传感器lis3dh,其有32级FIFO并支持FIFO溢出中断。
假设某场景要求ODR为50Hz,读取数据的方式有以下几种:
每20ms获取一次三轴数据,这样MCU不用干其他事了,对性能影响非常大。
使用传感器的FIFO,每100ms查询一次FIFO溢出的标志。这样不能及时处理数据。
使用传感器的FIFO+溢出中断。有中断触发后读取值。这样最为合理。
增加中断接口后,BabyOS编写LIS3DH驱动时可用第3种方式。
那使用什么样的中断接口呢?深入研究MCU内核的中断部分,像ametal那样将原厂SDK里的启动文件都重写?
结合BabyOS开源项目的实际情况,ametal的那种方式是不合适的:
没有充足的人力、时间投入去研究各类内核。
第1项不满足的情况,不能考虑对原厂SDK提供的文件进行修改。
最终采用如下方式:
#define bHAL_IT_REGISTER(name, _it, _index, _handler, _user_data) \
static bHalIt_t name; \
do \
{ \
name.it = _it; \
name.index = _index; \
name.handler = _handler; \
name.user_data = _user_data; \
bHalItRegister(&name); \
} while (0)
/**
* 注册中断处理函数。
* index : 例如,当int 为 B_HAL_IT_EXTI, index可以表示外部中断号
* 例如 当int 为 B_HAL_IT_UART_RX,index可以表示串口号
* 推荐使用:bHAL_IT_REGISTER(name, _interrupt, _index, _handler)
*/
int bHalItRegister(bHalIt_t *pit);
/**
* MCU触发中断后,通过此函数告诉BOS有中断发生,并将数据传给BOS
*/
int bHalItInvoke(bHalItNumber_t it, uint8_t index, bHalItParam_t *param);
select功能模块
紧接着上文,描述为什么增加这个模块。当中断触发后,读取FIFO数据到驱动的缓存等待被读取。
应用程序如何去知道lis3dh缓存已经有数据可读。
通过bCtl注册回调,驱动程序读取FIFO数据后调用回调
使用select,同时监控1个或多个句柄的可读、可写和异常情况。
相比回调,使用select可以让代码可读性更加友好。以下是可使用的接口:
#define bFD_ZERO(pfds)
#define bFD_SET(fd, pfds)
#define bFD_ISSET(fd, pfds)
#define B_PT_SELECT(pt, maxfdp, readfds, writefds, errorfds, timeout, result)
// bSelect是非阻塞的,如果要做到阻塞的效果,建议开启pt,并使用B_PT_SELECT
int bSelect(int maxfdp, bFdSet_t *readfds, bFdSet_t *writefds, bFdSet_t *errorfds);
lis3dh例程的代码便可以改写成这样:
static PT_THREAD(gsensor_task(struct pt *pt))
{
int count = 0;
bGsensor3Axis_t Gsensor[32];
static int fd = -1;
static bFdSet_t fdset;
PT_BEGIN(pt);
fd = bOpen(bLIS3DH, BCORE_FLAG_RW);
if (fd < 0)
{
return 0;
}
while (1)
{
bFD_ZERO(&fdset);
bFD_SET(fd, &fdset);
B_PT_SELECT(pt, fd + 1, &fdset, NULL, NULL, 2000, count);
b_log("select:%d\r\n", count);
if (count > 0)
{
if (bFD_ISSET(fd, &fdset))
{
bRead(fd, (uint8_t *)&Gsensor, sizeof(Gsensor));
for (int i = 0; i < 32; i++)
{
b_log("x:%d y:%d z:%d\r\n", Gsensor[i].x_mg, Gsensor[i].y_mg, Gsensor[i].z_mg);
}
}
}
}
PT_END(pt);
}
以上为抛砖引玉,希望有兴趣的盆友拉取最新的代码体验。对设计方面有建议可以在Issues提单或者基于dev分支修改代码后提交至仓库。