《uCOS51移植心得》---七年前之《快快樂樂跟我學51微控制器作業系統和IP棧》 第九部分在OSStart前開中斷引起的莫名其妙錯誤
巨龍公司VPN部 楊屹 [email protected] 2004/03/09
2004/03/07網友方呂ladderls來電詢問以下問題:
你的ucos-ii在51的移植為啥不能超過11個應用任務?更改任務數量設定無用。
我在keil v623軟環境下模擬,建立的任務與您的三個範例任務類同,修改配製檔案的最大任務數和最小優先順序數,超過11個任務即宕機。不知還要修改那些配製?
經檢查是ucos51的BUG。我的OS_EXIT_CRITICAL()巨集定義為EA=1;,上電後51自動關中斷(EA=0,ET0=0),因為在系統呼叫OSInit()時會自動建立一個優先順序最低的系統任務,建立過程中會呼叫OS_EXIT_CRITICAL()開啟EA。而我在InitTimer0函式裡使能了T0中斷,這個函式在OSStart()前執行,導致在OSStart()前產生中斷,致使系統崩潰。
按照我在《關於keilc51入出臨界區的內嵌彙編》一文裡的方法改正,可以解決這個問題。
或者這樣改:(ucos51V2最終採用這種方法)
//OS_CPU_C.C
//初始化定時器0
void InitTimer0(void) reentrant
{
TMOD=TMOD&0xF0;
TMOD=TMOD|0x01; //模式1(16位定時器),僅受TR0控制
TH0=0x70; //定義Tick=50次/秒(即0.02秒/次)
TL0=0x00; //OS_CPU_A.ASM 和 OS_TICKS_PER_SEC
//ET0=1; //允許T0中斷,此時EA=0(51上電預設值),中斷還不會發生,滿足在OSStart()前不產生中斷的要求。
TR0=1;
}
註釋掉InitTimer0函式裡的ET0=1,保證在OSStart()前不開時鐘中斷。
在最高優先順序任務裡開T0中斷:(切記是最高優先順序任務)
void TaskStartyya(void *yydata) reentrant
{
yydata=yydata;
//注意!在最高優先順序任務迴圈前開啟定時器中斷,以滿足在OSStart()前不產生中斷的要求。
//在系統呼叫OSInit()時會自動建立一個優先順序最低的系統任務,建立過程中會呼叫OS_EXIT_CRITICAL()開啟EA。
//若在InitTimer0()裡開啟T0中斷,則違反了在OSStart()前不產生中斷的要求。
//切記將ET0=1;放在最高優先順序任務裡,OSStart()將呼叫OSStartHighRdy()第一個執行最高優先順序任務,這樣ET0=1總能被第一個執行。
ET0=1;
for(;;){
PrintStr("\t01\n");
OSTimeDly(10*OS_TICKS_PER_SEC);
}
}
具體到ladderls網友的問題,因為在OSStart()前開了中斷,不符合作者要求,會導致系統崩潰。在建立12個以下任務時,時機上的巧合,不會出問題,這些建立函式在12個以下數量時所用時間恰好在T0時鐘中斷前完成,不會引起崩潰。
改動後的程式如下:
#include <includes.h>
void TaskStartyya(void *yydata) reentrant;
void TaskStartyyb(void *yydata) reentrant;
void TaskStartyyc(void *yydata) reentrant;
void TaskStartyyd(void *yydata) reentrant;
void TaskStartyye(void *yydata) reentrant;
void TaskStartyyf(void *yydata) reentrant;
void TaskStartyyg(void *yydata) reentrant;
void TaskStartyyh(void *yydata) reentrant;
void TaskStartyyi(void *yydata) reentrant;
void TaskStartyyj(void *yydata) reentrant;
void TaskStartyyk(void *yydata) reentrant;
void TaskStartyyl(void *yydata) reentrant;
void TaskStartyym(void *yydata) reentrant;
//注意:我在ASM檔案中設定?STACK空間為40H?
OS_STK TaskStartStkyya[MaxStkSize];
OS_STK TaskStartStkyyb[MaxStkSize];
OS_STK TaskStartStkyyc[MaxStkSize];
OS_STK TaskStartStkyyd[MaxStkSize];
OS_STK TaskStartStkyye[MaxStkSize];
OS_STK TaskStartStkyyf[MaxStkSize];
OS_STK TaskStartStkyyg[MaxStkSize];
OS_STK TaskStartStkyyh[MaxStkSize];
OS_STK TaskStartStkyyi[MaxStkSize];
OS_STK TaskStartStkyyj[MaxStkSize];
OS_STK TaskStartStkyyk[MaxStkSize];
OS_STK TaskStartStkyyl[MaxStkSize];
OS_STK TaskStartStkyym[MaxStkSize];
void main(void)
{
OSInit();
InitTimer0();
InitSerial();
InitSerialBuffer();
OSTaskCreate(TaskStartyya, (void *)0, &TaskStartStkyya[0],1);
OSTaskCreate(TaskStartyyb, (void *)0, &TaskStartStkyyb[0],2);
OSTaskCreate(TaskStartyyc, (void *)0, &TaskStartStkyyc[0],3);
OSTaskCreate(TaskStartyyd, (void *)0, &TaskStartStkyyd[0],4);
OSTaskCreate(TaskStartyye, (void *)0, &TaskStartStkyye[0],5);
OSTaskCreate(TaskStartyyf, (void *)0, &TaskStartStkyyf[0],6);
OSTaskCreate(TaskStartyyg, (void *)0, &TaskStartStkyyg[0],7);
OSTaskCreate(TaskStartyyh, (void *)0, &TaskStartStkyyh[0],8);
OSTaskCreate(TaskStartyyi, (void *)0, &TaskStartStkyyi[0],9);
OSTaskCreate(TaskStartyyj, (void *)0, &TaskStartStkyyj[0],10);
OSTaskCreate(TaskStartyyk, (void *)0, &TaskStartStkyyk[0],11);
OSTaskCreate(TaskStartyyl, (void *)0, &TaskStartStkyyl[0],14);
OSTaskCreate(TaskStartyym, (void *)0, &TaskStartStkyym[0],15);
OSStart();
}
void TaskStartyya(void *yydata) reentrant
{
yydata=yydata;
clrscr();
ET0=1;
for(;;){
PrintStr("\t01\n");
OSTimeDly(10*OS_TICKS_PER_SEC);
}
}
void TaskStartyyb(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t02\n");
OSTimeDly(10*OS_TICKS_PER_SEC);
}
}
void TaskStartyyc(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t03\n");
OSTimeDly(10*OS_TICKS_PER_SEC);
}
}
void TaskStartyyd(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t04\n");
OSTimeDly(10*OS_TICKS_PER_SEC);
}
}
void TaskStartyye(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t05\n");
OSTimeDly(10*OS_TICKS_PER_SEC);
}
}
void TaskStartyyf(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t06\n");
OSTimeDly(20*OS_TICKS_PER_SEC);
}
}
void TaskStartyyg(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t07\n");
OSTimeDly(20*OS_TICKS_PER_SEC);
}
}
void TaskStartyyh(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t08\n");
OSTimeDly(20*OS_TICKS_PER_SEC);
}
}
void TaskStartyyi(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t09\n");
OSTimeDly(20*OS_TICKS_PER_SEC);
}
}
void TaskStartyyj(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t10\n");
OSTimeDly(20*OS_TICKS_PER_SEC);
}
}
void TaskStartyyk(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t11\n");
OSTimeDly(30*OS_TICKS_PER_SEC);
}
}
void TaskStartyyl(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t12\n");
OSTimeDly(30*OS_TICKS_PER_SEC);
}
}
void TaskStartyym(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\t13\n");
OSTimeDly(30*OS_TICKS_PER_SEC);
}
}
相關推薦
《uCOS51移植心得》---七年前之《快快樂樂跟我學51微控制器作業系統和IP棧》 第五部分.NE2000網絡卡晶片驅動程式
NE2000網絡卡晶片驅動程式 巨龍公司系統整合開發部 楊屹 [email protected] 2002/10/20 引言 自從發表《uCOS51移植心得》以來,我收到了很多朋友們的來信,大家對公開源碼錶示鼓勵,謝謝大家的支援!很多人對於編寫自己的作業系統很感興趣,uCOS51是個不錯的
《uCOS51移植心得》---七年前之《快快樂樂跟我學51微控制器作業系統和IP棧》 第九部分在OSStart前開中斷引起的莫名其妙錯誤
在OSStart前開中斷引起的莫名其妙錯誤 巨龍公司VPN部 楊屹 [email protected] 2004/03/09 2004/03/07網友方呂ladderls來電詢問以下問題: 你的ucos-ii在51的
《uCOS51移植心得》---七年前之《快快樂樂跟我學51微控制器作業系統和IP棧》 第六部分ARP協議實現原理
ARP協議實現原理 作者<[email protected]> 2002/11/01 ARP是Address Resolution Protocol的縮寫。中文譯做“地址解析協議”,本質是完成網路地址到實體地址的對映。從概念上講就是找到一個對映方法f,使得“實
跟我學ASP.NET MVC之七:SportsStrore購物車
repos ras img sports collect dev PC RM VC 摘要: SportsStore應用程序進展很順利,但是我不能銷售產品直到設計了一個購物車。在這篇文章裏,我就將創建一個購物車。 在目錄下的每個產品旁邊添加一個添加到購物車按鈕。點擊這個按
跟我學 Java 8 新特性之 Stream 流(七)流與迭代器,流系列大結局
恭喜你們,馬上就要學完Java8 Stream流的一整系列了,其實我相信Stream流對很多使用Java的同學來說,都是一個知識盲點,因為這個原因,我才這麼細緻地講解Stream流的各個知識點,通過這一整個系列,我相信只要認真看了的同學,都已掌握的差不多了,就差實戰了。
跟我學ASP.NET MVC之四:使用Razor
ima pre 技術分享 C# 圖模型 med 執行 sys fonts 摘要: 視圖引擎處理ASP.NET內容,並查找指令,典型情況是向瀏覽器輸出插入動態內容。MVC框架視圖引擎的名字是Razor。 在本文中,我將帶領讀者快速認識Razor,以後你們看到他們的時候能夠
跟我學ASP.NET MVC之八:SportsStrore移動設備
ima 支持 web瀏覽器 css 客戶端瀏覽器 nts oat 重新 menu 摘要: 現在的web程序開發避免不了智能手機和平板電腦上的使用,如果你希望發布你的應用程序給更廣大客戶使用的話,你將要擁抱可移動web瀏覽器的世界。向移動設備用戶發布一個好的使用體驗是很困難
Java程式設計師從笨鳥到菜鳥之(八十五)跟我學jquery(一)愛之初體驗jquery
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
跟我學Flask(七)-flask工作原理
在對Flask程式碼基本結構有一定了解之後,為了以後學習的順利,我們需要進一步瞭解Flask工作的基本原理 *本文轉載自孫華強部落格:*https://blog.csdn.net/sunhuaqiang1/article/details/72808619 所有的 Python
【跟我學oracle18c】第十七天:Multitenant Architecture多租戶框架:2.2 Overview of Commonality in the CDB(藍色感悟)
在CDB中,每個使用者、角色或物件都是通用的或本地的。類似地,通常或區域性授予特權. This section contains the following topics: About Commonality in a CDB A common phenomenon defined i
跟我學springboot(二十五)springboot-過濾器之攔截不需要走過濾器的連結使用方法
1.建立專案 springboot怎麼建立不多說了,前面部落格已經有講解,下面是我們建立好的專案目錄。 2.編寫程式碼 過濾器可以指定我們排除的引數exclusions,我們把需要隔離的url統一封裝在這裡,然後在webconfig配置filterReg.ad
跟我學 Java 8 新特性之 Stream 流(四)並行流
隨著對流API認識的慢慢深入,本章我們要討論的知識點是流API裡面的並行流了。 在開始討論並行流之前,我先引發一下大家的思考,就你看到這篇文章的時間,你們是不是經常聽到,Intel i7 CPU什麼8核16執行緒,什麼Android手機8核4GB這種訊息,既然我們是處於
跟我學 Java 8 新特性之 Stream 流(三)縮減操作
和前面兩篇文章一起服用,效果會更佳。通過對流API的基礎體驗Demo和關鍵知識點的講解,相信大家對流API都有一定的認識了,但是流API強大的功能,可不僅僅像前面兩篇文章中說的那樣簡單,大家應該注意到,在第二篇中,我對Stream介面進行介紹的時候,並沒有把他的全部方法都
跟我學 Java 8 新特性之 Stream 流(二)關鍵知識點
我們的第一篇文章,主要是通過一個Demo,讓大家體驗了一下使用流API的那種酣暢淋漓的感覺。如果你沒有實踐,我還是再次呼籲你動手敲一敲,自己實實在跑一遍上一篇的Demo。 相信你的感受和理解也會隨之加深的。繼續探索流API的高階功能之前,我們先從介面級別全面瞭解一下流A
跟我學 Java 8 新特性之 Stream 流基礎體驗
Java8新增的功能中,要數lambda表示式和流API最為重要了.這篇文章主要介紹流API的基礎,也是流API系列的第一篇文章,話不多說,直奔主題. 什麼是流API? 它能做一些什麼? 我們應該知道(絕對知道~)API是一個程式向使用者提供的一些方法,通過這些方法就
跟我學 Java 8 新特性之 Stream 流(六)收集
我們前面的五篇文章基本都是在說將一個集合轉成一個流,然後對流進行操作,其實這種操作是最多的,但有時候我們也是需要從流中收集起一些元素,並以集合的方式返回,我們把這種反向操作稱為收集。 流API也給我們提供了相應的方法。 如何在流中使用收集功能? 我們先看一看流API
跟我學Kafka之Controller控制器詳解
作者:小程 我們的kafka原始碼分享已經進行過很多期了,主要的內容也都分享的差不多了,那麼在今後的分享中,主要集中在kafka效能優化和使用。 Kafka叢集中的其中一個Broker會被選舉為Controller,主要負責Partition管理和副本狀態管理,也會執行類似於重分配Partit
跟我學Kafka之NIO通訊機制
很久沒有做技術方面的分享了,今天閒來有空寫一篇關於Kafka通訊方面的文章與大家共同學習。 一、Kafka通訊機制的整體結構 這個圖採用的就是我們之前提到的SEDA多執行緒模型,連結如下: http://www.jianshu.com/p/e184fdc0ade4 1、對於broker來說
跟我學程式碼架構設計模式之--鎖和執行緒
上篇講到鎖可以用來解決多執行緒同時訪問同一資源時的同步問題,即鎖可以控制多執行緒對函式關聯資源的的同步訪問。這一篇我來簡單分析下鎖如何解決同步問題的。 在講鎖之前,我們我們先來討論下wait和notify方法,這兩個方法是用來控制執行緒執行的。說白了就是控制執行緒狀態的流轉,wait控制執行
跟我學程式碼架構設計模式之--Lock和Condition
# Condition和JDK中的Object類的wait、notify方法一樣是控制執行緒狀態的,使用Condition的前提也是必須要先獲得鎖物件。 # 之前的博文分析過鎖,這裡先來總結下鎖釋放的幾種方式: 1 呼叫鎖的unlock等方法手動釋放鎖 2 執行緒異常退出的時候虛擬機