bos框架使用


前面已经初步理解了bos框架,现在就看其关键的部分,如何实现的一个设备框架??

关于框架调度

除了在bos初识中说到的循环调度bExec();就是基于SysTIck的计时调度,可以说裸机的程序都有了。
使用时只要使用b_section.h里的BOS_REG_POLLING_FUNC()注册一下就可以了。这个一般在组件里使用,或自己写的函数。
定时调度,使用b_os.h中的 BOS_PERIODIC_TASK();注册一下就可以使用了。

更新

最近,在官网上看到,代码已经迭代了,具明显的就是不再分三个仓库了,而是把配置及hal仓库合并到了主仓库里面。

再顺一遍建工程流程

新建一个空工程

添加bos 代码

执行 git init;将工程目录变为git目录
执行git submodule add https://gitee.com/notrynohigh/BabyOS.git;将baby 添加进工程

将os代码添加进工程
路径部分/全部备注
bos/algorithm根据需要添加
bos/core全部添加
bos/drivers根据需要添加不需要的驱动不要添加到工程中
bos/hal全部添加
bos/mcu根据需要添加根据平台添加对应的代码,对应b_config.h中的配置
bos/modules全部添加全部添加后,可在b_config中配置
bos/thirdparty根据需要添加CmBacktrace 错误跟踪
FatFS 文件系统
littlefs 文件系统
FlexibleButton 使用按键模块则需要添加
nr_micro_shell 命令行
SFUD 使用SPIFLASH驱动需要添加
UGUI 简单的GUI库
bos/utils全部添加通用代码,有模拟的IIC和SPI代码,模拟串口接收空闲事件
bos/_configb_config.h BabyOS 配置文件
b_device_list.h 注册设备的文件
b_hal_if.h 驱动接口文件

首先将,需要全部添加的,都加进工程,其他根据需要添加。

添加头文件路径

添加两个路径即可:
bos/

_config/ 如果配置文件拷贝到其他路径了,则添加相应路径即可。

修改配置
配置项说明备注
Version Configuration版本配置项,硬件和固件版本
Platform Configuration平台配置项,指定心跳频率和MCU平台
Modules Configuration模块配置项,各个功能模块的配置
Thirdparty Configuration第三方开源代码配置项
调用必要的函数

Include头文件 b_os.h
①滴答定时器中断服务函数调用 bHalIncSysTick();
②初始化代码 bInit();
③主循环调用 bExec();

新版本特点

新版本加入了mcu部分,支持的mcu还是比较少的。如对st,只支持F107,这块还必须得有,否则会编译报错。并且,还需要完善,所以还是以旧版本为参考。

设备注册到使用

例子用到的spi与qspi区别:

SPI协议其实是包括:Standard SPI、Dual SPI和Queued SPI三种协议接口,分别对应3-wire, 4-wire, 6-wire。

  • Standard SPI,有4根信号线,分别为CLK、CS、MOSI和MISO。数据线工作在全双工。
  • Dual SPI,它只是针对SPI Flash而言,不是针对所有SPI外设。对于SPI Flash,全双工并不常用,因此扩展了mosi和miso的用法,让它们工作在半双工,用以加倍数据传输。也就是对于Dual SPI Flash,可以发送一个命令字节进入dual mode,这样mosi变成SIO0(serial io 0),mosi变成SIO1(serial io 1),这样一个时钟周期内就能传输2个bit数据,加倍了数据传输。
  • 类似的,还可以扩展,Qual SPI Flash增加了两根I/O线(SIO2,SIO3),目的是一个时钟内传输4个bit
    而QSPI就是Queued SPI的简写。

注册

/b_device_list.h,在里面添加使用的外设,B_DEVICE_REG(SPIFLASH, bSPIFLASH_Driver[0], "flash")
注意:这个头文件最后有个#undef B_DEVICE_REG,也就是说注册完了后,就取消了这个宏
随后在b_device.h中完成名称赋值,如下:

typedef enum
{
#define B_DEVICE_REG(dev, driver, desc) dev,
#include "b_device_list.h"
    bDEV_MAX_NUM
} bDeviceName_t;//设备号

在b_device.c中完成驱动及描述的赋值,如下:

static bDriverInterface_t *bDriverTable[bDEV_MAX_NUM] = {
#define B_DEVICE_REG(dev, driver, desc) &driver,
#include "b_device_list.h"
};//驱动接口  在相应的设备接口数组中注册

static const char *bDeviceDescTable[bDEV_MAX_NUM] = {
#define B_DEVICE_REG(dev, driver, desc) desc,
#include "b_device_list.h"
};

注册完后的操作,设备层实现

bSECTION_DEF_FLASH(driver_init, pbDriverInit_t)//这个就是要连接底层的中间宏
driver_init :很明显就是段名
pbDriverInit_t:在b_device.h中被定义为了指针函数。
这个其实就是要在初始化时,要初始化的设备地址的定义

映射到驱动层,完成初始化

驱动层要在硬件抽象层的上面,所以上面只是完成了要初始化接口,但具体初始化哪些设备呢?这个就要根据实际加上驱动。如要使用spi - flash ,就要加上b_drv_spiflash.c文件,这里面自然会有bDRIVER_REG_INIT(bSPIFLASH_Init);//bSPIFLASH_Init:这个便是初始化函数
这个就在映射ROM地图里找到相应的段。
在b_drive.h中,#define bDRIVER_REG_INIT(func) \bSECTION_ITEM_REGISTER_FLASH(driver_init, pbDriverInit_t, CONCAT_2(init, func)) = func//通过这个宏又跳到section
在b_section.h中,#define bSECTION_ITEM_REGISTER_FLASH(section_name, data_type, var_name) \BOS_SECTION_ITEM_REGISTER(section_name, const data_type var_name)
还得跳

#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6000000))
#define BOS_SECTION_ITEM_REGISTER(section_name, section_var) \
    section_var __attribute__((section(STRINGIFY(section_name)))) __attribute__((used))

当然这些底层的操作,要熟悉MDK链接。还是有难度的…通过这些操作,在main中调用bInit()就知道调用哪些设备来完成初始化了。也就相当于系统知道了初始化了。

bSPIFLASH_Init()函数代码
int bSPIFLASH_Init()
{
    size_t i = 0, number = sizeof(bSPIFLASH_HalIfTable) / sizeof(bSPIFLASH_HalIf_t);
    int    retval = 0;
    for (i = 0; i < number; i++)
    {
        sprintf(bSPIFlashName[i], "%03d", i);
        flash_table[i].name        = bSPIFlashName[i];
        flash_table[i].spi._hal_if = (void *)&bSPIFLASH_HalIfTable[i];

        bSPIFLASH_Driver[i]._hal_if     = (void *)&bSPIFLASH_HalIfTable[i];
        bSPIFLASH_Driver[i].open        = _bSPIFLASH_Open;//通过这些函数调用硬件抽象层
        bSPIFLASH_Driver[i].close       = _bSPIFLASH_Close;
        bSPIFLASH_Driver[i].ctl         = _bSPIFLASH_Ctl;
        bSPIFLASH_Driver[i].read        = _bSPIFLASH_ReadBuf;
        bSPIFLASH_Driver[i].write       = _bSPIFLASH_WriteBuf;
        bSPIFLASH_Driver[i].status      = 0;
        bSPIFLASH_Driver[i]._private._p = &flash_table[i];
    }

    for (i = 0; i < number; i++)
    {
        _bSPIFLASH_Open(&bSPIFLASH_Driver[i]);  // wakeup flash
    }

    if (sfud_init() != SFUD_SUCCESS)//调用万能spi驱动,实现硬件的初始化
    {
        for (i = 0; i < number; i++)
        {
            bSPIFLASH_Driver[i].status = -1;
        }
        retval = -1;
    }

    for (i = 0; i < number; i++)
    {
        _bSPIFLASH_Close(&bSPIFLASH_Driver[i]);  // powerdown flash
    }

    return retval;
}

bDRIVER_REG_INIT(bSPIFLASH_Init);

调用硬件抽象层

万能spi-flash 驱动库

SFUD–SFUD 全称 Serial Flash Universal Driver,是一款开源的串行 SPI Flash 通用驱动库。github项目地址,实际上,fllash首先得是 SFDP :它是 JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,这四个字符SFDP都存放到了flash特定区域中,以此来区分是否支持sfdp.这里就不展开了,资料也很多。

驱动层如何调用的硬件抽象层??

在b_drv_spiflash.c文件中bSPIFLASH_Init()函数中,定义的open、close 等函数,便是与硬件抽象层的接口。
拿open为例:

static int _bSPIFLASH_Open(bSPIFLASH_Driver_t *pdrv)
{
    bDRV_GET_HALIF(_if, bSPIFLASH_HalIf_t, pdrv);
    uint8_t cmd = 0xab;
    bHalGPIO_WritePin(_if->cs.port, _if->cs.pin, 0);//这里便是抽象层定义的函数
    if (_if->is_spi == 0)
    {
        return -1;
        // add qspi ...
    }
    else
    {
        bHalSPI_Send(_if->_if.spi, &cmd, 1);//这也是抽象层函数
    }
    bHalGPIO_WritePin(_if->cs.port, _if->cs.pin, 1);
    bHalDelayUs(10);
    return 0;
}
bDRV_GET_HALIF(_if, bSPIFLASH_HalIf_t, pdrv)实现了什么?

在b_drive.h中#define bDRV_GET_HALIF(name, type, pdrv) type *name = (type *)(pdrv->_hal_if)替换一下就是 bSPIFLASH_HaIIf_t *_if = (bSPIFLASH_HaIIf_t *)(pdrv->_hal_if),这就实现了函数指针的赋值。

调用底层库

库指的是芯片的操作库,直接由驱动层里的函数来实现调用,这样就可以操作芯片了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guangod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值