当前位置:首页 > 单片机 > 单片机
[导读] 一、MC68K CPU简介 MC68K及68020、68040等的著名的MOTOROLA32位微处理器,和与之兼容的68K、CPU32、CPU32+等CPU扩充定时处理单元TPU、队列串行模块QSM、系统控制模块和RAM等组成MC683xx系列单片机。

一、MC68K CPU简介

MC68K及68020、68040等的著名的MOTOROLA32位微处理器,和与之兼容的68K、CPU32、CPU32+等CPU扩充定时处理单元TPU、队列串行模块QSM、系统控制模块和RAM等组成MC683xx系列单片机。

CPU32 内部有8个32位通用数据寄存器,8个32位通用地址寄存器。8个通用数据寄存器可作为累加器使用,也可看成C语言中各种类型的变量;8个通用地址寄存器,可作为变址寄存器使用,也可看成C语言中的指针型变量。CPU32有独立的用户堆栈指针和系统堆栈指针,可区分程序区、数据区、系统区、用户区等存储空间,有7级中断。


要实现μC/OS-II向MC68K的移值,需要有MC68K的C编译器。我们使用的HIWARE公司的C编译器。该C编译器允许嵌入行汇编。

二、移植中所需修改的文件

和CPU相关的文件主要有三个:C语言文件OS_CPU32.C、头文件OS_CPU32.H和汇编文件OS_CPU32.ASM。

1.INCLUDES.H文件

INCLUDES.H 是主头文件,在所有后缀名为.C文件的开始都包含INCLUDES.H文件。对于不同类型的处理器,用户需要改定INCLUDES.H文件,增加自己的头文件,但必须加在文件末尾。在安装μC/OS-II的时候,附带了几个移植实例,例如,针对Intel 80x86的代码安装到IIL目录。我们为MC68K编写的移植实例都放在II下,在INCLUDES.H文件中增加有:

#include "iiK_CPU32.ASM"

#include "iiK_CPU32.C"

#include "iiK_CPU32.H"

2.OS_CPU32.H文件

OS_CPU32.H文件中定义了与硬件相关的基本信息:

typedef unsigned char INT8U; /*无符号8位数*/

typedef signed char INT8S; /*带符号8位数*/

typedef unsigned int INT16U; /*无符号16位数*/

typedef signed int INT16S; /*带符号16位数*/

typedef signed long INT32S; /*带符号32位数*/

typedef unsigned int OS_STK; /*堆栈入口宽度为16位*/

#define OS_STK_GROWTH1 /*堆栈由高地址向低地址增长*/

#define UCOS 0 /*用于任务切换的软中断*/

define OS_TASK_SW() _TRAP(UCOS)

#define OS_ENTER_CRITICAL() move.w#$2700,SR /*进入临界区*/

#define OS_EXIT_CRITICAL() move.w #$2000,SR /*退出临界区*/

(1)数据类型

由于不同的处理器有不同的字长,μC/OS-II的移植需要重新定义一系列的数据结构。由于 MC68K为32位MCU,整数(int)类型数据为16位,长整开有(long)为32位。在MC68K中堆栈都是按字进行操作的,所以堆栈数据类型 OS_STK声明为16位。所有的堆栈必须用OS_STK声明。

(2)代码临界区

μC/OS -II在进入系统临界代码区之间要关中断,等到退出临界区后再打开,从而保护核心数据不被多任务环境下的其他任务或中断破坏。在MC68K中,开关中断可以通过设置状态寄存器SR中的中断屏蔽位来实现。μC/OS-II中的宏OS_ENTER_CRITICAL()定义将状态寄存器的中断屏蔽位置位,屏蔽所有的七级中断;OS_EXIT_CRITICAL()定义将状态寄存器的中断屏蔽位清零,打开所有的七级中断。这种处理方法非常简单,但CPU32提供分级中断机制得不到使用。如果要使用分级中断,必须改写一些相关的函数,将在第4节中阐明。

(3)堆栈方向

MC68K处理器的堆栈是由高地址向低地址递减的,所以OS_STK_GROWTH必须设置为1。

(4)OS_TASK_SW()函数的定义

在μC/OS -II中,OS_TASK_SW()用来实现任务切换。就绪任务的堆栈初始化应该模拟一次中断发生后的样子,椎栈中应该按入栈次序设置好各个寄存器。 OS_TASK_SW()函数模拟一次断过程,在中断返回的进修进行任务切换。CPU32有16个软中断可供选用,称为陷阱TRAP调用。中断程序程序的入口必须指向汇编函数OSCtxSw()。

我们在μC/OS-II所提供的例程中使用的0号陷阱调用,由下面的语句完成定义:

#define OS_TASK_SW() -TRAP(UCOS)

3.OS_CPU32.ASM文件

μC/OS-II的移植需要用户改写OS_CPU_A.ASM中的4个函数:OSStartHighRdy()、OSCtxSw()、OSINTCtxSw()和OSTICkISR()。

(1)OSStartHighRdy()函数

该函数由OSStart()函数调用,功能是运行优先级最高的就绪态任务。在调用OSStart() 之前,用户必须先调用OSInit(),并且已经至少创建了一个任务。为启动任务,OSStartHighRdy()首先找到当前就绪的优先级最高的任务,OSTCBHighRdy中保存有优先级最高任务的任务控制块(TCB)的地址,并从任务的任务控制块中找到指向堆栈的指针,然后运行指令 MOVEM.L(A7)+,A0-A6/D0-D7,从堆栈中弹出全部寄存器的内容,运行RTE中断返回。由于任务创建时堆栈的结构就是按中断捕捞堆栈结构初始化的,执行RET指令后就切换到了新任务。有关μC/OS- II的任务切换机制,请参考系列计座(3).

OSStartHighRdy的汇编代码如下:

_OSStarHighRdy

MOVE.L(_OSTCBHighRdy),A1

;获取最高优先级就绪任务的TCB地址

MOVE.L A1,(_OSTCBCur)

MOVE.L (A1),A7 ;取得堆栈指针

MOVEM.L (A7)+,A0-A6/D0-D7

RTE ;中断返回,切换任务

(2)OSCtxSw( )函数

OSCtxSw( )是一个任务级的任务切换函数(在任务中调用,区别于在中断程序中调用的OSIntCtxSw(),在MC68K系统上,通过执行一条软中断指令来实现任务切换。软中断向量指向函数,而该函数的执行结构可能造成系统任务重新调度(例如,试图唤醒一个优先级更高的任务),则在函数的末尾会调用OSSched (),OSSched()将查找当前就绪的优先级最高的任务。如果不是当前任务,则判断是否需要进行任务调度,再找到该任务控制块OS_TCB的地址,并将该地址拷贝到变量OSTCBHighRdy中,然后通过宠OS_TASK_SW()执行软中断,进行任务切换。在此过程中,变量OSTCBCur始终包含一个指向当前运行任务OS_TCB的指针。OSCtxSw()的汇编代码如下:

_OSCtxSw

MOVEM.L A0-A6/D0-D7,-(A7) ;存储当前任务环境

MOVE.L (_OSTCBCur),A1 ;保存当前任务TCB指针

MOVE.L A7,(A1)

MOVE.L (_OSTCBHighRdy),A1 ;获取最高优先级就绪任务的TCB地址

MOVE.L A1,(_OSTCBCur) ;将就绪任务设置为当前运行任务

MOVE.L (A1),A7 ;取得新任务的堆栈指针

MOVEM.L (A7)+,A0-A6/D0-D7 ;

RTE ;中断返回,切换任务

(3)OSIntCtxSw()函数

在μC/OS -II中,由于中断的产生可能会引起任务切换,在中断服务程序的最后会调用OSICntExit()函数检查任务就绪状态。如果需要进行任务切换,将调用 OSIntCtxSw(),所以,OSIntCtxSw()又称为中断级的任务切换函数。由于在调用OSIntCtxSw()之前已经发生了中断, OSIntCtxSw()默认CPU寄存器已经保存在被中断任务的堆栈了。OSIntCtxSw()的代码与OSCtxSw()的大部分相同,不同之处是:第一,由于中断已经发生,此处不需要再保存CPU寄存器;第二,OSIntCtxSw()需要调整堆栈指针,去掉堆栈中一些不需要的内容,以使堆栈中包含任务的运行环境。

_OSIntCtxSw

ADDA #10,A7 ;忽略掉由于函数嵌套调

;用而压入堆栈的内容

MOVE.L (_CSTCBCur),A1 ;在TCB中保存当前

;任务的堆栈指针

MOVE.L A7,(A1)

MOVE.L (_OSTCBHighRdy),A1

;获取最高优先级就绪任务的TCB地址

MOVE.L A1,(_OSTCBCur) ;将就绪任务设备为当前

;运行任务

MOVE.L (A1),A7 ;取得堆栈指针

MOVEM.L (A7)+,A0-A6/D0-D7 ;

RTE ;中断返回,切换任务

(4)OSTickISR()函数

在μC/OS-II中,当调用OSStart()启动多任务环境后,时钟中断非常重要。在时钟中断中处理所有与定时相关的工作,如任务的延时、等待操作等等。在时钟中断中将查询处于等待状态的任务,判断是否延时结束,以重新进行任务调度。

和μC/OS -II中的其他中断服务程序一样,OSTICkISR()首先在被不断任务堆栈中保存CPU寄存器的值,然后调用OSIntEnter()。ΜC/OS- II要求在中断服务程序开头调用OSIntEnter(),其作用是将记录中断嵌套层数的全局变量OSIntNesting加1。如果不调用 OSIntEnter(),直接将OSIntNesting加1也是允许的。随垢,OSTickISR()调用OSTimeTick(),检查所有处于延时等待状态的任务,判断是否有延时结束并就绪的任务。在OSTickISR()的最后调用OSIntExit(),如果在中断中(或其他嵌套的中断)有更高优先级的任务就绪,并且当前中断为中断嵌套的最后一层,OSIntExit()将进行任务调度。注意,如果进行了任务调度,OSIntExit()将不再返回调用者,而是用新任务堆栈中的寄存器数值恢复CPU现场,然后用RTE实现任务切换。如果当前中断不是中断嵌套的最后一层,或中断中没有改变任务的就绪状态,OSIntExit()将返回调用者OSTickISR(),最后OSTickISR()返回被中断的任务。

4.OS_CPU32.C文件

μC/OS-II的移值需要用户在OS_CPU32.C中定义6个函数,而实际上需要定义的只有OSTaskStkInit()一个函数,其他5个函数需要声明,但

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

MIKROE增加了图形功能,CLANG支持ARM和RISC-V以及许多其他功能

关键字: 编译器 RISC-V架构 工业自动化

IAR Embedded Workbench for Arm已全面支持恩智浦最新的S32系列,可加速软件定义汽车的车身和舒适性应用的开发

关键字: 电机控制 电动汽车 编译器

这款新编译器专为dsPIC®数字信号控制器 (DSC)优化设计,可为实时应用定制许可选项

关键字: 编译器 数字信号控制器 自动驾驶

C语言编译器是一种用于将C语言源代码转换为可执行程序的软件工具。它的主要功能是将C语言代码翻译成机器语言,以便计算机能够理解和执行。C语言编译器通常包括预处理器、编译器、汇编器和链接器等多个组件,它们协同工作以完成编译过...

关键字: C语言 编译器 Microsoft Visual C++

IAR Embedded Workbench 9.40版本引入了与指针验证和分支目标识别(PACBTI)扩展的无缝兼容性,保护嵌入式应用程序免受各种安全攻击。

关键字: 代码 嵌入式应用程序 编译器

在过去数十年,摩尔定律一直支配着半导体的发展。随着MCU的性能越来越强,嵌入式产品也越来越智能,嵌入式软件也变得越来越复杂。编译器作为嵌入式软件开发的基础工具,将程序员编写的源代码转换为底层硬件可以执行的机器指令。一款优...

关键字: 摩尔定律 嵌入式 软件开发 编译器

Python的创始人是一位荷兰籍的程序员——吉多·范罗苏姆(Guido van Rossum),江湖外号“龟叔”。据说这个外号是由于Guido的开头与龟的拼音gui相同得来的,所以Guido也被程序员们戏称为“龟叔”。在...

关键字: Python 编译器 人工智能

从汇编角度来说,如果“test %al, %al”能改成“test %0x1, %al”就没有匪夷所思的问题了,如此一来应该会降低CPU的效率,毕竟执行指令还需要一个立即数,我没搞过编译器也没设计过CPU,纯属瞎猜,能搞...

关键字: 汇编 CPU 编译器

ZigBee 无线网络节点开发平台软件开发平台 IAR Embedded Workbench(简称 EW)的 C/C++交叉编译器和调试器是今天世界最完整的和最容易使用专业嵌入式应用开发工具。EW 对不同的微处理器提供一...

关键字: IAR 无线网络 编译器

PathWave RFPro 与新思科技定制化编译器相辅相成,可提供无线晶片设计工作流程所需的整合式电磁模拟工具

关键字: 是德科技 集成电路 编译器
关闭
关闭