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就可以了。