A. 怎样搭建ucos环境
一、建立环境
首先需要下载os-ii,这里使用光盘自带的版本。解压缩后,点击OS252.exe,就会在C盘下出现C:\SOFTWARE目录,里面包含了os-ii源码和例程源码。OS252.exe这里所做的工作就是把光盘中的SOFTWARE拷贝到C盘根目录下。
然后需要下载Borland C/C++ 4.5,解压后有一个文件夹,文件名为BC45。把文件夹复制到C盘根目录下,因为源程序包中默认的编译器路径是C:\BC45,在这里是为了偷一个懒不去修改。
最后一步就是把tasm.exe添加到C:\BC45\BIN目录下。TASM是Borland公司推出的汇编编译器,源程序包中使用了该编译器,所以需要添加到C:\BC45\BIN下。
二、测试环境
上面的工作准备好以后,我们就可以修改一下例程看看效果了,总共分为三步:
1)用记事本打开C:\SOFTWARE\OS-II\EX1_x86L\BC45\SOURCE下的TEST.C文件,把函数TaskStartDispInit()中Example#1改为Hoole#1(第126行),然后保存。
2)运行批处理MAKETEST.BAT。即双击C:\SOFTWARE\OS-II\EX1_x86L\BC45\TEST\下的MAKETEST.BAT即可将我们修改的程序编译成可执行的新的TEST.EXE文件;
3)运行TEST.EXE。这里有两种运行方法,一种是直接双击C:\SOFTWARE\OS-II\EX1_x86L\BC45\TEST下的TESTEXE文件;另一种是在DOS环境下进入到C:\SOFTWARE\OS-II\EX1_x86L\BC45\TEST目录下运行TEST.EXE。你会在显示窗口看到所做的修改。
就是这么简单,到此为止,我们学习OS-ii的编译调试环境就建立好了。
B. 求《uCOS-Ⅱ:源码公开的实时嵌入式操作系统》的光盘内容,是光盘哦,pdf我有。
ucos|4-ucosII|卢老师|UCOSII|源享科技ucosd操作系统网络网盘免费资源在线学习
链接: https://pan..com/s/10nfqoxR-bPi-kJyYJBswKw
ucos 4-ucosII 卢老师 UCOSII 源享科技ucosd操作系统.zip UCOS视频教程王华斌.rar UCOS移植资料 如何学习嵌入式开发.rar 零死角玩转stm32-系统篇1、uCOS-II 移植与深入实战指南.pdf 基于嵌入式实时操作系统的程序设计技术+周航慈.pdf 北航uCOS-II课件.pdf VC6.0 UCGUI3.90源码.zip uCOSⅡ中文教程(邵贝贝).pdf ucosii.rar uCOS2精华快速掌握.ppt
C. ucos-ii是怎样移植到Keil C上的
在移植的时候 尽量保证得到的源代码改动最少
并且调试方便 而且目录结构分类清晰
网上的各明滚个项目都有如下特点:
1:一来就吭哧吭哧修改头文件,每个文件都#include "includes.h"
2: ucos和其他文件 或者放在一个文件夹 或者在项目里面不管3721都加上
跳来跳去头都是大的 而且调试的时候出些莫名其妙的问题:比如贺扮
设不了断点 或者调试无法进入c文件等等
我的设想:前提 得到ucos2.84
1: 改动尽量少 即不按常规修改里面的#include "includes.h"等
ucos说放哪里我们就放哪里
2: 项目结构和文件存放结构合理,该有的有 不该有的就没有
3: 调试时编译器不会出现怪问题
4: 文档尽量清楚 每处和每步小小的修改都要说明
建议最开始看完 杨屹 大虾的文章
[里面的os_cfg_r.h->改成os_cfg.h] 至此,是ucos里面的[第一处修改]
1: 建立项目文件 拷贝原始文件 整理文件夹
目录如下:
FirstVersion: 根目录 project.uv就放下面
-ucos : 拷贝ucos2.83源代码和os_cpu_a.a51 等凡是ucos相关的到下面 去掉只读和存档属性 自己加一个app_cfg.h(ucos2.83增
加的) 里面内容是#include <reg51.h>嘿嘿
-output:
项目设置:
-SourceGroup
->STARTUP.A51 main.c
--ucos
->os_task.c os_core.c
2: 设置
1: Target1 -> options->output和Listing里面点"Select Folder for Objects" 改为\output
2: Target1->options -> C51和A51里面的 Include Paths->加入ucos
4: Target1 -> options->Target的MemoryModel和CodeRomSize都用Large
编译: 有四个警告 'OSIntCtxSw': missing function-prototype
'OSStartHighRdy': missing function-prototype
'OSCtxSw': missing function-prototype
UCOS\OS_CORE.C(1356): warning C275: expression with possibly no effect
第四个警告是由于OS_TaskIdle()里面
(void)p_arg; /* Prevent compiler warning for not using 'parg' */
没有起到作用 改成p_arg = p_arg;即可。 至此,是在ucos里面的[第二处修改]
3:加入 OS_CPU_C.C 不要问这个文件哪里来的 地球人都知道
在不管它通不通前 还有修改
1: 最前面保持跟其他.c文件一致 加入
#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif
2:加入若干个激拍余函数的函数体 大体都是带"hook"的, 这些个函数只在ucos_ii.h有个声明,但由于只有头文件有定义没有函数体 ,keil会
把它编译成LJMP STARTUP1的语句。知道有什么后果了吧
注意#if的条件头文件和c文件要一致
在这里感觉ucos是不是搞了点”技术处理“?反正n个函数头文件和c文件的#if条件不一致
一不小心会造成LJMP STARTUP1! 注意把os_core.c ucos_ii.h和os_cpu_c里面都要改完
至此,是在ucos里面的[第三处修改] 要改的地方还不少
//in ucos_ii.h
#if OS_CPU_HOOKS_EN
void OSInitHookBegin (void);
void OSInitHookEnd (void);
void OSTCBInitHook (OS_TCB *ptcb);
void OSTaskCreateHook (OS_TCB *ptcb);
void OSTaskDelHook (OS_TCB *ptcb);
void OSTaskStatHook (void);
void OSTaskIdleHook (void);
#endif
#if OS_TASK_SW_HOOK_EN
void OSTaskSwHook (void);
#endif
#if OS_TIME_TICK_HOOK_EN
void OSTimeTickHook (void);
#endif
4: 现在开始改OS_CPU_C.C里面的函数
将OSTaskStkInit()改成跟ucos_ii.h里面一样。具体就是原来里面yy大虾的函数是
void *OSTaskStkInit (void (*task)(void *pd), void *ppdata, void *ptos, INT16U opt)
总之网上各个版本都是ppdata..呵呵 。ucos2.83里面用的是p_arg.我们把它修改成
OS_STK *OSTaskStkInit (void (*task)(void *p_arg) ,
void *p_arg,
OS_STK *ptos,
INT16U opt)
编译能通过 先不管运行起来对不对
5: 在ucos组里面加入os_cpu_a.a51 不要问这个文件哪里来的 地球人都知道
编译 会出现错误: *** ERROR L102: EXTERNAL ATTRIBUTE MISMATCH
这是因为os_cpu_a.a51里面
EXTRN IDATA (OSTCBHighRdy)
EXTRN IDATA (OSRunning)
EXTRN IDATA (OSPrioCur)
EXTRN IDATA (OSPrioHighRdy)
对引用的外部变量作了idata的定义,而ucos_ii.h里面没有
在这里 os_cpu.h里面 先增加一个#define DATATYPE_1 idata
在ucos_ii.h找到这四个变量 增加idata定义 至此,是在ucos里面的[第三处修改]
编译能通过
6:在ucos_ii.h里面
#if 0
void OSStartHighRdy (void);
void OSIntCtxSw (void);
void OSCtxSw (void);
#endif
这就是造成上面的其中三个编译警告的原因 既然ucos2.83里面有说
* IMPORTANT: These prototypes MUST be placed in OS_CPU.H
那么我们就把它们placed in OS_CPU.H
不改动原来的代码 只
void OSStartHighRdy (void);
void OSIntCtxSw (void);
void OSCtxSw (void);
到os_cpu.h里面 再编译 现在就只有
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS的警告了
Program Size: data=84.0 xdata=2348 code=8721 //keil 8.06
至此 整个框架就搭起来了 下面就来慢慢对付OSTaskStkInit()这个函数
gogogo!!!!!!!!!!!!!!!!!!
1: os_cfg.h里面先 disable掉
OS_DEBUG_EN OS_FLAG_EN OS_MBOX_EN OS_MEM_EN OS_MUTEX_EN OS_Q_EN OS_SEM_EN
等等等等
题外话: 做一个Configuration Wizard的OS_CFG.H 这下方便多了 。这可是个体力活! 嘿嘿
也不违背了不改动原始文件的初衷
开始go了。建立最简单的一个东西
#include <ucos_ii.h>
void main(void)
{
OSInit();
OSStart();
}
发现走到os_cpu_a.a51里面的
OSStartHighRdy:
USING 0 ;上电后51自动关中断,此处不必用CLR EA指令,因为到此处还未开中断,本程序退出后,开中断。
LCALL _?OSTaskSwHook --》一call就call复位了 我靠
捣鼓了下建一个os_cpu_a.c 加入工程 且右键的options->Generate Assembleer SRC File打勾
内容为
#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif
void OSStartHighRdy(void) {
OSTaskSwHook();
} 看了看 生成的东西是这样的
?PR?OSStartHighRdy?OS_CPU_A SEGMENT CODE
EXTRN CODE (OSTaskSwHook)
PUBLIC OSStartHighRdy
RSEG ?PR?OSStartHighRdy?OS_CPU_A
OSStartHighRdy:
USING 0
LJMP OSTaskSwHook
END
简直莫名其妙 于是 将os_cpu_a.a51改成
;EXTRN CODE (_?OSTaskSwHook)
EXTRN CODE (OSTaskSwHook) ;keil8.06 <-----改这里
;子程序
;-------------------------------------------------------------------------
RSEG ?PR?OSStartHighRdy?OS_CPU_A
OSStartHighRdy:
USING 0 ;上电后51自动关中断,此处不必用CLR EA指令,因为到此处还未开中断,本程序退出后,开中断。
;LCALL _?OSTaskSwHook
LCALL OSTaskSwHook <-----改这里
再测试 ok 能进入OSIdleStask 并在里面循环 看来是c和汇编连接的一些问题 先把它放一边以后解决 [待解决的问题2]继续测试
这里又想到个问题 万一#define OS_TASK_SW_HOOK_EN 0 那么OSTaskSwHook()就不被编译。
在汇编里面调用会不会又复位?keil这点太……[不知道哪里可以设置 待解决的问题2],
测试了下 果然复位 我靠!作个说明“如果用keil,那么OS_TASK_SW_HOOK_EN 一定要为1
好了 就算第一步测试搞定 现在来做个”笨活路“ 给所有的函数加上reentrant! 内部的static就不用了。
现在开始调试serial 将yy大虾的serial.c搞过来 加入工程
1: 看到汇编和c混合头都是大的 把
#pragma asm
push IE
EA = 0;
之类的东东全部改成 _push_(IE); EA = 0;嘿嘿 当然不要忘记在app_cfg.h加#include <intrins.h>
现在有:
#include <ucos_ii.h>
void Task1(void *p_arg) keilReentrant;
void Task2(void *p_arg) keilReentrant;
void Task3(void *p_arg) keilReentrant;
OS_STK Task1Stack[MaxStkSize];//注意:我在ASM文件中设置?STACK空间为40H即64。
OS_STK Task2Stack[MaxStkSize];
OS_STK Task3Stack[MaxStkSize];
void main(void)
{
unsigned char ucReturn;
OSInit();
OSInitTimer0(); //也就是原来的InitTimer0();
InitSerial();
InitSerialBuffer();
ucReturn = OSTaskCreate(Task1, (void *)0, &Task1Stack[0] ,2);
ucReturn = OSTaskCreate(Task2, (void *)0, &Task2Stack[0] ,3);
ucReturn = OSTaskCreate(Task3, (void *)0, &Task3Stack[0] ,4);
OSStart();
}
void Task1(void *p_arg) keilReentrant
{
p_arg = p_arg;
ET0=1;
for(;;){
//PrintStr("Task 1 is active. \n");
OSTimeDly(3*OS_TICKS_PER_SEC);
}
}
void Task2(void *p_arg) keilReentrant
{
p_arg = p_arg;
for(;;){
PrintStr("Task 2 is active. \n");
OSTimeDly(2*OS_TICKS_PER_SEC);
}
}
void Task3(void *p_arg) keilReentrant
{
p_arg = p_arg;
for(;;){
PrintStr("Task 3 is active. \n");
OSTimeDly(3*OS_TICKS_PER_SEC);
}
}
运行 我靠 怎么就显示"Task 1 is active" 任务不切换 ?为啥。
原来os_time.c还没有加到项目里面去(因为这个项目没有把
ucos_ii.c加入项目);OSTimeDly()哪里会工作
加进去,运行->OK
OS_timr 把OS_Timr.c加入 并打开en的开关编译的时候会出现err。原因是回调函数参数太多的问题
解决方法见 http://www.keil.com/support/docs/2066.htm
在ucos-ii.h里面
/* add keilReentrant to to solve the Error 212: Indirect call: Parameters do not fit within registers */
typedef void (*OS_TMR_CALLBACK)(void *ptmr, void *parg) reentrant ;
附加一点就是项目里面直接加如.a文件 不用在include c51L.lib
然后加入一个lcd的驱动 呵呵很简单1602的。前提就是尽量不修改ucos的变量 函数名称和调用方式等
详细见工程。调试通过 不过是在proteus里面。在这里感谢jjj www.proteus.com.cn
记得因为lcd.c里面用到了sempost函数 所以如果要用就必须把OS_MAX_EVENTS 算进去,在你原来的设定值加一
到此 新鲜的ucos2.84出炉了。奉献此身体给大家。想来想去 唯一的卖点就是写了点细节,二是改了个os_cfg.h...呵呵
打包文件在下 ! 只有文档的兄台也不用发mail给我 自己网上找去 应该有下
熊伟 于大年初一 深圳 [email protected] jdsu光电
version2:
不知道怎么回事,一到 LCALL OSTaskSwHook --》一call就call复位了 我靠
又改回来 LCALL _?OSTaskSwHook 又好了
想了想 是不是我又加了.a文件的原因?
因为后来我又加了一个INT0Function.c 和INT0Function_a.a51
void Int0Function() keilReentrant
{ //中断在汇编中实现,去掉interrupt {//INT0中断服务子程序
}
#include <include_a.h>
NAME INT0FUNCTION_A ;模块名
?PR?_?INTOFunction?INT0FUNCTION_A SEGMENT CODE
EXTRN CODE (_?INTOFunction)
;-------------------------------------------------------------------------
CSEG AT 0013H ;INT0中断
LJMP INT0ISR ;工作于系统态,无任务切换。
RSEG ?PR?_?INTOFunction?INT0FUNCTION_A
INT0ISR:
USING 0
CLR EA ;先关中断,以防中断嵌套。
PUSHALL
LCALL _?INTOFunction
POPALL
SETB EA
RETI
;-------------------------------------------------------------------------
END
;-------------------------------------------------------------------------
D. stm32 ucos下串口不能发送数据
问题一步步解决,
一直停在while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
不知是哪设置错了
说明UART状态标志位获取不正确,首先看UART的源代码,多看看初始化的流程图,是否完全一致,还得多看看那些控制寄存器,这也是写低屋的一些应有的步聚
使用printf函数,其实是在调用UART的应用,这个函数原形在网上很多地方能找到,这里面主要是用UART实现C语言里的printf()函数打印功能一样的,只是这里是通过UART送到PC上显示
使用printf函数(使用Micro Lib)有如下提示:
.\Obj\uCOSDemo.axf: Error: L6218E: Undefined symbol __use_two_region_memory (referred from stm32f10x_startup.o).
这个错误的意思是未定义"use_two_region_memory ",而这个错误是在STARTUP里面,你个你说得没错!
提示startup.o这人个信息,任何时候调试都要注意了,".O"这说明这是在汇编文件或在.H的头文件
我认为这是在Startup.s里面调用了一些没定义的变量
.\Obj\uCOSDemo.axf: Error: L6218E: Undefined symbol __initial_sp (referred from entry2.o
这错误的信息和上面类似:initial_sp 这个变量未定义, 而文件是在entry2里面
解决这个种问题
首先从低层开始:
1.把其它功能都disable,only enable UART(串口)的功能,看能否打印;
如果不能说明串口程序的问题,解决方法:
a. 首先看源代码,也可以上STM32的官方网站找源代码
b. 看连接线,串口接收软件是否设好对应的BPS和COMS;
2.如果使用串口,就会造成死机,这也说明你UCOS能正常跑吗?最好用一个LED灯,闪来显示运行状态
说这些调试方法应该可以拿来到分了吧!谢谢了!有不明白给我EMAIL
[email protected]
E. 为什么说操作系统ucos是实时的ucos是多任务的
白话一点解释一下,希望纳大能帮助你:
实时:指OS能够满足用户根据需求所设计的切换时机和切换延时的要求。任意时刻,你希望你的系统里嫌茄模,哪一个事务最应该被优先处理?如果ucOS能满足你的要求(通过你对任务的合理设计),那么就可以说他是实时的OS。
使用ucOS构建系统时,你的所有用户事务(需要做的事情)可以被划分到多个任务里,ucOS可以根据你的实际设计,按优先级调度他们(协调该先执行哪一个任务,并立即执行),芹缓这就可以说,ucOS是多任务了。
F. Keil u4 编译uCOSIII移植有错误 Error: L6218E: Undefined symbol Mem_Copy (referred from lib_mem.o)
在lib_cfg.h文件里有这样的宏定义#define LIB_MEM_CFG_OPTIMIZE_ASM_EN DEF_ENABLED
而mem_的定义事这样的
//#if (LIB_MEM_CFG_OPTIMIZE_ASM_EN != DEF_ENABLED)
void Mem_Copy ( void *pdest,
const void *psrc,
CPU_SIZE_T size)
也就是说LIB_MEM_CFG_OPTIMIZE_ASM_EN 定义为DEF_DISABLED就可以了。