Merge branch 'master' of https://github.com/xuos/xuos-web
This commit is contained in:
commit
ef46906e68
|
@ -47,6 +47,10 @@ module.exports = {
|
||||||
text: '内核',
|
text: '内核',
|
||||||
link: '/doc/kernel/',
|
link: '/doc/kernel/',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: '组件',
|
||||||
|
link: '/doc/component/'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: '处理器',
|
text: '处理器',
|
||||||
link: '/doc/processor/',
|
link: '/doc/processor/',
|
||||||
|
@ -68,12 +72,16 @@ module.exports = {
|
||||||
link: '/doc/board/',
|
link: '/doc/board/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '应用开发',
|
text: '自研终端',
|
||||||
link: '/doc/appdev/',
|
link: '/doc/selfterminal/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '应用框架',
|
text: '应用框架',
|
||||||
link: '/doc/apparch/'
|
link: '/doc/apparch/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '快速上手',
|
||||||
|
link: '/doc/appdev/',
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -117,6 +125,10 @@ module.exports = {
|
||||||
title: '内核',
|
title: '内核',
|
||||||
children: getSidebarByCategory('kernel','en')
|
children: getSidebarByCategory('kernel','en')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '组件',
|
||||||
|
children: getSidebarByCategory('component','en')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '处理器',
|
title: '处理器',
|
||||||
children: getSidebarByCategory('processor','en')
|
children: getSidebarByCategory('processor','en')
|
||||||
|
@ -138,14 +150,24 @@ module.exports = {
|
||||||
children: getSidebarByCategory('board','en')
|
children: getSidebarByCategory('board','en')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '应用开发',
|
title: '自研终端',
|
||||||
children: getSidebarByCategory('appdev','en')
|
children: getSidebarByCategory('selfterminal','en')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '应用架构',
|
title: '应用框架',
|
||||||
children: getSidebarByCategory('apparch','en')
|
children: getSidebarByCategory('apparch','en')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '快速上手',
|
||||||
|
children: getSidebarByCategory('appdev','en')
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
'/about/': [
|
||||||
|
['','项目概况'],
|
||||||
|
['xuos','XiUOS操作系统计划'],
|
||||||
|
['contact','联系方式'],
|
||||||
|
['license','开源协议']
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 199 KiB |
Binary file not shown.
After Width: | Height: | Size: 490 KiB |
Binary file not shown.
After Width: | Height: | Size: 487 KiB |
|
@ -1,12 +1,18 @@
|
||||||
const sidebar = {
|
const sidebar = {
|
||||||
'intro': [
|
'intro': [
|
||||||
'/doc/intro',
|
'/doc/intro',
|
||||||
],
|
],
|
||||||
'kernel': [
|
'kernel': [
|
||||||
'/doc/kernel/task',
|
'/doc/kernel/task',
|
||||||
'/doc/kernel/mm',
|
'/doc/kernel/mm',
|
||||||
'/doc/kernel/synchron',
|
'/doc/kernel/int',
|
||||||
'/doc/kernel/threadcommunication'
|
'/doc/kernel/tmr'
|
||||||
|
],
|
||||||
|
'component': [
|
||||||
|
'/doc/component/fs',
|
||||||
|
'/doc/component/drvmodel',
|
||||||
|
'/doc/component/lib',
|
||||||
|
'/doc/component/gui'
|
||||||
],
|
],
|
||||||
'board': [
|
'board': [
|
||||||
'/doc/board/aiit-arm32',
|
'/doc/board/aiit-arm32',
|
||||||
|
@ -42,7 +48,8 @@ const sidebar = {
|
||||||
'/doc/sensor/magneto_sensor',
|
'/doc/sensor/magneto_sensor',
|
||||||
'/doc/sensor/photoelec_sensor',
|
'/doc/sensor/photoelec_sensor',
|
||||||
'/doc/sensor/pressure_sensor',
|
'/doc/sensor/pressure_sensor',
|
||||||
'/doc/sensor/voice_sensor'
|
'/doc/sensor/voice_sensor',
|
||||||
|
'/doc/sensor/image_sensor'
|
||||||
],
|
],
|
||||||
'appdev': [
|
'appdev': [
|
||||||
'/doc/appdev/env',
|
'/doc/appdev/env',
|
||||||
|
@ -57,8 +64,12 @@ const sidebar = {
|
||||||
],
|
],
|
||||||
'processor': [
|
'processor': [
|
||||||
'/doc/processor/riscv',
|
'/doc/processor/riscv',
|
||||||
'/doc/processor/riscv_sk',
|
'/doc/processor/arm',
|
||||||
'/doc/processor/riscv_fpga'
|
'/doc/processor/riscv_sfcore'
|
||||||
|
],
|
||||||
|
'selfterminal': [
|
||||||
|
'/doc/selfterminal/aiit-arm',
|
||||||
|
'/doc/selfterminal/aiit-riscv'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# 应用开发
|
# 应用框架
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -6,6 +6,6 @@
|
||||||
|
|
||||||
* [联](/doc/apparch/lian.md)
|
* [联](/doc/apparch/lian.md)
|
||||||
|
|
||||||
* [智](/doc/apparch/zhi.md)
|
* [知](/doc/apparch/zhi.md)
|
||||||
|
|
||||||
* [控](/doc/apparch/kong.md)
|
* [控](/doc/apparch/kong.md)
|
||||||
|
|
|
@ -1 +1,310 @@
|
||||||
# 控
|
# 控
|
||||||
|
|
||||||
|
工业生产中控制逻辑的复杂程度千变万化,往往需要具体行业专业人员完成专门的设计,从而提高了行业的技术壁垒,严重阻碍了工业领域的自动化和智能化升级。
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
|
@ -1 +1,15 @@
|
||||||
# 智
|
# 知 - 智能框架
|
||||||
|
|
||||||
|
## 基本框架
|
||||||
|
|
||||||
|
工厂中不仅有气压、温度等环境数据,还有很多图像、声音等数据,比如工业设备仪表盘、厂房工人分布等,这些数据也需要检测并处理。传统方案使用嵌入式终端采集、云端处理的架构。而当前越来越多的硬件厂商开始将一部分AI算力下沉到嵌入式终端上,比如 ST 推出的针对 STM 平台的神经网络加速库 STM32 Cube.AI,ARM 即将发布的针对嵌入式场景的 Ethos-U55 神经网络处理器,以及 勘智 K210 平台嵌入了一颗卷积网络加速器 KPU。本系统提供了在嵌入式节点端做轻量级AI处理的应用框架,可以在 Arm Cortex-M 或者 有神经网络加速器的平台(比如 勘智 K210)运行。对于复杂的 AI 应用,可以选择完全在 边缘或者云侧处理,也可以选择在 节点端做简单预处理,在 边缘或者云侧做后续的处理。基本结构如下:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
端侧智能运行框架中,目前在 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)”章节,详细说明后续补充。
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# 应用开发
|
# 快速上手
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# 应用开发
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
* [文件系统](/doc/component/fs.md)
|
||||||
|
|
||||||
|
* [驱动模型](/doc/component/drvmodel.md)
|
||||||
|
|
||||||
|
* [第三方库](/doc/component/lib.md)
|
||||||
|
|
||||||
|
* [GUI图形库](/doc/component/gui.md)
|
|
@ -0,0 +1 @@
|
||||||
|
# 驱动模型
|
|
@ -0,0 +1 @@
|
||||||
|
# 文件系统
|
|
@ -0,0 +1 @@
|
||||||
|
# GUI引擎
|
|
@ -0,0 +1 @@
|
||||||
|
# 第三方库
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
- [西门子](/doc/controller/ximenzi.md)
|
- [西门子](/doc/controller/ximenzi.md)
|
||||||
|
|
||||||
- [线程管理](/doc/controller/shinaide.md)
|
- [施耐德](/doc/controller/shinaide.md)
|
||||||
|
|
||||||
- [资源管理](/doc/controller/sanling.md)
|
- [三菱](/doc/controller/sanling.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 |
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
- [任务管理](/doc/kernel/task.md)
|
||||||
|
|
||||||
- [内存管理](/doc/kernel/mm.md)
|
- [内存管理](/doc/kernel/mm.md)
|
||||||
|
|
||||||
- [线程管理](/doc/kernel/task.md)
|
- [中断机制](/doc/kernel/int.md)
|
||||||
|
|
||||||
- [资源管理](/doc/kernel/synchron.md)
|
|
||||||
|
|
||||||
- [线程间通信](/doc/kernel/threadcommunication.md)
|
|
||||||
|
|
||||||
|
- [节拍机制](/doc/kernel/tmr.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()
|
||||||
|
|
|
@ -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 |
|
|
@ -1 +0,0 @@
|
||||||
# 资源管理
|
|
|
@ -1 +1,539 @@
|
||||||
# 线程管理
|
# 任务
|
||||||
|
|
||||||
|
* [任务管理](#management)
|
||||||
|
* [任务状态](#state)
|
||||||
|
* [任务调度](#sched)
|
||||||
|
* [任务结构定义](#struct)
|
||||||
|
* [任务函数接口](#api)
|
||||||
|
* [任务通信](#communication)
|
||||||
|
* [消息队列](#msg_quque)
|
||||||
|
* [信号量](#sem)
|
||||||
|
* [互斥量](#mutex)
|
||||||
|
* [事件集](#event)
|
||||||
|
* [使用场景](#situation)
|
||||||
|
|
||||||
|
<span id="management"></span>
|
||||||
|
|
||||||
|
## 任务管理
|
||||||
|
|
||||||
|
|
||||||
|
任务(task)是XiUOS中处理器使用权分配的最小单位。每个任务有自己的程序栈与寄存器上下文,在多处理器平台上可以互不干扰地同时运行,但单个处理器上任意时刻只能有一个任务在运行。用户可以使用XiUOS提供的接口创建任意数量的任务。内核会对系统中的所有任务按照一定策略(抢占式优先级或先来先服务)进行调度,以最大限度地利用处理器资源。用户可以使用XiUOS提供的接口创建任意数量的任务。
|
||||||
|
<span id="state"></span>
|
||||||
|
|
||||||
|
### 任务状态
|
||||||
|
|
||||||
|
系统中的任务在任意时刻都处于就绪(ready)、运行(running)、阻塞/挂起(suspend)、退出(quit)四种状态之一。状态之间的变化关系如下图所示。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
任务在创建完成后会进入就绪状态并被加入就绪队列等待内核调度。当任务被调度开始运行时,任务会进入运行状态。若任务在运行过程中被更高优先级的任务抢占,则被强占的任务会回到就绪队列并再次进入就绪状态。当任务在运行过程中申请资源失败时,任务会被挂起并进入挂起状态,并在所申请资源能够被满足时回到就绪状态。当任务执行完成,即从入口函数返回时,会进入终止状态,并由内核回收其相关资源。
|
||||||
|
<span id="sched"></span>
|
||||||
|
|
||||||
|
### 任务调度
|
||||||
|
|
||||||
|
任务调度即从系统就绪队列中按一定策略选择任务,使其进入运行状态的过程。XiUOS支持以下调度方式:
|
||||||
|
|
||||||
|
* 抢占式优先级调度:在创建任务时可以指定任务的优先级,内核总是选取就绪队列中优先级最高的任务。当新创建的任务优先级高于正在运行的任务的优先级时,当前运行的任务会被抢占。若就绪队列中最高优先级任务有多个,则这些任务会按时间片轮转交替运行。
|
||||||
|
* 先来先服务(FIFO)调度:任务按照被创建的顺序依次被执行。当一个任务运行完成后,系统才会让下一个任务开始运行。
|
||||||
|
* 时间片轮转(RR)调度:任务按照分配的时间片执行,时间片结束,调度一个新的就绪任务执行,当前任务重新就绪,等待下一次的调度。
|
||||||
|
<span id="struct"></span>
|
||||||
|
|
||||||
|
### 任务结构定义
|
||||||
|
|
||||||
|
每个任务在内核中由一个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。
|
||||||
|
<span id="api"></span>
|
||||||
|
|
||||||
|
### 任务函数接口
|
||||||
|
|
||||||
|
```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 | 任务名称 |
|
||||||
|
|
||||||
|
|
||||||
|
<span id="communication"></span>
|
||||||
|
|
||||||
|
## 任务通信
|
||||||
|
|
||||||
|
XiUOS提供多种任务间通信机制,包括消息队列、信号量、互斥量与事件集。
|
||||||
|
<span id="msg_quque"></span>
|
||||||
|
|
||||||
|
### 消息队列
|
||||||
|
|
||||||
|
消息队列(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 |
|
||||||
|
<span id="sem"></span>
|
||||||
|
|
||||||
|
### 信号量
|
||||||
|
|
||||||
|
信号量(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 | 重置的信号量的值 |
|
||||||
|
<span id="mutex"></span>
|
||||||
|
|
||||||
|
### 互斥量
|
||||||
|
|
||||||
|
互斥量(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 |
|
||||||
|
<span id="event"></span>
|
||||||
|
|
||||||
|
### 事件集
|
||||||
|
|
||||||
|
事件集(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 |
|
||||||
|
<span id="situation"></span>
|
||||||
|
|
||||||
|
## 使用场景
|
||||||
|
|
||||||
|
* 在多处理器设备上,多个任务可以并行运行,从而提高处理器的利用率。
|
||||||
|
* 在一些中断驱动的应用中,如果中断需要处理的工作过于复杂,则可以创建一个任务专门用于处理相关工作,从而改善中断延迟。
|
|
@ -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`。</br>
|
|
||||||
| 参数 | 描述 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| mq | 消息队列对象指针 |
|
|
||||||
| name | 消息队列名称 |
|
|
||||||
| msgpool | 指向存放消息的内存空间的指针 |
|
|
||||||
| msg_size | 一条消息的最大长度 |
|
|
||||||
| pool_size | 存放消息的内存区大小 |
|
|
||||||
| flag | 消息队列采用的等待方式,可取FIFO或PRIO |
|
|
||||||
</br>
|
|
||||||
|
|
||||||
```C
|
|
||||||
xs_err_t xs_DetachMessageQueue(xs_messagequeue_t mq)
|
|
||||||
```
|
|
||||||
该函数用于将一个静态消息队列从消息队列管理列表中移除。移除成功则返回`XS_OK`。</br>
|
|
||||||
| 参数 | 描述 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| mq | 消息队列对象指针 |
|
|
||||||
</br>
|
|
||||||
|
|
||||||
```C
|
|
||||||
xs_messagequeue_t xs_CreateMessageQueue(const char *name,
|
|
||||||
xs_size_t msg_size,
|
|
||||||
xs_size_t max_msgs,
|
|
||||||
xs_uint8 flag)
|
|
||||||
```
|
|
||||||
该函数用于动态创建一个消息队列,并将消息队列加入消息队列管理列表。</br>
|
|
||||||
| 参数 | 描述 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| name | 消息队列名称 |
|
|
||||||
| msg_size | 缓冲区的大小 |
|
|
||||||
| max_msgs | 一条消息的最大长度 |
|
|
||||||
| flag | 消息队列采用的等待方式,可取FIFO或PRIO |
|
|
||||||
</br>
|
|
||||||
|
|
||||||
```C
|
|
||||||
xs_err_t xs_DeleteMessageQueue(xs_messagequeue_t mq)
|
|
||||||
```
|
|
||||||
该函数用于将由`xs_CreateMessageQueue`创建的消息队列从消息队列管理列表中删除。</br>
|
|
||||||
| 参数 | 描述 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| mq | 消息队列对象指针 |
|
|
||||||
</br>
|
|
||||||
|
|
||||||
```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`。</br>
|
|
||||||
|
|
||||||
| 参数 | 描述 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| mq | 消息队列对象指针 |
|
|
||||||
| buffer | 消息内容 |
|
|
||||||
| size | 消息大小 |
|
|
||||||
| timeout | 超时时间 |
|
|
||||||
</br>
|
|
||||||
|
|
||||||
```C
|
|
||||||
xs_err_t xs_MessageQueueSend(xs_messagequeue_t mq, const void *buffer, xs_size_t size)
|
|
||||||
```
|
|
||||||
该函数是timeout为0的`xs_MessageQueueSendwait`。
|
|
||||||
</br>
|
|
||||||
|
|
||||||
| 参数 | 描述 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| mq | 消息队列对象指针 |
|
|
||||||
| buffer | 消息内容 |
|
|
||||||
| size | 消息大小 |
|
|
||||||
</br>
|
|
||||||
|
|
||||||
```C
|
|
||||||
xs_err_t xs_MessageQueueUrgentSend(xs_messagequeue_t mq, const void *buffer, xs_size_t size)
|
|
||||||
```
|
|
||||||
|
|
||||||
发送紧急消息和发送普通消息的区别是:当发送紧急消息时,从空闲消息链表上取下来的消息块不是挂到消息队列的队尾,而是挂到队首,这样,接收者就能够优先接收到紧急消息,从而及时进行消息处理。</br>
|
|
||||||
|
|
||||||
| 参数 | 描述 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| mq | 消息队列对象指针 |
|
|
||||||
| buffer | 消息内容 |
|
|
||||||
| size | 消息大小 |
|
|
||||||
</br>
|
|
||||||
|
|
||||||
```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`。
|
|
||||||
</br>
|
|
||||||
|
|
||||||
| 参数 | 描述 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| mq | 消息队列对象指针 |
|
|
||||||
| buffer | 消息内容 |
|
|
||||||
| size | 消息大小 |
|
|
||||||
| timeout | 超时时间 |
|
|
||||||
</br>
|
|
||||||
|
|
||||||
```C
|
|
||||||
xs_err_t xs_CmdControlMessageQueue(xs_messagequeue_t mq, int cmd, void *arg)
|
|
||||||
```
|
|
||||||
该函数用于获取或设置消息队列的其他属性。目前当cmd == XS_LINKLIST_CMD_RESET时,重新初始化消息队列。
|
|
||||||
</br>
|
|
||||||
|
|
||||||
| 参数 | 描述 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| mq | 消息队列对象指针 |
|
|
||||||
| cmd | 需要执行的命令 |
|
|
||||||
| arg | 命令的参数 |
|
|
||||||
</br>
|
|
||||||
|
|
||||||
## 管道
|
|
|
@ -0,0 +1 @@
|
||||||
|
# 节拍机制
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
# ARM
|
|
@ -1 +1 @@
|
||||||
# 三菱
|
# RISC-V
|
|
@ -1 +0,0 @@
|
||||||
# 西门子
|
|
|
@ -0,0 +1 @@
|
||||||
|
# RISC-V 软核
|
|
@ -1 +0,0 @@
|
||||||
# 施耐德
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# 自研终端
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
* [aiit_arm](/doc/selfterminal/aiit-arm.md)
|
||||||
|
|
||||||
|
* [aiit_riscv](/doc/selfterminal/aiit-riscv.md)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
# aiit-arm
|
|
@ -0,0 +1 @@
|
||||||
|
# aiit-riscv
|
|
@ -18,3 +18,5 @@
|
||||||
|
|
||||||
- [声音传感器](/doc/sensor/voice_sensor.md)
|
- [声音传感器](/doc/sensor/voice_sensor.md)
|
||||||
|
|
||||||
|
- [图像传感器](/doc/sensor/image_sensor.md)
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,41 @@
|
||||||
|
# 图像传感器
|
||||||
|
|
||||||
|
## 传感器介绍
|
||||||
|
|
||||||
|
| 传感器信号 | 传感器说明 | 驱动支持 | 传感器外形 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| OV7670 | 最大支持 40x480,30万像素,不支持 JPEG 输出,不支持自动对焦 | 已支持 |  |
|
||||||
|
| OV2640 | 最大支持 1600x1200,200万像素,支持 JPEG 输出,不支持自动对焦 | 待支持 |  |
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
本系统支持 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);
|
||||||
|
```
|
|
@ -0,0 +1,174 @@
|
||||||
|
# 任务管理
|
||||||
|
|
||||||
|
任务(task)是XiUOS中处理器使用权分配的最小单位。每个任务有自己的程序栈与寄存器上下文,在多处理器平台上可以互不干扰地同时运行,但单个处理器上任意时刻只能有一个任务在运行。用户可以使用XiUOS提供的接口创建任意数量的任务。内核会对系统中的所有任务按照一定策略(抢占式优先级或先来先服务)进行调度,以最大限度地利用处理器资源。用户可以使用XiUOS提供的接口创建任意数量的任务。
|
||||||
|
|
||||||
|
## 任务状态
|
||||||
|
|
||||||
|
系统中的任务在任意时刻都处于就绪(ready)、运行(running)、阻塞/挂起(suspend)、退出(quit)四种状态之一。状态之间的变化关系如下图所示。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
任务在创建完成后会进入就绪状态并被加入就绪队列等待内核调度。当任务被调度开始运行时,任务会进入运行状态。若任务在运行过程中被更高优先级的任务抢占,则被强占的任务会回到就绪队列并再次进入就绪状态。当任务在运行过程中申请资源失败时,任务会被挂起并进入挂起状态,并在所申请资源能够被满足时回到就绪状态。当任务执行完成,即从入口函数返回时,会进入终止状态,并由内核回收其相关资源。
|
||||||
|
|
||||||
|
## 任务调度
|
||||||
|
|
||||||
|
任务调度即从系统就绪队列中按一定策略选择任务,使其进入运行状态的过程。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 | 任务名称 |
|
||||||
|
|
||||||
|
## 使用场景
|
||||||
|
|
||||||
|
* 在多处理器设备上,多个任务可以并行运行,从而提高处理器的利用率。
|
||||||
|
* 在一些中断驱动的应用中,如果中断需要处理的工作过于复杂,则可以创建一个任务专门用于处理相关工作,从而改善中断延迟。
|
Loading…
Reference in New Issue