建立一个 AVR的RTOS(4)—只有延时服务的协作式的内核

发布者:芳华逝水最新更新时间:2016-09-30 来源: eefocus关键字:AVR  RTOS  延时服务  协作式  内核 手机看文章 扫描二维码
随时随地手机看文章
第四篇:只有延时服务的协作式的内核

Cooperative Multitasking

前后台系统,协作式内核系统,与占先式内核系统,有什么不同呢?

记得在21IC上看过这样的比喻,“你(小工)在用厕所,经理在外面排第一,老板在外面排第二。如果是前后台,不管是谁,都必须按排队的次序使用厕所;如果是协作式,那么可以等你用完厕所,老板就要比经理先进入;如果是占先式,只要有更高级的人在外面等,那么厕所里无论是谁,都要第一时间让出来,让最高级别的人先用。”

#include

#include

#include

 

unsigned char Stack[200];

register unsigned char OSRdyTbl asm("r2"); //任务运行就绪表

register unsigned char OSTaskRunningPrio asm("r3"); //正在运行的任务

 

#define OS_TASKS 3 //设定运行任务的数量

 

struct TaskCtrBlock //任务控制块

{

unsigned int OSTaskStackTop; //保存任务的堆栈顶

unsigned int OSWaitTick; //任务延时时钟

} TCB[OS_TASKS+1];

 

//防止被编译器占用

register unsigned char tempR4 asm("r4");

register unsigned char tempR5 asm("r5");

register unsigned char tempR6 asm("r6");

register unsigned char tempR7 asm("r7");

register unsigned char tempR8 asm("r8");

register unsigned char tempR9 asm("r9");

register unsigned char tempR10 asm("r10");

register unsigned char tempR11 asm("r11");

register unsigned char tempR12 asm("r12");

register unsigned char tempR13 asm("r13");

register unsigned char tempR14 asm("r14");

register unsigned char tempR15 asm("r15");

register unsigned char tempR16 asm("r16");

register unsigned char tempR16 asm("r17");

 

//建立任务

void OSTaskCreate(void (*Task)(void),unsigned char *Stack,unsigned char TaskID)

{

unsigned char i;

*Stack--=(unsigned int)Task>>8; //将任务的地址高位压入堆栈,

*Stack--=(unsigned int)Task; //将任务的地址低位压入堆栈,

*Stack--=0x00; //R1 __zero_reg__

*Stack--=0x00; //R0 __tmp_reg__

*Stack--=0x80; //SREG在任务中,开启全局中断

for(i=0;i<14;i++) //在 avr-libc 中的 FAQ中的 What registers are used by the C compiler?

*Stack--=i; //描述了寄存器的作用

TCB[TaskID].OSTaskStackTop=(unsigned int)Stack; //将人工堆栈的栈顶,保存到堆栈的数组中

OSRdyTbl|=0x01<

}

 

//开始任务调度,从最低优先级的任务的开始

void OSStartTask()

{

OSTaskRunningPrio=OS_TASKS;

SP=TCB[OS_TASKS].OSTaskStackTop+17;

__asm__ __volatile__( "reti" "\n\t" );

}

 

//进行任务调度

void OSSched(void)

{

// 根据中断时保存寄存器的次序入栈,模拟一次中断后,入栈的情况

__asm__ __volatile__("PUSH __zero_reg__ \n\t"); //R1

__asm__ __volatile__("PUSH __tmp_reg__ \n\t"); //R0

__asm__ __volatile__("IN __tmp_reg__,__SREG__ \n\t"); //保存状态寄存器SREG

__asm__ __volatile__("PUSH __tmp_reg__ \n\t");

__asm__ __volatile__("CLR __zero_reg__ \n\t"); //R0重新清零

__asm__ __volatile__("PUSH R18 \n\t");

__asm__ __volatile__("PUSH R19 \n\t");

__asm__ __volatile__("PUSH R20 \n\t");

__asm__ __volatile__("PUSH R21 \n\t");

__asm__ __volatile__("PUSH R22 \n\t");

__asm__ __volatile__("PUSH R23 \n\t");

__asm__ __volatile__("PUSH R24 \n\t");

__asm__ __volatile__("PUSH R25 \n\t");

__asm__ __volatile__("PUSH R26 \n\t");

__asm__ __volatile__("PUSH R27 \n\t");

__asm__ __volatile__("PUSH R30 \n\t");

__asm__ __volatile__("PUSH R31 \n\t");

__asm__ __volatile__("PUSH R28 \n\t"); //R28与R29用于建立在堆栈上的指针

__asm__ __volatile__("PUSH R29 \n\t"); //入栈完成

 

TCB[OSTaskRunningPrio].OSTaskStackTop=SP; //将正在运行的任务的堆栈底保存

 

unsigned char OSNextTaskID; //在现有堆栈上开设新的空间

for (OSNextTaskID = 0; //进行任务调度

OSNextTaskID < OS_TASKS && !(OSRdyTbl & (0x01<

OSNextTaskID++);

OSTaskRunningPrio = OSNextTaskID ;

 

cli(); //保护堆栈转换

SP=TCB[OSTaskRunningPrio].OSTaskStackTop;

sei();

 

//根据中断时的出栈次序

__asm__ __volatile__("POP R29 \n\t");

__asm__ __volatile__("POP R28 \n\t");

__asm__ __volatile__("POP R31 \n\t");

__asm__ __volatile__("POP R30 \n\t");

__asm__ __volatile__("POP R27 \n\t");

__asm__ __volatile__("POP R26 \n\t");

__asm__ __volatile__("POP R25 \n\t");

__asm__ __volatile__("POP R24 \n\t");

__asm__ __volatile__("POP R23 \n\t");

__asm__ __volatile__("POP R22 \n\t");

__asm__ __volatile__("POP R21 \n\t");

__asm__ __volatile__("POP R20 \n\t");

__asm__ __volatile__("POP R19 \n\t");

__asm__ __volatile__("POP R18 \n\t");

__asm__ __volatile__("POP __tmp_reg__ \n\t"); //SERG 出栈并恢复

__asm__ __volatile__("OUT __SREG__,__tmp_reg__ \n\t"); //

__asm__ __volatile__("POP __tmp_reg__ \n\t"); //R0 出栈

__asm__ __volatile__("POP __zero_reg__ \n\t"); //R1 出栈

//中断时出栈完成

}

 

void OSTimeDly(unsigned int ticks)

{

if(ticks) //当延时有效

{

OSRdyTbl &= ~(0x01<

TCB[OSTaskRunningPrio].OSWaitTick=ticks;

OSSched(); //从新调度

}

}

 

void TCN0Init(void) // 计时器0

{

TCCR0 = 0;

TCCR0 |= (1<

TIMSK |= (1<

TCNT0 = 100; // 置计数起始值

}

 

SIGNAL(SIG_OVERFLOW0)

{

unsigned char i;

 

for(i=0;i

{

if(TCB[i].OSWaitTick)

{

TCB[i].OSWaitTick--;

if(TCB[i].OSWaitTick==0) //当任务时钟到时,必须是由定时器减时的才行

{

OSRdyTbl |= (0x01<

}

}

}

 

TCNT0=100;

}

 

void Task0()

{

unsigned int j=0;

 

while(1)

{

PORTB=j++;

OSTimeDly(2);

}

}

 

void Task1()

{

unsigned int j=0;

 

while(1)

{

PORTC=j++;

OSTimeDly(4);

}

}

 

void Task2()

{

unsigned int j=0;

 

while(1)

{

PORTD=j++;

OSTimeDly(8);

}

}

 

void TaskScheduler()

{

while(1)

{

OSSched(); //反复进行调度

}

}

 

int main(void)

{

TCN0Init();

OSRdyTbl=0;

OSTaskRunningPrio=0;

OSTaskCreate(Task0,&Stack[49],0);

OSTaskCreate(Task1,&Stack[99],1);

OSTaskCreate(Task2,&Stack[149],2);

OSTaskCreate(TaskScheduler,&Stack[199],OS_TASKS);

OSStartTask();

}

在上面的例子中,一切变得很简单,三个正在运行的主任务,都通过延时服务,主动放弃对CPU的控制权。

在时间中断中,对各个任务的的延时进行计时,如果某个任务的延时结束,将任务重新在就绪表中置位。

最低级的系统任务TaskScheduler(),在三个主任务在放弃对CPU的控制权后开始不断地进行调度。如果某个任务在就绪表中置位,通过调度,进入最高级别的任务中继续运行。

关键字:AVR  RTOS  延时服务  协作式  内核 引用地址:建立一个 AVR的RTOS(4)—只有延时服务的协作式的内核

上一篇:建立一个AVR的RTOS(5)—完善的协作式的内核
下一篇:建立一个AVR的RTOS(3)—GCC中对寄存器的分配与使用

推荐阅读最新更新时间:2024-03-16 15:12

可编程数字电位器在AVR单片机中的应用
1 引言    AVR 嵌入式单片机具有丰富的硬件、软件资源,其中的串行I2C接口能满足很多应用场合的要求,两个 AVR 单片机通过I2C总线直接连接就可实现单片机相互通信; AVR 单片机还可以和任何具有I2C总线接口的外设直接连接而无须其它硬件电路支持。而X9221系列可编程数字电位器在智能测试设备上应用非常广泛,通过I2C总线可以简单地构成单片机与各种外设之间乃至与计算机之间的通信,建立友好的人机界面联系。硬件设计简单、灵活,只需要将所有设备的SDA和SCL信号线分别并联在一起并加上拉电阻即可,有助于提高设备的自动化水平、可靠性、稳定性及电气装配的工艺性。 AVR 单片机和X9221系列可编程数字电位器都有内置的E2ROM
[单片机]
基于Small RTOS51的数据采集器设计
摘要:介绍如何运用Small RTOS51多任务操作系统进行嵌入式控制器的软件设计。首先介绍Small RTOS51多任务操作系统,然后介绍基于该操作系统进行数据采集器软件系统的设计。 关键词:Small RTOS51 多任务操作系统 数据采集器 引 言   随着嵌入式系统的发展,嵌入式软件设计向软件平台靠近,单片机软件设计不再是单一线程结构方式,而是逐步采用多任务的设计思想。实时内核也称为实时操作系统或RTOS。它使得实时应用程序的设计、扩展和维护变得更容易,不需要大的改动就可以增加新的功能。通过应用程序分割成若干独立的任务,RTOS使得应用程序的设计过程大为简化。使用可剥夺性内核时,所有时间要求苛刻的事件都得到了尽可能快
[应用]
AVR单片机对电子时钟的设计
#include #include #include #include #defineucharunsignedchar #defineuintunsignedint #definextal8 #defineCSPA5 #defineSIDPA6 #defineSCLKPA7 #defineSet_CS()DDRA|=(1《#defineSet_SID()DDRA|=(1《#defineSet_SCLK()DDRA|=(1《 #defineClr_CS()DDRA|=(1《#defineClr_SID()DDRA|=(1《#defineClr_SCLK()DDRA|=(1《 #defineHH2//定义时为2 #define
[单片机]
<font color='red'>AVR</font>单片机对电子时钟的设计
avr中把大数据放入flash中的方法
GCC中把大数组存入flash区的方法大全 AVRGCC中将变量定义在flash空间的方法(大数据存储) (1)flash常量: #include avrpgmspace.h //须增加的头文件 const prog_uchar FlashConst = 3; //定义uchar型的常量n定义在flash里(flash常量) unsigned char RamVar; //定义无符号整型变量(Ram变量) RamVar = pgm_read_byt
[单片机]
用VMLAB进行AVR单片机硬件/软件协仿真
前言 在单片机应用开发过程中,当源文件的编译成功后,就要进行仿真调试工作。仿真调试可分为两大类--芯片级仿真和代码级仿真。芯片级仿真是指使用仿真软件和ICE硬件工具相配合,在实际硬件上进行仿真调试工作;而代码级仿真则完全在计算机上完成,不需要硬件的参与。两种类型的仿真各有特点,使用的场合不同。本文基于VMLAB,讲述了进行AVR单片机硬件/软件协同仿真的方法。 VMLAB的全称为:VisualMicroLab。它针对于AVR以及ST62系列单片机设计,是一个单片机的虚拟原型(virtualprototype)框架(frame),它可以提供给用户一个真正意义上的虚拟微控制器(MCU)设计实验室。它具有强大的多窗口、多文件的编辑器
[单片机]
用VMLAB进行<font color='red'>AVR</font>单片机硬件/软件协仿真
AVR AT24C02 程序
/********************************************************************* 目 的: 建立AT24C02操作库 目标系统: 基于AVR单片机 应用软件: ICCAVR *********************************************************************/ /*010101010101010101010101010101010101010101010101010101010101010
[单片机]
将模拟组件与Arm微控制器内核进行集成解决嵌入系统问题
嵌入式系统的设计带来了复杂的挑战,因为在性能,成本,功耗,尺寸,新功能和效率方面都有进步的积极目标。然而,有一种新兴的设计方案可以解决这些复杂问题 - 模拟组件与ARM ®微控制器内核智能集成。这种与传统模拟集成的区别在于现在提供的高性能以及为解决特定系统级问题而进行的优化。虽然每个市场都会对这些领域的订单排名进行改进,但同时满足多个因素是非常需要的,并且可以来自众多分立组件的集成。从逻辑上讲,组合部件可以解决许多嵌入式系统目标,但只需将几个分立元件和一个处理器放在一个封装中就不是答案;解决方案要复杂得多,需要智能集成。 模拟和数字智能集成 高性能模拟组件(放大器,ADC,DAC,电压基准,温度传感器)的智能集成,无线收发器等
[单片机]
将模拟组件与Arm微控制器<font color='red'>内核</font>进行集成解决嵌入<font color='red'>式</font>系统问题
用FPGA搭建一个STM32内核
1.必要的基础知识 为了更快的完成在FPGA上实现ARM Cortex-M3软核,一些必要的基础知识还是要有的! FPGA开发基础知识,如FPGA开发流程,设计、综合、布局、布线、约束、下载 Xilinx Vivado开发环境使用基础,如BlockDesign设计方式,管脚分配,Bit流文件生成与下载 ARM Cortex-M3内核的使用基础,如STM32、MM32、GD32、CH32等微控制器的开发。 Keil-MDK开发环境的使用基础,基本的工程建立、编译、下载流程。 如果以上知识都具备,那么,恭喜你!可以在2小时内完成ARM Cortex-M3软核在FPGA上的实现。 2.Cortex-M3 FPGA IP核下载 首先,
[单片机]
用FPGA搭建一个STM32<font color='red'>内核</font>?
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved