搜索
bottom↓
回复: 11

a simple multi-tasking "operating system" for microcontrollers

[复制链接]

出0入0汤圆

发表于 2010-8-29 09:08:13 | 显示全部楼层 |阅读模式
sometimes, we really need to run multiple pieces of code on one mcu and that can get tricky.

implemented below is a quick piece of code that utilizes a timer interrupt + a state machine to dynamically switch up to 255 tasks (including an optional idle process), implemented on a 8051 but can be easily migrated to other mcus as well.

here is the code, for the basic shells:

=========code=============
//a simple multi-tasking OS
//each task has a pre-define time slot (XOS_slot), + an idle slot
//user can add up to 255 tasks (including the idle task).
//each task has to take less than the time slot to finish.
//the os uses tmr0 so no task can utilize tmr0

#include <REGX51.H>
#include "gpio.h"

//XOS configuration
//#define XOS_STATE_MAX        4    //max number of state
unsigned char XOS_state;    //xos state indicator
unsigned char XOS_state_prev;          //previous state
unsigned short XOS_slot;    //xos time slot, in terms of timer ticks (1tick=1us for 12Mhz xtal)

void XOS_isr(void) interrupt 1 {  //xos interrupt on tmr0
TF0=0;        //clear flag - done by hardware
TH0=0xff-(XOS_slot >> 8);          //reset th0
TL0=0xff-(XOS_slot & 0x00ff);  //reset tlo
//XOS_state=(XOS_state==XOS_STATE_MAX)? 0: XOS_state+1;        //update state indicator
XOS_state++;      //increment XOS_state;
}

void XOS_init(unsigned short slot) {            //initiate xos
//set tmr0 to 16 bit timer operation (mode 1)
TMOD &= 0xf0;      //clear tmod's lower 4 bits
TMOD |= 0x01;      //not gated, tmr operation, mode 1
TF0=0;        //clear flag - done by hardware

//define slot size, in tmr ticks
XOS_slot=slot;      //define xos time slot

//set tmr0
TH0=0xff-(XOS_slot >> 8);          //reset th0
TL0=0xff-(XOS_slot & 0x00ff);  //reset tlo

//set interrupt
ET0=1;        //enable tmr0 interrupt
EA=1;        //enable all  interrupt
TR0=1;        //turn on tmr0

//set XOS state variables
XOS_state=0;      //reset xos_state
XOS_state_prev=XOS_state;          //reset xos_state_prev
}
//end XOS configuration

//define XOS port / pin definitions
#define TASK_PORT  P2
#define TASK_DDR  P2
#define TASK0          (1<<0)          //p2.0
#define TASK1          (1<<2)          //p2.2
#define TASK2          (1<<6)          //p2.5       

void mcu_init(void) {            //initiate the mcu
IO_CLR(TASK_PORT, TASK0 | TASK1 | TASK2);  //clear task pins
IO_OUT(TASK_DDR, TASK0 | TASK1 | TASK2);  //task pins as output
}

//dummy tasks
void XOS_task0(void) {
IO_FLP(TASK_PORT, TASK0);          //flip task0 one
}

void XOS_task1(void) {
IO_FLP(TASK_PORT, TASK1);          //flip task1 one
//IO_FLP(TASK_PORT, TASK1);          //flip task1 one
}

void XOS_task2(void) {
IO_FLP(TASK_PORT, TASK2);          //flip task2 one
//IO_FLP(TASK_PORT, TASK2);          //flip task2 one
//IO_FLP(TASK_PORT, TASK2);          //flip task2 one
}


int main(void) {
mcu_init();              //initiate the mcu
XOS_init(10000);            //time slot to be 10ms

while (1) {
switch (XOS_state) {
        case 0:  XOS_task0(); break;  //run task0
        case 1:  XOS_task1(); break;  //run task1
        case 2:  XOS_task2(); break;  //run task2
        //add additional user tasks
        default:        XOS_state=0; break;  //reset XOS_state
}
//idle till the next tmr0 interrupt
while (XOS_state == XOS_state_prev) continue;
XOS_state_prev=XOS_state;    //update xos_state_prev
}
}
===========end code===============

here, we have time slots of 10ms (for each task), and three tasks (XOS_task0/1/2), + an idle process - which you can program out.

each of the tasks here simple flips certain leds. the time slots can be from a few us to up to 64K (we use 16-bit timer here).

all you need to do is to implement your own XOS_tasks0/1/2, or add / delete tasks in the switch() statement, and define the time slot in the XOS_init() process.

simple enough?

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2010-8-29 09:17:57 | 显示全部楼层
the above example is just a demo. it compiles to just over 160 bytes, with the overhead. so it can be implemented quite efficiently even on smaller mcus.

here is a more realistic implementation, with sub state machines for some of the tasks.
点击此处下载 ourdev_578497.rar(文件大小:14K) (原文件名:C51 XOS LCD.rar)

it contains the code, proteus sim, and the .hex file.

this is an example where we have 10ms slots, and four tasks. two of the tasks flip LEDs on P0 @ 4s intervals and P1 @ 40ms intervals; one task simulates adc (once every 6x40ms), and another one displays the result of the adc on a lcd, once every 8x40ms.

to naked eyes, it is as if the mcu is simultaneously processing all the tasks.



(原文件名:XOS 3.PNG)

出0入0汤圆

 楼主| 发表于 2010-8-29 09:26:42 | 显示全部楼层
the approach I have taken so far is to run each task at a pre-determined interval. it has the advantage of predictable execution: each task is executed at exactly the same slot.

an alternative approach is to start the next task once the previous task has finished. After all tasks have ended, we can idle the mcu. This approach is more efficient, but offers uncertain timing for task execution.

you can easily implement the 2nd approach if you wish - it is actually simpler to implement.

出0入0汤圆

 楼主| 发表于 2010-8-29 09:27:15 | 显示全部楼层
BTW, the 2nd code compiles to about 1.6K bytes under Keil.

出0入0汤圆

 楼主| 发表于 2010-8-29 09:29:35 | 显示全部楼层
a "HUGE" limitation of this "operating system" (task scheduler is probably a better name) is that each task has to finish within the time slot - because this "operating system" does not have any context saving / loading capabilities.

so it is going to be quite inefficient if your tasks have wildly different timing profile.

出0入0汤圆

 楼主| 发表于 2010-8-29 09:30:37 | 显示全部楼层
portability: this code should be very easily to port to other systems as the only "hardware" specific portion of the code is in the setting up the timer and the timer interrupt service routine.

everything else is 100% C.

出0入0汤圆

发表于 2010-8-29 09:36:13 | 显示全部楼层
也许可以和djyos的罗老大沟通沟通

出0入0汤圆

发表于 2010-8-29 09:43:37 | 显示全部楼层
mk

出0入0汤圆

发表于 2010-8-29 10:43:06 | 显示全部楼层
高手啊!学习了

出0入0汤圆

发表于 2010-8-29 11:15:59 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2010-8-29 11:24:32 | 显示全部楼层
Time trig sys

出0入0汤圆

 楼主| 发表于 2010-8-29 18:39:26 | 显示全部楼层
I just implemented this on a PIC12F675. the "OS" itself takes less than 100 bytes!

with three processes + 1 idle process, blinking leds at different rates, I was using just 1/4 of the flash space on the chip.

pretty amazing.


(原文件名:XOS 12F675 1.PNG)
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-16 04:34

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表