基于ARM7(LPC2131)平台的μC/OSⅡ的移植

一.准备工作

1.μC/OS-简介

   uC/OS-II读做“micro COS2”, 意为“微控制器操作系统版本2”。uC/OS-II是著名的,源代码公开的实时内核,可用于各类8位,16位和32位单片机或DSP。从uC/OS算起,该内核已有十多年应用历史,在诸多领域得到广泛应用。

2.μC/OS-的特点

(1)提供源代码

(2)可固化

(3)可裁剪

(4)可剥夺

(5)多任务

(6)可确定性

(7)任务栈

(8)系统服务

(9)中断管理

(10)稳定性与可靠性

3.编译器的选择

ARM处理器核的C编译器有很多,大概有SDT,ADS1.2,IAR,TASKING和GCC等。我最终选择的是ADS1.2编译程序和调试。

4.ARM7简介

ARM7处理器核具有用户,系统,管理,中止,未定义,中断和快中断7中工作模式。其中除了用户模式外其他均为特权模式。同时支持两个指令集:16位Thumb指令集和32位ARM指令集。

5.开发环境的搭建

操作系统:Windows XP

集成开发环境:ADS1.2

调试环境:AXD(ADS1.2配套的软件)

串口调试工具

6.项目中所运用到的技术创新

(1)实现了加密程序,保护了用户应用程序代码,利用在特定的地址0x1fc处写入特定的值0x87654321实现加密

(2)通过工程配置文件加载程序代码,实现了写应用程序的模板工程,不用每次配置工程设置

(3)初始化程序和操作系统代码都留有很多扩充的接口,方便不同的用户需要实现不同的启动代码功能和扩充操作系统的功能

7.项目的特色

(1)在本文档中有完整的源代码,并且有很详细的注释

(2)只要具备同样的软硬件环境,根据我的《过程与结果总结报告》完全可以实现这个项目

(3)同时完成了引导程序和操作系统的移植

(4)涉及到软硬件的知识,不仅仅只是软件

二.移植过程

1.编写bootloader(ARM启动代码)

1.启动代码综述

在一般32位ARM应用系统中,软件大多数采用C语言进行编程,并且以嵌入式操作系统为开发平台,这样大大的提高了开发效率及软件性能。为了能够进行系统初始化,通常会用一个汇编文件作为启动代码。它可以实现向量表定义、堆栈初始化、系统变量初始化、中断系统初始化、I/O初始化、外围初始化和地址重映射等操作。

ARM公司之设计内核,不生产芯片,只是把内核授权给其他厂商。其他厂商购买了授权后加入自己的外设,生产出各具特色的芯片。这样就促进了基于ARM处理器核的芯片的多元化,但也使得各种芯片的启动代码差别很大,不易编写出统一的启动代码。

2.文件的组成

汇编文件1.Startup.S:异常向量表、各模式堆栈初始化和跳到main()函数入口等

     2.IRQ.S :负责管理中断嵌套

C文件   Target.C :初始化目标板

头文件 Config.H :系统配置和类型定义

Target.H :一些和目标板相关的声明

LPC2294.H :LPC2000系列芯片特殊寄存器定义

分散加载文件mem_a.Scf:在片内Flash发布,RelInFLASH

Mem_b.Scf:在片内RAM调试,DebugInRAM,在uCOSII中不使用这种布局模式

Mem_c.Scf:在片内Flash调试,DebugInFLASH

3.各源代码文件内容及其注释

1.Startup.S:

;**--------------File Info---------------------------------------------

;** File name:  Startup.s

;** Last modified Date:  2009-08-17

;** Last Version:  1.0

;** Descriptions: 为 LPC2100系列芯片的启动代码,从这里开始执行,包括初始化代码,为每一种模

;**               式 的进入口和任务的堆栈

;定义堆栈的大小

SVC_STACK_LEGTH         EQU         0

FIQ_STACK_LEGTH         EQU         0

IRQ_STACK_LEGTH         EQU         256

ABT_STACK_LEGTH         EQU         0

UND_STACK_LEGTH         EQU         0

NoInt       EQU 0x80 ;Bit7,I位

NoFIQ EQU 0x40 ;Bit6,F位

USR32Mode   EQU 0x10 ;M[4:0]=10000,用户模式

SVC32Mode   EQU 0x13 ;M[4:0]=10011,管理模式

SYS32Mode   EQU 0x1f ;M[4:0]=11111,系统模式

IRQ32Mode   EQU 0x12 ;M[4:0]=10010,IRQ中断

FIQ32Mode   EQU 0x11 ;M[4:0]=10001,快速中断

    IMPORT __use_no_semihosting_swi

;引入的外部标号在这声明

    IMPORT  FIQ_Exception                   ; 快速中断异常处理程序

    IMPORT  __main                          ; C语言主程序入口 

    IMPORT  TargetResetInit                 ;目标板基本初始化

;给外部使用的标号在这声明

    EXPORT  bottom_of_heap

    EXPORT  StackUsr

    EXPORT  Reset

    EXPORT __user_initial_stackheap

    CODE32

    AREA    vectors,CODE,READONLY

        ENTRY

;中断向量表

Reset

        LDR     PC, ResetAddr ;0x00,复位

        LDR     PC, UndefinedAddr ;0x04,未定义地址

        LDR     PC, SWI_Addr ;0x08,软件中断

        LDR     PC, PrefetchAddr ;0x0c,预取指中止

        LDR     PC, DataAbortAddr ;0x10,数据中止

        DCD     0xb9205f80 ;0x14,保留

        LDR     PC, [PC, #-0xff0] ;0x18,IRQ中断

        LDR     PC, FIQ_Addr ;0x1C,快速中断

ResetAddr           DCD     ResetInit ;复位初始化处理程序地址

UndefinedAddr       DCD     Undefined ;未定义指令处理程序地址

SWI_Addr            DCD     SoftwareInterrupt ;软件中断处理程序地址

PrefetchAddr        DCD     PrefetchAbort ;预取指中止处理程序地址

DataAbortAddr       DCD     DataAbort ;数据中止处理程序地址

Nouse               DCD     0 ;未使用

IRQ_Addr            DCD     0 ;IRQ中断,已在"LDR [PC,#-0xff0]"中处理

FIQ_Addr            DCD     FIQ_Handler

;未定义指令

Undefined

        B       Undefined ;死循环

;软中断

SoftwareInterrupt

;        B       SoftwareInterrupt

;//增加开/关中断处理                                 

        CMP     R0, #4 ;判断传过来的参数是否大于4

        LDRLO   PC, [PC, R0, LSL #2] ;小于4(参数正确),进行查表

        MOVS    PC, LR ;大于或者等于4(参数出错),则返回

SwiFunction

        DCD     IRQDisable        ;0号调用,禁止IRQ中断

        DCD     IRQEnable         ;1号调用,使能IRQ中断

        DCD FIQDisable   ;2号调用,禁止FIQ中断

        DCD FIQEnable   ;3号调用,使能FIQ中断

IRQDisable

        ;关IRQ中断

        MRS     R0, SPSR ;读取SPSR的值

        ORR     R0, R0, #NoInt ;置位I位,设置关IRQ中断

        MSR     SPSR_c, R0 ;回写SPSR

        MOVS    PC, LR ;返回

IRQEnable

        ;开IRQ中断

        MRS   R0, SPSR

        BIC   R0, R0, #NoInt ;清零I位,设置开IRQ中断

        MSR   SPSR_c, R0

        MOVS    PC, LR  

FIQDisable

        ;关FIQ中断

        MRS     R0, SPSR

        ORR     R0, R0, #NoFIQ ;置位F位,设置关FIQ中断

        MSR     SPSR_c, R0

        MOVS    PC, LR

FIQEnable

        ;开FIQ中断

        MRS   R0, SPSR

        BIC   R0, R0, #NoFIQ ;清零F位,设置开FIQ中断

        MSR   SPSR_c, R0

        MOVS    PC, LR

;取指令中止

PrefetchAbort

        B       PrefetchAbort ;死循环

;取数据中止

DataAbort

        B       DataAbort ;死循环

;快速中断

FIQ_Handler

        STMFD   SP!, {R0-R3, LR} ;寄存器R0~R3,LR入栈

        BL      FIQ_Exception ;调用FIQ处理程序

        LDMFD   SP!, {R0-R3, LR} ;寄存器R0~R3,LR出栈

        SUBS    PC,  LR,  #4         ;计算返回地址

;/*****************************************************************************************

;** unction name  函数名称:  InitStack

;** Descriptions  功能描述:    初始化堆栈

;** Created by  作 者:  吴友强

;** Created Date  日 期:  2009/07/20 2009年7月20日

;*****************************************************************************************/

;初始化堆栈,此时禁止IRQ和FIQ中断,处于ARM状态

InitStack    

        MOV     R0, LR

;Build the SVC stack

;设置管理模式堆栈

        MSR     CPSR_c, #0xd3

        LDR     SP, StackSvc

;Build the IRQ stack

;设置中断模式堆栈

        MSR     CPSR_c, #0xd2

        LDR     SP, StackIrq

;Build the FIQ stack

;设置快速中断模式堆栈

        MSR     CPSR_c, #0xd1

        LDR     SP, StackFiq

;Build the DATAABORT stack

;设置中止模式堆栈

        MSR     CPSR_c, #0xd7

        LDR     SP, StackAbt

;Build the UDF stack

;设置未定义模式堆栈

        MSR     CPSR_c, #0xdb

        LDR     SP, StackUnd

;Build the SYS stack

;设置系统模式堆栈

        MSR     CPSR_c, #0xdf ;切换到系统模式,之后将在系统模式下运行

        LDR     SP, =StackUsr ;除非进行模式切换

        MOV     PC, R0

;/*****************************************************************************************

;** unction name  函数名称:  ResetInit

;** Descriptions  功能描述:   复位入口

;** Created by  作 者:  吴友强

;** Created Date  日 期:  2009/07/20 2009年7月20日

;**----------------------------------------------------------------------------------------

;*****************************************************************************************/

ResetInit    

        BL      InitStack               ;初始化堆栈 

        BL      TargetResetInit         ;目标板基本初始化 

        B       __main                  ;跳转到c语言入口 

;/*****************************************************************************************

;** unction name  函数名称:  __user_initial_stackheap

;** Descriptions  功能描述:  库函数初始化堆和栈,不能删除

;** Created by  作 者:  吴友强

;** Created Date  日 期:  2009/07/20 2009年7月20日

;*****************************************************************************************/

__user_initial_stackheap    

    LDR   r0,=bottom_of_heap

;    LDR   r1,=StackUsr

    MOV   pc,lr

StackSvc           DCD     SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4 ;管理模式堆栈

StackIrq           DCD     IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4 ;IRQ模式堆栈

StackFiq           DCD     FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4 ;FIQ模式堆栈

StackAbt           DCD     AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4 ;中止模式堆栈

StackUnd           DCD     UndtStackSpace + (UND_STACK_LEGTH - 1)* 4;未定义模式堆栈

;/*****************************************************************************************

;** unction name  函数名称:  CrpData

;** Descriptions  功能描述:  芯片加密,代码保护

;** input parameters  输 入:    None 无

;** Returned value    输 出 :   None 无

;** Used global variables 全局变量:  None 无

;** Calling modules  调用模块:  None 无

;** 

;** Created by  作 者:  吴友强

;** Created Date  日 期:  2009/07/20 2009年7月20日

;*****************************************************************************************/

    IF :DEF: EN_CRP

        IF  . >= 0x1fc

        INFO    1,"/nThe data at 0x000001fc must be 0x87654321./nPlease delete some source before this line."

        ENDIF

CrpData

    WHILE . < 0x1fc ;循环用NOP填充,直到0x1FC

    NOP

    WEND

CrpData1

    DCD     0x87654321          ;/* 当此数为0x87654321时,用户程序被保护 */

    ENDIF

;/* 分配堆栈空间 */

        AREA    MyStacks, DATA, NOINIT, ALIGN=2

SvcStackSpace      SPACE   SVC_STACK_LEGTH * 4  ; 管理模式堆栈空间

IrqStackSpace      SPACE   IRQ_STACK_LEGTH * 4  ; 中断模式堆栈空间

FiqStackSpace      SPACE   FIQ_STACK_LEGTH * 4  ; 快速中断模式堆栈空间

AbtStackSpace      SPACE   ABT_STACK_LEGTH * 4  ; 中止义模式堆栈空间

UndtStackSpace     SPACE   UND_STACK_LEGTH * 4  ; 未定义模式堆栈

        AREA    Heap, DATA, NOINIT ;Heap通过分散加载文件定位

bottom_of_heap    SPACE   1

        AREA    Stacks, DATA, NOINIT ;Stack通过分散加载文件定位

StackUsr

    END

2.IRQ.S

NoInt       EQU 0x80

USR32Mode   EQU 0x10

SVC32Mode   EQU 0x13

SYS32Mode   EQU 0x1f

IRQ32Mode   EQU 0x12

FIQ32Mode   EQU 0x11

    CODE32

    AREA    IRQ,CODE,READONLY

    MACRO

$IRQ_Label HANDLER $IRQ_Exception_Function

        EXPORT  $IRQ_Label                      ; 输出的标号

        IMPORT  $IRQ_Exception_Function         ; 引用的外部标号

$IRQ_Label

        SUB     LR, LR, #4                      ; 计算返回地址

        STMFD   SP!, {R0-R3, R12, LR}           ; 保存任务环境

        MRS     R3, SPSR                        ; 保存状态

        STMFD   SP, {R3,LR}^                    ; 保存SPSR和用户状态的SP,注意不能回写

                                                ; 如果回写的是用户的SP,所以后面要调整SP

        NOP

        SUB     SP, SP, #4*2

        MSR     CPSR_c, #(NoInt | SYS32Mode)    ;  切换到系统模式    

        BL      $IRQ_Exception_Function         ;  调用c语言的中断处理程序

        MSR     CPSR_c, #(NoInt | IRQ32Mode)    ; Switch bak to IRQ mode 切换回irq模式

        LDMFD   SP, {R3,LR}^                    ; 恢复SPSR和用户状态的SP,注意不能回写

                                                ; 如果回写的是用户的SP,所以后面要调整SP

        MSR     SPSR_cxsf, R3

        ADD     SP, SP, #4*2                    

        LDMFD   SP!, {R0-R3, R12, PC}^          

    MEND

;/* 以下可添加中断句柄,根据实际情况改变 */

;Timer0_Handler  HANDLER Timer0

    END

3.Target.C

#define IN_TARGET

#include "config.h"

void __irq IRQ_Exception(void)

{

    while(1);                   //  这一句替换为自己的代码

}

void FIQ_Exception(void)

{

    while(1);                   //  这一句替换为自己的代码

}

void TargetInit(void)

{

    /* 添加自己的代码 */

}

        void TargetResetInit(void)

{

#ifdef __DEBUG_RAM     //如果在片内RAM调试

    MEMMAP = 0x2;                   //映射到片内RAM

#endif

#ifdef __DEBUG_FLASH     //如果在片内Flash调试

    MEMMAP = 0x1;                   //映射到片内FLASH

#endif

#ifdef __IN_CHIP     //如果在片内Flash发布(将会被加密)

    MEMMAP = 0x1;                   //映射到片内FLASH

#endif

/* 设置系统各部分时钟 */

    PLLCON = 1; //设置激活但未连接PLL

#if (Fpclk / (Fcclk / 4)) == 1

    VPBDIV = 0;

#endif

#if (Fpclk / (Fcclk / 4)) == 2

    VPBDIV = 2;

#endif

#if (Fpclk / (Fcclk / 4)) == 4

    VPBDIV = 1;

#endif

//设定PLL的乘因子M和除因子P的值

#if (Fcco / Fcclk) == 2

    PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5);

#endif

#if (Fcco / Fcclk) == 4

    PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5);

#endif

#if (Fcco / Fcclk) == 8

    PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5);

#endif

#if (Fcco / Fcclk) == 16

    PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5);

#endif

    PLLFEED = 0xaa; //发送PLL馈送序列,执行设定PLL的动作

    PLLFEED = 0x55;

    while((PLLSTAT & (1 << 10)) == 0); //等待PLL锁定

    PLLCON = 3; //设置激活并连接PLL

    PLLFEED = 0xaa; //发送PLL馈送序列,执行激活和链接动作

    PLLFEED = 0x55;

    /* 设置存储器加速模块 */

    MAMCR = 0; //禁止MAM功能

#if Fcclk < 20000000 //根据Fcclk的大小来设置MAM定时寄存器

    MAMTIM = 1;

#else

#if Fcclk < 40000000

    MAMTIM = 2;

#else

    MAMTIM = 3;

#endif

#endif

    MAMCR = 2; //使能MAM

    /* 初始化VIC */

    VICIntEnClr = 0xffffffff; //清零所有中断

    VICVectAddr = 0;

    VICIntSelect = 0;

    /* 添加其他的代码 */

}

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

**                  以下为一些与系统相关的库函数的实现

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

#include <rt_sys.h>

#include <stdio.h>

#pragma import(__use_no_semihosting_swi)

 int __rt_div0(int a)

{

    a = a;

    return 0;

}

 int fputc(int ch,FILE *f)

{

    ch = ch;

    f = f;

    return 0;

}

int fgetc(FILE *f)

{

    f = f;

    return 0;

}

int _sys_close(FILEHANDLE fh)

{

    fh = fh;

    return 0;

}

int _sys_write(FILEHANDLE fh, const unsigned char * buf, unsigned len, int mode)

{

    fh = fh;

    buf = buf;

    len =len;

    mode = mode;

    return 0;

}

int _sys_read(FILEHANDLE fh, unsigned char * buf,

                     unsigned len, int mode)

{

    fh = fh;

    buf = buf;

    len =len;

    mode = mode;

    return 0;

}

void _ttywrch(int ch)

{

    ch = ch;

}

int _sys_istty(FILEHANDLE fh)

{

    fh = fh;

    return 0;

}

int _sys_seek(FILEHANDLE fh, long pos)

{

    fh = fh;

    return 0;

}

int _sys_ensure(FILEHANDLE fh)

{

    fh = fh;

    return 0;

}

long _sys_flen(FILEHANDLE fh)

{

    fh = fh;

    return 0;

}

int _sys_tmpnam(char * name, int sig, unsigned maxlen)

{

    name = name;

    sig = sig;

    maxlen = maxlen;

    return 0;

}

void _sys_exit(int returncode)

{

    returncode = returncode;

}

char *_sys_command_string(char * cmd, int len)

{

    cmd = cmd;

    len = len;

    return 0;

}

4.config.h

#ifndef __CONFIG_H 

#define __CONFIG_H

#ifndef TRUE

#define TRUE  1

#endif

#ifndef FALSE

#define FALSE 0

#endif

typedef unsigned char  uint8;                   /* 无符号8位整型变量  */

typedef signed   char  int8;                    /* 有符号8位整型变量  */

typedef unsigned short uint16;                  /* 无符号16位整型变量 */

typedef signed   short int16;                   /* 有符号16位整型变量 */

typedef unsigned int   uint32;                  /* 无符号32位整型变量 */

typedef signed   int   int32;                   /* 有符号32位整型变量 */

typedef float          fp32;                    /* 单精度浮点数(32位长度) */

typedef double         fp64;                    /* 双精度浮点数(64位长度) */

#include    "LPC2294.h"

/* 系统设置, Fosc、Fcclk、Fcco、Fpclk必须定义*/

#define Fosc            11059200        //应当与实际一至晶振频率,10MHz~25MHz,应当与实际一至

#define Fcclk           (Fosc * 4)      //系统频率,必须为Fosc的整数倍(1~32),且<=60MHZ

#define Fcco            (Fcclk * 4)  //CCO频率,必须为Fcclk的2、4、8、16倍,范围为156MHz~320MHz

#define Fpclk           (Fcclk / 4) * 1   //VPB时钟频率,只能为(Fcclk / 4)的1、2、4倍

#include    "target.h"             

#endif

5.target.h

#ifndef __TARGET_H 

#define __TARGET_H

    #ifdef __cplusplus

    extern "C" {

    #endif

    #ifndef IN_TARGET 

extern void Reset(void); //复位

extern void TargetInit(void); //目标板初始化

    #endif

    #ifdef __cplusplus

    }

    #endif

#endif

__swi(0x00) void SwiHandle1(int Handle); //软件中断

#define IRQDisable() SwiHandle1(0) //禁止IRQ中断

#define IRQEnable() SwiHandle1(1) //使能IRQ中断

#define FIQDisable() SwiHandle1(2) //禁止FIQ中断

#define FIQEnable() SwiHandle1(3) //使能FIQ中断

6.LPC2294.H

/* 向量中断控制器(VIC)的特殊寄存器 */

#define VICIRQStatus    (*((volatile unsigned long *) 0xFFFFF000))

#define VICFIQStatus    (*((volatile unsigned long *) 0xFFFFF004))

#define VICRawIntr      (*((volatile unsigned long *) 0xFFFFF008))

#define VICIntSelect    (*((volatile unsigned long *) 0xFFFFF00C))

#define VICIntEnable    (*((volatile unsigned long *) 0xFFFFF010))

#define VICIntEnClr     (*((volatile unsigned long *) 0xFFFFF014))

#define VICSoftInt      (*((volatile unsigned long *) 0xFFFFF018))

#define VICSoftIntClear (*((volatile unsigned long *) 0xFFFFF01C))

#define VICProtection   (*((volatile unsigned long *) 0xFFFFF020))

。。。。。。省略

7.men_a.Scf适用于片内Flash发布

ROM_LOAD 0x00000000 ;加载区,从0x00000000开始

{

    ROM_EXEC 0x00000000 ;执行区,起始地址,空间大小要和加载区一致

    {

        Startup.o (vectors, +First) ;startup.S中的向量表

        * (+RO) ;其他代码

    }

    IRAM 0x40000000 ;变量区,内部RAM开始

    {

        Startup.o (MyStacks) ;startup.S中的MyStacks

        * (+RW,+ZI) ;文件中的其他变量

    }

    HEAP +0 UNINIT ;系统堆空间

    {

        Startup.o (Heap) ;startup.S中的Heap

    }

    STACKS 0x40002000 UNINIT ;LPC2131片内RAM最高端

    { ;系统的堆空间

        Startup.o (Stacks) ;startup.S中的Stacks

    }

}

8.men_c.Scf适用于片内Flash调试

ROM_LOAD 0x0

{

    ROM_EXEC 0x00000000

    {

        Startup.o (vectors, +First)

        * (+RO)

    }

    IRAM 0x40000000

    {

        Startup.o (MyStacks)

        * (+RW,+ZI)

    }

    HEAP +0 UNINIT

    {

        Startup.o (Heap)

    }

    STACKS 0x40002000 UNINIT

    {

        Startup.o (Stacks)

    }

}

2.启动代码工作流程

1.芯片复位后,PC=0x00000000,在异常向量表0x00000000处

2.芯片根据异常处理程序地址表,得到复位程序的地址

3.跳转到复位处理程序处

4.调用InitStack()函数,初始化个模式的堆栈

5.调用Target.c中的TargetResetInit函数,初始化目标板:设置Remap,各部分时钟,存储器加速模块和VIC等

6.跳转到用户C程序入口main()处

3.修改uC/OSII代码(完成移植)

1.要移植一个操作系统到一个特定的CPU体系结构上,并不是一件很容易的事情。对移植者有以下要求:

(1)对目标体系结构要有深入的了解:

     参考资料:ARM公司。ARM Architecture Reference Manual。

(2)对OS原理要有深入的了解;

 参考资料:Labrosse J Jean。嵌入式实时操作系统uC/OS-II(第二版)。邵贝贝等译。

(3)对所使用的编译器要有较深的了解;

   参考资料:ADS自带的编译器和连接器的手册

(4)对需要移植的操作系统要有相当的了解;

 参考资料:Labrosse J Jean。嵌入式实时操作系统uC/OS-II(第二版)。邵贝贝等译。

(5)对具体使用的芯片也要一定的了解;

 参考资料:LPC2131的数据手册和使用手册

2.需要移植的文件有:OS_CPU.H,OS_CPU_A.ASM,OS_CPU_C.C,IRQINC

(1).OS_CPU.H文件:定义与编译器无关的数据类型和堆栈的数据类型,以及一些开关中断的宏代码,例如:BOOLEAN,INT8U等数据类型,OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()开关中断宏,OS_STK_GROWTH堆栈的增长方向,OS_TASLK_SW任务切换时执行的代码。源代码如下:

/****************************************Copyright (c)************************************

**                              FreshAir嵌入式软件开发团队

**                                     软件开发团队

**                                        技术部 

**                                 http://www.freshiair.com

**--------------文件信息-------------------------------------------------------------------

**文   件   名: os_cpu.h

**创   建   人: 吴友强

**最后修改日期: 2009年7月28日

**描        述: μCOS-II在LPC210x上的移植代码CPU配置部分,用ADS1.2编译

**--------------当前版本修订---------------------------------------------------------------

** 修改人: 吴友强

** 日 期: 2009年7月18日

** 描 述: 增加函数

**-----------------------------------------------------------------------------------------

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

#ifdef OS_CPU_GLOBALS

#define OS_CPU_EXT

#else

#define OS_CPU_EXT extern

#endif

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

*                    定义与编译器无关的数据类型

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

typedef  unsigned char  BOOLEAN;

typedef unsigned char  INT8U;

typedef  signed char  INT8S;

typedef  unsigned short  INT16U;

typedef  signed short  INT16S;

typedef unsigned int INT32U;

typedef signed int INT32S;

typedef float FP32;

typedef double FP64;

typedef unsigned int OS_STK;

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

*                    与ARM7体系结构相关的一些定义

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

#define OS_CRITICAL_METHOD 2 /*选择开、关中断的方式*/

__swi(0x00) void OS_TASK_SW(void); /*任务级任务切换函数*/

__swi(0x01) void _OSStartHighRdy(void); /*运行优先级最高的任务*/

__swi(0x02) void OS_ENTER_CRITICAL(void); /*关中断*/

__swi(0x03) void OS_EXIT_CRITICAL(void); /*开中断*/

__swi(0x80) void ChangeToSYSMode(void); /*任务切换到系统模式*/

__swi(0x81) void ChangeToUSRMode(void); /*任务切换到用户模式*/

__swi(0x82) void TaskIsARM(INT8U prio); /*任务代码是ARM代码*/

__swi(0x83) void TaskIsTHUMB(INT8U prio); /*任务代码是Thumb代码*/

__swi(0x40) void *GetOSFunctionAddr(int Index); /*获取系统服务函数入口*/

__swi(0x41) void *GetUsrFunctionAddr(int Index);/*获取自定义服务函数入口*/

__swi(0x42) void OSISRBegin(void); /*中断开始处理*/

__swi(0x43) void OSISRNeedSwap(void); /*判断中断是否需要切换*/

#define OS_STK_GROWTH 1 /*堆栈是从上往下长的*/

#define USR32Mode 0x10

#define SYS32Mode 0x1f

#define NoInt 0x80

#ifndef USER_USING_MODE

#define USER_USING_MODE USER32Mode /*任务缺省模式*/

#endif

#ifndef OS_SELF_EN

#define OS_SELF_EN 0 /*允许返回OS与任务分别编译、固化*/  

#endif

OS_CPU_EXT INT32U OsEnterSum; /*关中断计数器(开关中断的信号量)*/

(2).OS_CPU_C.C文件:OSTaskStkInit()任务堆栈初始化函数和一些uC/OS-II在执行某些操作时调用的用户函数,一般为空,但是需要,避免编译警告。源代码如下:

/****************************************Copyright (c)************************************

**                              FreshAir嵌入式软件开发团队

**                                     软件开发团队

**                                        技术部 

**                                 http://www.freshiair.com

**--------------文件信息-------------------------------------------------------------------

**文   件   名: os_cpu_c.c

**创   建   人: 吴友强

**最后修改日期: 2009年7月28日

**描        述: μCOS-II在LPC210x上的移植代码CPU配置部分,用ADS1.2编译

**--------------当前版本修订---------------------------------------------------------------

** 修改人: 吴友强

** 日 期: 2009年7月18日

** 描 述: 增加函数

**-----------------------------------------------------------------------------------------

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

#define  OS_CPU_GLOBALS

#include "config.h"

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

** 函数名称: OSTaskStkInit

** 功能描述: 任务堆栈初始化代码,本函数调用失败会使系统崩溃

** 输 入: task  : 任务开始执行的地址

**         pdata :传递给任务的参数

**         ptos  :任务的堆栈开始位置

**         opt   :附加参数,当前版本对于本函数无用,具体意义参见OSTaskCreateExt()的opt参数

** 输 出: 栈顶指针位置

** 作 者: 吴友强

** 日 期: 2009年7月28日

**-----------------------------------------------------------------------------------------

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

OS_STK *OSTaskStkInit(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)

{

    OS_STK *stk ;

    opt    = opt;                           /* 'opt' is not used, prevent warning       */

    stk    = ptos;           /* Load stack pointer       */

    /* build a context for the new task */

    *stk = (OS_STK)task;    /* pc */

    *--stk = (OS_STK)task;        /* lr */

    *--stk = 0;                         /* r12 */

    *--stk = 0;                         /* r11 */

    *--stk = 0;                         /* r10 */

    *--stk = 0;                         /* r9 */

    *--stk = 0;                         /* r8 */

    *--stk = 0;                         /* r7 */

    *--stk = 0;                         /* r6 */

    *--stk = 0;                         /* r5 */

    *--stk = 0;                         /* r4 */

    *--stk = 0;                         /* r3 */

    *--stk = 0;                         /* r2 */

    *--stk = 0;                         /* r1 */

    *--stk = (unsigned int) pdata;      /* r0 ,第一个参数使用R0传递*/

    *--stk = (USER_USING_MODE | 0x00);  /* spsr, 允许IRQ,FIQ中断*/

    *--stk = 0;                  /* 关中断计数器OsEnterSum */

    return (stk);

}

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

** 函数名称: SWI_Exception

** 功能描述: 软中断异常处理程序,提供一些系统服务

**           

** 输 入:  SWI_Num:功能号

**          Regs[0] 为第一个参数,也是返回值

**          Regs[1] 为第二个参数

**          Regs[2] 为第三个参数

**          Regs[3] 为第四个参数

** 输 出: 根据功能而定

** 作 者: 吴友强

** 日 期: 2009年7月19日

**-----------------------------------------------------------------------------------------

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

#if OS_SELF_EN > 0

extern int const _OSFunctionAddr[];

extern int const _UsrFunctionAddr[];

#endif

void SWI_Exception(int SWI_Num, int *Regs)

{

OS_TCB *ptcb;

switch (SWI_Num)

{

case 0x02: /* 关中断函数OS_ENTER_CRITICAL()*/

__asm

{

MRS R0,SPSR

ORR R0,R0,#NoInt

MSR SPSR_c,R0

}

OsEnterSum++;

break;

case 0x03: /* 开中断函数OS_EXIT_CRITICAL()*/

if (--OsEnterSum == 0)

{

__asm

{

MRS R0,SPSR

BIC R0,R0,#NoInt

MSR SPSR_c,R0

}

}

break;

#if OS_SELF_EN > 0

case 0x40: /* 返回指定系统服务函数的地址       */

                                        /* 函数地址存于数组_OSFunctionAddr中*/

                                        /* 数组_OSFunctionAddr需要另外定义  */

                                        /* Regs[0] 为第一个参数,也是返回值 */

                                        /* Regs[1] 为第二个参数             */

                                        /* Regs[2] 为第三个参数             */

                                        /* Regs[3] 为第四个参数             */

                                        /* 仅有一个参数为系统服务函数的索引 */

            Regs[0] = _OSFunctionAddr[Regs[0]];

            break;

            

            case 0x41:

                                        /* 返回指定用户的服务函数的地址     */

                                        /* 函数地址存于数组_UsrFunctionAddr中*/

                                        /* 数组_UsrFunctionAddr需要另外定义 */

                                        /* Regs[0] 为第一个参数,也是返回值 */

                                        /* Regs[1] 为第二个参数             */

                                        /* Regs[2] 为第三个参数             */

                                        /* Regs[3] 为第四个参数             */

                                        /* 仅有一个参数为用户服务函数的索引 */

            Regs[0] =  _UsrFunctionAddr[Regs[0]];

            break;

        case 0x42:                      /* 中断开始处理 */

            OSIntNesting++;

            break;         

        case 0x43:                      /*  判断中断是否需要切换             */

            if (OSTCBHighRdy == OSTCBCur)

            {

                Regs[0] = 0;

            }

            else

            {

                Regs[0] = 1;

            }

            break;

#endif

case 0x80: /* 任务切换到系统模式 */

__asm

{

MRS R0,SPSR

BIC R0,R0,#0x1f

ORR R0,R0,#SYS32Mode

MSR SPSR_c,R0

}

break;

case 0x81: /* 任务切换到用户模式 */

__asm

{

MRS R0,SPSR

BIC R0,R0,#0x1f

ORR R0,R0,#USR32Mode

MSR SPSR_c,R0

}

break;

case 0x82: /* 任务是ARM代码 */

if (Regs[0] <= OS_LOWEST_PRIO)

{

ptcb = OSTCBPrioTbl[Regs[0]];

if (ptcb != NULL)

{

ptcb->OSTCBStkPtr[1] &= ~(1 << 5);

}

}

break;

case 0x83: /* 任务是THUMB代码 */

if (Regs[0] <= OS_LOWEST_PRIO)

{

ptcb = OSTCBPrioTbl[Regs[0]];

if (ptcb != NULL)

{

ptcb->OSTCBStkPtr[1] |= (1 << 5);

}

}

break;

default:

break;

}

}

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

** 函数名称: OSStartHighRdy

** 功能描述: uC/OS-II启动时使用OSStartHighRdy运行第一个任务,

**           实质是产生swi 1指令

** 作 者: 吴友强

** 日 期: 2009年7月28日

**-----------------------------------------------------------------------------------------

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

void OSStartHighRdy(void)

{

    _OSStartHighRdy();

}

/* 以下为一些钩子函数,全部为空函数。*/

#if OS_CPU_HOOKS_EN

#if OS_VERSION > 203

void OSInitHookBegin (void)

{

}

#endif

#if OS_VERSION > 203

void OSInitHookEnd (void)

{

}

#endif

void OSTaskCreateHook (OS_TCB *ptcb)

{

    ptcb = ptcb;                       /* Prevent compiler warning   */

}

void OSTaskDelHook (OS_TCB *ptcb)

{

    ptcb = ptcb;                       /* Prevent compiler warning   */

}

void OSTaskSwHook (void)

{

}

void OSTaskStatHook (void)

{

}

#if OS_VERSION > 203

void OSTCBInitHook (OS_TCB *ptcb)

{

    ptcb = ptcb;                       /* Prevent Compiler warning     */

}

#endif

#if OS_VERSION >= 251

void OSTaskIdleHook (void)

{

}

#endif

#endif

(3)OS_CPU_A.ASM文件:进入多任务环境时,应运行优先级最高的任务OSStartHighRdy()函数,中断退出时的任务切换函数OSIntCtxSw()和时钟节拍中断服务程序;为使用ADS1.2编译器的管理这个文件改名为OS_CPU_A.S。源代码如下:

;/****************************************Copyright (c)************************************

;**                              FreshAir嵌入式软件开发团队

;**                                     软件开发团队

;**                                        技术部 

;**                                 http://www.freshiair.com

;**--------------文件信息------------------------------------------------------------------

;**文   件   名: os_cpu_a.s

;**创   建   人: 吴友强

;**最后修改日期: 2009年7月19日

;**--------------当前版本修订--------------------------------------------------------------

;** 修改人: 吴友强

;** 日 期: 2009年7月29日

;**----------------------------------------------------------------------------------------

;*****************************************************************************************/

;定义系统模式堆栈的大小

SVC_STACK_LEGTH EQU 32

NoInt EQU 0x80

USR32Mode EQU 0x10

SVC32Mode EQU 0x13

SYS32Mode EQU 0x1f

IRQ32Mode EQU 0x12

FIQ32Mode EQU 0x11

;T_bit用于检测进入异常前cpu是否处于THUMB状态

T_bit EQU 0x20

CODE32

AREA |subr|,CODE,READONLY

IMPORT  OSTCBCur                    ;指向当前任务TCB的指针

            IMPORT  OSTCBHighRdy                ;指向将要运行的任务TCB的指针

            IMPORT  OSPrioCur                   ;当前任务的优先级

            IMPORT  OSPrioHighRdy               ;将要运行的任务的优先级

            IMPORT  OSTaskSwHook                ;任务切换的钩子函数

            IMPORT  OSRunning                   ;uC/OS-II运行标志

            IMPORT  OsEnterSum                  ;关中断计数器(关中断信号量)

            IMPORT  SWI_Exception               ;软中断异常处理程序         

            EXPORT  __OSStartHighRdy            

            EXPORT  OSIntCtxSw                  ;中断退出时的入口,参见startup.s中的IRQ_Handler

            EXPORT  SoftwareInterrupt           ;软中断入口

            

            

;/*****************************************************************************************

;** 函数名称: SoftwareInterrupt

;** 功能描述: 软件中断,用于提供一些系统服务

;** 输 入:   依功能而定

;** 输 出 :  依功能而定

;** 调用模块: SWI_Exception

;** 作 者: 吴友强

;** 日 期: 2009年7月29日

;**----------------------------------------------------------------------------------------

;*****************************************************************************************/

;软件中断

SoftwareInterrupt

        LDR     SP, StackSvc            ; 重新设置堆栈指针

        STMFD   SP!, {R0-R3, R12, LR}

        MOV     R1, SP                  ; R1指向参数存储位置

        MRS     R3, SPSR

        TST     R3, #T_bit              ; 中断前是否是Thumb状态

        LDRNEH  R0, [LR,#-2]            ; 是: 取得Thumb状态SWI号

        BICNE   R0, R0, #0xff00

        LDREQ   R0, [LR,#-4]            ; 否: 取得arm状态SWI号

        BICEQ   R0, R0, #0xFF000000

                                        ; r0 = SWI号,R1指向参数存储位置

        CMP     R0, #1

        LDRLO   PC, =OSIntCtxSw

        LDREQ   PC, =__OSStartHighRdy   ; SWI 0x01为第一次任务切换

        BL      SWI_Exception     

        LDMFD   SP!, {R0-R3, R12, PC}^        

StackSvc           DCD     (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)

;/*****************************************************************************************

;** 函数名称: OSIntCtxSw

;** 功能描述: 中断退出时的入口

;** 输 入:   R3    :当前任务的状态寄存器CPSR(即SPSR的值)

;**           R4-R12:当前任务的R4-R11

;**           当前处理器模式的堆栈结构(出栈次序):R0-R3、R12、PC(当前任务的)

;** 输 出 :  无

;** 全局变量: OSPrioCur,OSPrioHighRdy,OSPrioCur,OSPrioHighRdy

;** 作 者: 吴友强

;** 日 期: 2009年7月29日

;**----------------------------------------------------------------------------------------

;*****************************************************************************************/

OSIntCtxSw

                                                    ;下面为保存任务环境

        LDR     R2, [SP, #20]                       ;获取PC

        LDR     R12, [SP, #16]                      ;获取R12

        MRS     R0, CPSR

        MSR     CPSR_c, #(NoInt | SYS32Mode)

        MOV     R1, LR

        STMFD   SP!, {R1-R2}                        ;保存LR,PC

        STMFD   SP!, {R4-R12}                       ;保存R4-R12

        MSR     CPSR_c, R0

        LDMFD   SP!, {R4-R7}                        ;获取R0-R3

        ADD     SP, SP, #8                          ;出栈R12,PC        

        MSR     CPSR_c, #(NoInt | SYS32Mode)

        STMFD   SP!, {R4-R7}                        ;保存R0-R3        

        LDR     R1, =OsEnterSum                     ;获取OsEnterSum

        LDR     R2, [R1]

        STMFD   SP!, {R2, R3}                       ;保存CPSR,OsEnterSum

                                                    ;保存当前任务堆栈指针到当前任务的TCB

        LDR     R1, =OSTCBCur

        LDR     R1, [R1]

        STR     SP, [R1]

        BL      OSTaskSwHook                        ;调用钩子函数

                                                    ;OSPrioCur <= OSPrioHighRdy

        LDR     R4, =OSPrioCur

        LDR     R5, =OSPrioHighRdy

        LDRB    R6, [R5]

        STRB    R6, [R4]

                                                    ;OSTCBCur <= OSTCBHighRdy

        LDR     R6, =OSTCBHighRdy

        LDR     R6, [R6]

        LDR     R4, =OSTCBCur

        STR     R6, [R4]

OSIntCtxSw_1

                                                    ;获取新任务堆栈指针

        LDR     R4, [R6]

        ADD     SP, R4, #68                         ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP

        LDR     LR, [SP, #-8]

        MSR     CPSR_c, #(NoInt | SVC32Mode)        ;进入管理模式

        MOV     SP, R4                              ;设置堆栈指针

        LDMFD   SP!, {R4, R5}                       ;CPSR,OsEnterSum

                                                    ;恢复新任务的OsEnterSum

        LDR     R3, =OsEnterSum

        STR     R4, [R3]

        MSR     SPSR_cxsf, R5                       ;恢复CPSR

        LDMFD   SP!, {R0-R12, LR, PC }^             ;运行新任务

;/*****************************************************************************************

;** 函数名称: __OSStartHighRdy

;** 功能描述: uC/OS-II启动时使用OSStartHighRdy运行第一个任务,

;**           OSStartHighRdy会调用__OSStartHighRdy

;** 输 入:   无

;** 输 出 :  无

;** 全局变量: OSRunning,OSTCBCur,OSTCBHighRdy,OsEnterSum

;** 调用模块: OSTaskSwHook

;** 作 者: 吴友强

;** 日 期: 2009年7月29日

;**----------------------------------------------------------------------------------------

;*****************************************************************************************/

__OSStartHighRdy

        MSR     CPSR_c, #(NoInt | SYS32Mode)

                                                ;告诉uC/OS-II自身已经运行

        LDR     R4, =OSRunning

        MOV     R5, #1

        STRB    R5, [R4]

        BL      OSTaskSwHook                    ;调用钩子函数

        LDR     R6, =OSTCBHighRdy

        LDR     R6, [R6]

        B       OSIntCtxSw_1

        AREA    SWIStacks, DATA, NOINIT,ALIGN=2

SvcStackSpace      SPACE   SVC_STACK_LEGTH * 4  ;管理模式堆栈空间

    END

(4)IRQ.INC定义了一个宏汇编,并且是uC/OS-II for ARM7通用的中断服务程序的汇编与C语言接口代码,需要自己编写。源代码如下:

;/****************************************Copyright (c)************************************

;**                              FreshAir嵌入式软件开发团队

;**                                     软件开发团队

;**                                        技术部 

;**                                 http://www.freshiair.com

;**--------------文件信息------------------------------------------------------------------

;**文   件   名: irq.inc

;**创   建   人: 吴友强

;**最后修改日期: 2009年7月28日

;**描        述: 定义IRQ汇编接口代码宏

;**--------------历史版本信息--------------------------------------------------------------

;** 创建人: 吴友强

;** 版  本: v1.0

;** 日 期: 2009年7月29日

;*****************************************************************************************/

NoInt       EQU 0x80

USR32Mode   EQU 0x10

SVC32Mode   EQU 0x13

SYS32Mode   EQU 0x1f

IRQ32Mode   EQU 0x12

FIQ32Mode   EQU 0x11

;引入的外部标号在这声明

        IMPORT  OSIntCtxSw                      ;任务切换函数

        IMPORT  OSIntExit                       ;中断退出函数

        IMPORT  OSTCBCur

        IMPORT  OSTCBHighRdy

        IMPORT  OSIntNesting                    ;中断嵌套计数器

        IMPORT  StackUsr

        IMPORT  OsEnterSum

    CODE32

    AREA    IRQ,CODE,READONLY

    MACRO

$IRQ_Label HANDLER $IRQ_Exception_Function

        EXPORT  $IRQ_Label                      ; 输出的标号

        IMPORT  $IRQ_Exception_Function         ; 引用的外部标号

$IRQ_Label

        SUB     LR, LR, #4                      ; 计算返回地址

        STMFD   SP!, {R0-R3, R12, LR}           ; 保存任务环境

        MRS     R3, SPSR                        ; 保存状态

        STMFD   SP, {R3, SP, LR}^               ; 保存用户状态的R3,SP,LR,注意不能回写

                                                ; 如果回写的是用户的SP,所以后面要调整SP

        LDR     R2,  =OSIntNesting              ; OSIntNesting++

        LDRB    R1, [R2]

        ADD     R1, R1, #1

        STRB    R1, [R2]

        SUB     SP, SP, #4*3     

        MSR     CPSR_c, #(NoInt | SYS32Mode)    ; 切换到系统模式

        CMP     R1, #1

        LDREQ   SP, =StackUsr

        BL      $IRQ_Exception_Function         ; 调用c语言的中断处理程序

        MSR     CPSR_c, #(NoInt | SYS32Mode)    ; 切换到系统模式

        LDR     R2, =OsEnterSum                 ; OsEnterSum,使OSIntExit退出时中断关闭

        MOV     R1, #1

        STR     R1, [R2]

        BL      OSIntExit

        LDR     R2, =OsEnterSum                 ; 因为中断服务程序要退出,所以OsEnterSum=0

        MOV     R1, #0

        STR     R1, [R2]

        MSR     CPSR_c, #(NoInt | IRQ32Mode)    ; 切换回irq模式

        LDMFD   SP, {R3, SP, LR}^               ; 恢复用户状态的R3,SP,LR,注意不能回写

                                                ; 如果回写的是用户的SP,所以后面要调整SP

        LDR     R0, =OSTCBHighRdy

        LDR     R0, [R0]

        LDR     R1, =OSTCBCur

        LDR     R1, [R1]

        CMP     R0, R1

        ADD     SP, SP, #4*3                    ; 

        MSR     SPSR_cxsf, R3

        LDMEQFD SP!, {R0-R3, R12, PC}^          ; 不进行任务切换

        LDR     PC, =OSIntCtxSw                 ; 进行任务切换

    MEND

    END

2.注意事项:

(1)OS_STK_GROWTH中指定堆栈的生长方式:为1表示堆栈从下往上生长,0表示堆栈从上往下生长。

(2)在OSTaskStkInt初始化堆栈的函数必须保存CPU相关资源,如寄存器。

3.其他的都在移植源代码中有相关注释及说明。

   三.完成项目

1.源代码编译通过,完成了所有的移植工作,项目也达到预期的效果,操作系统正常的跑起来了。

2.通过应用程序的测试,下面是运行成功后的第一个应用的主程序:

/****************************************Copyright(c)**************************************

**                            FreshAir嵌入式软件开发团队

**                                      FreshAir

**                                 http://www.FreshAir.com

**--------------File Info------------------------------------------------------------------

** File name: main.c

** Last modified Date:  2009-07-22

** Created by: 吴友强

**Created date:2009年7月21日0:00

** Version: V1.0

** Descriptions:成功移植uCOSII操作系统后的第一个应用程序:GPIO输出实验

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

#include "config.h"

#include "stdlib.h"

#define LED1 (1 << 18)

#define LED2 (1 << 19)

#define TaskStkLengh 64 //定义用户任务0的堆栈长度

#define TaskLED1StkSize 128 //定义用户任务1的堆栈长度

#define TaskLED2StkSize 128 //定义用户任务2的堆栈长度

 

OS_STK TaskStk [TaskStkLengh]; //定义用户任务0的堆栈

OS_STK TaskLED1Stk[TaskLED1StkSize];//定义用户任务1的堆栈

OS_STK TaskLED2Stk[TaskLED2StkSize];//定义用户任务2的堆栈

void  Task0(void *pdata); //Task0 任务0

void TaskLED1(void *data);

void TaskLED2(void *data);

int main (void)

{

OSInit ();

OSTaskCreate (Task0,(void *)0, &TaskStk[TaskStkLengh - 1], 2);

OSStart ();

return 0;

}

/******************************************************************************************                             Task0 任务0

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

void Task0 (void *pdata)

{

pdata = pdata;

TargetInit ();

OSTaskCreate(TaskLED1, (void *)0, &TaskLED1Stk[TaskLED1StkSize - 1], 3);

OSTaskCreate(TaskLED2, (void *)0, &TaskLED2Stk[TaskLED2StkSize - 1], 4);

while (1)

{

OSTimeDly(10);

}

}

void TaskLED1(void *pdata)

{

pdata = pdata;

PINSEL2 = PINSEL2 & (~0x08);

IO1DIR |= LED1;

IO1SET = LED1;

for (; ;)

{

IO1CLR = LED1;

OSTimeDly(OS_TICKS_PER_SEC / 4);

IO1SET = LED1;

OSTimeDly(OS_TICKS_PER_SEC / 2);

}

}

void TaskLED2(void *pdata)

{

pdata = pdata;

PINSEL2 = PINSEL2 & (~0x08);

IO1DIR |= LED2;

IO1SET = LED2;

for (; ;)

{

IO1CLR = LED2;

OSTimeDly(OS_TICKS_PER_SEC / 2);

IO1SET = LED2;

OSTimeDly(OS_TICKS_PER_SEC / 1);

}

}

四.项目经验总结及心得

1.通过长期的学习相关知识和不断的尝试编码及测试,终于成功的所有的源代码通过编译,在看到没有错误提示的那一刻是多么的兴奋无法形容。

2.虽然这个项目成功并且是出色的完成了,但这只是开始,是以后做项目的开端,可以把这个项目运用到以后项目中去

3.通过自学和不断的摸索让自己的自学能力有很大幅度提高,项目的成功完成也让我对自己未来的学习更有信心,为自己下一步学习linux操作系统和ARM9及ARM10或ARM11打下了良好的基础。

4.通过<<嵌入式实时操作系统μC/OS-Ⅱ(第二版)>>阅读让我基本掌握了μC/OS-Ⅱ这个操作系统,主要学习里面的设计思想,这个操作系统属于RTOS,对于这一类设计思想有了一个很好的了解,更重要的一点在阅读这个系统的源代码时吸收了许多很好的编程风格和编程思路,当然还有更多的编程技巧。

5.移植过程中遇到主要问题解决:

(1)编译器产生#error这个地方错误,通过查看编译器的文档,通过加入-Ep编译选项成功解决。

(2)头文件包含错误,主要是文件组织结构没有弄好,最后还是下定决心从新开始,通过解决一个两个等的编译错误最终成功并且运行 

(3)移植的过程中对于很多宏定义出现错误,要不是没有定义,要不是重复定义,最终通过耐心修改源代码得以解决

6.通过解决项目过程中遇到的很多问题,提高了自己解决问题的能力,也让自己相信,只要努力做一件事并且坚持不懈,最终是能够成功的

原文地址:https://www.cnblogs.com/brucewoo/p/2252039.html