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分支修改代码后提交至仓库。