# 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,读取数据的方式有以下几种: 1. 每20ms获取一次三轴数据,这样MCU不用干其他事了,对性能影响非常大。 2. 使用传感器的FIFO,每100ms查询一次FIFO溢出的标志。这样不能及时处理数据。 3. 使用传感器的FIFO+溢出中断。有中断触发后读取值。这样最为合理。 增加中断接口后,BabyOS编写LIS3DH驱动时可用第3种方式。 那使用什么样的中断接口呢?深入研究MCU内核的中断部分,像ametal那样将原厂SDK里的启动文件都重写? 结合BabyOS开源项目的实际情况,ametal的那种方式是不合适的: 1. 没有充足的人力、时间投入去研究各类内核。 2. 第1项不满足的情况,不能考虑对原厂SDK提供的文件进行修改。 最终采用如下方式: ```c #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); ``` ![中断](../_static/interrupt.png) ## select功能模块 紧接着上文,描述为什么增加这个模块。当中断触发后,读取FIFO数据到驱动的缓存等待被读取。 应用程序如何去知道lis3dh缓存已经有数据可读。 1. 通过bCtl注册回调,驱动程序读取FIFO数据后调用回调 2. 使用select,同时监控1个或多个句柄的可读、可写和异常情况。 相比回调,使用select可以让代码可读性更加友好。以下是可使用的接口: ```c #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例程的代码便可以改写成这样: ```c 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分支修改代码后提交至仓库。