μC/OS-II就绪表算法在ARM架构上的改动

发布者:渤海湾最新更新时间:2021-04-30 来源: eefocus关键字:μC  OS-II  就绪表算法  ARM架构 手机看文章 扫描二维码
随时随地手机看文章

引言

μC/OSII的就绪表设置、清除、查找算法,是高效的、跨平台的程序。它使用了两个查找数组OSMapTbl[8]和OSUnMapTbl[256],以提高查找就绪表的速度,尽快获取就绪任务的最高优先级。


CortexM3是ARM公司较新的一种架构版本,主要应用在单片机领域。基于它生产的32位芯片日益增多;CortexM3只支持Thumb2指令集,在效能和代码密度间能取得更佳的表现。


1在ARM上改动算法的因由利弊

由于就绪表操作是在关中断状态下运行的,其执行影响到系统的中断响应时间,因此就绪表操作算法的效率是衡量实时操作系统优劣的基准之一。


在CortexM3所用的指令集中,一些指令功能不可小觑,如前导零计数clz、字内位反转rbit、位清除bic。其中的clz和bic为μC/OS就绪表的高优先级获取算法指出了另一条道路。


(1) 改动后的优势

① 节省存储空间。不再使用查找数组OSMapTbl[8]和OSUnMapTbl[256]。设立这两个数组的目的,是为了提高查找就绪表的效率。

② 提升查找效率。clz是单周期指令,使用带移位的加法指令,大幅缩短运算时间。

③ 增加了μC/OSII支持的任务数量,从64提升到了1 024(2.84版支持的任务数量已经到了256,不过效率有所下降)。

(2) 存在的不足

① Realview MDK(这里使用的是3.20版及其指令模拟器)尚不支持在C语言程序中使用Thumb2指令内联汇编。使用内嵌汇编函数时,函数的调用(跳转返回)降低了执行效率。

② C语言对clz指令的支持尚有不足,故新算法跨平台性差。但鉴于ARM芯片应用广泛,指令又被ARM9之后的芯片广泛兼容,所以应用空间还算广阔。

2μC/OSII就绪表算法介绍与具体改动

μC/OSII就绪表是一个数组,数组元素一位的值(1或0)对应了一个任务就绪与否,该位在数组中的位置表示任务的优先级。当需要调度已就绪的最高优先级任务运行时,就在就绪表中查找该任务。


2.1μC/OSII就绪表算法简介

一种解决方法是,对数组各项依次判断是否为0:若>0,进入该项查找最小权的置1位位置;若=0,优先级加一个基数,查下一项,直至查到该优先级。


μC/OSII技高一筹,设置了一个对就绪表各项判断是否为0的变量,称之为就绪表组。就绪表组一位为0或1,对应就绪表一项的值是否为0。通过查找就绪表组最小权位的置1位位置,就确定了对应首个>0的就绪表项的下标,从而避免了循环,大幅度提高了效率。


2.2改动方式与源码

clz算法接受了μC/OSII的思路,再通过使用clz指令来进行优化。不同的是,clz是从右往左查,二进制的高权位对应高优先级,而μC/OSII优先级以值小为高。


考虑到有时用不到很多任务,这时用数组作就绪表不免浪费。因此当任务总数小于32时,就用32位无符号整数变量作就绪表。注意,此时就绪表组变量OSRdyGrp被当作就绪表使用。


常量OS_LES_TSK表示是否使用较小任务数,0表示使用最多32个任务,1表示使用最多1 024个任务。


常量RdySt是将32位整数的最高权位置1,以便移位使用。


2.3C语言实现

以下算法利用内嵌clz指令的函数编写,实现了指定优先级任务在就绪表的设置、清除,在就绪表中查找就绪任务的最高优先级。


#defineOS_LES_TSK 0

#defineRdySt #0x80000000

intOSRdyGrp ;//任务就绪表组,任务数<32当作就绪表用

intOSRdyTbl[32] ;//任务就绪表

//将优先级为prio的任务在就绪表置位

voidOSRdySET(unsigned shortprio) {

prio=prio;//设防某些编译器报错

//当任务总数<32时不编译OSRdyTbl[],以提升效率

#ifOS_LES_TSK

OSRdyGrp|=(RdySt>>prio);

#else

//任务数在1~1 024之间,调度将多花些时间

//prio>>5:任务组OSRdyGrp需置1的位的位置,

//即OSRdyTbl[]下标

OSRdyGrp|=(RdySt>>(prio>>5));

//prio & 31:按位与,取prio的低5位,设置数组元素

OSRdyTbl[prio>>5]|=(RdySt>>(prio & 31));

#endif

}

//将优先级为prio的任务在就绪表清零

voidOSRdyCLR(unsigned shortprio) {

prio=prio;

#ifOS_LES_TSK//当任务总数<32

OSRdyGrp&=~(RdySt>>prio);

#else

//任务数在1~1 024之间,调度将多花些时间

//prio>>5:就绪表组OSRdyGrp需清零的位的位置,

//即就绪表OSRdyTbl[]下标

//prio & 31:按位与,取prio的低5位,设置数组元素

OSRdyTbl[prio>>5] &= ~(RdySt>>(prio & 31));

//若就绪表OSRdyTbl[]一项为零,则清零其对应的就

//绪表组的一位

if(OSRdyTbl[prio>>5]==0 )

OSRdyGrp &= ~(RdySt>>(prio>>5));

#endif

}

//前导零计数:内嵌汇编函数,可能降低执行效率

__asm unsigned shortClzGet(intOSRdyGrp) {

clz.w r0,r0

bx lr//不写也能返回,详见后文

}

//获取任务就绪组/表的最高优先级,前导零计数

//函数调用降低效率,可以将下面的语句写在别的函数中

unsignedshortOSPrioHighRdy() {

unsignedshorty;

#ifOS_LES_TSK

//任务数<32,可以考虑将y定义为8位无符号整数

//unsignedchar y;

y=ClzGet(OSRdyGrp);

#else

//任务数在1~1 024之间,调度将多花些时间

y=ClzGet(OSRdyGrp);

y=ClzGet(OSRdyTbl[y])+(y<<5);

#endif

returny;

}

//检查执行结果是否正确,33是适合检查用的数值

intmain() {

unsigned shortprio=0;

while(prio<1024) {

OSRdySET(prio); //根据优先级设置任务就绪表位、组位

prio=OSPrioHighRdy(); //获取就绪表中任务的最高优先级

OSRdyCLR(prio);//根据优先级清除对应的

//就绪表位、组位

prio+=33;

if(prio>1023)

prio=0;

}

}


程序中的bx r14,有些资料上要求必须写,不过查看反汇编代码,编译程序已经给加上了。看来是编译程序已升级,会不会出错要看使用的编译器,建议还是按规范写上。由于内嵌函数调用返回耗时,查找算法未能充分发挥,需改进编译后的汇编代码以实现更高的效率,或使用汇编代码重写这部分程序。


2.4THUMB2汇编指令实现

用汇编语言写程序时的技巧:在最高优先级任务的设置、清除函数中,C语言运算符“|= ”对等汇编指令“orr”,“&= ~”对等汇编指令“bic”。这两条指令都可以进行预移位操作,大幅提高执行效率。可以查看反汇编源码,看C编译器是否利用了这一便利。


在查找函数中,可以省去C语言程序中的内嵌汇编调用,减少冗余指令。示意伪代码如下:

ldr r0,=OSRdyGrp ;加载就绪表组变量OSRdyGrp地址

ldr r1, [r0];取就绪表组变量OSRdyGrp值

#ifOS_LES_TSK

clz.w r0, r1;取最高优先级

#else

clz..w r0, r1;获取最高优先级所在就绪表项的下标

ldr r2,=OSRdyTbl;加载就绪表首地址

add.wr2, r2,r0,#2;计算最高优先级所在就绪表项地址

ldr r3, [r2];取该项的值

Clz.w r1,r3;取该项内的最高优先级

add.w r0,r1,r0 ,lsl #5;计算得到最高优先级

#endif

bx r14


可以看出,除了数据加载指令外,查找的核心算法仅3条指令(使用<32个任务时,仅1条指令)。不过在实际设计算法的时候,还需要考虑指令流水线停顿,方能达到最佳的效果。


2.5μC/OSII 2.84版相关源码介绍

以下是翻译整理后的μC/OSII优先级查找算法源码(2.84版),较长的注释是添加的算法说明。


/************************************

*查找就绪表中的最高优先级任务运行

*说明: 本函数被其他μC/OSII服务调用,以确保就绪表中的

*最高优先级任务最早被执行,全局变量“OSPrioHighRdy”也随

*之改变

*提示:①这是μC/OSII的内部函数,用户程序不要调用它

*② 该函数被调用时需要关中断

*************************************

//就绪优先级调度新算法,将优先级数由8×8=64扩展到

//16×16=256

staticvoidOS_SchedNew (void) {

#if OS_LOWEST_PRIO <= 63//参考最多提供64个优先级

INT8Uy;

/*数组OSUnMapTbl[256]的作用:

当给定一个位二进制无符号整数,如OSRdyGrp,怎么判断它被置1的最小权位是哪个,即如何从右往左查找第一个1出现的位置?当处理器没有现成的指令时,可以先将数的256种状况

存入数组OSUnMapTbl[256]中,判断最小权位时,查询数组

OSUnMapTbl[OSRdyGrp]即可*/

y = OSUnMapTbl[OSRdyGrp];

OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);

#else//现在能提供256个优先级

INT8Uy;//就绪表组,用1或0标记

有无就绪任务

INT16U *ptbl;//就绪表某一项指针,计算后确定是哪一项

/*当16位整数OSRdyGrp低8位不为零,获取就绪表组置1的最小权位0~7,

则获取8~15位*/

if ((OSRdyGrp & 0xFF) != 0) {

y = OSUnMapTbl[OSRdyGrp & 0xFF];

} else {

y = OSUnMapTbl[(OSRdyGrp >> 8) & 0xFF] + 8;

}

ptbl = &OSRdyTbl[y];/*就绪表数组某一项指针赋值*/

if ((*ptbl & 0xFF) != 0) {

OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl & 0xFF)]);

} else {

OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8);

}

#endif

}


clz最高优先级查找算法,与μC/OS的新算法有所不同:返回的结果分别是8位、16位整数。这是因为8位已经不能表示>255的值;过程中clz算法更多地使用16或32位整数,以充分利用芯片性能。


3适用范围

等待任务列表使用了与就绪表操作相似的过程,注意要同时更改其数据类型和算法。算法虽然是在CortexM3上执行的,但适用于ARM9及其以后芯片。支持ARM指令集的芯片,可以在C语言中使用内嵌汇编,不必再编写汇编查找函数。


本文所叙述的算法适用于下述两种情况。

① 使用μC/OSII系统:

◆ 要求更多的任务优先级;

◆ 要求产品性能优越或是时间关键的应用,想进一步提高效率;

◆ 学习、研究或希望优化μC/OSII以扩展其应用范围。


② 未使用μC/OSII系统:

◆ 移植改造其他操作系统的就绪表算法;

◆ 编写新操作系统或执行调度程序;

◆ 编程爱好者借鉴、改进编程方法。


关键字:μC  OS-II  就绪表算法  ARM架构 引用地址:μC/OS-II就绪表算法在ARM架构上的改动

上一篇:基于ARM和POE的网络指纹门禁系统设计
下一篇:看嵌入式操作系统浅析

推荐阅读最新更新时间:2024-11-09 22:44

物联网之STM32开发八(I2C总线通信)
STM32-I2C总线通信 内容概要 I2C总线通信原理 三轴加速度传感器mpu6050介绍 I2C通信实例 I2C总线通信原理 内容概要: I2C总线简介 I2C总线协议 I2C总线读写操作 STM32F0-I2C控制器特性 I2C总线简介: I2C总线介绍:I2C(Inter-Integrated Circuit)总线(也称IIC或I2C)是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备,是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,期间封装形式少,通信速率高等优点。 I2C总线特征: 两条总线线路:一
[单片机]
物联网之STM32开发八(I2<font color='red'>C</font>总线通信)
ARM芯片S3C2440A智能小车可移动视频监控系统
  本文介绍的智能小车可移动视频监控系统,以“飞思卡尔杯”智能小车竞赛提供的车模装置为基础,利用ARM芯片S3C2440A控制图像采集、网络传输、速度采集干扰小的模块,利用FPGA芯片控制电机驱动、舵机控制、电量采集干扰大的模块,当上位机通过Internet访问智能小车服务器时,在监控界面上点击按钮来控制小车的运行、图像拍摄、速度采集。   1 系统总体设计   该系统采用三星公司的ARM芯片S3C2440A作为主控制芯片及Altera公司的FPGA芯片EP2C5T144C8作为辅助控制芯片,ARM上装有Windows CE5.0操作系统。S3C2440A内置丰富的外设资源包括中断控制器、GPIO、I2C、相机接口等接口电路,
[单片机]
ARM芯片S3<font color='red'>C</font>2440A智能小车可移动视频监控系统
STM32之模拟I2C读取加速度传感器
前言:由于之前学会了SPI,软硬件SPI都会了,发现只要读懂时序图,其他都是小菜一碟,I2C也是如此,不过本少爷还是花了1天时间去理解了I2C的一些知识,发现模拟比硬件更能理解其中的工作原理,虽然速度慢点。 废话:时间有限,暂时写一点核心内容,该内容本人从MMA8451Q加速度传感器的手册上读的。坑爹的新浪居然不支持我上传图片,很无奈 正文: ------------------------------------------------模拟I2C---------------------------------------------------- 1.start 2.写入7位device地址+1位写W 3.等待从设备握
[单片机]
51单片机C语言学习 3
第三课 生成HEX文件和最小化系统   在开始C语言的主要内容时,我们先来看看如何用KEIL uVISION2来编译生成用于烧写芯片的HEX文件。HEX文件格式是Intel公司提出的按地址排列的数据信息,数据宽度为字节,所有数据使用16进制数字表示, 常用来保存单片机或其他处理器的目标程序代码。它保存物理程序存储区中的目标代码映象。一般的编程器都支持这种格式。我们先来打开第一课做的第一项目,打开它的所在目录,找到test.Uv2的文件就可以打开先前的项目了。然后右击图3-1中的1项目文件夹,弹出项目功能菜单,选Options for Target'Target1',弹出项目选项设置
[单片机]
基于C8051F040多路浸水时刻记录电路设计
在某型水下航行器自沉系统中,某合金材料在海水中一定时间内能正常工作,但正常时间过后会被海水腐蚀;从而实现该航行器的自沉功能。为此设计了该电路,用以测试铝铬合金材料在不同温度的多组时间信息。 1 系统硬件结构 基于C8051F040多路浸水时刻记录电路硬件部分由6个主要模块组成:浸水传感器、信号电平转换电路、达接斯时钟模块、串行存储器M25P80模块、单片机C8051F040模块和CAN通讯模块。系统硬件结构框图如图1所示。 1.1 单片机08051F040 C8051F040由美国Silicon Labs公司设计,对原51单片机内核进行了较大改造,由原来12个时钟执行一条指令,改进为一个时钟执行一条单周期指令,
[单片机]
基于<font color='red'>C</font>8051F040多路浸水时刻记录电路设计
S3C2440内存控制详解
软件可编程的大小端模式; 地址空间:每个BANK可寻址128MB(总共8个BANK 1GB空间); 可编程的访问位宽:BANK0为16或32位,其他BANK为8或16或32位; 8个存储器BANK,其中6个用于ROM或者SRAM,2个用于ROM、SRAM或者SDRAM; BANK0~BANK6的起始地址固定; BANK7的起始地址和大小可编程; 所有存储器BANK的访问周期可编程; 外部wait信号可延长总线周期; 支持SDRAM的自刷新和掉电模式。 BANK0总线宽度由OM 引脚决定,当OM =01时,booting ROM datawidth是16位,
[单片机]
S3C2440之裸机之汇编点亮LED灯
虚拟机环境:Oracle VM VirtualBox Linux系统:ubuntu_14.04.6 交叉编译工具: (https://eyun.baidu.com/s/3b1UtLc) 100ask分享的所有文件 002_JZ2440资料光盘_20180516(免费) 资料光盘 A盘 tools.zip arm-linux-gcc-4.3.2.tar.bz2 gcc-3.4.5-glibc-2.3.6/bin 第一步:查看原理图 输出低电平点亮LED灯 输出高电平熄灭LED灯 第二步:查看芯片手册 相应引脚配置为输出 输出低电平 第三步:编写程序 led_on.S: .text .global _
[单片机]
S3<font color='red'>C</font>2440之裸机之汇编点亮LED灯
STC89C52单片机 点亮LED灯
点亮LED灯 一、什么是LED LED全称为半导体发光二极管,采用半导体材料制成的,以直接将电能转化为光能,电号转换成光信号的发光器件;其特点是功耗低、高亮度、色彩艳丽、坑振动、寿命长(正常发光8-10万小时)、冷光源等优点,是真正的“绿色照明”。 二、LED工作参数 LED(发光二极管)在电路图中的符号为: 它具有二极管的基本特性正向导通,反向截止。要想点亮LED那么需要从正向流过工作电流。 普通发光二极管工作压降为:1.6~2.1V。 工作电流为:1~20mA。 有图中LED的通过电流我们可以根据欧姆定律I(电流) = U(电压) /R(电阻) 可以算出为3mA。 三、原理图分析 四、C语言知识 关键字: sb
[单片机]
STC89<font color='red'>C</font>52单片机 点亮LED灯
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved