diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index e2f2059..8732dd2 100755 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -47,6 +47,10 @@ module.exports = { text: '内核', link: '/doc/kernel/', }, + { + text: '组件', + link: '/doc/component/' + }, { text: '处理器', link: '/doc/processor/', @@ -68,12 +72,16 @@ module.exports = { link: '/doc/board/', }, { - text: '应用开发', - link: '/doc/appdev/', + text: '自研终端', + link: '/doc/selfterminal/' }, { text: '应用框架', link: '/doc/apparch/' + }, + { + text: '快速上手', + link: '/doc/appdev/', } ] }, @@ -117,6 +125,10 @@ module.exports = { title: '内核', children: getSidebarByCategory('kernel','en') }, + { + title: '组件', + children: getSidebarByCategory('component','en') + }, { title: '处理器', children: getSidebarByCategory('processor','en') @@ -138,14 +150,24 @@ module.exports = { children: getSidebarByCategory('board','en') }, { - title: '应用开发', - children: getSidebarByCategory('appdev','en') + title: '自研终端', + children: getSidebarByCategory('selfterminal','en') }, { - title: '应用架构', + title: '应用框架', children: getSidebarByCategory('apparch','en') + }, + { + title: '快速上手', + children: getSidebarByCategory('appdev','en') } ], + '/about/': [ + ['','项目概况'], + ['xuos','XiUOS操作系统计划'], + ['contact','联系方式'], + ['license','开源协议'] + ] } }, diff --git a/docs/.vuepress/public/images/framework-ai-arch.png b/docs/.vuepress/public/images/framework-ai-arch.png new file mode 100644 index 0000000..a23df14 Binary files /dev/null and b/docs/.vuepress/public/images/framework-ai-arch.png differ diff --git a/docs/.vuepress/public/images/sensor-ov2640.png b/docs/.vuepress/public/images/sensor-ov2640.png new file mode 100644 index 0000000..6509537 Binary files /dev/null and b/docs/.vuepress/public/images/sensor-ov2640.png differ diff --git a/docs/.vuepress/public/images/sensor-ov7670.png b/docs/.vuepress/public/images/sensor-ov7670.png new file mode 100644 index 0000000..1a58532 Binary files /dev/null and b/docs/.vuepress/public/images/sensor-ov7670.png differ diff --git a/docs/.vuepress/sidebar.js b/docs/.vuepress/sidebar.js index 652135e..bff45fa 100755 --- a/docs/.vuepress/sidebar.js +++ b/docs/.vuepress/sidebar.js @@ -1,12 +1,18 @@ const sidebar = { - 'intro': [ + 'intro': [ '/doc/intro', ], 'kernel': [ '/doc/kernel/task', '/doc/kernel/mm', - '/doc/kernel/synchron', - '/doc/kernel/threadcommunication' + '/doc/kernel/int', + '/doc/kernel/tmr' + ], + 'component': [ + '/doc/component/fs', + '/doc/component/drvmodel', + '/doc/component/lib', + '/doc/component/gui' ], 'board': [ '/doc/board/aiit-arm32', @@ -42,7 +48,8 @@ const sidebar = { '/doc/sensor/magneto_sensor', '/doc/sensor/photoelec_sensor', '/doc/sensor/pressure_sensor', - '/doc/sensor/voice_sensor' + '/doc/sensor/voice_sensor', + '/doc/sensor/image_sensor' ], 'appdev': [ '/doc/appdev/env', @@ -57,8 +64,12 @@ const sidebar = { ], 'processor': [ '/doc/processor/riscv', - '/doc/processor/riscv_sk', - '/doc/processor/riscv_fpga' + '/doc/processor/arm', + '/doc/processor/riscv_sfcore' + ], + 'selfterminal': [ + '/doc/selfterminal/aiit-arm', + '/doc/selfterminal/aiit-riscv' ] } diff --git a/docs/doc/apparch/README.md b/docs/doc/apparch/README.md index 578a1b2..760ffde 100644 --- a/docs/doc/apparch/README.md +++ b/docs/doc/apparch/README.md @@ -1,4 +1,4 @@ -# 应用开发 +# 应用框架 --- @@ -6,6 +6,6 @@ * [联](/doc/apparch/lian.md) -* [智](/doc/apparch/zhi.md) +* [知](/doc/apparch/zhi.md) * [控](/doc/apparch/kong.md) diff --git a/docs/doc/apparch/kong.md b/docs/doc/apparch/kong.md index 4078b33..922bdfb 100644 --- a/docs/doc/apparch/kong.md +++ b/docs/doc/apparch/kong.md @@ -1 +1,310 @@ -# 控 \ No newline at end of file +# 控 + +工业生产中控制逻辑的复杂程度千变万化,往往需要具体行业专业人员完成专门的设计,从而提高了行业的技术壁垒,严重阻碍了工业领域的自动化和智能化升级。 + +XiUOS应用程序框架中的“控”子框架从“控制需求”本身出发,同时面向专业用户和非专业用户,通过对“控制需求”本身和复杂的工业控制流程进行深入分析,通过软件定义的方式,提出以“元控制”为核心的“控”制流程。具体地,本设计通过解耦复杂的工业控制流程,将工业生产中的各种复制工业控制流程分解为各种类型的“元控制”命令,这些“元控制”的命令以软件API的形式交互给用户使用,从而屏蔽了以PLC为中心的各种控制器的巨大差异,形成了方便易用的接口,降低了专业的技术壁垒,加速了工业领域的智能化升级。 + +## 1. XiUOS“控”制框架的关键数据结构定义和解析 + +```c +struct xs_PlcAbility { + const char name[XS_NAME_MAX]; /* name of the plc ability instance */ + enum xs_PlcCtlType type; /* type of control the plcable to excute, such as HSC or PID control */ + char address[XS_PLC_ADDRESS_MAX]; /* The address for this function in the plc*/ + struct xs_PlcDevice *pdev;/* corresponding plc device */ + struct XS_DOUBLE_LINKLIST_NODE link;/* link list node */ +}; +``` + +name成员是一个可读的名字,用于唯一标识一个xs_PlcAbility结构。 +type成员表示该xs_PlcAbility可控制的类型,用一个枚举变量表示: + +```c +enum xs_PLcCtlType { + XS_PLC_CONTROL_TYPE_HSC = 0, /* high-speed counter */ + XS_PLC_CONTROL_TYPE_PID , /* proportional,integral,derivative */ + XS_PLC_CONTROL_TYPE_PHASING , /* phasing control*/ + + /* ...... */ + XS_PLC_CONTROL_TYPE_END, +}; +``` + +由于plc里控制指令执行都是向数据模块DB写数据,需要知道该函数功能对应的数据块地址,这个用address标识。 + +pdev成员表示该xs_PlcAbility所属的xs_PlcDevice结构,其具体定义在下文给出。 + +最后,在系统中不同控制类型的xs_PlcAbility被分别组织成不同的双链表,如高速计数器xs_PlcAbility链表、PID控制xs_PlcAbility链表等,使用的链表节点即为link成员。 + +```c +struct xs_PlcDevice { + const char name[XS_NAME_MAX]; /* name of the device */ + struct xs_PlcInfo info;/* Plc info, such as vendor name and model name */ + struct xs_PlcOps ops;/* filesystem-like APIs for data transferring */ + struct xs_PlcInterface interface;/* protocls used for transferring data from program to plc */ + structXS_DOUBLE_LINKLIST_NODE link;/* link list node */ +}; +``` + +name成员记录PLC设备在系统中的名字,用于唯一标识一个xs_PlcDevice结构。 + +```c +structxs_PlcInfo { + uint32_t ability; + const char *vendor; + const char *product_model; +}; +``` + +info成员记录PLC设备的一些属性信息,包括PLC的能力ability、厂家名vendor与型号product_model,其中ability用一个位图表示该PLC设备可以控制进行的操作: + +```c +#define XS_PLC_ABILITY_HSC ((uint32_t)(1 << XS_CONTROL_TYPE_HSC)) +#define XS_PLC_ABILITY_PID ((uint32_t)(1 << XS_CONTROL_TYPE_PID)) +#define XS_PLC_ABILITY_Phasing ((uint32_t)(1 << XS_CONTROL_TYPE_PHASING)) +/* ...... */ +``` + +ps成员包含统一的、类似文件系统的API,用于和PLC设备通信,进行实际的数据读写和对PLC设备实现控制功能。在使用一个PLC设备前后需要打开(open)/关闭(close)该PLC,实际为建立和关闭连接;read、write分别用与从PLC接收数据与向PLC发送数据,ioctl用于向PLC设备发送控制指令: + +```c +structxs_PlcOps { + int (*open)(struct xs_PlcDevice *pdev); + void (*close)(struct xs_PlcDevice*pdev); + int (*read)(struct xs_PlcDevice*pdev, void *buf, size_tlen); + int (*write)(struct xs_PlcDevice*pdev, constvoid *buf, size_tlen); + int (*ioctl)(struct xs_PlcDevice*pdev, intcmd, void *arg); +}; +``` + +interface成员表示用于与PLC进行通信时所用到的协议: + +```c +struct xs_PlcInterface { +enum xs_plc_protocol protocol; +enum xs_plc_transport transport; +}; +``` + +xs_plc_protocol和xs_plc_transport是两个枚举类型,标识PLC设备和自研的两种终端之间用到的通讯协议,其定义如下: + +```c +enum xs_plc_protocol{ + AB-ETH = 0, + ADS/AMS, + BACnet/IP, + DeltaV, + DF1, + EtherNet/IP, + Firmata, + KNXnet/IP, + Modbus, + OPC UA, + S7, + Simulated, +}; +enum xs_plc_transport{ + TCP = 0, + UDP, + Serial, + Raw Socket, + PCAP Replay, +}; +``` + +:::tip +注意两者间有对应关系而不是随意组合,如S7(STEP 7)只能采用TCP协议,而Modbus支持tcp/serial/raw socket/pcap replay,可以定义一个函数检查类型: +xs_PlcProtocolCheck(struct xs_PlcDevice*); +::: + +最后,系统中所有注册过的PLC设备被组织成一个双链表,即link成员。 + +## 2.XiUOS Plc控制框架驱动开发 + +以HSC高速计数器为例。控制框架针对每个具体的控制类型将xs_PlcAbility进行扩充,采用类似面向对象的手段添加其他必要成员,如: + +```c +struct xs_PlcAbilityHsc { + struct xs_PlcAbility parent;/* inherit from xs_PlcAbility*/ + uint32_t (*write)(struct xs_PlcAbilityHsc *abl, void* param); + void (*read)(struct xs_PlcAbilityHsc *abl, void* param) +}; +``` + +实现xs_PlcOps中的数据通信API,具体实现细节取决于PLC型号,无法实现的API可以置为NULL: + +```c +structxs_PlcOpshsc_example_ops = { + .open = hsc_example_open; + .close = hsc_example_close; + .read = hsc_example_read; + .write = hsc_example_write; + .ioctl = hsc_example_ioctl; +}; +``` + +实现xs_PlcAbilityHsc中的write和read接口,该接口用于向PLC的HSC模块发送控制参数和读取返回参数。在实现过程中可以使用xs_PlcOps中的接口与plc进行通信。 + +其中param为一个void类型指针,由于要写入的命令参数和要读取的返回参数往往不止一个,可以根据不同的控制类型定义不同的数据读写结构体,最后使用结构体指针进行强制类型转换即可。例如对于HSC: +定义数据写入结构体: + +```c +struct hsc_write{ + char id[id_max]; /* id_max is to identify the max HSC ctrl instruction of HSC */ + int cmd; /* HSC control type * +}; +``` + +其中id用来标识HSC, cmd表示要发送的具体指令,具体的指令可以用一个枚举类型来表示: + +```c +enum HscCmdSubType{ + EnHsc = 0; /* enable HSC */ + EnCapture; /* enable the function of capturing the inputs */ + EnSync; /* enable the function of synchronous inputs */ + EnHSCRESET + + En_CTRL_UPTODOWN + + ... ... +}; +``` + +同理,其他的类型 + +```c +enum PIDcmdSubType{ + ENHsc = 0 + EN_XS_PLC_CONTROL_TYPE_PID_COMPACT + XS_PLC_CONTROL_TYPE_PID_3STEP /* valve of motor-driven */ + ... ... +}; +enum PHASEcmdSubType{ + ENPhase = 0 + XS_PLC_CONTROL_TYPE_PHASING_MC_HALT + XS_PLC_CONTROL_TYPE_PHASING_MC_HALT_MOVE_ABSOLUTE + ... ... +} +``` + +定义数据输出结构体: + +```c +struct hsc_read{ + uint32_t value; /* the main value you want to get, depends on the cmd */ + bool done; /* indicate whether the SFB has been done */ + bool busy; /* indicate whether the function is busy */ + bool error; /* indicate whether there is error */ +}; +``` + +value是指定返回的变量值,与结构体hsc_write发送的指令cmd类型有关,down/busy/error是一些状态指示位。 +如我们要使用write函数向PLC发送HSC类型的控制指令: + +```c +struct hsc_write write_example; +``` + +struct xs_PlcAbilityHsc hsc_example进行必要的初始化后,用强制类型转换作为参数传递给write函数: +```c +hsc_example ->write(&hsc_example,(struct hsc_write*)&write_example); +``` +最后,将plc设备添加到plc框架。分别填充xs_PlcDevice与对应物理量的xs_PlcAbility结构(高速计数器即为xs_PlcAbilityHsc),并依次使用xs_PlcDeviceRegister和xs_PlcAbilityRegister函数将其注册到plc框架: + +```c +int xs_PlcDeviceRegister (struct xs_PlcDeviceRegister *pdev); +int xs_PlcAbilityRegister (struct xs_PlcAbilityRegister *abl); + +extern struct xs_PlcOps plc_example_ops; +extern uint32_t plc_example_write(struct xs_PlcAbilityHsc *abl, void *param); +extern void plc_example_read(struct xs_PlcAbilityHsc *abl, void *param); + +/* declare xs_PlcDevice and xs_PlcAbilityHsc objects */ +struct xs_PlcDevice hsc_example_pdev; +struct xs_PlcAbilityHsc hsc_example_abl; + +void register_example_plc() +{ + /* initialize and register the xs_PlcDevice object */ + memset(&hsc_example_pdev, 0, sizeof(xs_PlcDevice)); + + hsc_example_pdev.name = "plc1"; + hsc_example_pdev.info.ability |= XS_PLC_ABILITY_HSC; + hsc_example_pdev.info.vendor = "Siemens"; + hsc_example_pdev.info.product_model = "yyy"; + hsc_example_pdev.ops = &hsc_example_ops; + hsc_example_pdev.interface.xs_plc_protocol = S7; + hsc_example_pdev.interface.xs_plc_transport = TCP; + + xs_PlcDeviceRegister(&hsc_example_pdev); + + /* initialize and register the xs_PlcAbility of hsc object */ + memset(&hsc_example_abl, 0, sizeof(xs_PlcAbilityHsc)); + + hsc_example_abl.parent.name = "hsc_1"; + hsc_example_abl.parent.type = XS_PLC_TYPE_HSC; + hsc_example_abl.parent.pdev = &hsc_example_pdev; + hsc_example_abl.read = hsc_example_read; + hsc_example_abl.write = hsc_example_write; + + xs_PlcAbilityRegister((struct xs_PlcAbility *)&hsc_example_abl); + /* initialize and register otherxs_PlcAbilityobject */ + memset(&other_example_abl, 0, sizeof(xs_PlcAbilityOther)); + ... ... +} +``` + +## 3. XiUOS Plc控制框架的使用示例 +PLC控制应用开发者使用PLC控制框架提供的API操作PLC,PLC的API可以分为通用API与控制类型特有API。通用API用于PLC的获取、打开与关闭,控制类型特有API用于不同种类PLC的不同控制指令。以具有HSC高速计时器功能的PLC为例: + +```c +/* generic API: find a plcability instance by its name */ +struct xs_PlcAbility *xs_PlcAbilityFind(const char *name); + +/* generic API: open/close a plc ability instance */ +int xs_PlcAbilityOpen(struct xs_PlcAbility *abl); +void xs_PlcAbilityClose(struct xs_PlcAbility *abl); + +/* HSC API: send control parameter to PLC and read HSC condition*/ +uint32_t xs_PlcHscWrite(struct xs_PlcAbilityHsc *abl, void *param); +void xs_PlcHscRead(struct xs_PlcAbilityHsc *abl, void *param); +``` + +在发送命令和获取数据前,需要先获取并打开要使用的PLC;PLC打开后可以随时对PLC发送指令和对其数据进行读取;使用完毕后,须关闭PLC。完整的使用过程示例如下: + +```c +int main(int argc, char *argv[]) +{ + int ret; + structxs_PlcAbility *abl; + structxs_PlcAbilityHsc *hsc_abl; + + /* get the Plc hsc ability instance */ + abl = xs_PlcAbilityFind("hsc_1"); + XS_ASSERT(abl->type == XS_PLC_CONTROL_TYPE_HSC); + + /* open the Plc hscability instance */ + hsc_abl = (struct xs_PlcAbilityHsc*)abl; + ret = xs_PlcAbilityOpen(abl); + XS_ASSERT(ret == XS_EOK); + + /* initialize the write and read data structure */ + structhsc_write write1={ + .id = "xxx"; + .cmd = EnHsc; + }; + struct hsc_read read1; + /* send control param to the HSC, just for demonstration */ + xs_PlcHscWrite(hsc_abl,write1); + /* read data from hsc, just for demonstration */ + xs_PlcHscRead(hsc_abl,read1); + if(!read1.error) + xs_kprintf("Read data from PLC HSC is \n", read1.value); + else + xs_kprintf("Read data from PLC HSC wrong!\n") + xs_PlcAbilityClose(abl); + + return 0; +} +``` + diff --git a/docs/doc/apparch/zhi.md b/docs/doc/apparch/zhi.md index c849bcd..0ce584f 100644 --- a/docs/doc/apparch/zhi.md +++ b/docs/doc/apparch/zhi.md @@ -1 +1,15 @@ -# 智 \ No newline at end of file +# 知 - 智能框架 + +## 基本框架 + +工厂中不仅有气压、温度等环境数据,还有很多图像、声音等数据,比如工业设备仪表盘、厂房工人分布等,这些数据也需要检测并处理。传统方案使用嵌入式终端采集、云端处理的架构。而当前越来越多的硬件厂商开始将一部分AI算力下沉到嵌入式终端上,比如 ST 推出的针对 STM 平台的神经网络加速库 STM32 Cube.AI,ARM 即将发布的针对嵌入式场景的 Ethos-U55 神经网络处理器,以及 勘智 K210 平台嵌入了一颗卷积网络加速器 KPU。本系统提供了在嵌入式节点端做轻量级AI处理的应用框架,可以在 Arm Cortex-M 或者 有神经网络加速器的平台(比如 勘智 K210)运行。对于复杂的 AI 应用,可以选择完全在 边缘或者云侧处理,也可以选择在 节点端做简单预处理,在 边缘或者云侧做后续的处理。基本结构如下: + +![智能框架架构](/images/framework-ai-arch.png) + +端侧智能运行框架中,目前在 STM32 平台上支持 TensorFlow Lite for Microcontroller,勘智K210 上支持 KPU Model,CV算子目前暂不支持。模型库中有一些已经训练好的模型,可以直接使用,比如人物检测模型,仪表盘识别模型等。 + +## 端侧 Framework 的使用说明 + +在 STM32 平台,本系统提供 TensorFlow Lite for Microcontroller 框架,关于 TF Lite for MCU 的使用,可以参照 [TF Lite for MCU 官方教程](https://www.tensorflow.org/lite/microcontrollers) ,详细说明后续补充。 + +在 勘智 K210 平台,本系统提供 KPU Model 的框架,详细使用可以参考 [勘智官方说明](https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_standalone_programming_guide_v0.3.0.pdf) 的 “神经网络处理器(KPU)”章节,详细说明后续补充。 diff --git a/docs/doc/appdev/README.md b/docs/doc/appdev/README.md index ff90ed6..bcd1977 100644 --- a/docs/doc/appdev/README.md +++ b/docs/doc/appdev/README.md @@ -1,4 +1,4 @@ -# 应用开发 +# 快速上手 --- diff --git a/docs/doc/component/README.md b/docs/doc/component/README.md new file mode 100644 index 0000000..34471ba --- /dev/null +++ b/docs/doc/component/README.md @@ -0,0 +1,11 @@ +# 应用开发 + +--- + +* [文件系统](/doc/component/fs.md) + +* [驱动模型](/doc/component/drvmodel.md) + +* [第三方库](/doc/component/lib.md) + +* [GUI图形库](/doc/component/gui.md) diff --git a/docs/doc/component/drvmodel.md b/docs/doc/component/drvmodel.md new file mode 100644 index 0000000..caa6f2d --- /dev/null +++ b/docs/doc/component/drvmodel.md @@ -0,0 +1 @@ +# 驱动模型 \ No newline at end of file diff --git a/docs/doc/component/fs.md b/docs/doc/component/fs.md new file mode 100644 index 0000000..984c68f --- /dev/null +++ b/docs/doc/component/fs.md @@ -0,0 +1 @@ +# 文件系统 diff --git a/docs/doc/component/gui.md b/docs/doc/component/gui.md new file mode 100644 index 0000000..bce78b0 --- /dev/null +++ b/docs/doc/component/gui.md @@ -0,0 +1 @@ +# GUI引擎 \ No newline at end of file diff --git a/docs/doc/component/lib.md b/docs/doc/component/lib.md new file mode 100644 index 0000000..f73fc57 --- /dev/null +++ b/docs/doc/component/lib.md @@ -0,0 +1 @@ +# 第三方库 \ No newline at end of file diff --git a/docs/doc/controller/README.md b/docs/doc/controller/README.md index 103047d..4e755f9 100644 --- a/docs/doc/controller/README.md +++ b/docs/doc/controller/README.md @@ -4,7 +4,7 @@ - [西门子](/doc/controller/ximenzi.md) -- [线程管理](/doc/controller/shinaide.md) +- [施耐德](/doc/controller/shinaide.md) -- [资源管理](/doc/controller/sanling.md) +- [三菱](/doc/controller/sanling.md) diff --git a/docs/doc/ipc.md b/docs/doc/ipc.md new file mode 100644 index 0000000..38ae26a --- /dev/null +++ b/docs/doc/ipc.md @@ -0,0 +1,338 @@ +# 任务通信 + +XiUOS提供多种任务间通信机制,包括消息队列、信号量、互斥量与事件集。 + +## 消息队列 + +消息队列(message queue)提供可供多个任务读或写的消息缓冲区,其中消息指固定长度的任意数据块。消息队列的容量有限。当消息队列满时,向消息队列写入的任务会被挂起;当消息队列空时,从消息队列读取的任务会被挂起。 + +### 消息队列结构定义 + +```c +struct xs_MsgQueue +{ + xs_uint16 id; + + void *msg_buf; + xs_uint16 index; + xs_uint16 num_msgs; + xs_uint16 each_len; + xs_uint16 max_msgs; + + XS_DOUBLE_LINKLIST send_pend_list; + XS_DOUBLE_LINKLIST recv_pend_list; + XS_DOUBLE_LINKLIST link; +}; +``` + +| 成员 | 描述 | +| --- | --- | +| id | 消息队列ID,用于唯一标识一个消息队列 | +| msg_buf | 用于存储消息的缓冲区的首地址 | +| index | 当前缓冲区中第一个消息的序号 | +| num_msgs | 当前缓冲区中的消息数量 | +| each_len | 每条消息的大小,单位为字节 | +| max_msgs | 缓冲区中最多能存放的消息数量 | +| send_pend_list | 被挂起的发送任务链表 | +| recv_pend_list | 被挂起的接收任务链表 | +| link | 系统中所有消息队列构成的链表 | + +### 消息队列函数接口 + +```c +xs_int32 xs_UserMsgQueueCreate(xs_uint16 msg_len, xs_uint16 max_msgs); +``` + +该函数用于创建一个消息队列。创建成功后,新的消息队列会被加入内核的消息队列管理链表,并返回该消息队列的ID,ID默认范围0-255,可配置。 + +| 参数 | 描述 | +| --- | --- | +| msg_len | 每条消息的长度,单位为字节 | +| max_msgs | 缓冲区中最多存放的消息数量 | + +```c +void xs_UserMsgQueueDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的消息队列。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的消息队列ID | + +```c +xs_int32 xs_UserMsgQueueSend(xs_uint16 id, const void *msg, xs_uint16 size, xs_ticks_x wait_time); +``` + +该函数用于向消息队列发送一个消息。若消息发送成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 目标消息队列ID | +| msg | 消息数据首地址 | +| size | 消息长度 | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserMsgQueueRecv(xs_uint16 id, void *buf, xs_uint16 size, xs_ticks_x wait_time); +``` + +该函数用于从消息队列接收一个消息。若消息接收成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | +| buf | 用于接收消息数据的缓冲区 | +| size | 缓冲区大小 | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserMsgQueueReinit(xs_uint16 id); +``` + +该函数用于将一个消息队列复位。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | + + +## 信号量 + +信号量(semaphore)具有一个给定的初值。任务可以获取或释放一个信号量。当任务获取信号量时信号量的值递减,释放信号量时值递增。当信号量值递减至0时,后续尝试获取信号量的任务会被挂起。每当一个已获取信号量的任务释放信号量时,内核会从信号量挂起队列上唤醒一个任务。信号量可以用于实现任务间的同步与互斥。 + +### 信号量结构定义 + +```c +struct xs_Semaphore +{ + xs_uint16 id; + xs_uint16 value; + + XS_DOUBLE_LINKLIST pend_list; + XS_DOUBLE_LINKLIST link; +}; +``` + +| 成员 | 描述 | +| --- | --- | +| id | 信号量ID,用于唯一标识一个信号量 | +| value | 信号量的当前值 | +| pend_link | 挂起任务链表 | +| link | 系统中所有信号量构成的链表 | + +### 信号量函数接口 + +```c +xs_int32 xs_UserSemaphoreCreate(xs_uint16 val); +``` + +该函数用于创建一个信号量。创建成功后,新的信号量会被加入内核的信号量管理链表,并返回该信号量的ID,ID默认范围0-255,可配置。 + +| 参数 | 描述 | +| --- | --- | +| val | 信号量的初值| + +```c +void xs_UserSemaphoreDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的信号量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的信号量的ID | + +```c +xs_int32 xs_UserSemaphoreObtain(xs_uint16 id, xs_ticks_x wait_time); +``` + +该函数用于获取一个信号量。若获取成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 欲获取的信号量的ID | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserSemaphoreAbandon(xs_uint16 id); +``` + +该函数用于释放一个信号量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待释放的信号量的ID | + +```c +xs_int32 xs_UserSemaphoreSetValue(xs_uint16 id, xs_uint16 val); +``` + +该函数用于将一个信号量的值进行重置。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | +| val | 重置的信号量的值 | + +## 互斥量 + +互斥量(mutex)可以视作一个初值为1的信号量,同样有获取和释放操作。互斥量一般用于任务间的互斥。 + +### 互斥量结构定义 + +struct xs_Mutex +{ + xs_uint16 id; + + xs_uint8 origin_prio; + xs_uint8 recursive_cnt; + + struct task_descriptor *holder; + + XS_DOUBLE_LINKLIST pend_list; + XS_DOUBLE_LINKLIST link; +}; + +| 成员 | 描述 | +| --- | --- | +| id | 互斥量ID,用于唯一标识一个互斥量 | +| origin_prio | 持有互斥量的任务的原优先级,用于避免优先级反转 | +| recursive_cnt | 持有互斥量的任务获取互斥量的次数,用于实现递归锁 | +| holder | 持有互斥量的任务 | +| pend_list | 挂起任务链表 | +| link | 系统中所有互斥量构成的链表 | + +### 互斥量函数接口 + +```c +xs_int32 xs_UserMutexCreate(void); +``` + +该函数用于创建一个互斥量。创建成功后,新的互斥量会被加入内核的互斥量管理链表,并返回该互斥量的ID,ID默认范围0-255,可配置。 + +```c +void xs_UserMutexDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的互斥量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的互斥量的ID | + +```c +xs_int32 xs_UserMutexObtain(xs_uint16 id, xs_ticks_x wait_time); +``` + +该函数用于获取一个互斥量。若获取成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 欲获取的互斥量的ID | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserMutexAbandon(xs_uint16 id); +``` + +该函数用于释放一个互斥量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待释放的互斥量的ID | + +## 事件集 + +事件集(event set)允许用户定义一个事件集合,集合中的每个事件都可以被任务触发或等待。任务可以同时等待多个事件,此时等待触发的条件可以配置为AND或者OR:当等待触发条件配置为AND时,只有所有被等待的事件均被触发才视作等待结束;当等待触发条件配置为OR时,任意一个被等待的事件触发即视作等待结束。使用事件集可以实现多对多的任务间同步与互斥。 + +### 事件集结构定义 + +```c +#define XS_EVENT_AND (1 << 29) +#define XS_EVENT_OR (1 << 30) +#define XS_EVENT_AUTOCLEAN (1 << 31) +#define XS_EVENTS(x) (1 << x) + +struct xs_event +{ + xs_uint16 id; + xs_uint32 trigge_way; + + XS_DOUBLE_LINKLIST pend_list; + XS_DOUBLE_LINKLIST link; +}; +``` + +| 成员 | 描述 | +| --- | --- | +| id | 事件集ID,用于唯一标识一个事件集 | +| trigge_way | 高3位用于记录事件集属性(等待触发条件、是否自动清空),低29位用于表示至多29个事件 | +| pend_list | 等待任务链表 | +| link | 系统中所有事件集构成的链表 | + +### 事件集函数接口 + +```c +xs_int32 xs_UserEventCreate(xs_uint32 options); +``` + +该函数用于创建一个事件集。options参数用于配置事件集的属性。可配置的属性有等待触发方式(XS_EVENT_AND或XS_EVENT_OR)及等待触发后是否自动清空其他已触发的事件(XS_EVENT_AUTOCLEAN)。创建成功后,新的事件集会被加入内核的事件集管理链表,并返回该事件集的ID,ID默认范围0-255,可配置。 + +| 参数 | 描述 | +| --- | --- | +| options | 事件集配置选项,须在XS_EVENT_AND及XS_EVENT_OR中指定其一,并可以按位或上XS_EVENT_AUTOCLEAN | + +```c +void xs_UserEventDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的事件集。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的事件集的ID | + +```c +xs_int32 xs_UserEventTrigger(xs_uint16 id, xs_uint32 events); +``` + +该函数用于触发事件集中的一组事件。 + +| 参数 | 描述 | +| --- | --- | +| id | 事件集ID | +| events | 欲触发的事件,其中被置1的位标识被触发的事件 ,可以使用XS_EVENTS宏按位或发送事件类型| + +```c +xs_int32 xs_UserEventProcess(xs_uint16 id, xs_uint32 events, xs_ticks_x wait_time); +``` + +该函数用于等待事件集中的一组事件。若等待成功则返回XS_EOK,此时若XS_EVENT_AUTOCLEAN被打开则事件集中所有已触发事件会被清空;若等待失败(超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 事件集ID | +| events | 欲等待的事件,其中被置1的位标识被等待的事件,可以使用XS_EVENTS宏按位或接收事件类型| +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserEventConfig(xs_uint16 id, xs_uint32 options); +``` + +该函数用于配置事件集中的一种事件类型。若等配置成功则返回XS_EOK,options参数用于配置事件集的属性。可配置的属性有等待触发方式(XS_EVENT_AND或XS_EVENT_OR)及等待触发后是否自动清空其他已触发的事件(XS_EVENT_AUTOCLEAN)。 + +| 参数 | 描述 | +| --- | --- | +| id | 事件集ID | +| options | 事件集配置选项,须在XS_EVENT_AND及XS_EVENT_OR中指定其一,并可以按位或上XS_EVENT_AUTOCLEAN | + +```c +xs_int32 xs_UserEventReinit(xs_uint16 id); +``` + +该函数用于将一个事件的值进行重置。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | \ No newline at end of file diff --git a/docs/doc/kernel/README.md b/docs/doc/kernel/README.md index c64d2fb..0bc5923 100644 --- a/docs/doc/kernel/README.md +++ b/docs/doc/kernel/README.md @@ -2,11 +2,10 @@ --- +- [任务管理](/doc/kernel/task.md) + - [内存管理](/doc/kernel/mm.md) -- [线程管理](/doc/kernel/task.md) - -- [资源管理](/doc/kernel/synchron.md) - -- [线程间通信](/doc/kernel/threadcommunication.md) +- [中断机制](/doc/kernel/int.md) +- [节拍机制](/doc/kernel/tmr.md) \ No newline at end of file diff --git a/docs/doc/kernel/int.md b/docs/doc/kernel/int.md new file mode 100644 index 0000000..097f3f8 --- /dev/null +++ b/docs/doc/kernel/int.md @@ -0,0 +1,98 @@ +# 中断机制 +## 简介 + 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。 + 中断的触发一般是由外设或者CPU内部产生,由中断控制器进行处理再通知到CPU进行中断响应过程,其要点如下: + + •外设或者CPU内部产生的这个中断来源称为中断源; + •CPU响应中断转入到的新的处理程序称为中断服务程序; + •中断处理完成后,处理器需要恢复之前的现场,简称“恢复现场”; + •当多个中断源请求中断的时候,需要通过优先级区分中断,便于CPU进行中断的处理; + •低优先级可以被高优先级打断,这个过程称之为中断嵌套; + •中断可以被屏蔽; + •所有的中断源都有一个编号,称为“中断号”; + •每一个中断号通过中断向量表与中断服务程序一一对应,中断向量表保存的是所有的中断服务程序的入口地址,该入口地址被称之为中断向量; + + +## 中断机制 + ## RISC-V架构的中断和异常 + ### 概述 + 从广义上来说,中断和异常属于一个概念;对于处理器而言,通常只区分为同步异常和异步异常。 + 同步异常:同步异常是指由于执行程序或者试图执行指令而产生的异常;例如,非法指令访问; + 异步异常:最常见的异步异常是外部中断,例如外设触发一个外部中断。 +### 异常处理机制 + • 进入异常时,RISC-V架构规定(以机器模式为例): + 1、当前的程序执行流停止执行,直接跳转到CSR寄存器的mtvec定义的PC地址执行; + 2、硬件同时更新下列几个CSR寄存器(具体情况可参考RISC-V架构介绍): + • mcause(Machine Cause Register):机器模式异常原因寄存器 + • mepc(Machine Exception Program Register):机器模式异常PC寄存器 + • mtval(Machine Trap Value Register):机器模式异常值寄存器 + • mstatus(Machine Status Register):机器模式状态寄存器 + mstatus寄存器的Exception Code域标识是何种异常或者何种中断。定义如下图表格所示: + + + • 退出异常时,需要从异常服务程序中退出,并返回主程序。RISC-V架构定义了一组专门的退出异常指令:MRET、SRET、URET,分别 + 对应机器模式、监督模式、用户模式的退出。 + 以MRET为例,当处理器执行MRET指令后,硬件行为如下: + 1、当前程序执行流程停止执行,跳转到mepc的地址运行; + 2、更新mstatus状态寄存器(具体情况可参考RISC-V架构介绍); +### 中断类型 + RISC-V 架构定义的中断类型分为 4 种。 + • 外部中断(External Interrupt) :指来自处理器核外部的中断,例如GPIO、UART等产生的中断。 + • 计时器中断(Timer Interrupt) :计时器中断是指来自计时器的中断。 + • 软件中断(Software Interrupt) :软件中断是指来自软件自己触发的中断。 + • 调试中断(Debug Interrupt):专用于实现调试器(Debugger)。 + +### 中断控制器 + 1、CLINT 模块生成计时器中断和软件中断 + CLINT 的全称为处理器核局部中断控制器(Core Local Interrupts Controller),主要用于产生计时器中断(Timer Interrupt)和软件中断(Software Interrupt)。 + 2、PLIC 管理多个外部中断 + PLIC 全称为平台级别中断控制器(Platform Level Interrupt Controller),它是 RISC-V架构标准定义的系统中断控制器,主要用于多个外部中断源的优先级仲裁。 + RISC-V中断控制器如下图所示: + +### 中断处理流程 +#### 中断服务程序 + 每一个中断源对应一个中断号,每一个中断号又通过中断向量表和中断服务程序进行关联。当中断产生后,通过中断向量表 + 跳转到中断服务程序的入口地址进行执行。如下图所示: + +#### 中断处理流程 + CPU响应中断并进行处理,通常经历以下过程:保存当前线程的栈信息、跳转中断服务程序运行、恢复被打断的线程栈继续运行。 + 如下图所示: + + +### 中断函数接口 + +```c +xs_int32 xs_RegisterHwIrq(xs_uint32 irq, void * handler, void *arg, char *name); +``` +该函数用于 +```c +xs_int32 xs_FreeHwIrq(); +``` + +```c +xs_int32 xs_DisableHwIrq(); +``` + +```c +xs_int32 xs_EnableHwIrq(); +``` + +## 使用场景 + + + + + + + + +/* 底层的中断控制器操作函数*/ + +xs_int32 xs_DisableHwPlicIrq() ///< RISCV平台级别中断控制器中断关闭接口,控制片上外设中断 +xs_int32 xs_EnableHwPlicIrq() ///< RISCV平台级别中断控制器中断使能接口,控制片上外设中断 + +xs_int32 xs_DisableHwClintIrq()///< RISCV局部中断控制器中断关闭接口,控制片上定时器中断和软件中断 +xs_int32 xs_EnableHwClintIrq() ///< RISCV局部中断控制器中断使能接口,控制片上定时器中断和软件中断 + +xs_int32 xs_DisableGloableIrq() + diff --git a/docs/doc/kernel/ipc.md b/docs/doc/kernel/ipc.md new file mode 100644 index 0000000..38ae26a --- /dev/null +++ b/docs/doc/kernel/ipc.md @@ -0,0 +1,338 @@ +# 任务通信 + +XiUOS提供多种任务间通信机制,包括消息队列、信号量、互斥量与事件集。 + +## 消息队列 + +消息队列(message queue)提供可供多个任务读或写的消息缓冲区,其中消息指固定长度的任意数据块。消息队列的容量有限。当消息队列满时,向消息队列写入的任务会被挂起;当消息队列空时,从消息队列读取的任务会被挂起。 + +### 消息队列结构定义 + +```c +struct xs_MsgQueue +{ + xs_uint16 id; + + void *msg_buf; + xs_uint16 index; + xs_uint16 num_msgs; + xs_uint16 each_len; + xs_uint16 max_msgs; + + XS_DOUBLE_LINKLIST send_pend_list; + XS_DOUBLE_LINKLIST recv_pend_list; + XS_DOUBLE_LINKLIST link; +}; +``` + +| 成员 | 描述 | +| --- | --- | +| id | 消息队列ID,用于唯一标识一个消息队列 | +| msg_buf | 用于存储消息的缓冲区的首地址 | +| index | 当前缓冲区中第一个消息的序号 | +| num_msgs | 当前缓冲区中的消息数量 | +| each_len | 每条消息的大小,单位为字节 | +| max_msgs | 缓冲区中最多能存放的消息数量 | +| send_pend_list | 被挂起的发送任务链表 | +| recv_pend_list | 被挂起的接收任务链表 | +| link | 系统中所有消息队列构成的链表 | + +### 消息队列函数接口 + +```c +xs_int32 xs_UserMsgQueueCreate(xs_uint16 msg_len, xs_uint16 max_msgs); +``` + +该函数用于创建一个消息队列。创建成功后,新的消息队列会被加入内核的消息队列管理链表,并返回该消息队列的ID,ID默认范围0-255,可配置。 + +| 参数 | 描述 | +| --- | --- | +| msg_len | 每条消息的长度,单位为字节 | +| max_msgs | 缓冲区中最多存放的消息数量 | + +```c +void xs_UserMsgQueueDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的消息队列。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的消息队列ID | + +```c +xs_int32 xs_UserMsgQueueSend(xs_uint16 id, const void *msg, xs_uint16 size, xs_ticks_x wait_time); +``` + +该函数用于向消息队列发送一个消息。若消息发送成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 目标消息队列ID | +| msg | 消息数据首地址 | +| size | 消息长度 | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserMsgQueueRecv(xs_uint16 id, void *buf, xs_uint16 size, xs_ticks_x wait_time); +``` + +该函数用于从消息队列接收一个消息。若消息接收成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | +| buf | 用于接收消息数据的缓冲区 | +| size | 缓冲区大小 | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserMsgQueueReinit(xs_uint16 id); +``` + +该函数用于将一个消息队列复位。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | + + +## 信号量 + +信号量(semaphore)具有一个给定的初值。任务可以获取或释放一个信号量。当任务获取信号量时信号量的值递减,释放信号量时值递增。当信号量值递减至0时,后续尝试获取信号量的任务会被挂起。每当一个已获取信号量的任务释放信号量时,内核会从信号量挂起队列上唤醒一个任务。信号量可以用于实现任务间的同步与互斥。 + +### 信号量结构定义 + +```c +struct xs_Semaphore +{ + xs_uint16 id; + xs_uint16 value; + + XS_DOUBLE_LINKLIST pend_list; + XS_DOUBLE_LINKLIST link; +}; +``` + +| 成员 | 描述 | +| --- | --- | +| id | 信号量ID,用于唯一标识一个信号量 | +| value | 信号量的当前值 | +| pend_link | 挂起任务链表 | +| link | 系统中所有信号量构成的链表 | + +### 信号量函数接口 + +```c +xs_int32 xs_UserSemaphoreCreate(xs_uint16 val); +``` + +该函数用于创建一个信号量。创建成功后,新的信号量会被加入内核的信号量管理链表,并返回该信号量的ID,ID默认范围0-255,可配置。 + +| 参数 | 描述 | +| --- | --- | +| val | 信号量的初值| + +```c +void xs_UserSemaphoreDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的信号量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的信号量的ID | + +```c +xs_int32 xs_UserSemaphoreObtain(xs_uint16 id, xs_ticks_x wait_time); +``` + +该函数用于获取一个信号量。若获取成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 欲获取的信号量的ID | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserSemaphoreAbandon(xs_uint16 id); +``` + +该函数用于释放一个信号量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待释放的信号量的ID | + +```c +xs_int32 xs_UserSemaphoreSetValue(xs_uint16 id, xs_uint16 val); +``` + +该函数用于将一个信号量的值进行重置。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | +| val | 重置的信号量的值 | + +## 互斥量 + +互斥量(mutex)可以视作一个初值为1的信号量,同样有获取和释放操作。互斥量一般用于任务间的互斥。 + +### 互斥量结构定义 + +struct xs_Mutex +{ + xs_uint16 id; + + xs_uint8 origin_prio; + xs_uint8 recursive_cnt; + + struct task_descriptor *holder; + + XS_DOUBLE_LINKLIST pend_list; + XS_DOUBLE_LINKLIST link; +}; + +| 成员 | 描述 | +| --- | --- | +| id | 互斥量ID,用于唯一标识一个互斥量 | +| origin_prio | 持有互斥量的任务的原优先级,用于避免优先级反转 | +| recursive_cnt | 持有互斥量的任务获取互斥量的次数,用于实现递归锁 | +| holder | 持有互斥量的任务 | +| pend_list | 挂起任务链表 | +| link | 系统中所有互斥量构成的链表 | + +### 互斥量函数接口 + +```c +xs_int32 xs_UserMutexCreate(void); +``` + +该函数用于创建一个互斥量。创建成功后,新的互斥量会被加入内核的互斥量管理链表,并返回该互斥量的ID,ID默认范围0-255,可配置。 + +```c +void xs_UserMutexDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的互斥量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的互斥量的ID | + +```c +xs_int32 xs_UserMutexObtain(xs_uint16 id, xs_ticks_x wait_time); +``` + +该函数用于获取一个互斥量。若获取成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 欲获取的互斥量的ID | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserMutexAbandon(xs_uint16 id); +``` + +该函数用于释放一个互斥量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待释放的互斥量的ID | + +## 事件集 + +事件集(event set)允许用户定义一个事件集合,集合中的每个事件都可以被任务触发或等待。任务可以同时等待多个事件,此时等待触发的条件可以配置为AND或者OR:当等待触发条件配置为AND时,只有所有被等待的事件均被触发才视作等待结束;当等待触发条件配置为OR时,任意一个被等待的事件触发即视作等待结束。使用事件集可以实现多对多的任务间同步与互斥。 + +### 事件集结构定义 + +```c +#define XS_EVENT_AND (1 << 29) +#define XS_EVENT_OR (1 << 30) +#define XS_EVENT_AUTOCLEAN (1 << 31) +#define XS_EVENTS(x) (1 << x) + +struct xs_event +{ + xs_uint16 id; + xs_uint32 trigge_way; + + XS_DOUBLE_LINKLIST pend_list; + XS_DOUBLE_LINKLIST link; +}; +``` + +| 成员 | 描述 | +| --- | --- | +| id | 事件集ID,用于唯一标识一个事件集 | +| trigge_way | 高3位用于记录事件集属性(等待触发条件、是否自动清空),低29位用于表示至多29个事件 | +| pend_list | 等待任务链表 | +| link | 系统中所有事件集构成的链表 | + +### 事件集函数接口 + +```c +xs_int32 xs_UserEventCreate(xs_uint32 options); +``` + +该函数用于创建一个事件集。options参数用于配置事件集的属性。可配置的属性有等待触发方式(XS_EVENT_AND或XS_EVENT_OR)及等待触发后是否自动清空其他已触发的事件(XS_EVENT_AUTOCLEAN)。创建成功后,新的事件集会被加入内核的事件集管理链表,并返回该事件集的ID,ID默认范围0-255,可配置。 + +| 参数 | 描述 | +| --- | --- | +| options | 事件集配置选项,须在XS_EVENT_AND及XS_EVENT_OR中指定其一,并可以按位或上XS_EVENT_AUTOCLEAN | + +```c +void xs_UserEventDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的事件集。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的事件集的ID | + +```c +xs_int32 xs_UserEventTrigger(xs_uint16 id, xs_uint32 events); +``` + +该函数用于触发事件集中的一组事件。 + +| 参数 | 描述 | +| --- | --- | +| id | 事件集ID | +| events | 欲触发的事件,其中被置1的位标识被触发的事件 ,可以使用XS_EVENTS宏按位或发送事件类型| + +```c +xs_int32 xs_UserEventProcess(xs_uint16 id, xs_uint32 events, xs_ticks_x wait_time); +``` + +该函数用于等待事件集中的一组事件。若等待成功则返回XS_EOK,此时若XS_EVENT_AUTOCLEAN被打开则事件集中所有已触发事件会被清空;若等待失败(超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 事件集ID | +| events | 欲等待的事件,其中被置1的位标识被等待的事件,可以使用XS_EVENTS宏按位或接收事件类型| +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserEventConfig(xs_uint16 id, xs_uint32 options); +``` + +该函数用于配置事件集中的一种事件类型。若等配置成功则返回XS_EOK,options参数用于配置事件集的属性。可配置的属性有等待触发方式(XS_EVENT_AND或XS_EVENT_OR)及等待触发后是否自动清空其他已触发的事件(XS_EVENT_AUTOCLEAN)。 + +| 参数 | 描述 | +| --- | --- | +| id | 事件集ID | +| options | 事件集配置选项,须在XS_EVENT_AND及XS_EVENT_OR中指定其一,并可以按位或上XS_EVENT_AUTOCLEAN | + +```c +xs_int32 xs_UserEventReinit(xs_uint16 id); +``` + +该函数用于将一个事件的值进行重置。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | \ No newline at end of file diff --git a/docs/doc/kernel/synchron.md b/docs/doc/kernel/synchron.md deleted file mode 100755 index 3ba5e03..0000000 --- a/docs/doc/kernel/synchron.md +++ /dev/null @@ -1 +0,0 @@ -# 资源管理 diff --git a/docs/doc/kernel/task.md b/docs/doc/kernel/task.md old mode 100755 new mode 100644 index dfc369a..a75b882 --- a/docs/doc/kernel/task.md +++ b/docs/doc/kernel/task.md @@ -1 +1,539 @@ -# 线程管理 +# 任务 + +* [任务管理](#management) + * [任务状态](#state) + * [任务调度](#sched) + * [任务结构定义](#struct) + * [任务函数接口](#api) +* [任务通信](#communication) + * [消息队列](#msg_quque) + * [信号量](#sem) + * [互斥量](#mutex) + * [事件集](#event) +* [使用场景](#situation) + + + +## 任务管理 + + +任务(task)是XiUOS中处理器使用权分配的最小单位。每个任务有自己的程序栈与寄存器上下文,在多处理器平台上可以互不干扰地同时运行,但单个处理器上任意时刻只能有一个任务在运行。用户可以使用XiUOS提供的接口创建任意数量的任务。内核会对系统中的所有任务按照一定策略(抢占式优先级或先来先服务)进行调度,以最大限度地利用处理器资源。用户可以使用XiUOS提供的接口创建任意数量的任务。 + + +### 任务状态 + +系统中的任务在任意时刻都处于就绪(ready)、运行(running)、阻塞/挂起(suspend)、退出(quit)四种状态之一。状态之间的变化关系如下图所示。 + +![task_status](task_status.png) + +任务在创建完成后会进入就绪状态并被加入就绪队列等待内核调度。当任务被调度开始运行时,任务会进入运行状态。若任务在运行过程中被更高优先级的任务抢占,则被强占的任务会回到就绪队列并再次进入就绪状态。当任务在运行过程中申请资源失败时,任务会被挂起并进入挂起状态,并在所申请资源能够被满足时回到就绪状态。当任务执行完成,即从入口函数返回时,会进入终止状态,并由内核回收其相关资源。 + + +### 任务调度 + +任务调度即从系统就绪队列中按一定策略选择任务,使其进入运行状态的过程。XiUOS支持以下调度方式: + +* 抢占式优先级调度:在创建任务时可以指定任务的优先级,内核总是选取就绪队列中优先级最高的任务。当新创建的任务优先级高于正在运行的任务的优先级时,当前运行的任务会被抢占。若就绪队列中最高优先级任务有多个,则这些任务会按时间片轮转交替运行。 +* 先来先服务(FIFO)调度:任务按照被创建的顺序依次被执行。当一个任务运行完成后,系统才会让下一个任务开始运行。 +* 时间片轮转(RR)调度:任务按照分配的时间片执行,时间片结束,调度一个新的就绪任务执行,当前任务重新就绪,等待下一次的调度。 + + +### 任务结构定义 + +每个任务在内核中由一个task_descriptor结构表示,二者一一对应。 + +```c +struct task_descriptor +{ + void *stack_pointer; + + struct dync_sched_member dync_sched_member_x; + + struct t_baseinfo t_baseinfo_x; + + #ifdef XS_USING_SMP + struct smp_info smp_info_x; + #endif + +#if defined(XS_USING_EVENT) + xs_uint32 event_ctrl1:3; + xs_uint32 event_ctrl2:29; +#endif + + xs_err_t error; + XS_DOUBLE_LINKLIST link; +}; +``` + +其中stack_pointer成员表示该任务的栈的起始地址,dync_sched_member_x成员包含与任务调度相关的信息,t_baseinfo_x包含任务的基本信息,smp_info_x包含与多处理器相关的信息,event_ctrl1/event_ctrl2用于实现事件集机制(见任务间通信部分文档),error为任务调用内核接口时最近的错误码,link用于将系统中的所有任务组织成一个双链表。各复合成员的详细定义如下: + +```c +struct task_baseinfo { + char name[XS_NAME_MAX]; + void *func_entry; + void *func_param; + xs_uint32 stack_size; + xs_uint8 origin_prio; +}; +``` + +struct task_baseinfo结构记录了任务的基本属性,包括任务的名称(name)、入口函数和参数(func_entry、func_param)、栈大小(stack_size)、优先级(origin_prio)。 + +```c +struct dync_sched_member { + xs_uint8 stat; + xs_uint8 advance_cnt; + xs_uint8 cur_prio; + xs_ubase origin_timeslice; + xs_ubase rest_timeslice; +#ifdef XS_USING_TASK_ISOLATION + xs_uint8 isolation_flag; + void *isolation; +#endif + union { + XS_DOUBLE_LINKLIST sched_link; + XS_AVL sched_avl; + } + XS_DOUBLE_LINKLIST pend_link; + xs_Timer_t task_timer; +}; + +#define XS_SUSPEND ((1) << (0)) +#define XS_READY ((1) << (1)) +#define XS_RUNNING ((1) << (2)) +#define XS_QUIT ((1) << (3)) +``` + +struct dync_sched_member结构的成员用于记录与调度相关的信息。stat表示任务的当前状态,可以为挂起(XS_SUSPEND)、就绪(XS_READY)、运行(XS_RUNNING)或退出(XS_QUIT)。advance_cnt表示在配置成短作业预先调度时优先处理的时间片周期个数。cur_prio表示任务当前的优先级:为防止出现优先级反转,该优先级可以高于任务创建时配置的优先级。origin_timeslice表示在时间片轮转调度中该任务每次运行的时间片。地址空间隔离信息(isolation_flag变量和指针isolation)。sched_link、sched_avl构成的联合体为就绪队列节点,XiUOS中就绪队列可以配置为双链表(sched_link)或AVL树(sched_avl)。pend_link为任务挂起时使用的等待队列节点。task_timer用于任务睡眠的计时。 + +```c +struct smp_info { + xs_uint8 combined_coreid; + xs_uint8 runing_coreid; +}; +``` + +struct smp_info结构包含多处理器相关的信息,其成员分别表示该任务绑定的CPU ID与正在运行的CPU ID。 + + +### 任务函数接口 + +```c +struct xs_utask +{ + char name[XS_NAME_MAX]; + void *func_entry; + void *func_param; + xs_uint32 stack_size; + xs_uint8 prio; +}; +typedef struct xs_utask struct xs_utask; + +struct task_descriptor* xs_UserTaskCreate(xs_utask_x task); +``` + +该函数用于用户态创建一个任务。任务的各个属性由一个struct xs_utask结构表示,包括任务的名称、入口函数及参数、栈大小和优先级,在调用该函数时需要传入该结构的实例用于配置任务。任务创建成功后,内核会为其分配指定大小的栈及其他结构(如struct task_descriptor)结构,并返回任务描述符指针。 + +| 参数 | 描述 | +| --- | --- | +| task | 任务配置属性 | + +```c +xs_int32 xs_UserTaskDelete(struct task_descriptor task); +``` + +该函数用于删除一个任务,强制使其进入退出状态。若删除成功则返回XS_EOK,若失败则返回-XS_ERROR。 + +| 参数 | 描述 | +| --- | --- | +| task| 待删除的任务描述符 | + +```c +xs_int32 xs_UserTaskCoreCombine(struct task_descriptor task, xs_uint8 coreid); +``` + +该函数用于将任务绑定至指定的处理器上。若绑定成功则返回XS_EOK,若失败则返回-XS_ERROR。 + +| 参数 | 描述 | +| --- | --- | +| task_id | 待绑定的任务描述符 | +| coreid | 带绑定的处理器ID | + +```c +xs_int32 xs_UserTaskCoreUncombine(struct task_descriptor task); +``` + +该函数用于解除任务与处理器的绑定。若解除成功则返回XS_EOK,若失败则返回-XS_ERROR。 + +| 参数 | 描述 | +| --- | --- | +| task | 待解除绑定的任务描述符 | + +```c +xs_int32 xs_UserTaskDelay(xs_ticks_x ticks); +``` + +该函数用于将当前任务挂起一定时间,单位为tick。挂起时间结束后,任务会进入就绪状态,可以继续被调度。 + +| 参数 | 描述 | +| --- | --- | +| ticks | 任务挂起时间,单位为tick | + +```c +struct task_descriptor* xs_UserTaskSearch(char *name) +``` + +该函数用于从任务名称获取任务描述符。 + +| 参数 | 描述 | +| --- | --- | +| name | 任务名称 | + + + + +## 任务通信 + +XiUOS提供多种任务间通信机制,包括消息队列、信号量、互斥量与事件集。 + + +### 消息队列 + +消息队列(message queue)提供可供多个任务读或写的消息缓冲区,其中消息指固定长度的任意数据块。消息队列的容量有限。当消息队列满时,向消息队列写入的任务会被挂起;当消息队列空时,从消息队列读取的任务会被挂起。 + +#### 消息队列结构定义 + +```c +struct xs_MsgQueue +{ + xs_uint16 id; + + void *msg_buf; + xs_uint16 index; + xs_uint16 num_msgs; + xs_uint16 each_len; + xs_uint16 max_msgs; + + XS_DOUBLE_LINKLIST send_pend_list; + XS_DOUBLE_LINKLIST recv_pend_list; + XS_DOUBLE_LINKLIST link; +}; +``` + +| 成员 | 描述 | +| --- | --- | +| id | 消息队列ID,用于唯一标识一个消息队列 | +| msg_buf | 用于存储消息的缓冲区的首地址 | +| index | 当前缓冲区中第一个消息的序号 | +| num_msgs | 当前缓冲区中的消息数量 | +| each_len | 每条消息的大小,单位为字节 | +| max_msgs | 缓冲区中最多能存放的消息数量 | +| send_pend_list | 被挂起的发送任务链表 | +| recv_pend_list | 被挂起的接收任务链表 | +| link | 系统中所有消息队列构成的链表 | + +#### 消息队列函数接口 + +```c +xs_int32 xs_UserMsgQueueCreate(xs_uint16 msg_len, xs_uint16 max_msgs); +``` + +该函数用于创建一个消息队列。创建成功后,新的消息队列会被加入内核的消息队列管理链表,并返回该消息队列的ID,ID默认范围0-255,可配置。 + +| 参数 | 描述 | +| --- | --- | +| msg_len | 每条消息的长度,单位为字节 | +| max_msgs | 缓冲区中最多存放的消息数量 | + +```c +void xs_UserMsgQueueDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的消息队列。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的消息队列ID | + +```c +xs_int32 xs_UserMsgQueueSend(xs_uint16 id, const void *msg, xs_uint16 size, xs_ticks_x wait_time); +``` + +该函数用于向消息队列发送一个消息。若消息发送成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 目标消息队列ID | +| msg | 消息数据首地址 | +| size | 消息长度 | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserMsgQueueRecv(xs_uint16 id, void *buf, xs_uint16 size, xs_ticks_x wait_time); +``` + +该函数用于从消息队列接收一个消息。若消息接收成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | +| buf | 用于接收消息数据的缓冲区 | +| size | 缓冲区大小 | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserMsgQueueReinit(xs_uint16 id); +``` + +该函数用于将一个消息队列复位。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | + + +### 信号量 + +信号量(semaphore)具有一个给定的初值。任务可以获取或释放一个信号量。当任务获取信号量时信号量的值递减,释放信号量时值递增。当信号量值递减至0时,后续尝试获取信号量的任务会被挂起。每当一个已获取信号量的任务释放信号量时,内核会从信号量挂起队列上唤醒一个任务。信号量可以用于实现任务间的同步与互斥。 + +#### 信号量结构定义 + +```c +struct xs_Semaphore +{ + xs_uint16 id; + xs_uint16 value; + + XS_DOUBLE_LINKLIST pend_list; + XS_DOUBLE_LINKLIST link; +}; +``` + +| 成员 | 描述 | +| --- | --- | +| id | 信号量ID,用于唯一标识一个信号量 | +| value | 信号量的当前值 | +| pend_link | 挂起任务链表 | +| link | 系统中所有信号量构成的链表 | + +#### 信号量函数接口 + +```c +xs_int32 xs_UserSemaphoreCreate(xs_uint16 val); +``` + +该函数用于创建一个信号量。创建成功后,新的信号量会被加入内核的信号量管理链表,并返回该信号量的ID,ID默认范围0-255,可配置。 + +| 参数 | 描述 | +| --- | --- | +| val | 信号量的初值| + +```c +void xs_UserSemaphoreDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的信号量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的信号量的ID | + +```c +xs_int32 xs_UserSemaphoreObtain(xs_uint16 id, xs_ticks_x wait_time); +``` + +该函数用于获取一个信号量。若获取成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 欲获取的信号量的ID | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserSemaphoreAbandon(xs_uint16 id); +``` + +该函数用于释放一个信号量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待释放的信号量的ID | + +```c +xs_int32 xs_UserSemaphoreSetValue(xs_uint16 id, xs_uint16 val); +``` + +该函数用于将一个信号量的值进行重置。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | +| val | 重置的信号量的值 | + + +### 互斥量 + +互斥量(mutex)可以视作一个初值为1的信号量,同样有获取和释放操作。互斥量一般用于任务间的互斥。 + +#### 互斥量结构定义 + +struct xs_Mutex +{ + xs_uint16 id; + + xs_uint8 origin_prio; + xs_uint8 recursive_cnt; + + struct task_descriptor *holder; + + XS_DOUBLE_LINKLIST pend_list; + XS_DOUBLE_LINKLIST link; +}; + +| 成员 | 描述 | +| --- | --- | +| id | 互斥量ID,用于唯一标识一个互斥量 | +| origin_prio | 持有互斥量的任务的原优先级,用于避免优先级反转 | +| recursive_cnt | 持有互斥量的任务获取互斥量的次数,用于实现递归锁 | +| holder | 持有互斥量的任务 | +| pend_list | 挂起任务链表 | +| link | 系统中所有互斥量构成的链表 | + +#### 互斥量函数接口 + +```c +xs_int32 xs_UserMutexCreate(void); +``` + +该函数用于创建一个互斥量。创建成功后,新的互斥量会被加入内核的互斥量管理链表,并返回该互斥量的ID,ID默认范围0-255,可配置。 + +```c +void xs_UserMutexDelete(xs_uint16 id); +``` + +该函数用于删除一个已创建的互斥量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的互斥量的ID | + +```c +xs_int32 xs_UserMutexObtain(xs_uint16 id, xs_ticks_x wait_time); +``` + +该函数用于获取一个互斥量。若获取成功则返回XS_EOK,若不成功(等待超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 欲获取的互斥量的ID | +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserMutexAbandon(xs_uint16 id); +``` + +该函数用于释放一个互斥量。 + +| 参数 | 描述 | +| --- | --- | +| id | 待释放的互斥量的ID | + + +### 事件集 + +事件集(event set)允许用户定义一个事件集合,集合中的每个事件都可以被任务触发或等待。任务可以同时等待多个事件,此时等待触发的条件可以配置为AND或者OR:当等待触发条件配置为AND时,只有所有被等待的事件均被触发才视作等待结束;当等待触发条件配置为OR时,任意一个被等待的事件触发即视作等待结束。使用事件集可以实现多对多的任务间同步与互斥。 + +#### 事件集结构定义 + +```c +#define XS_EVENT_AND (1 << 29) +#define XS_EVENT_OR (1 << 30) +#define XS_EVENT_AUTOCLEAN (1 << 31) +#define XS_EVENTS(x) (1 << x) + +struct xs_event +{ + xs_uint16 id; + xs_uint32 trigge_way; + + XS_DOUBLE_LINKLIST pend_list; + XS_DOUBLE_LINKLIST link; +}; +``` + +| 成员 | 描述 | +| --- | --- | +| id | 事件集ID,用于唯一标识一个事件集 | +| trigge_way | 高3位用于记录事件集属性(等待触发条件、是否自动清空),低29位用于表示至多29个事件 | +| pend_list | 等待任务链表 | +| link | 系统中所有事件集构成的链表 | + +#### 事件集函数接口 + +```c +xs_int32 xs_UserEventCreate(xs_uint32 options); +``` + +该函数用于创建一个事件集。options参数用于配置事件集的属性。可配置的属性有等待触发方式(XS_EVENT_AND或XS_EVENT_OR)及等待触发后是否自动清空其他已触发的事件(XS_EVENT_AUTOCLEAN)。创建成功后,新的事件集会被加入内核的事件集管理链表,并返回该事件集的ID,ID默认范围0-255,可配置。 + +| 参数 | 描述 | +| --- | --- | +| options | 事件集配置选项,须在XS_EVENT_AND及XS_EVENT_OR中指定其一,并可以按位或上XS_EVENT_AUTOCLEAN | + +```c +void xs_UserEventDele## +该函数用于删除一个已创建的事件集。 + +| 参数 | 描述 | +| --- | --- | +| id | 待删除的事件集的ID | + +```c +xs_int32 xs_UserEventTrigger(xs_uint16 id, xs_uint32 events); +``` + +该函数用于触发事件集中的一组事件。 + +| 参数 | 描述 | +| --- | --- | +| id | 事件集ID | +| events | 欲触发的事件,其中被置1的位标识被触发的事件 ,可以使用XS_EVENTS宏按位或发送事件类型| + +```c +xs_int32 xs_UserEventProcess(xs_uint16 id, xs_uint32 events, xs_ticks_x wait_time); +``` + +该函数用于等待事件集中的一组事件。若等待成功则返回XS_EOK,此时若XS_EVENT_AUTOCLEAN被打开则事件集中所有已触发事件会被清空;若等待失败(超时)则返回-XS_ETIMEOUT。 + +| 参数 | 描述 | +| --- | --- | +| id | 事件集ID | +| events | 欲等待的事件,其中被置1的位标识被等待的事件,可以使用XS_EVENTS宏按位或接收事件类型| +| wait_time | 等待时间上限,单位ticks;若为0,则不等待 | + +```c +xs_int32 xs_UserEventConfig(xs_uint16 id, xs_uint32 options); +``` + +该函数用于配置事件集中的一种事件类型。若等配置成功则返回XS_EOK,options参数用于配置事件集的属性。可配置的属性有等待触发方式(XS_EVENT_AND或XS_EVENT_OR)及等待触发后是否自动清空其他已触发的事件(XS_EVENT_AUTOCLEAN)。 + +| 参数 | 描述 | +| --- | --- | +| id | 事件集ID | +| options | 事件集配置选项,须在XS_EVENT_AND及XS_EVENT_OR中指定其一,并可以按位或上XS_EVENT_AUTOCLEAN | + +```c +xs_int32 xs_UserEventReinit(xs_uint16 id); +``` + +该函数用于将一个事件的值进行重置。 + +| 参数 | 描述 | +| --- | --- | +| id | 来源消息队列ID | + + +## 使用场景 + +* 在多处理器设备上,多个任务可以并行运行,从而提高处理器的利用率。 +* 在一些中断驱动的应用中,如果中断需要处理的工作过于复杂,则可以创建一个任务专门用于处理相关工作,从而改善中断延迟。 \ No newline at end of file diff --git a/docs/doc/kernel/threadcommunication.md b/docs/doc/kernel/threadcommunication.md deleted file mode 100644 index f077f2b..0000000 --- a/docs/doc/kernel/threadcommunication.md +++ /dev/null @@ -1,179 +0,0 @@ -# 线程间通信 -XiUOS 的线程间通信使用管道和消息队列进行通信。下面将分别介绍。 - -## 消息队列 -### 消息队列的工作机制 -消息队列能够接收线程或中断产生的不固定长度的消息,并储存到自己的内存空间中。其他线程可以从消息队列中读取相应的消息。当消息队列为空时,挂起读取线程,当有新的消息到达时,唤醒读取线程进行读取。 -### 结构体定义和函数接口 -#### 结构体定义 -```C -struct xs_MessageQueue -{ - char name[XS_NAME_MAX]; - xs_uint8 style; - - xs_uint8 sign; - - - xs_list_t link; - - xs_list_t pend_list; - - void *msg_buf; - - xs_uint16 size; - xs_uint16 max_msgs; - - xs_uint16 index; - - void *mq_listhead; - void *mq_listtail; - void *mq_free; - - xs_list_t pend_sender_thread; -}; -typedef struct xs_MessageQueue *xs_messagequeue_t; -``` -| 参数 | 描述 | -| ------ | ------ | -| name | 消息队列名称 | -| style | 线程等待的方式,可以取FIFO或PRIO | -| sign | 标记消息队列的创建方式,静态创建或动态创建 | -| link | 消息队列存放的列表 | -| pend_list | 线程等待队列 | -| msg_buf | 存放消息的缓存区 | -| size | 缓存区大小 | -| max_msgs | 一条消息的最大长度 | -| index | 当前消息数 | -| mq_listhead | 消息链表头 | -| mq_listtail | 消息链表尾 | -| mq_free | 空闲消息链表 | -| pend_sender_thread | 发送线程的挂起等待队列 | - - -#### 函数接口 -```C -xs_err_t xs_InitMessageQueue(xs_messagequeue_t mq, - const char *name, - void *msgpool, - xs_size_t msg_size, - xs_size_t pool_size, - xs_uint8 flag) -``` -该函数用于初始化一个静态消息队列,并将它加入消息队列管理列表中。创建成功后返回`XS_OK`。
-| 参数 | 描述 | -| ------ | ------ | -| mq | 消息队列对象指针 | -| name | 消息队列名称 | -| msgpool | 指向存放消息的内存空间的指针 | -| msg_size | 一条消息的最大长度 | -| pool_size | 存放消息的内存区大小 | -| flag | 消息队列采用的等待方式,可取FIFO或PRIO | -
- -```C -xs_err_t xs_DetachMessageQueue(xs_messagequeue_t mq) -``` -该函数用于将一个静态消息队列从消息队列管理列表中移除。移除成功则返回`XS_OK`。
-| 参数 | 描述 | -| ------ | ------ | -| mq | 消息队列对象指针 | -
- -```C -xs_messagequeue_t xs_CreateMessageQueue(const char *name, - xs_size_t msg_size, - xs_size_t max_msgs, - xs_uint8 flag) -``` -该函数用于动态创建一个消息队列,并将消息队列加入消息队列管理列表。
-| 参数 | 描述 | -| ------ | ------ | -| name | 消息队列名称 | -| msg_size | 缓冲区的大小 | -| max_msgs | 一条消息的最大长度 | -| flag | 消息队列采用的等待方式,可取FIFO或PRIO | -
- -```C -xs_err_t xs_DeleteMessageQueue(xs_messagequeue_t mq) -``` -该函数用于将由`xs_CreateMessageQueue`创建的消息队列从消息队列管理列表中删除。
-| 参数 | 描述 | -| ------ | ------ | -| mq | 消息队列对象指针 | -
- -```C -xs_err_t xs_MessageQueueSendwait(xs_messagequeue_t mq, - const void *buffer, - xs_size_t size, - xs_int32 timeout) -``` -发送消息时,消息队列对象先从空闲消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上,然后把该消息块挂到消息队列的尾部,成功则返回`XS_EOK`。如果消息长度大于最大长度,则返回`XS_ERROR`。如果消息队列满了,则根据超时时间设定进行等待,超时则返回`-XS_EFULL`。
- -| 参数 | 描述 | -| ------ | ------ | -| mq | 消息队列对象指针 | -| buffer | 消息内容 | -| size | 消息大小 | -| timeout | 超时时间 | -
- -```C -xs_err_t xs_MessageQueueSend(xs_messagequeue_t mq, const void *buffer, xs_size_t size) -``` -该函数是timeout为0的`xs_MessageQueueSendwait`。 -
- -| 参数 | 描述 | -| ------ | ------ | -| mq | 消息队列对象指针 | -| buffer | 消息内容 | -| size | 消息大小 | -
- -```C -xs_err_t xs_MessageQueueUrgentSend(xs_messagequeue_t mq, const void *buffer, xs_size_t size) -``` - -发送紧急消息和发送普通消息的区别是:当发送紧急消息时,从空闲消息链表上取下来的消息块不是挂到消息队列的队尾,而是挂到队首,这样,接收者就能够优先接收到紧急消息,从而及时进行消息处理。
- -| 参数 | 描述 | -| ------ | ------ | -| mq | 消息队列对象指针 | -| buffer | 消息内容 | -| size | 消息大小 | -
- -```C -xs_err_t xs_MessageQueueReceive(xs_messagequeue_t mq, - void *buffer, - xs_size_t size, - xs_int32 timeout) -``` -当队列中有消息时,接收消息。队列中没有消息时,根据超时时间设定进行等待。接收一个消息后消息队列上的队首消息被转移到了空闲消息链表的尾部。成功收到消息返回`XS_EOK`,超时返回`XS_ETIMEOUT`。接收消息失败返回`-XS_ERROR`。 -
- -| 参数 | 描述 | -| ------ | ------ | -| mq | 消息队列对象指针 | -| buffer | 消息内容 | -| size | 消息大小 | -| timeout | 超时时间 | -
- -```C -xs_err_t xs_CmdControlMessageQueue(xs_messagequeue_t mq, int cmd, void *arg) -``` -该函数用于获取或设置消息队列的其他属性。目前当cmd == XS_LINKLIST_CMD_RESET时,重新初始化消息队列。 -
- -| 参数 | 描述 | -| ------ | ------ | -| mq | 消息队列对象指针 | -| cmd | 需要执行的命令 | -| arg | 命令的参数 | -
- -## 管道 \ No newline at end of file diff --git a/docs/doc/kernel/tmr.md b/docs/doc/kernel/tmr.md new file mode 100644 index 0000000..ba6f687 --- /dev/null +++ b/docs/doc/kernel/tmr.md @@ -0,0 +1 @@ +# 节拍机制 \ No newline at end of file diff --git a/docs/doc/processor/README.md b/docs/doc/processor/README.md index 0969728..0fe48a3 100644 --- a/docs/doc/processor/README.md +++ b/docs/doc/processor/README.md @@ -1,10 +1,10 @@ -# 控制器 +# 处理器 --- -- [西门子](/doc/processor/riscv.md) +- [RISC-V](/doc/processor/riscv.md) -- [线程管理](/doc/processor/riscv_sk.md) +- [ARM](/doc/processor/arm.md) -- [资源管理](/doc/processor/riscv_fpga.md) +- [RISC-V软核](/doc/processor/riscv_sfcore.md) diff --git a/docs/doc/processor/arm.md b/docs/doc/processor/arm.md new file mode 100644 index 0000000..435256a --- /dev/null +++ b/docs/doc/processor/arm.md @@ -0,0 +1 @@ +# ARM \ No newline at end of file diff --git a/docs/doc/processor/riscv.md b/docs/doc/processor/riscv.md index 20090ef..ec37ab0 100644 --- a/docs/doc/processor/riscv.md +++ b/docs/doc/processor/riscv.md @@ -1 +1 @@ -# 三菱 \ No newline at end of file +# RISC-V \ No newline at end of file diff --git a/docs/doc/processor/riscv_fpga.md b/docs/doc/processor/riscv_fpga.md deleted file mode 100644 index bda7473..0000000 --- a/docs/doc/processor/riscv_fpga.md +++ /dev/null @@ -1 +0,0 @@ -# 西门子 \ No newline at end of file diff --git a/docs/doc/processor/riscv_sfcore.md b/docs/doc/processor/riscv_sfcore.md new file mode 100644 index 0000000..3a86557 --- /dev/null +++ b/docs/doc/processor/riscv_sfcore.md @@ -0,0 +1 @@ +# RISC-V 软核 \ No newline at end of file diff --git a/docs/doc/processor/riscv_sk.md b/docs/doc/processor/riscv_sk.md deleted file mode 100644 index 47afe82..0000000 --- a/docs/doc/processor/riscv_sk.md +++ /dev/null @@ -1 +0,0 @@ -# 施耐德 \ No newline at end of file diff --git a/docs/doc/selfterminal/README.md b/docs/doc/selfterminal/README.md new file mode 100644 index 0000000..85036e6 --- /dev/null +++ b/docs/doc/selfterminal/README.md @@ -0,0 +1,8 @@ +# 自研终端 + +--- + +* [aiit_arm](/doc/selfterminal/aiit-arm.md) + +* [aiit_riscv](/doc/selfterminal/aiit-riscv.md) + diff --git a/docs/doc/selfterminal/aiit-arm.md b/docs/doc/selfterminal/aiit-arm.md new file mode 100644 index 0000000..d2e8330 --- /dev/null +++ b/docs/doc/selfterminal/aiit-arm.md @@ -0,0 +1 @@ +# aiit-arm \ No newline at end of file diff --git a/docs/doc/selfterminal/aiit-riscv.md b/docs/doc/selfterminal/aiit-riscv.md new file mode 100644 index 0000000..7e41bf8 --- /dev/null +++ b/docs/doc/selfterminal/aiit-riscv.md @@ -0,0 +1 @@ +# aiit-riscv \ No newline at end of file diff --git a/docs/doc/sensor/README.md b/docs/doc/sensor/README.md index 54ebf0d..e136ff3 100644 --- a/docs/doc/sensor/README.md +++ b/docs/doc/sensor/README.md @@ -18,3 +18,5 @@ - [声音传感器](/doc/sensor/voice_sensor.md) +- [图像传感器](/doc/sensor/image_sensor.md) + diff --git a/docs/doc/sensor/gas_sensor.md b/docs/doc/sensor/gas_sensor.md index 48bc920..b3ee862 100644 --- a/docs/doc/sensor/gas_sensor.md +++ b/docs/doc/sensor/gas_sensor.md @@ -122,1681 +122,3 @@ 注意: 通讯分为主动上传和问答式,上电默认为问答式。 - -#### 二、 传输模式切换指令 -+ 切换到主动上传 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位保留切换命令主动上传保留保留保留保留校验值
0xFF0x010x780x400x000x000x000x000x47
-
- -+ 切换到被动上传 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位保留切换命令主动上传保留保留保留保留校验值
0xFF0x010x780x410x000x000x000x000x46
-
- -#### 三、 查询模式下命令 -+ 获取传感器类型,最大量程,单位小数位数指令:`0xD1` -
-返回值:
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
传感器类型最大量程高位最大量程低位单位保留保留保留数据小数位数(bit[4]~bit[7]),数据正负号(bit[0]~bit[3])校验值
0x180x000xC80x020x000x000x000x010x35
-
-**说明:**
-最大量程 = (最大量程高位 << 8) | 最大量程低位
-单位: 0x02( $ ppm $ 和 $mg/m_3$ )
-正负号: 0(正数) 1(负数)
-小数位数: 读出的浓度值是代多少个小数,小数位数最多是3位 - -+ 获取传感器类型,最大量程,单位,单位小数位数指令:`0xD7` -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
指令头1指令头2传感器类型最大量程高位最大量程低位单位数据小数位数(bit[4]~bit[7]),数据正负号(bit[0]~bit[3])保留校验值
0xFF0xD70x180x000xC80x020x010x000x46
-
- -**说明:**
-校验和:1~7位数据相加,生成一个8位的数据,各位相反,末尾加1
-小数位数bit[4]~bit[7]:
-`(bit[7]<<3) | (bit[6]<<2) | (bit[5]<<1) | bit[4] = 小数位数` -

- -数据正负号(bit[0]~bit[3])
-`(bit[3]<<3) | (bit[2]<<2) | (bit[1]<<1) | bit[0] = 0` 负向抑制 -
-`(bit[3]<<3) | (bit[2]<<2) | (bit[1]<<1) | bit[0] = 0` 正向抑制 -
-
-单位: -0x02: 单位为$mg/{m^3}$和$ppm$
-0x04: 单位为$um/{m^3}$和$ppb$
-0x08: 单位为$10g/{m^3}$和$%$ - -+ 主动读气体浓度值格式如下: -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位保留命令保留保留保留保留保留校验值
0xFF0x010x860x000x000x000x000x000x79
-
-返回值: -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位命令气体浓度高位($ug/{m^3}$)气体浓度低位($ug/{m^3}$)满量程高位满量程低位气体浓度高位($ppb$)气体浓度低位($ppb$)校验值
0xFF0x860x000x2A0x000x000x000x000x30
-
- -**说明:**
-校验和:1~7位数据相加,生成一个8位数据,各位取反,末尾加1
-气体浓度值 = 气体浓度高位 * 256 + 气体浓度低位
-(浓度高位和浓度低位需要从16进制换算为10进制后再带入本公式计算) - -+ 气体浓度值和温湿度合并读取指令 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位保留命令保留保留保留保留保留校验值
0xFF0x010x870x000x000x000x000x000x78
-
-返回值: -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位命令气体浓度高位($ug/{m^3}$)气体浓度低位($ug/{m^3}$)满量程高位满量程低位气体浓度高位($ppb$)气体浓度低位($ppb$)温度高位
0xFF0x870x000x2A0x030xE80x000x200x09
9101112
温度低位湿度高位湿度低位校验和
0xC40x130x880xDC
-
- -**说明:**
-校验和: 1~11位数据相加,生成1个8位的数据,各位取反,末尾加1
-气体浓度值 = 气体浓度高位 * 256 + 气体浓度低位;
-(浓度高位和浓度低位需要从16进制换算为10进制再带入本公式计算)

-温度是带符号和两位小数的数据,单位是(°C),伪代码计算公式:
-`T = (float)(int)((0x0A<<8)|0x09)/100`

-湿度是不带符号和两位小数的数据,单位是(rh%),伪代码计算公式:
-`Rh = (float)(uint)((0x0A<<8)|0x09)/100` - - -+ 获取当前温度和湿度 -指令:`0xD2` -
- - - - - - - - - - - - - - - - - - - -
0123
温度高8位温度低8位湿度高8位湿度低8位
0x0A0x090x110xF4
-
- -**说明:**
-温度是带符号和两位小数的数据,单位是(°C),伪代码计算公式:
-`T = (float)(int)((0x0A<<8)|0x09)/100`

-湿度是不带符号和两位小数的数据,单位是(rh%),伪代码计算公式:
-`Rh = (float)(uint)((0x0A<<8)|0x09)/100` - -+ 获取当前温度和湿度带校验 -指令:`0xD6` -
- - - - - - - - - - - - - - - - - - - - - - -
01234
温度高8位温度低8位湿度高8位湿度低8位校验和
0x0A0x090x110xF40xE8
-
- -**说明:**
-校验和:0~3位数据相加,生成一个8位的数据,各位取反,末尾加1 - -#### 四、 主动上传模式下数据 -上传数据格式如下: -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位命令气体浓度高位($ug/{m^3}$)气体浓度低位($ug/{m^3}$)满量程高位满量程低位气体浓度高位($ppb$)气体浓度低位($ppb$)校验值
0xFF0x860x000x2A0x000x000x000x200x30
-
- -**说明:**
-校验和:0~11位数据相加,生成一个8位的数据,各位取反,末尾加1
-气体浓度值 = 气体浓度值高位 * 256 + 气体浓度值低位;
-(浓度高位和浓度低位需要从16进制换算为10进制后再带入本公式计算) - -*其他关于低功耗的指令详见数据手册* - -## TB600B-WQ-HCHO-1-O 甲醛气体检测模组 - -
- - - - - -
- - TB600B_HCHO - - - ppb级高精度环境监测应用;

- 极强的抗干扰能力,对低浓度乙醇、CO、芳香烃、异味、烟气、空气清新剂等有很好的抗干扰能力;

- 长寿命、检测稳定、可靠性高;

- 快速响应;

- 独立温湿度数字传感器,结合智能算法,环境适应性强;

-
-
- -### 应用领域 -+ 室内家居空气质量污染监测 -+ 家用、商用新风在线净化系统 -+ 家用新风机、净化器 -+ 商业场所空气质量污染监测 -+ 室内温湿度监测仪 -+ 车载空气净化器 -+ 公共交通工具空间内空气监测 -+ 暖通空调系统 -+ 智能可穿戴设备(腕表、口罩、手机) -+ 健康运动设备 - -*接线及通信协议与TB600B-IAQ-10 空气质量检测模组相同,这里不再赘述。更为详细的指令详见数据手册* - -## TB600B-TVOC-10 有机挥发物气体检测模组 - -
- - - - - -
- - TB600B_TVOC - - - ppb级高精度环境监测应用;

- ppb级TVOC气体传感器;

- 可对300多类以上的VOC气体反应;

- 长寿命、检测稳定、可靠性高;

- 快速响应;

- 独立温湿度数字传感器,结合智能算法,环境适应性强;

- 小体积低功耗;

-
-
- -### 应用领域 -+ 室内家居空气质量污染监测 -+ 家用、商用新风在线净化系统 -+ 家用新风机、净化器 -+ 商业场所空气质量污染监测 -+ 室内温湿度监测仪 -+ 车载空气净化器 -+ 公共交通工具空间内空气监测 -+ 暖通空调系统 -+ 智能可穿戴设备(腕表、口罩、手机) -+ 健康运动设备 -+ 抽油烟机和智能家具产品 -+ 实验室排风柜系统 -+ 超净实验室环境监测 -+ 小型无人机环境空气质量监测 - -*接线及通信协议与TB600B-IAQ-10 空气质量检测模组相同,这里不再赘述。更为详细的指令详见数据手册* - - -## G8 二氧化碳气体检测模组 - -
- - - - - -
- - G8 - - - 非色散红外技术,精确监测CO2

- 定期自动校准和手动校准,可选

-
-
- -### 应用领域 -+ 室内空气质量 -+ 采暖通风与空调系统 -+ 环境监测 -+ 绿色建筑 - -### 性能指标 - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
检测气种 二氧化碳
应用原理 非色散红外技术
检测范围400ppm ~ 2000ppm
可扩展为0~10000ppm
测量周期4 秒
准确度 ±50ppm±读数的3%
响应时间(T90) 120秒
预热时间上电8秒(输出浓度)上电3分钟(准确输出)
-
- -### 接线说明 -
- G8_pin -
-
- -**工作电压为4.5V ~ 5.25V** - -### 通信协议 -#### 一、通用设置 -传感器使用串行通讯方式。 - -
- - - - - - - - - - - - - - - - - -
波特率9600
数据位8位
停止位1位
校验位
-
- -#### 二、数据包格式 - -
- - - - - - - - - - - - - - - - - - -
Byte1......ByteN0x09校验字0x0d0x0a
数据区Tab校验区回车换行
-
- -1. 一个数据包是由 ASCII 码组成的字符串 -2. 校验字算法:数据区(Byte1~ByteN,不包含 Tab)的所有字节累加求和,记为 -Sum,则校验字 Checksum = (unsigned char)(-(signed char)Sum) -3. 校验区内容:是校验字的两位 ASCII 码(占两个字节),例如校验字为 0x23,则 -校验区为 0x32,0x33(即字符'2','3');又如校验字是 0xab,则校验区为 -0x41,0x42(即字符'A','B',注意此处应是大写字母) - -### 串口协议命令表 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
指令功能名称说明
R0读取传感器序列号及版本号/
R4读取传感器量程及单位/
R6读浓度/
RA查看零点校准功能状态包括开关、进行阶段、周期、基准值
SA+时间(h)设定零点校准周期+开关时间为0时表示暂停此功能;
时间大于0时表示开启此功能,并将周期设为相应时间
SC+浓度(ppm)设定零点校准基准值/
B+浓度(ppm)单点标定/
F0切换到F0模式传感器进入不主动发送浓度值状态
F1切换到F1模式传感器进入主动发送浓度值状态
-
- -#### 协议示例 -+ 读取传感器序列号及版本号 - -发送: -
- - - - - - - - - - - - - - - - - - - -
0123456
0x520x300x090x370x450x0D0x0A
-
- -转换为ASCII 码: R0 7E
-应答(ASCII 码): ID:718D FA31 FW:207 MAP:1 11

-说明:
-ID:718D FA31 —— 序列号
- FW:207 —— 固件版本号
- MAP:1 —— 寄存器映射版本号
- - + 读取浓度值 - -发送: -
- - - - - - - - - - - - - - - - - - - -
0123456
0x520x360x090x370x380x0D0x0A
-
- -转换为ASCII 码: R6 78
-应答(ASCII 码): 1265 32

-说明:
-浓度值为1265ppm - -*更多示例详见数据手册* - -## AS830 可燃(有毒)气体探测模块 - -
- - - - - -
- - AS830 - - - 监测可燃气体和一氧化碳的浓度;

- 具有燃气泄漏报警功能;

- 具有燃气不完全燃烧报警功能。
-
-
- -### 应用领域 -+ 可燃(有毒)气体泄漏报警; -+ 燃气炉具、热水器不完全燃烧监控; -+ 室内空调环境下,空气质量监测。 - -*注:该模块可独立使用,也可安装在燃气器具内配套使用。* - -### 技术参数 - -
- - - - - - - - - - - - - - - - - - - - - - -
分型产品(可选)分型号可探测气体传感器
AS830CO 和 CH4SB-95-12
AS830/CO COSB-500-12
AS830/CH4 CH4 SB-12A
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
项目规格
供电电源DC5V±10%,≤100mA
监视状态:电流≤40mA 报警状态:电流≤70mA
预热时间通电后 180s(3 分钟)*1
报警方式CO 浓度低于 100ppm,不报警;
浓度在 150ppm〜300ppm 区间,保持 180s,发出低段报警;
浓度高于 300ppm 且保持 30s,发出高段报警。
CH4 洁净空气,不报警;
浓度高于 6%LEL,保持 30s,发出高段报警。
注:报警区间和报警点可以依据客户要求设计。
指示灯状态 指示灯
自检 绿、红、黄色灯依次点亮
预热 绿灯 快速闪亮
正常监视 绿灯 慢速闪亮
故障 黄灯 快速闪亮
报警 甲烷报警: 红灯 常亮
低段报警(一氧化碳):红灯 慢速闪亮
高段报警(一氧化碳):红灯 快速闪亮
蜂鸣器有源蜂鸣器距离 1 米处声压级 70dB〜95dB
状态 蜂鸣器
自检 短鸣一声
预热 预热完成短鸣一声,提醒退出预热状态
故障 每隔 10 秒“滴”一声
报警 低段报警:每隔 2 秒“滴、滴”慢速鸣叫
高段报警:每隔 0.5 秒“滴、滴”快速鸣叫
按键内置微动开关,通过针孔,使用一个工具按压,实现自检和消音*2 功能
输出方式PWM 格式信号,峰值电平≤3.3V
输出格式工作状态 输出波形
正常监视 高电平
电源偏移高 5ms 低 5ms 的方波
传感器断路 高 5ms 低 10ms 的方波
传感器短路 高 5ms 低 15ms 的方波
CO 低段报警 高 5ms 低 20ms 的方波
CO 高端报警 高 5ms 低 25ms 的方波
CH4 高段报警 高 5ms 低 30ms 的方波
-
- -### 接线说明 -
- AS830_pin -
-
-连接线束可采用标准MicroUSB接口和标准4PIN端子。 -
- - - - - - - - - - - - - - - - - - - - -
引脚说明MicroUSB (安卓手机充电器标准接口)
4PIN端子(XH-A卧式)
VCC 电源正 5 V
PWM 状态输出引脚,输出 PWM 波形
GND电源地
-
- - -### 通信协议 -#### 一、通用设置 -
- - - - - - - - - - - - - - - - - -
波特率9600
数据位8位
停止位1位
校验位
-
- -#### 二、数据说明 - -模块上电发送产品信息,然后每 13 秒发送一次浓度数据,数据示例如下:
-AS830_CH4_CON_V1.0_202006093E
-0000000078  11
-0     D0
-……
-7     C9
-12    9D
-20    9E
-……
-0     D0 - -#### 三、数据格式 -浓度(1 个或 2 个字符) tab (0x09)校验码(2 个字符)0x0D 0x0A
-浓度单位为%LEL,量程 0~20%LEL -#### 四、校验码计算方法 -将从头到 tab(不包含 tab)前的所有字符求取单字节累加和 s. 则校验字为 `checksum= (unsigned char)(-(signed char)s)`
-浓度为 0 时,s=0x30,`checksum = (unsigned char)(-0x30)=0xD0`,转换成 ASCII 格式 D0
-浓度为 7 时,s=0x37,`checksum =(unsigned char)(-0x37)=0xC9`,转换成 ASCII 格式 C9
-浓度为 12 时,s=0x31+0x32=0x63,`checksum=(unsigned char)(-0x63)=0x9D`,转换成 ASCII 格式 9D
- -## WZ-H3-K型选择性甲醛检测模组 -
- - - - - -
- - WZ-H3-K - - - 选择性检测甲醛

- 测量精度高

- 响应速度快

- 使用寿命长

- 稳定可靠

- 低功耗 -
-
- -### 应用领域 -+ 新风系统 -+ 空气净化器 -+ 便携式仪表 -+ 可穿戴设备 -+ 智能家居 - -### 管脚定义 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Pin1 VCC3.3V-5V
Pin2GND
Pin3RST复位
Pin4SW程序接口
Pin5NC悬空
Pin6TXD传感器发送引脚
Pin7RXD传感器接收引脚
-
- -### 技术指标 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
产品型号 WZ-H3-K
检测气体甲醛
检测量程0-2ppm
最大过载 5ppm
供电电压3.3-5V
响应时间(T90) <120S
分辨率 0.01ppm
检测精度 ±30ppb 或±10%取大值(25±3℃)(50±5%RH)
-
- - -### 通信协议 -#### 通用设置 -传感器模块使用串行通讯方式,通讯配置参数如下: -
- - - - - - - - - - - - - - - - - -
波特率9600
数据位8位
停止位1位
校验位
-
- -#### 通讯命令 -通讯分主动上传和问答式,出厂默认为主动上传,每隔 1 秒发送 1 次浓度值。
-命令行格式如下:
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位气体名称单位小数位数无 气体浓度高位气体浓度低位满量程高位满量程低位校验值
0xFFCH2O=0x17Ppb=0x040x000x000x250x070xD00x25
-
-气体浓度值=气体浓度高位*256+气体浓度低位;
-(浓度高位和浓度低位需从 16 进制换算为 10 进制后再代入本公式计算)
-切换到问答式,命令行格式如下:
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位保留切换命令问答 保留 保留 保留 保留 校验值
0xFF0x010x780x410x000x000x000x000x46
-
-切换到主动上传,命令行格式如下:
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位保留切换命令主动上传 保留 保留 保留 保留 校验值
0xFF0x010x780x400x000x000x000x000x47
-
-读气体浓度值格式如下:
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位保留命令保留 保留 保留 保留 保留 校验值
0xFF0x010x860x000x000x000x000x000x79
-
-传感器返回值格式如下:
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
012345678
起始位命令气体浓度高位(ug/m3)气体浓度低位(ug/m3) 保留 保留 气体浓度高位(ppb) 气体浓度低位(ppb) 校验值
0xFF0x860x000x2A0x000x000x000x200x30
-
- -气体浓度值=气体浓度高位*256+气体浓度低位
-(浓度度高位和浓度低位需从 16 进制换算为 10 进制后再代入本公式计算) - -## PS5308/PS5308A 激光颗粒物传感器 - -
- - - - - -
- - PS5308A - - - 实时检测输出

- 数据准确可靠

- 最小分辨粒径 0.3 微米

- 特定激光防衰减恒定亮度功能                

- 具备抗干扰能力

- 标准 TTL 串口数据输出

- 小尺寸易安装 -
-
- -### 应用领域 -+ 空气净化器 -+ 新风系统 -+ 空调 -+ 车载空气净化器 -+ 空气质量监测仪 -+ 环境监测 -+ 手持式空气质量检测仪 -### 管脚定义 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Pin1 VCC电源 5V
Pin2GND电源地
Pin3WKUP高电平或悬空:工作状态;
低电平:休眠状态.
TTL 电平@3.3V
Pin4RXD串口接收,TTL 电平@3.3V
Pin5TXD串口发送,TTL 电平@3.3V
Pin6REST传感器复位信号 TTL 电平@3.3V,低电平复位
Pin7NC悬空
Pin8NC悬空
-
- -### 技术指标 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
产品型号 PS5308/PS5308A
颗粒物测量范围 PM2.5(PM10 选配)
检测量程0~1000 ug/ m³
颗粒物质量浓度一致性 ≥100 ug/ m³:±10%
<100 ug/ m³:±10 ug/ m³
颗粒物质量浓度准确性(参考标准:TSI 8530) ≥100 ug/ m³:±10%
<100 ug/ m³:±10 ug/ m³
电源电压 DC 5±0.5V,纹波<50mV
-
- -### 通信协议 -#### 一、通用设置 -传感器使用串行通讯方式。 - -
- - - - - - - - - - - - - - - - - -
波特率9600
数据位8位
停止位1位
校验位
-
- -#### 二、数据包格式 -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字节序号 数据定义
0 0x44起始符 1
1 0x4D 起始符 2
2 0x00数据帧长度(字节 4 数据至校验位)
3 0x1C
4 XXPM1.0 浓度值(进风口带 60~80 目滤网时),单位:ug/m³
5 XX
6 XXPM2.5 浓度值(进风口带 60~80 目滤网时),单位:ug/m³
7 XX
8 XXPM10 浓度值(进风口带 60~80 目滤网时),单位:ug/m³
9 XX
10 XXPM1.0 浓度值(进出风口无障碍物时),单位:ug/m³
11 XX
12 XXPM2.5 浓度值(进出风口无障碍物时),单位:ug/m³
13 XX
14 XXPM10 浓度值(进出风口无障碍物时),单位:ug/m³
15 XX
16 XX0.1 升空气中直径在 0.3um 以上颗粒物个数
17 XX
18 XXP0.1 升空气中直径在 0.5um 以上颗粒物个数
19 XX
20 XX0.1 升空气中直径在 1.0um 以上颗粒物个数
21 XX
22 XX0.1 升空气中直径在 2.5um 以上颗粒物个数
23 XX
24 XX0.1 升空气中直径在 5.0um 以上颗粒物个数
25 XX
26 XX0.1 升空气中直径在 10um 以上颗粒物个数
27 XX
28 XX
29 XX
30 XX校验和=字节 0 数据+字节 1 数据+„„+字节 29 数据
31 XX
-
- -数据说明: -1. 主要输出为空气中 PM2.5 颗粒物质量浓度,单位:ug/ m³。 -2. 传感器输出为主动输出。传感器上电后,主动向主机发送串行数据,时间间隔为 1 秒。 -3. 定义为“空白”的字节为厂家备用字节。 -4. “进出风口无障碍物”意指:传感器进出风量未受到影响。 \ No newline at end of file diff --git a/docs/doc/sensor/image_sensor.md b/docs/doc/sensor/image_sensor.md new file mode 100644 index 0000000..efc56b2 --- /dev/null +++ b/docs/doc/sensor/image_sensor.md @@ -0,0 +1,41 @@ +# 图像传感器 + +## 传感器介绍 + +| 传感器信号 | 传感器说明 | 驱动支持 | 传感器外形 | +| --- | --- | --- | --- | +| OV7670 | 最大支持 40x480,30万像素,不支持 JPEG 输出,不支持自动对焦 | 已支持 | ![ov7670](/images/sensor-ov7670.png) | +| OV2640 | 最大支持 1600x1200,200万像素,支持 JPEG 输出,不支持自动对焦 | 待支持 | ![ov7670](/images/sensor-ov2640.png) | + +## 使用说明 + +本系统支持 dev fs,camera 设备会在 /dev 下面注册。 + +相关数据结构: + +```c +enum CameraOutputFormat { + RGB565, + JPEG, +}; +struct CameraInfo { + int width; + int height; + CameraOutputFormat format; +}; +``` + +基本使用说明: + +```c +// open camera device +int fd = open(“/dev/cam1”); + +// get camera info +struct CameraInfo cam_info; +int ret = ioctl(fd, GET_INFO, &cam_info); + +// read camera data to buf +void *buf = malloc(cam_info.width * cam_info.height * 2); // assume the format is RGB565 +int ret = read(fd, buf, size); +``` diff --git a/docs/doc/task.md b/docs/doc/task.md new file mode 100644 index 0000000..ad4ca79 --- /dev/null +++ b/docs/doc/task.md @@ -0,0 +1,174 @@ +# 任务管理 + +任务(task)是XiUOS中处理器使用权分配的最小单位。每个任务有自己的程序栈与寄存器上下文,在多处理器平台上可以互不干扰地同时运行,但单个处理器上任意时刻只能有一个任务在运行。用户可以使用XiUOS提供的接口创建任意数量的任务。内核会对系统中的所有任务按照一定策略(抢占式优先级或先来先服务)进行调度,以最大限度地利用处理器资源。用户可以使用XiUOS提供的接口创建任意数量的任务。 + +## 任务状态 + +系统中的任务在任意时刻都处于就绪(ready)、运行(running)、阻塞/挂起(suspend)、退出(quit)四种状态之一。状态之间的变化关系如下图所示。 + +![task_status](task_status.png) + +任务在创建完成后会进入就绪状态并被加入就绪队列等待内核调度。当任务被调度开始运行时,任务会进入运行状态。若任务在运行过程中被更高优先级的任务抢占,则被强占的任务会回到就绪队列并再次进入就绪状态。当任务在运行过程中申请资源失败时,任务会被挂起并进入挂起状态,并在所申请资源能够被满足时回到就绪状态。当任务执行完成,即从入口函数返回时,会进入终止状态,并由内核回收其相关资源。 + +## 任务调度 + +任务调度即从系统就绪队列中按一定策略选择任务,使其进入运行状态的过程。XiUOS支持以下调度方式: + +* 抢占式优先级调度:在创建任务时可以指定任务的优先级,内核总是选取就绪队列中优先级最高的任务。当新创建的任务优先级高于正在运行的任务的优先级时,当前运行的任务会被抢占。若就绪队列中最高优先级任务有多个,则这些任务会按时间片轮转交替运行。 +* 先来先服务(FIFO)调度:任务按照被创建的顺序依次被执行。当一个任务运行完成后,系统才会让下一个任务开始运行。 +* 时间片轮转(RR)调度:任务按照分配的时间片执行,时间片结束,调度一个新的就绪任务执行,当前任务重新就绪,等待下一次的调度。 + +## 任务结构定义 + +每个任务在内核中由一个task_descriptor结构表示,二者一一对应。 + +```c +struct task_descriptor +{ + void *stack_pointer; + + struct dync_sched_member dync_sched_member_x; + + struct t_baseinfo t_baseinfo_x; + + #ifdef XS_USING_SMP + struct smp_info smp_info_x; + #endif + +#if defined(XS_USING_EVENT) + xs_uint32 event_ctrl1:3; + xs_uint32 event_ctrl2:29; +#endif + + xs_err_t error; + XS_DOUBLE_LINKLIST link; +}; +``` + +其中stack_pointer成员表示该任务的栈的起始地址,dync_sched_member_x成员包含与任务调度相关的信息,t_baseinfo_x包含任务的基本信息,smp_info_x包含与多处理器相关的信息,event_ctrl1/event_ctrl2用于实现事件集机制(见任务间通信部分文档),error为任务调用内核接口时最近的错误码,link用于将系统中的所有任务组织成一个双链表。各复合成员的详细定义如下: + +```c +struct task_baseinfo { + char name[XS_NAME_MAX]; + void *func_entry; + void *func_param; + xs_uint32 stack_size; + xs_uint8 origin_prio; +}; +``` + +struct task_baseinfo结构记录了任务的基本属性,包括任务的名称(name)、入口函数和参数(func_entry、func_param)、栈大小(stack_size)、优先级(origin_prio)。 + +```c +struct dync_sched_member { + xs_uint8 stat; + xs_uint8 advance_cnt; + xs_uint8 cur_prio; + xs_ubase origin_timeslice; + xs_ubase rest_timeslice; +#ifdef XS_USING_TASK_ISOLATION + xs_uint8 isolation_flag; + void *isolation; +#endif + union { + XS_DOUBLE_LINKLIST sched_link; + XS_AVL sched_avl; + } + XS_DOUBLE_LINKLIST pend_link; + xs_Timer_t task_timer; +}; + +#define XS_SUSPEND ((1) << (0)) +#define XS_READY ((1) << (1)) +#define XS_RUNNING ((1) << (2)) +#define XS_QUIT ((1) << (3)) +``` + +struct dync_sched_member结构的成员用于记录与调度相关的信息。stat表示任务的当前状态,可以为挂起(XS_SUSPEND)、就绪(XS_READY)、运行(XS_RUNNING)或退出(XS_QUIT)。advance_cnt表示在配置成短作业预先调度时优先处理的时间片周期个数。cur_prio表示任务当前的优先级:为防止出现优先级反转,该优先级可以高于任务创建时配置的优先级。origin_timeslice表示在时间片轮转调度中该任务每次运行的时间片。地址空间隔离信息(isolation_flag变量和指针isolation)。sched_link、sched_avl构成的联合体为就绪队列节点,XiUOS中就绪队列可以配置为双链表(sched_link)或AVL树(sched_avl)。pend_link为任务挂起时使用的等待队列节点。task_timer用于任务睡眠的计时。 + +```c +struct smp_info { + xs_uint8 combined_coreid; + xs_uint8 runing_coreid; +}; +``` + +struct smp_info结构包含多处理器相关的信息,其成员分别表示该任务绑定的CPU ID与正在运行的CPU ID。 + +## 任务函数接口 + +```c +struct xs_utask +{ + char name[XS_NAME_MAX]; + void *func_entry; + void *func_param; + xs_uint32 stack_size; + xs_uint8 prio; +}; +typedef struct xs_utask struct xs_utask; + +struct task_descriptor* xs_UserTaskCreate(xs_utask_x task); +``` + +该函数用于用户态创建一个任务。任务的各个属性由一个struct xs_utask结构表示,包括任务的名称、入口函数及参数、栈大小和优先级,在调用该函数时需要传入该结构的实例用于配置任务。任务创建成功后,内核会为其分配指定大小的栈及其他结构(如struct task_descriptor)结构,并返回任务描述符指针。 + +| 参数 | 描述 | +| --- | --- | +| task | 任务配置属性 | + +```c +xs_int32 xs_UserTaskDelete(struct task_descriptor task); +``` + +该函数用于删除一个任务,强制使其进入退出状态。若删除成功则返回XS_EOK,若失败则返回-XS_ERROR。 + +| 参数 | 描述 | +| --- | --- | +| task| 待删除的任务描述符 | + +```c +xs_int32 xs_UserTaskCoreCombine(struct task_descriptor task, xs_uint8 coreid); +``` + +该函数用于将任务绑定至指定的处理器上。若绑定成功则返回XS_EOK,若失败则返回-XS_ERROR。 + +| 参数 | 描述 | +| --- | --- | +| task_id | 待绑定的任务描述符 | +| coreid | 带绑定的处理器ID | + +```c +xs_int32 xs_UserTaskCoreUncombine(struct task_descriptor task); +``` + +该函数用于解除任务与处理器的绑定。若解除成功则返回XS_EOK,若失败则返回-XS_ERROR。 + +| 参数 | 描述 | +| --- | --- | +| task | 待解除绑定的任务描述符 | + +```c +xs_int32 xs_UserTaskDelay(xs_ticks_x ticks); +``` + +该函数用于将当前任务挂起一定时间,单位为tick。挂起时间结束后,任务会进入就绪状态,可以继续被调度。 + +| 参数 | 描述 | +| --- | --- | +| ticks | 任务挂起时间,单位为tick | + +```c +struct task_descriptor* xs_UserTaskSearch(char *name) +``` + +该函数用于从任务名称获取任务描述符。 + +| 参数 | 描述 | +| --- | --- | +| name | 任务名称 | + +## 使用场景 + +* 在多处理器设备上,多个任务可以并行运行,从而提高处理器的利用率。 +* 在一些中断驱动的应用中,如果中断需要处理的工作过于复杂,则可以创建一个任务专门用于处理相关工作,从而改善中断延迟。 \ No newline at end of file