16196|18

57

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

一套适合小型项目使用的通用代码 [复制链接]

 

BabyOS

logo

为小型项目而生,一个如孩童般需要集体喂养的弱操作系统。为什么称它为弱操作系统,因为相比已有的嵌入式操作系统,这个显得比较弱鸡。这里姑且称之为操作系统吧,其本质是一份代码集中营。


适用项目

BOS: 当前项目是否需要使用像FreeRTOS等操作系统?

U: 需要!

BOS:不好意思,我可能不适合你。

U: 开玩笑的,不需要用操作系统

BOS: 那您可以尝试使用我哦!

说一说写这么个东西的原因,大概就知道这份BOS有哪些功能。

................

某天、一位猿说,现在对项目就只有两个要求,功耗和开发时间。99.874%产品是电池供电,功耗是重点考虑对象。其次产品的功能都不复杂,项目之间也有很多重复的部分,是否有套代码能够减少重复的工作,加速产品demo的开发。

..............

功耗,为减小功耗,对于外设的操作原则是,唤醒外设,操作完成后进入睡眠。这样的操作形式和文件的操作很类似,文件的操作步骤是打开到编辑到关闭。决定将外设的操作看作是对文件的操作进行。每个外设打开后返回一个描述符,后续代码中对外设的操作都是基于这个描述符进行。关闭外设后回收描述符。那么在外设的驱动中,打开和关闭操作可以执行对设备的唤醒和睡眠。利用描述符来操作外设还有一个好处是,当更换外设后,只需更换驱动接口,业务部分的代码不需要变动。

快速开发,小型项目的开发中,有较多使用率高的功能模块,例如:UTC、错误管理、电池电量、存储数据、上位机通信、固件升级等等。将这些功能都做成独立的模块,不依赖于硬件。再配合一份配置文件,每次根据功能需求选择当前项目使用的功能模块。简单来说就是搭积木。

BOS 0.0.1版本驱动只加入模拟串口和华邦flash。存在的功能模块如下表所示。

序号 功能模块 说明
1 电量检测 支持设置阈值用于判断电量状态,正常或者低电量
2 校验计算 支持CRC32,累加和,异或和校验
3 错误管理 支持两种等级的错误管理
4 事件管理 支持事件触发某个操作
5 MODBUS协议 支持MODBUS协议RTU传输组包和解析
6 私有协议 协议格式:[header|id|len|cmd|data|crc]
7 固件升级 支持固件升级(私有协议基础上完成新固件的接收与存储)
8 数据存取 支持三种数据存储方式(定时存储、单次存储、连续存储)
9 发送管理 管理发送数据的秩序,防止未发送完成时又有新数据请求发送
10 UTC 支持UTC的转换,UTC起始时间为2000-1-1 0:0:0

电量检测 需要提供ADC转换的接口,设置阈值,判断当前电池的状态

校验计算 提供几种校验方式,在需要时使用

错误管理 提供两种等级的错误管理,低等级错误是只反馈一次异常,高等级错误是需要手动清除管理单元的异常信息,否则间隔时间到后就反馈异常。系统异常时,提交异常至管理单元并指定相同错误的最小间隔,防止同一个异常短时间多次被提交

事件管理 支持注册一个功能函数,在需要时去触发执行

MODBUS 支持RTU协议的组包发送和数据解析

私有协议 支持私有协议,格式: 头(1字节)|ID(4字节)|Len(1字节)|Cmd(1字节)|数据|CRC(1字节)

固件升级 支持基于私有协议接收和存储新固件

数据存取 支持三种数据存取,定时存储(例如每小时存储一次、每天存储一次这样的场景),单次存储(加校验存储数据,例如存储配置数据),连续存储(flash上连续存储固定大小的数据,支持获取已存储数据的数量,例如存储异常日志以及获取已存储日志的数量)

发送管理 支持管理数据的发送,保证数据发送完成后新的发送请求才能成功

UTC 支持UTC和年月日时分秒的转换,UTC起始时间是2000-1-1 0:0:0

部分功能模块需要使用具体外设,创建功能模块实例时需要指定具体设备。例如数据存取,创建功能模块时指定其对应的flash设备。

如果某个产品的功能是每小时采集一次数据存储并上报,支持上位机取历史数据。物联网领域中有许多这样功能简单的终端设备,完成这个功能只需要添加2、6、8、9、10。如果需要监测设备异常状态则加入3,需要固件升级加入7,电池供电加入1。

 

使用方法

1、添加文件

bos/core/src目录文件全部添加至工程

bos/driver/src选择需要的添加至工程

bos/hal/ 添加至工程,根据具体平台进行修改

2、选择功能模块

对于b_config.h进行配置,根据自己的需要选择功能模块。

opt

3、列出需要使用的设备

找到b_device_list.h,在里面添加使用的外设。例如当前项目只需要使用flash和模拟串口,那么添加如下代码:

//           设备        驱动接口      描述
B_DEVICE_REG(W25QXX, bW25X_Driver, "flash")
B_DEVICE_REG(SUART, SUART_Driver, "suart")

4、使用设备

 

bInit();    //初始化,外设的初始化会在此处调用
//下面举例使用设备
int fd;
fd = bOpen(SUART, BCORE_FLAG_RW);    //其中SUART是在b_device_list.h中添加的设备
if(fd >= 0)
{
     bWrite(fd, (uint8_t *)"hello world\r\n", strlen("hello world\r\n")); //发送字符串
     bClose(fd);
}

如果一个设备被打开正在使用,那么无法再次被打开。

5、使用功能模块

int sdb_no;
sdb_no = bSDB_Regist(0, 1, W25QXX);//创建B类数据存储实例,指定设备W25QXX,获的功能模块实例IDsdb_no
//sdb_no大于等于0则有效
int bSDB_Write(int no, uint8_t *pbuf);
int bSDB_Read(int no, uint8_t *pbuf);
//读写函数传入实例ID sdb_no

喂养

之所以称其为需要喂养的弱操作系统,因为驱动和功能模块都需要一点点加入进去,加入的越多,后续开发起来就越快。 

  • 饲料1: 通用的功能模块
  • 饲料2: 能被BOS消化的驱动代码
  • 投食方式:
  1. 推送至https://github.com/notrynohigh/BabyOS

  2. 推送至https://gitee.com/notrynohigh/BabyOS

 

补充内容 (2020-1-2 19:09): 2019.12.04~2020.01.02 3项功能模块:FIFO、AT、Nr_micro_shell 详情见https://gitee.com/notrynohigh/Ba ... %8E?sort_id=1840013 补充内容 (2020-2-13 15:53): 2020年02月更新 功能模块:Xmodem128, Ymodem 驱动:xpt2046 详情见https://gitee.com/notrynohigh/Ba ... %8E?sort_id=1904945
此帖出自单片机论坛

最新回复

学习学习   详情 回复 发表于 2020-5-8 10:08

赞赏

2

查看全部赞赏

点赞 关注(5)
 

回复
举报

57

帖子

0

TA的资源

一粒金砂(中级)

来自 2楼
 

BabyOS是一个活跃的项目,保持一直更新。后续不再到此贴回复最新更新。有兴趣的可以直接到源码地址查看最新动态!

补充内容 (2020-3-8 12:44): 为了方便使用,增加BabyOS使用教程: https://gitee.com/notrynohigh/BabyOS_Example 在每个分支的README都写有详细步骤。 子模块为BabyOS master分支 https://gitee.com/notrynohigh/BabyOS
此帖出自单片机论坛
 
 

回复

1万

帖子

25

TA的资源

版主

板凳
 

不错的想法,如果可以适配多种单片机就更有潜力了。

此帖出自单片机论坛
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(中级)

4
 

还是需要网友增加驱动和功能模块,这些丰富了,才能体现出它的优势,加速小项目的开发。

此帖出自单片机论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

5
 

不错@过来好好看看,学习学习。。

此帖出自单片机论坛
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(中级)

6
 
110gm 发表于 2019-12-18 12:53 不错@过来好好看看,学习学习。。

欢迎添加驱动和功能模块哦,码云上的代码比github上访问快一些

https://gitee.com/notrynohigh/BabyOS

此帖出自单片机论坛
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(中级)

7
 

很有趣的想法,期待能提供自己的贡献

此帖出自单片机论坛

点评

有兴趣咱们可以一起开发的。  详情 回复 发表于 2019-12-24 09:34
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(中级)

8
 
symic 发表于 2019-12-23 21:19 很有趣的想法,期待能提供自己的贡献

有兴趣咱们可以一起开发的。

此帖出自单片机论坛
 
 
 

回复

4008

帖子

0

TA的资源

版主

9
 
本帖最后由 huo_hu 于 2019-12-24 11:09 编辑

不太感兴趣,那有那么简单啊,就拿adc来说吧,如果不考虑数据传输,采样位数,采样通道数,采样频率,采样时间同步,同时工作的ADC数量...那问题就很简单了,可是这些都不涉及的需求基本是没有的.

而这些条件组合起来,再考虑不同的平台,可能性是成千上万如何做啊

此帖出自单片机论坛

点评

还是拿你这个ADC说吧,ADC确实是要考虑你所说的采样位数、通道、频率和采样时间等等。注意哦,你说的这些都是驱动部分。而我这份代码里面所涉及的功能模块是不依赖具体硬件。比如电池电量的采样,ADC采样的函数是做  详情 回复 发表于 2019-12-24 11:21
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(中级)

10
 
huo_hu 发表于 2019-12-24 11:07 不太感兴趣,那有那么简单啊,就拿adc来说吧,如果不考虑数据传输,采样位数,采样通道数,采样频率,采样时间同步 ...

还是拿你这个ADC说吧,ADC确实是要考虑你所说的采样位数、通道、频率和采样时间等等。注意哦,你说的这些都是驱动部分。而我这份代码里面所涉及的功能模块是不依赖具体硬件。比如电池电量的采样,ADC采样的函数是做的一个弱函数,ADC实现是用户根据自己的硬件去实现。所以你提到的这些完全不是问题。

       再从驱动来说,第一ADC是MCU自带的还是外置芯片,如果是ADC自带的,那么使用时需要根据自己的平台去实现。第二如果是外置芯片,那么是不是可以将这个芯片的驱动写成通用的代码。

       不管从功能模块还是驱动来说,你提到的都不是问题

此帖出自单片机论坛

点评

其实并不存在所谓的通用软硬件,只是符合一定的协议标准的设备而已,没有协议都是空的.  详情 回复 发表于 2019-12-24 14:26
 
 
 

回复

4008

帖子

0

TA的资源

版主

11
 
liklon 发表于 2019-12-24 11:21 还是拿你这个ADC说吧,ADC确实是要考虑你所说的采样位数、通道、频率和采样时间等等。注意哦,你说的这些 ...

其实并不存在所谓的通用软硬件,只是符合一定的协议标准的设备而已,没有协议都是空的.

此帖出自单片机论坛

点评

很高兴能和您针对这方面做讨论,对于MCU的通用,我是这样想的。 功能模块方面,不依赖于硬件的一套代码,例如FIFO,UTC转换,存储机制,这些在项目中都会用到,而这些功能模块我们确实能写成不依赖硬件。那么这就是  详情 回复 发表于 2019-12-24 15:05
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(中级)

12
 
huo_hu 发表于 2019-12-24 14:26
其实并不存在所谓的通用软硬件,只是符合一定的协议标准的设备而已,没有协议都是空的.

很高兴能和您针对这方面做讨论,对于MCU的通用,我是这样想的。
功能模块方面,不依赖于硬件的一套代码,例如FIFO,UTC转换,存储机制,这些在项目中都会用到,而这些功能模块我们确实能写成不依赖硬件。那么这就是对于MCU的通用功能模块。
驱动方面,能够有一套标准的接口去操作外设,对于MCU来说也是通用,例如这份代码中,我联系将操作外设的接口写成文件操作。这样我们用起来的时候非常方便,更换硬件不需要动业务部分代码。
      总的来说,通用并不是一套代码能够满足任何项目,而是一套标准的东西能方便开发,或者是减少开发时间,拿来就可以用。
此帖出自单片机论坛
 
 
 

回复

295

帖子

1

TA的资源

版主

13
 
本帖最后由 hotsauce1861 于 2019-12-25 08:04 编辑

赞了,感觉挺不错的,看你的api风格感觉和posix挺像,比较友好

此帖出自单片机论坛
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(中级)

14
 
本帖最后由 liklon 于 2020-1-3 09:25 编辑

2019_12_04~2020_01_02更新部分说明

使用说明

FIFO

int bFIFO_Regist(uint8_t *pbuf, uint16_t size);     //注册FIFO实例
int bFIFO_Length(int no, uint16_t *plen);           //获取有效数据长度
int bFIFO_Flush(int no);                                //FIFO读写复位
int bFIFO_Write(int no, uint8_t *pbuf, uint16_t size);  //写入数据
int bFIFO_Read(int no, uint8_t *pbuf, uint16_t size);   //读取数据

AT

typedef struct
{
    uint8_t *pResp;        //响应数据
    uint16_t len;          //响应数据长度
    uint32_t timeout;      //给定超时时间,调用bAT_Write之前给定超时时间
}bAT_ExpectedResp_t;

int bAT_Regist(pAT_TX ptx);     //注册AT使用实例,ptx是发送数据的接口
int bAT_Write(int no, bAT_ExpectedResp_t *pe_resp, const char *pcmd, ...);
//发送AT指令,   实例ID               结构体,如所述            不定长参数
int bAT_Read(int no, uint8_t *pbuf, uint16_t size);
//例如AT指令通过串口进行收发,串口接收到模块响应数据后将数据通过这个函数提交给AT单元

//使用详情可见bos/drivers/src/b_f8l10d.c

Nr_micro_shell

int bShellStart(void);                      //shell 初始化
int bShellParse(uint8_t *pbuf, uint16_t len);
//例如用串口进行交互,串口收到数据后将数据通过此函数丢给shell进行解析

此帖出自单片机论坛
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(中级)

15
 

BabyOS过年前最后更新一次。最近新增一项,大家帮忙看看是否有优化地方,在过年前将其改好。

新增:K/V键值对存取b_kv.c b_kv.h

基于SPI Flash存取,无文件系统。占用SPI Flash 4个最小擦除单位(4 * 4K),占用MCU内存 N * 12 Bytes (N表示最多存储多少个键值对,b_config.h配置)。

将4块最小擦除单位分为两组A,B每组两块分别存储数据索引和数据

A1  存储数据索引   
A2  存储数据


B1   存储数据索引
B2   存储数据

每次修改或者新增一条K/V键值对就将信息头和数据按照顺序写入A1 A2。当A1或者A2有一块存储满后将有效数据索引和数据抽取转移到B1 B2,将主要存储去转移到B组,B组存储满后按照同样的方法转移到A组。

每次新增或者修改不会对Flash进行擦除,保证了使用寿命。
一块最小擦除单位存满后抽取有效的部分转移到另一块区域,没有在内存定义大的buffer去处理,主要考虑到MCU的内存是稀缺资源不能随意占用。

使用例子:
 


如图所示,利用KV存储进行系统参数的存取、修改是比较方便的。结果如下:
欢迎大家指导!https://gitee.com/notrynohigh/BabyOS

此帖出自单片机论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

16
 

要是能适配多种单片机就给力了,希望后期会适配,也希望能出一两期使用的视频教程,赞赞赞

此帖出自单片机论坛
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(中级)

17
 

新增两项方便传输文件至MCU

Xmodem128

 

//Xmodem128的接收部分
int bXmodem128Init(pcb_t fcb, psend fs);  //初始化,注册回调以及指定发送字节的函数
int bXmodem128Parse(uint8_t *pbuf, uint8_t len);
//数据解析,接收到数据后调用此函数。需要将一段数据接收完成后再调用此函数,不能一个字节一个字节的往里放
int bXmodem128Start(void);   //启动接收
int bXmodem128Stop(void);    //中断接收
void bXmodem128Timeout(void);   //判断超时,由bExec()调用
​
typedef void (*pcb_t)(uint8_t number, uint8_t *pbuf); 
//回调函数,number为序号,pbuf为数据指针。每次的数据长度都是128字节
​

 

 

Ymodem

int bYmodemInit(pymcb_t fcb, pymsend fs); //初始化,注册回调以及指定发送字节的函数
int bYmodemParse(uint8_t *pbuf, uint16_t len);
//数据解析,接收到数据后调用此函数。需要将一段数据接收完成后再调用此函数,不能一个字节一个字节的往里放
int bYmodemStart(void);  //启动接收
int bYmodemStop(void);   //中断接收
void bYmodemTimeout(void);   //判断超时,由bExec()调用
​
typedef void (*pymcb_t)(uint8_t t, uint8_t number, uint8_t *pbuf, uint16_t len); 
//回调函数,t为数据类型(文件名/数据)number为序号,pbuf为数据指针,len为数据长度
​

 

代码中有实例,利用Xmodem128和Ymodem接收文件,存储至spiflash内,传输结束后读取出来通过串口输出。实验效果:

此帖出自单片机论坛
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(中级)

18
 

又有更新了,学习去

此帖出自单片机论坛
 
 
 

回复

104

帖子

0

TA的资源

一粒金砂(中级)

19
 

学习学习

此帖出自单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表