轮询
所有事件都是主循环中的函数调用
void main(void) {
while(TRUE) {
if (device_A requires service)
service device_A
if (device_B requires service)
service device_B
if (device_C requires service)
service device_C
...
}
}
通过调整轮询的顺序和频率,我们可以调整任务的优先级。
优先级:无优先级,所有事件顺序执行
响应时间:所有任务的总和
变化的影响:非常大,其会影响其他所有任务
结构十分简单,没有共享数据的问题。
看门狗
一种任务机制,设置一个看门狗监视任务,如果长时间没有触发这个任务就会触发看门狗的重置任务。
状态机
将系统视为状态机,在循环中根据状态进行计算与状态转移
while(1) {
switch(state) {
case IDLE:
check_buttons();
LEDisplay_hex(NUM1);
if (BUTTON1 | BUTTON2 | BUTTON3)
state=SHOW;
break;
case SHOW:
NUM1=0;
if (BUTTON1) NUM1 += 0x0001;
if (BUTTON2) NUM1 += 0x0010;
if (BUTTON3) NUM1 += 0x0100;
state=IDLE;
break;
}
}
与轮询类似,但只有状态对应程序才执行。
每个状态决定下一个状态(非顺序执行)。
优先级:每个状态决定下一个状态的优先级
响应时间:所有任务的总和
变化的影响:非常大,其会影响其他所有任务
结构十分简单,没有共享数据的问题。
带中断的轮询
在轮询中加入中断机制。
BOOL flag_A = FALSE; /* Flag for device_A follow-up processing */
/* Interrupt Service Routine for high priority device_A */
ISR_A(void) {
... handle urgent requirements for device_A in the ISR,
then set flag for follow-up processing in the main loop ...
flag_A = TRUE;
}
void main(void) {
while(TRUE) {
if (flag_A)
flag_A = FALSE
... do follow-up processing with data from device_A
if (device_B requires service)
service device_B
if (device_C requires service)
service device_C
... and so on until all high and low priority devices have been serviced
}
}
实例是前后台系统
优先级:中断优先级高于主循环
响应时间:所有任务的总和或中断响应时间
变化带来的影响:ISR部分较低,主循环部分和轮询一样。
共享数据:需要处理ISR的数据共享
纯中断
所有任务都由中断表现。
SET_VECTOR(P3AD, button_isr);
SET_VECTOR(TIMER1, display_isr);
while(1) {
;
}
当ISR太多时会产生问题。
如果高优先级任务比低优先级任务时间长,会导致一些中断被忽视,除非选择处理嵌套中断
优先级:中断优先级
响应时间:中断执行时间
变化带来的影响:低
共享数据:需要处理ISR的数据共享
函数队列
将函数指针加入队列中,然后主循环遍历队列来执行任务。新的任务和中断会往队列添加任务、
main() {
LEDisplay_init();
LEDisplay_clear();
init_buttons();
add_task(button_task);
while(1) {
if(tasks[current_task]==NULL) {
;
}
else {
(*tasks[current_task])();
tasks[current_task]=NULL;
}
current_task++;
if(current_task>=MAX_TASKS) current_task=0;
}
}
优先级:中断有优先级,任务是顺序执行
响应时间:最长任务的执行时间
变化带来的影响:低。中断管理优先级函数,队列管理低优先级。
共享数据:需要处理ISR的数据共享
多线程
使用基于时钟的任务切换程序,可以看作是有一个操作系统内核。
共享数据需要使用同步策略,包括消息队列、信号量或无阻塞设计等。
微内核与宏内核
微内核
内核只提供内存分配、线程切换等基本功能。用户进程实现文件系统、网络接口等主要功能。
当任务切换和任务通信很快时,微内核效果很好,但反之则效果不好。
宏内核
内核完成了基本所有的功能