UCOS-II移植ARM的读书笔记(12.11).doc_第1页
UCOS-II移植ARM的读书笔记(12.11).doc_第2页
UCOS-II移植ARM的读书笔记(12.11).doc_第3页
UCOS-II移植ARM的读书笔记(12.11).doc_第4页
UCOS-II移植ARM的读书笔记(12.11).doc_第5页
已阅读5页,还剩36页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

真是很郁闷,昨天晚上边看移植代码边记下来的笔记不知道怎么回事在保存的时候竟然不见了。5555。一个晚上工作的结果啊,关键是我是第一次也是正式开始移植的学习之路啊。真是够倒霉的。今天在工作之前先把昨天的笔记重新回顾一下,其实后来想想也许是件好事,可以让我今天在不借助其他的帮助的情况下自己看代码自己跟自己讲一遍,其实很多看起来是倒霉看起来是灰心的事情把我们的观点换一下那么就是一件好事。这样的情况发生在我的身上已经挺多次了。好啦,废话不说,开始补昨天的日记UCOS-II的移植需要提供2,3个文件分别介绍如下:一:OS_CPU.H1 与编译器有关的数据类型 只是按照不同的编译器编写对应的数据类型的typedef 对应于ARM7的数据类型的编写如下typedef unsigned char BOOLEAN; /* 布尔变量 */typedef unsigned char INT8U; /* 无符号8位整型变量 */typedef signed char INT8S; /* 有符号8位整型变量 */typedef unsigned short INT16U; /* 无符号16位整型变量 */typedef signed short INT16S; /* 有符号16位整型变量 */typedef unsigned int INT32U; /* 无符号32位整型变量 */typedef signed int INT32S; /* 有符号32位整型变量 */typedef float FP32; /* 单精度浮点数(32位长度) */typedef double FP64; /* 双精度浮点数(64位长度) */ 在上面定义的各种数据类型中按照ARM7的堆栈宽度选择INT32Utypedef INT32U OS_STK; /* 堆栈是32位宽度 */ 接下来一部分是为了兼容低版本UCOS的数据类型所编写的代码,在UCOS-II中暂不考虑2 与处理器相关的代码 先定义中断的实现方式,预先设定的中断方式有三种,在ARM7中设置为方式2#define OS_CRITICAL_METHOD 2 /* 选择开、关中断的方式 */ 接下来的一段是我暂时还没有完全搞懂的一部分,只知道是设定了12个软件中断的函数,当调用这些函数之前都会执行对应中断号的事情。具体的看到后面应该能完全搞懂软件中断的实现方式,该段代码在后面的文件中会有具体的解释,这里暂时不看 定义堆栈的生长方式,ARM7内核支持两种生长方式,但是ADS的C语言编译器只支持从上往下的生长方式,因此:#define OS_STK_GROWTH 1 /* 堆栈是从上往下长的,0从下往上的生长方式 */ 最后几行分别定义了用户模式01和系统模式1f以及IRQ中断禁止的指令80三个立即数,方便调用。 还有两个预定义往后看应该知道作用,暂不考虑,不是很重要。二:OS_CPU_C.C 个文件中要求用户编写10个简单的C函数,但是只有1个函数是必要的,其余的函数必须声明,但不一定要包含任何代码,大致看了一下作用好像是用来调试之类的。唯一要编写的是OSTaskStkInit() OSTaskStkInit()函数的功能是初始化任务的栈结构,任务的堆栈结构与CPU的体系结构、编译器有密切的关联。从ARM的结构可以写出如下的栈结构:程序计数器PC,程序链接器LR,R12R1,R0用于传递第一个参数pdata,CPSR/SPSR,关中断计数器(用于计算关中断的次数,这样就实现了中断的嵌套),返回的地址指针是指向的最后一个存入的数据,而不是一个空地址。 软件中断异常SWI服务程序C语言部分 void SWI_Exception(int SWI_Num, int *Regs):参数SWI_Num对应前面文件中定义的功能号,其中0、1号的功能在后面的文件中定义,这里只定义了其他10个功能。 2、3分别对应关中断和开中断 关中断:MRS R0, SPSR/在软件中断的时候直接对程序状态保存寄存器SPSR操作也就是对CPSR的操作 ORR R0, R0, #NoInt/在汇编语言中对寄存器的对应位置位用ORR,清零用BICMSR SPSR_c, R0 /SPSR_c表示的是只改变SPSR的控制段的8位代码,其他三段_f,_s,_x中标志位在_f段,其他为保留位 开中断:MRS R0, SPSR/在开中断中基本与上面相同,只是ORR改成BIC清零BIC R0, R0, #NoIntMSR SPSR_c, R 由于需要实现中断嵌套,所以只有当关中断的计数器减为0的时候才能够开中断,而且每次关中断的时候该计数器都应该加1。另外,插入汇编语言时用_asm指令。80、81、82、83分别对应系统模式、用户模式、ARM指令集、THUMB指令集 系统模式:MRS R0, SPSR BIC R0, R0, #0x1f/先将控制模式的低5位清零 ORR R0, R0, #SYS32Mode /设置成系统模式的1F MSR SPSR_c, R0 用户模式:MRS R0, SPSR BIC R0, R0, #0x1f ORR R0, R0, #USR32Mode /设置成用户模式的10 MSR SPSR_c, R0 ARM指令集与THUMB指令集的代码如下: ptcb = OSTCBPrioTblRegs0; if (ptcb != NULL) ptcb - OSTCBStkPtr1 &= (1 OSTCBStkPtr1 |= (1 5); 昨天就是看到这里,出现了一个意识到是不能忽悠的地方就是UCOS里面的任务控制块OS_TCB的概念,因此今天的任务就是把这部分看看。-UCOS-II移植ARM的读书笔记(12.13)一点一点来,什么不会就学什么,都不会就都学。没有问题只要你肯努力。_OSStartHighRdy MSR CPSR_c, #(NoInt | SYS32Mode) ;MSR:在ARM中只有MSR能够直接设置状态寄存器CPSR或SPSR,可以是立即数或者源寄存器,NoInt是禁止中断,SYS32Mode是系统模式 ;告诉uC/OS-II自身已经运行 LDR R4, =OSRunning ;OSRunning正在运行多任务的标志,OSRunning是把OSRunning的地址加载到R4,R4里存的是一个地址。 MOV R5, #1 STRB R5, R4 ;将R5存储到R4存的地址的变量即OSRunning中,也就是将OSRunning置1 BL OSTaskSwHook ;调用钩子函数,OSTaskSwHook是用于扩展的,在任务切换的时候执行用户自己定义的功能。 LDR R6, =OSTCBHighRdy ;OSTCBHighRdy指向最高优先级任务的控制块TCB的指针!将放指针的地址放到R6中。 LDR R6, R6 ;将R6地址处的数据读出即OSTCBHighRdy的地址放到R6中 B OSIntCtxSw_1 ;跳转到OSIntCtxSw_1 AREA SWIStacks, DATA, NOINIT,ALIGN=2SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;管理模式堆栈空间继续昨天没有看完的代码OSIntCtxSw ;下面为保存任务环境 LDR R2, SP, #20 ;获取PC,放入R2 LDR R12, SP, #16 ;获取R12,/R12存的什么东西啊? MRS R0, CPSR MSR CPSR_c, #(NoInt | SYS32Mode);进入系统模式并禁止中断 MOV R1, LR;R1放LR值 STMFD SP!, R1-R2 ;保存LR,PC,将R1,R2存入SP STMFD SP!, R4-R12 ;保存R4-R12,将R4-12存入SP 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, R4OSIntCtxSw_1 ;获取新任务堆栈指针 LDR R4, R6 ;把OSTCBHighRdy指向最高优先级任务的控制块TCB的指针给R4 ADD SP, R4, #68 ;17寄存器:CPSR,OsEnterSum,R0-R12,LR,SP LDR LR, SP, #-8 ;取出LR放到LR MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式并且保持禁止中断 MOV SP, R4 ;设置堆栈指针 LDMFD SP!, R4, R5 ;CPSR,OsEnterSum。LDMFD数据出栈,放入R4,R5 ;恢复新任务的OsEnterSum LDR R3, =OsEnterSum ;OsEnterSum的地址存入R3 STR R4, R3 ;把R4的值赋给OsEnterSum MSR SPSR_cxsf, R5 ;恢复CPSR;在管理模式里是修改SPSR LDMFD SP!, R0-R12, LR, PC ;运行新任务 ,恢复现场,异常处理返回-UCOS-II移植ARM的读书笔记(12.15)-移植的工作难以分析下去,先来几个UCOS的使用范例看看吧 第一个范例:void main (void) PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); /*PC的清屏函数,PC_DispClrScr(INT8U color),这里调用时是前景色为白色,背景色为黑色*/ OSInit(); /* Initialize uC/OS-II,初始化UCOS-II,在使用任何功能之前必须调用OSInit函数,建立两个任务:空闲任务所有其他任务均未就绪时运行,统计任务计算CPU的利用率*/ PC_DOSSaveReturn(); /* Save environment to return to DOS允许程序在正式开始多任务前,保存重要的寄存器的值,以保证UCOS能够正常地返回DOS */ PC_VectSet(uCOS, OSCtxSw); /* Install uC/OS-IIs context switch vector ,用于设定中断向量表的内容。*/ RandomSem = OSSemCreate(1); /* Random number semaphore,建立一个信号量,并制定信号量的初值为1,OSSemCreate(1)返回一个指向信号量的指针,那么之后对该信号量的操作全部通过这个指针来实现 */ OSTaskCreate(TaskStart, (void *)0, &TaskStartStkTASK_STK_SIZE - 1, 0); /*至少建立一个任务,TaskStart为指向该任务运行代码的指针,第二个参数是一个指向任务初始化数据的指针,第三个是任务的堆栈栈顶,当堆栈是从上到下,必须把堆栈高地址传给该函数,最后一个参数指定建立的任务的优先级,数值越小优先级越高,每个任务的优先级都是介于062之间独一无二的。*/ OSStart(); /* Start multitasking,调用该函数将控制权交给内核,开始运行多任务*/OSStart函数会让优先级最高的就绪任务开始运行,即TaskStartvoid TaskStart (void *pdata)#if OS_CRITICAL_METHOD = 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr;#endif char s100; INT16S key; pdata = pdata; /* Prevent compiler warning,这是这个参数是当任务建立时传递过来的一个指针 */ TaskStartDispInit(); /* Initialize the display初始化屏幕显示 */ OS_ENTER_CRITICAL(); /*关中断*/ PC_VectSet(0x08, OSTickISR); /* Install uC/OS-IIs clock tick ISR */ PC_SetTickRate(OS_TICKS_PER_SEC); /* Reprogram tick rate */ OS_EXIT_CRITICAL(); /*开中断*/ OSStatInit(); /* Initialize uC/OS-IIs statistics测试所使用的处理器的速度,得知处理器在运行所有应用任务时实际的CPU使用率 */ TaskStartCreateTasks(); /* Create all the application tasks建立更多任务,10个显示不同字符的任务,在每次建立一个新任务的时候,UCOS都会判断新建立的任务是否比建立它们的任务优先级更高,如果更高,这个新建立的任务将立刻开始运行。 */ for (;) TaskStartDisp(); /* Update the display */ if (PC_GetKey(&key) = TRUE) /* See if key has been pressed */ if (key = 0x1B) /* Yes, see if its the ESCAPE key */ PC_DOSReturn(); /* Return to DOS */ OSCtxSwCtr = 0; /* Clear context switch counter每秒都将记录任务切换次数的清零 */ OSTimeDlyHMSM(0, 0, 1, 0); /* Wait one second将自身挂起1s,1s是通过四个参数传送的,小时,分钟,秒,毫秒 */ static void TaskStartCreateTasks (void) INT8U i; for (i = 0; i N_TASKS; i+) /* Create N_TASKS identical tasks */ TaskDatai = 0 + i; /* Each task will display its own letter */ OSTaskCreate(Task, (void *)&TaskDatai, &TaskStkiTASK_STK_SIZE - 1, i + 1); 上面的函数循环建立了十个Task任务,下面是Task任务的代码void Task (void *pdata) INT8U x; INT8U y; INT8U err; for (;) OSSemPend(RandomSem, 0, &err); /* 获取信号量*/ x = random(80); /* 获得随机数x*/ y = random(16); /*获得随机数y*/ OSSemPost(RandomSem); /* 释放信号量*/ /* Display the task number on the screen */ PC_DispChar(x, y + 5, *(char *)pdata, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY); OSTimeDly(1); /* Delay 1 clock tick通知ucos该任务本次运行已经结束,可以让其他低优先级的任务运行了,参数1代表该任务延时1个时钟节拍,在200Hz的情况下就是5ms */ -UCOS-II移植ARM的读书笔记(12.16)-范例二:void main (void) OS_STK *ptos; OS_STK *pbos; INT32U size; PC_DispClrScr(DISP_FGND_WHITE); /* Clear the screen */ OSInit(); /* Initialize uC/OS-II */ PC_DOSSaveReturn(); /* Save environment to return to DOS */ PC_VectSet(uCOS, OSCtxSw); /* Install uC/OS-IIs context switch vector */ PC_ElapsedInit(); /* Initialized elapsed time measurement初始化时间测量功能,用来精确地记录PC_ElapsedStart()和PC_ElapsedStop()的函数调用时刻,通过这两个时刻的差值可以很容易得到这两个时刻之间的执行代码的运行时间 */ ptos = &TaskStartStkTASK_STK_SIZE - 1; /* TaskStart() will use Floating-Point */ pbos = &TaskStartStk0; size = TASK_STK_SIZE; OSTaskStkInit_FPE_x86(&ptos, &pbos, &size); OSTaskCreateExt(TaskStart, (void *)0, ptos, TASK_START_PRIO, TASK_START_ID,/*任务标志符,范例二中没有使用它*/ pbos, size, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* 使用了OSTaskCreate的扩展函数,支持对堆栈的修改和运行时对堆栈容量的检查。最后一个参数的设置表明允许堆栈检查并且需要在任务建立时将堆栈清零*/ OSStart(); /* Start multitasking让最高优先级的任务运行即TaskStart*/TaskStart的代码如下:void TaskStart (void *pdata)#if OS_CRITICAL_METHOD = 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr;#endif INT16S key; pdata = pdata; /* Prevent compiler warning */ TaskStartDispInit(); /* Setup the display初始化屏幕,在该函数内部设定屏幕初始化的图像*/ OS_ENTER_CRITICAL(); /*关中断 */ PC_VectSet(0x08, OSTickISR); PC_SetTickRate(OS_TICKS_PER_SEC); /* Reprogram tick rate设定时钟节拍大小 */ OS_EXIT_CRITICAL(); OSStatInit(); /* Initialize uC/OS-IIs statistics测试所使用的处理器的速度,得知处理器在运行所有应用任务时实际的CPU使用率 */ AckMbox = OSMboxCreate(void *)0); /* Create 2 message mailboxes在范例二中涉及到了消息的概念,任务4将向任务5发送消息,并且任务5会回复一个应答消息,因此这里建立了两个通信工具即邮箱,它允许任务或中断向另一个任务发送指针变量*/ TxMbox = OSMboxCreate(void *)0); TaskStartCreateTasks(); /* Create all other tasks创建所有其他的任务 */ for (;) TaskStartDisp(); /* Update the display更新各项统计数据并显示*/ if (PC_GetKey(&key) /* See if key has been pressed */ if (key = 0x1B) /* Yes, see if its the ESCAPE key */ PC_DOSReturn(); /* Yes, return to DOS */ OSCtxSwCtr = 0; /* Clear context switch counter */ OSTimeDly(OS_TICKS_PER_SEC); /* Wait one second挂起1s */ 创建其他六个任务,暂不执行,只是创建,等待CPU被放出static void TaskStartCreateTasks (void) OSTaskCreateExt(TaskClk, (void *)0, &TaskClkStkTASK_STK_SIZE - 1, TASK_CLK_PRIO, TASK_CLK_ID, &TaskClkStk0, TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); OSTaskCreateExt(Task1, (void *)0, &Task1StkTASK_STK_SIZE - 1, TASK_1_PRIO, TASK_1_ID, &Task1Stk0, TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); OSTaskCreateExt(Task2, (void *)0, &Task2StkTASK_STK_SIZE - 1, TASK_2_PRIO, TASK_2_ID, &Task2Stk0, TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); OSTaskCreateExt(Task3, (void *)0, &Task3StkTASK_STK_SIZE - 1, TASK_3_PRIO, TASK_3_ID, &Task3Stk0, TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); OSTaskCreateExt(Task4, (void *)0, &Task4StkTASK_STK_SIZE-1, TASK_4_PRIO, TASK_4_ID, &Task4Stk0, TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); OSTaskCreateExt(Task5, (void *)0, &Task5StkTASK_STK_SIZE-1, TASK_5_PRIO, TASK_5_ID, &Task5Stk0, TASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);分别看其他几个任务的代码如下:void Task1 (void *pdata) INT8U err; OS_STK_DATA data; /* Storage for task stack data */ INT16U time; /* Execution time (in uS) */ INT8U i; char s80; pdata = pdata; for (;) for (i = 0; i 7; i+) PC_ElapsedStart(); err = OSTaskStkChk(TASK_START_PRIO + i, &data); /*该函数是用来检查任务堆栈使用情况*/ time = PC_ElapsedStop(); /*测量上面的OSTaskStkChk函数的运行时间,方法是将这个函数放在PC_ElapsedStart()和PC_ElapsedStop()之间即可,它会返回以ms计量的时间间隔*/ if (err = OS_NO_ERR) sprintf

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论