移植ucosII到STM32F103ZE(五)

发布者:shmilyde最新更新时间:2015-10-23 来源: eefocus关键字:移植  ucosII  STM32F103ZE 手机看文章 扫描二维码
随时随地手机看文章
os_cpu_a.asm   
这个文件包含着必须用汇编写的代码。
    EXTERN  OSRunning    ; External references  
    EXTERN  OSPrioCur  
    EXTERN  OSPrioHighRdy  
    EXTERN  OSTCBCur  
    EXTERN  OSTCBHighRdy  
    EXTERN  OSIntNesting  
    EXTERN  OSIntExit  
    EXTERN  OSTaskSwHook  
申明这些变量是在其他文件定义的,本文件只做引用(有几个好像并未引用,不过没有关系)。
    EXPORT  OS_CPU_SR_Save   ; Functions declared in this file  
    EXPORT  OS_CPU_SR_Restore  
    EXPORT  OSStartHighRdy  
    EXPORT  OSCtxSw  
    EXPORT  OSIntCtxSw  
    EXPORT  OS_CPU_PendSVHandler    ; #0
     #0这里 OS_CPU_PendSVHandler 要替换为PendSV_Handler;如下图:
 
替换后的 PPendSV中断
声明这些函数是在本文件中定义的。EXPORT这个关键字是跟编译器有关的,能被keil识别,但不能被IAR 识别。
NVIC_INT_CTTRL     EQU     0xE000ED04   ;中断控制及状态寄存器 ICSR 的地址
NVIC_SYSPRI14      EQU     0xE000ED22   ;PendSV优先级寄存器的地址
NVIC_PENDSV_PRI   EQU     00xFF         ; PendSV 中断的优先级为 255(最低)
NVIC_PENDSVSET   EQU      0x10000000   ; 位 28 为 1  
     ;定义几个常量,类似 C 语言中的#define预处理指令。
S_CPU_SR_Save  
     MRS     R0, PRIMASK   ;读取 PRIMASK 到R0 中,R0 为返回值  
     CPSID                ;PRIMASK=1,关中断(NMI 和硬 fault 可以响应)  
     BX       LR            ;返回 
  
OS_CPU_SR_Restore  
     MSR     PRIMASK, R0   ;读取 R0 到PRIMASK 中,R0 为参数 
     BX      LR              ;返回 
  
OSStartHighRdy()由 OSStart()调用,用来启动最高优先级任务,当然任务必须在OSStart()前已被创建。  
OSStartHighRdy      
     ;设置 PendSV 中断的优先级 #1  
     LDR     R0, =NVIC_SYSPRI14      ;R0 = NVIC_SYSPRI14  
     LDR     R1, =NVIC_PENDSV_PRI   ;R1 = NVIC_PENDSV_PRI  
     STRB    R1, [R0]                ; *(uint8_t *)NVIC_SYSPRI14 = NVIC_PENDSV_PRI 
     ;设置 PSP 为0  #2  
     MOVS    R0, #0                ;R0 = 0  
     MSR     PSP, R0               ;PSP = R0 
     ;设置 OSRunning 为TRUE  
     LDR     R0, =OSRunning         ;R0 = OSRunning  
     MOVS   R1, #1                 ;R1 = 1  
     STRB    R1, [R0]                ;OSRunning = 1  
     ;触发 PendSV 中断 #3  
     LDR     R0, =NVIC_INT_CTRL     ;R0 = NVIC_INT_CTRL  
     LDR     R1, =NVIC_PENDSVSET  ;R1 = NVIC_PENDSVSET  
     STR     R1, [R0]                  ; *(uint32_t *)NVIC_INT_CTRL = NVIC_PENDSVSET 
     CPSIE                          ;开中断  
OSStartHang    
     ;死循环,应该不会到这里 
          OSStartHang   
     #1.PendSV 中断的优先级应该为最低优先级,原因在<>的 7.6 节已有说明。  
     #2.PSP 设置为 0,是告诉具体的任务切换程序(OS_CPU_PendSVHandler()),这是第一次任务切换。做过切换后 PSP 就不会为0了,后面会看到。  
     #3.往中断控制及状态寄存器 ICSR(0xE000ED04)第 28 位写 1 即可产生 PendSV 中断。这个<>8.4.5 其它异常的配置寄存器有说明。  
     当一个任务放弃 cpu 的使用权,就会调用OS_TASK_SW()宏,而 OS_TASK_SW()就是 OSCtxSw()。OSCtxSw()应该做任务切换。但是在 CM3 中,所有任务切换都被放到PendSV 的中断处理函数中去做了,因此 OSCtxSw() 只需简单的触发 PendSV中断即可。OS_TASK_SW()是由OS_Sched()调用。  
void  OS_Sched (void)  
 
# if  OS_CRITICAL_METHOD==3  
     OS_CPU_SR  cpu_sr = 0;  
#endif
OS_ENTER_CRITICAL();  
     
    if (OSIntNesting ==0) {  
        if (OSLockNesting == 0) {  
            OS_SchedNew();  
            if (OSPrioHighRdy != OSPrioCur) 
             
                OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];  
#if OS_TASK_PROFILE_EN > 0  
                OSTCBHighRdy->OSTCBCtxSwCtr++;  
#endif  
                OSCtxSwCtr++;   
                OS_TASK_SW();      
            
        
    
     
   OS_EXIT_CRITICAL();    

  
OSCtxSw     ;触发PendSV 中断 
    LDR     R0, =NVIC_INT_CTRL     ;R0 = NVIC_INT_CTRL   
    LDR     R1, =NVIC_PENDSVSET   ;R1 = NVIC_PENDSVSET  
    STR     R1, [R0]               ;*(uint32_t *)NVIC_INT_CTRL = NVIC_PENDSVSET  
    BX      LR                    ;返回      
     当一个中断处理函数退出时,OSIntExit()会被调用来决定是否有优先级更高的任务需要执行。如果有
OSIntExit()对调用 OSIntCtxSw()做任务切换。  
OSIntCtxSw     ;触发 PendSV 中断 
    LDR     R0, =NVIC_INT_CTRL  
    LDR     R1, =NVIC_PENDSVSET  
    STR     R1, [R0]  
    BX      LR 
     看到这里有人可能奇怪怎么 OSCtxSw()和OSIntCtxSw()完全一样,事实上,这两个函数的意义是不一样的,OSCtxSw()做的是任务之间的切换,如任务 A 因为等待某个资源或是做延时切换到任务 B,而
OSIntCtxSw()则是中断退出时,由中断状态切换到另一个任务。由中断切换到任务时,CPU 寄存器入栈的工作已经做完了,所以无需做第二次了(参考邵老师书的 3.10 节)。这里只不过由于 CM3 的特殊机制导致了在这两个函数中只要做触发 PendSV中断即可,具体切换由 PendSV 中断来处理。   
     前面已经说过真正的任务切换是在 PendSV 中断处理函数里做的,由于 CM3 在中断时会有一半的寄存器自动保存到任务堆栈里,所以在 PendSV 中断处理函数中只需保存 R4-R11并调节堆栈指针即可。  [page]
     PendSV 中断处理函数伪代码如下:  
OS_CPU_PendSVHandler()  
 
        if (PSP != NULL) {  
                Save R4-R11 onto task stack;  
                OSTCBCur->OSTCBStkPtr = SP;  
 
        
        OSTaskSwHook();  
        OSPrioCur = OSPrioHighRdy;  
        OSTCBCur = OSTCBHighRdy;  
        PSP = OSTCBHighRdy->OSTCBStkPtr;  
        Restore  R4-R11 from new task stack;  
        Return  from exception;   
 
  
OS_CPU_PendSVHandler            ;xPSR, PC, LR, R12, R0-R3 已自动保存 #0 
     CPSID                      ;任务切换期间需要关中断 
     MRS     R0, PSP              ;R0 = PSP  
     ;如果 PSP ==0,跳到OS_CPU_PendSVHandler_nosave 执行 #1  
     CBZ     R0, OS_CPU_PendSVHandler_nosave     
     ;保存 R4-R11 到任务堆栈 
    SUBS    R0, R0, #0x20        ;R0 -= 0x20                           
    STM     R0, {R4-R11}         ;保存 R4-R11 到任务堆栈 
    ;OSTCBCur->OSTCBStkPtr = SP;  
    LDR     R1, =OSTCBCur        ;R1 = &OSTCBCur  
    LDR     R1, [R1]             ;R1 = *R1 (R1 = OSTCBCur)  
    STR     R0, [R1]             ;*R1 = R0 (*OSTCBCur = SP) #2                        
  
OS_CPU_PendSVHandler_nosave 
     ;调用 OSTaskSwHook()  
     PUSH    {R14}                ;保存 R14,因为后面要调用函数      
    LDR     R0, =OSTaskSwHook   ;R0 = &OSTaskSwHook   
    BLX     R0                   ;调用 OSTaskSwHook()  
    POP     {R14}                ;恢复 R14 
    ;OSPrioCur = OSPrioHighRdy;  
    LDR     R0, =OSPrioCur       ;R0 = &OSPrioCur  
    LDR     R1, =OSPrioHighRdy   ;R1 = &OSPrioHighRdy  
    LDRB    R2, [R1]             ;R2 = *R1 (R2 = OSPrioHighRdy)  
    STRB    R2, [R0]             ;*R0 = R2 (OSPrioCur = OSPrioHighRdy) 
    ;OSTCBCur = OSTCBHighRdy;  
    LDR     R0, =OSTCBCur      ;R0 = &OSTCBCur        
    LDR     R1, =OSTCBHighRdy  ;R1 = &OSTCBHighRdy  
    LDR     R2, [R1]              ;R2 = *R1 (R2 = OSTCBHighRdy)  
    STR     R2, [R0]              ;*R0 = R2 (OSTCBCur = OSTCBHighRdy) 
     LDR     R0, [R2]             ;R0 = *R2 (R0 = OSTCBHighRdy), 此时 R0 是新任务的 SP  
     ;SP = OSTCBHighRdy->OSTCBStkPtr   #3   
     LDM     R0, {R4-R11}        ;从任务堆栈 SP 恢复 R4-R11  
     ADDS    R0, R0, #0x20       ;R0 += 0x20  
     MSR     PSP, R0            ;PSP = R0,用新任务的 SP 加载PSP  
     ORR     LR, LR, #0x04      ;确保 LR 位2 为1,返回后使用进程堆栈 #4   
     CPSIE                    ;开中断 
     BX      LR                 ;中断返回 
   END 
#0 OS_CPU_PendSVHandler 要替换为 PendSV_Handler。
移植ucosII到STM32F103ZE(五)
 
  #1 如果 PSP==0,说明OSStartHighRdy()启动后第一次做任务切换,而任务刚创建时 R4-R11 已经保存在堆栈中了,所以不需要再保存一次了。 
    #2 OSTCBStkPtr 是任务控制块结构体的第一个变量,所以*OSTCBCur = SP(不是很科学)就是  OSTCBCur->OSTCBStkPtr = SP;  
    #3 和#2 类似。 
    #4 因为在中断处理函数中使用的是 MSP,所以在返回任务后必须使用PSP,所以LR位2必须为1。 
os_dbg.c   
    用于系统调试,可以不管。 
    需要修改的代码就介绍到这里,如果还有不明白之处,就再看看 AN-1018.pdf,邵老师的书和<
Cortex-M3 权威指南>>。
App.c
App.c文件中建立如下函数  App文件中有对 SysTick的初始化函数(上面已经解释过)。
     static void systick_init(void); //函数声明 
      
     static void systick_init(void)  
     
        RCC_ClocksTypeDef  rcc_clocks;  
        RCC_GetClocksFreq(&rcc_clocks);   //调用标准库函数,获取系统时钟。 
        SysTick_Config(rcc_clocks.HCLK_Frequency / OS_TICKS_PER_SEC);  //调用库函数,初始化并使能 SysTick 
                                             //OS_TICKS_PER_SEC是在 os_cfg.h 中定义的 
    
os_cfg.h 是用来配置 ucosii 系统的,对其做如下修改:   共9处
#define  OS_APP_HOOKS_EN            //关掉App 钩子功能 
#define  OS_DEBUG_EN                   //关掉uC/OS 自带调试功能 
#define  OS_EVENT_MULTI_EN             //
#define  OS_SCHED_LOCK_EN             //关掉调度加锁功能 
#define  OS_TASK_CHANGE_PRIO_EN     //关掉改变任务优先级功能 
#define  OS_TASK_QUERY_EN              //关掉任务查询功能 
#define  OS_TASK_STAT_EN                //关掉 CPU 使用率统计功能 
#define  OS_TASK_STAT_STK_CHK_EN     //关掉 CPU 使用率统计功能的堆栈设置 
#define  OS_TASK_SUSPEND_EN          //关掉任务挂起功能 
     所做的修改主要是把一些功能给去掉,减少内核大小,也利于调试。等移植完成后,如果需要该功能,
再做开启。
最后,还要记得把stm32f10x_it.h文件中的void PendSV_Handler(void);注释掉,以防和 OS_CPU.HH
文件中的声明冲突,stm32f10x_it.c 中的相应函数体也得注释掉。如图: 
移植ucosII到STM32F103ZE(五)

移植ucosII到STM32F103ZE(五)


 
 
                                     注释掉多余的PendSV 声明   
关键字:移植  ucosII  STM32F103ZE 引用地址:移植ucosII到STM32F103ZE(五)

上一篇:移植ucosII到STM32F103ZE(六)
下一篇:移植ucosII到STM32F103ZE(四)

推荐阅读最新更新时间:2024-03-16 14:37

linux-3.0移植到FL2440(只做基本的移植
首先补丁包来自凌云实验室: 1.先打补丁: patch -p1 ../linux-3.0-s3c2440.patch 2.修改 Makefile: ARCH ?= arm CROSS_COMPILE ?= arm-linux- 3.修改补丁的错误: 在/arch/arm/plat-s3c24xx/devs.c //#ifdef CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X /* UDA1341 add by guowenxue, 2012.03.30 */ //注释掉 . . . //#endif 4.make s3c2410_defconfig 5.裁剪
[单片机]
S3C2416裸机开发系列十七_GCC下Fatfs的移植
对于固态存储器,其存储容量可以很大,往往需要一款文件系统对存储器用户数据进行组织文件的管理。它对文件存储器空间进行组织和分配,负责文件的存储并对存入的文件进行保护和检索。在嵌入式系统中,往往需要采用windows兼容的文件系统,像相机的照片、视频监控、语音产品等,很多都需要从windows计算机上提取资源或在windows计算机上进一步处理。Fatfs由于其开源免费,支持fat32,受到了广泛的应用,笔者此处就s3c2416移植Fatfs,对sd卡进行读写访问作一个简单的介绍。 1. Fatfs概述 Fatfs是由日本工程师ChaN所编写的fat文件系统模块,从06年发布第一个Fatfs版本开始,作者就从未停止维护和更新。Fat
[单片机]
STM32F103移植到AT32F403A之MDK(二)
上一篇我们已经实现了不改硬件,只改软件情况下将STM32F103C8T6替换为AT32F403ACGT7的过程,但毕竟STM32F103C8T6已经是10多年前的东西了,用现在的AT32F403ACGT7替换实在是大材小用了,毕竟这颗是主频能到240M的M4。 上篇我们解决了替换能用的问题,本篇我们来结合AT32F403ACGT7的优势,实现不改硬件只改BOM降成本的方法。 从接触MCU开始,MCU外围电路中就缺少不了很重要的器件,那就晶振,晶振是MCU的时钟源。随着技术的不断发展,越来越多的MCU将晶振集成到了MCU内部,但集成到内部后真的就能够省略掉外部晶振吗,当然不是,由于技术和工艺问题,前些年的MCU还无法完全摆脱
[单片机]
STM32F103<font color='red'>移植</font>到AT32F403A之MDK(二)
一文了解移植3.4.2的Kernel到JZ2440
本文将介绍如何移植linux-3.4.2内核到JZ2440开发板上的全过程,使用的交叉编译工具版本为 arm-linux-gcc-4.3.2.tar.bz2 下面来一步一步介绍如何移植。 由于kernel的启动参数是由Uboot传递的,关键的参数有 R0=0 R1=Mach-Type R2=Tag参数地址 其中,Mach-Type为内核支持板子的硬件型号,tag参数为Uboot存放传递给Kernel参数的内存地址。 内核启动时,根据传入的Mach-Type参数选择对应的板级初始化函数来初始化,然后解析tag参数,设置相应系统状态值,装载驱动程序,最后挂载根文件系统。 1. 编译内核 修改根目录下面的Make
[单片机]
移植u-boot-2010.09到S3C2440(一)——硬件初始化与测试
在u-boot的代码选择中,只有201009是最近的可直接编译通过的,不带memset.s的u-boot版本。 屏蔽lowlevel_init的调用之后,将我在u-boot-201112版本中所做的硬件初始化全部挪到本版本中,包括串口驱动的修改,时钟设置,LED的点亮。 这个时候通过开发板自带的u-boot写到SDRAM调试就直接有串口输出与提示符。 注:本系列文档只注释难点部分,其它略过。
[单片机]
人体器官移植突破:男子植入3D打印椎骨获新生
如今已经两个多月过去了,约塞夫斯基的恢复情况相当不错。    据外媒报道,人体器官移植频传福音,3D打印再写医疗新里程。澳大利亚医生为一名患了癌症的男子进行一项全球第一例手术,替他移除被癌细胞严重破坏的椎骨,再为他植入一条用3D打印技术打印出来旳椎骨。该病人现时康复的进展良好,重获新生。   据报道,病人约塞夫斯基患了脊索瘤,是一种十分罕见的癌症。癌细胞攻击他的脊椎和头骨,并在他的颈项上方位置生长,令他饮食和说话都有困难。医学界估计,每100万人当中,只有一人患上这种病。   去年12月,神经科医生莫布斯为他进行长达15小时的手术,移除本来的椎骨,植入3D打印的脊骨。   莫布斯称,“如果不动手术,又不进行
[医疗电子]
Fedora8上交叉编译qtopia4移植成功到s3c2410开发板
教程是这样的: 一.硬件平台 1.主机: PC机,512M内存以上。 2.目标机: UP-NetARM2410-S实验平台。 二.移植软件资源 1.Red Hat Linux 9.0(主机操作系统) 2.gcc-3.4.1.tar.gz(主机编译器) 3.arm-linux-gcc-3.4.1.tar.bz2(交叉编译器) 4.tslib-1.3.tar.bz2(管理目标平台的触摸屏) 5.qtopia-opensource-src-4.2.1.tar.gz(包含Qt, Qtopia core) 2 . GUI(QT)的移植过程 编译前的约定: 1)我的工作目录为:/mnt/nfs。 2)qtopia-o
[单片机]
U-Boot在基于ADSP BF533的嵌入式Linux系统上的移植
1 引言 Boot Loader(内核引导程序)是在操作系统内核运行之前运行的一段自举程序,用于初始化硬件设备、改变处理器运行模式、重组中断向量和建立内存空间映射图,从而将系统的软硬件带到一个合适的状态或者用户定制的特定状态,以便为最终加载操作系统内核准备好正确的环境 。 嵌入式Linux系统常用的Boot Loader有arm-boot、redboot、U-Boot等。U-Boot (全称Universal Boot Loader)是当前比较流行的遵循GPL条件的开放源码项目。U-Boot具有源码公开的特点,开发人员可根据自身需要进行裁减;支持多种处理器和嵌入式操作系统内核;具有多种设备驱动源码:支持种引导方式;具有功能强大
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

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

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

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