搜索
bottom↓
回复: 6

Mega16的简单多线程OS

[复制链接]

出10入23汤圆

发表于 2013-6-9 14:58:38 | 显示全部楼层 |阅读模式
本帖最后由 zouzhichao 于 2013-6-9 15:01 编辑

代码如下,4个线程

#include <avr\io.h>
#include <avr\interrupt.h>
#include <util\delay.h>

#define int8_ char
#define uint8_ unsigned char
#define int16_ short
#define uint16_ unsigned short
#define int32_ long
#define uint32_ unsigned long

#define PUSH()\
{\
        asm volatile(\
        "push r2\n\t"\
        "push r3\n\t"\
        "push r4\n\t"\
        "push r5\n\t"\
        "push r6\n\t"\
        "push r7\n\t"\
        "push r8\n\t"\
        "push r9\n\t"\
        "push r10\n\t"\
        "push r11\n\t"\
        "push r12\n\t"\
        "push r13\n\t"\
        "push r14\n\t"\
        "push r15\n\t"\
        "push r16\n\t"\
        "push r17\n\t"\
        "push r19\n\t"\
        "push r26\n\t"\
        "push r27\n\t"\
        "push r28\n\t"\
        "push r29\n\t"\
         : : );\
}

#define POP()\
{\
        asm volatile(\
        "pop r29\n\t"\
        "pop r28\n\t"\
        "pop r27\n\t"\
        "pop r26\n\t"\
        "pop r19\n\t"\
        "pop r17\n\t"\
        "pop r16\n\t"\
        "pop r15\n\t"\
        "pop r14\n\t"\
        "pop r13\n\t"\
        "pop r12\n\t"\
        "pop r11\n\t"\
        "pop r10\n\t"\
        "pop r9\n\t"\
        "pop r8\n\t"\
        "pop r7\n\t"\
        "pop r6\n\t"\
        "pop r5\n\t"\
        "pop r4\n\t"\
        "pop r3\n\t"\
        "pop r2\n\t"\
         : : );\
}

#define OsTaskStateSave(pTask)\
{\
        PUSH();\
        (pTask)->StackPoint = (uint8_*)SP;\
}

#define OsTaskStateLoad(pTask)\
{\
        SP = (uint16_)((pTask)->StackPoint);\
        POP();\
}

#define OsTaskRun(pTask)\
{\
        SP = (uint16_)((pTask)->StackPoint);\
        POP();\
        asm volatile(\
        "pop r31\n\t"\
        "pop r30\n\t"\
        "pop r25\n\t"\
        "pop r24\n\t"\
        "pop r23\n\t"\
        "pop r22\n\t"\
        "pop r21\n\t"\
        "pop r20\n\t"\
        "pop r18\n\t"\
        "pop r0\n\t"\
        "out __SREG__, r0\n\t"\
        "pop r0\n\t"\
        "pop r1\n\t"\
        : : );\
        return;\
}

typedef struct tagTASK
{
        int8_ (*TaskFunction)(int16_ Para);
        uint8_* StackPoint;
        uint8_ Stack[128];
        uint8_ Flag;
}TASK;

int8_ OsTaskInit(int8_ (*TaskFun)(int16_ Para), int16_ TaskFunPara, TASK *Task)
{
        Task->TaskFunction = TaskFun;
        Task->StackPoint = (uint8_*)Task->Stack + sizeof(Task->Stack) - 1;
        *(Task->StackPoint--) = (uint8_)((uint16_)(Task->TaskFunction)); /* Put task start address on top of stack */
    *(Task->StackPoint--) = (uint8_)(((uint16_)(Task->TaskFunction)) >> 8);
        *(Task->StackPoint--) = 0x00; /* R1 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R0 = 0x00 */
        *(Task->StackPoint--) = 0x80; /* SREG = Interrupts enabled */
        *(Task->StackPoint--) = 0x00; /* R18 = 0x00 */
        *(Task->StackPoint--) = 0x00; /* R20 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R21 = 0x00 */
        *(Task->StackPoint--) = 0x00; /* R22 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R23 = 0x00 */
    *(Task->StackPoint--) = (uint8_)TaskFunPara; /* Simulate call to function with argument */
    *(Task->StackPoint--) = (uint8_)(TaskFunPara >> 8);        /* R24, R25 contains argument pointer pdata */
        *(Task->StackPoint--) = 0x00; /* R30 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R31 = 0x00 */
        *(Task->StackPoint--) = 0x00; /* R2 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R3 = 0x00 */
        *(Task->StackPoint--) = 0x00; /* R4 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R5 = 0x00 */
        *(Task->StackPoint--) = 0x00; /* R6 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R7 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R8 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R9 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R10 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R11 = 0x00 */
        *(Task->StackPoint--) = 0x00; /* R12 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R13 = 0x00 */
        *(Task->StackPoint--) = 0x00; /* R14 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R15 = 0x00 */
        *(Task->StackPoint--) = 0x00; /* R16 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R17 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R19 = 0x00 */
        *(Task->StackPoint--) = 0x00; /* R26 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R27 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R28 = 0x00 */
    *(Task->StackPoint--) = 0x00; /* R29 = 0x00 */
        return 0;
}


int8_ OsTickInit(void)
{
        cli(); //disable all interrupts
        TCCR0 = 0x00; //stop
        TCNT0 = 0x00; //set count
        OCR0  = 0x0E;  //set compare
        TCCR0 = 0x05; //start timer
        MCUCR = 0x00;
        GICR  = 0x00;
        TIMSK = 0x01; //timer interrupt sources
        sei(); //re-enable interrupts
        return 0;
}

int8_ TaskFun0(int16_ Para)
{
        for ( ; ; )
        {
                _delay_us(20);
                PORTA ^= 0x01;
        }
        return 0;
}

int8_ TaskFun1(int16_ Para)
{
        for ( ; ; )
        {
                _delay_us(20);
                PORTA ^= 0x02;
        }
        return 0;
}

int8_ TaskFun2(int16_ Para)
{
        for ( ; ; )
        {
                _delay_us(20);
                PORTA ^= 0x04;
        }
        return 0;
}

int8_ TaskFun3(int16_ Para)
{
        for ( ; ; )
        {
                _delay_us(20);
                PORTA ^= 0x08;
        }
        return 0;
}

static TASK Task[4];
static uint8_t ID = 0;
int main()
{
        DDRA |= 0xff;
        PORTA ^= 0xff;
        OsTaskInit(TaskFun0, 10, &Task[0]);
        OsTaskInit(TaskFun1, 1, &Task[1]);
        OsTaskInit(TaskFun2, 2, &Task[2]);
        OsTaskInit(TaskFun3, 3, &Task[3]);
        OsTickInit();
        OsTaskRun(&Task[0]);
        for ( ; ; )
                ;
        return 0;
}

ISR(TIMER0_OVF_vect)
{
        OsTaskStateSave(&Task[ID]);
        if (4 == ++ID)
                ID = 0;
        OsTaskStateLoad(&Task[ID]);
}

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

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2013-6-9 15:12:02 来自手机 | 显示全部楼层
SREG也需要保存的。
SP指针因为是双字节的,切换时必须屏蔽中断。

出10入23汤圆

 楼主| 发表于 2013-6-9 15:14:06 | 显示全部楼层
本帖最后由 zouzhichao 于 2013-6-9 15:17 编辑
mitchell 发表于 2013-6-9 15:12
SREG也需要保存的。
SP指针因为是双字节的,切换时必须屏蔽中断。


后面那句是对的,我考虑不周
前一句你说的是对的,但是我也已经保护了SREG了,只是你没看到

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出10入23汤圆

 楼主| 发表于 2013-6-9 15:23:29 | 显示全部楼层
mitchell 发表于 2013-6-9 15:12
SREG也需要保存的。
SP指针因为是双字节的,切换时必须屏蔽中断。

R0,R1,SREG,R18,R20,R21,R22,R23,R24,R25,R30,R31的保护是中断时编译器生成的代码实现的,PUSH()源代码里不是直接可见

出0入0汤圆

发表于 2013-6-9 15:24:46 来自手机 | 显示全部楼层
zouzhichao 发表于 2013-6-9 15:14
后面那句是对的,我考虑不周
前一句你说的是对的,但是我也已经保护了SREG了,只是你没看到
...

嗯,进入中断时自动保存的。
如果只在中断里进行调度,sp切换也不要关中断,因为reti之前中断本来就关着的,哈哈。

出10入23汤圆

 楼主| 发表于 2013-6-9 15:29:18 | 显示全部楼层
mitchell 发表于 2013-6-9 15:24
嗯,进入中断时自动保存的。
如果只在中断里进行调度,sp切换也不要关中断,因为reti之前中断本来就关着 ...

这个有点投机取巧了,十分依赖编译器编译出来的代码,我是一边写,一边看编译出来的汇编代码写的,换了别的环境或者开优化,很可能就是错的了,并且中断里面的东西不能随便乱加
如果完全用汇编写中断处理代码就不会有这问题了,我这是取的对C语言动刀尽可能小的方式去实现

出10入23汤圆

 楼主| 发表于 2013-6-9 15:32:56 | 显示全部楼层
除了几个PUSH,POP之外,没有动用别的汇编代码,尽可能地用C实现
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-7-23 09:23

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

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