|
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周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|