1. 程式人生 > >《uCOS51移植心得》---七年前之《快快樂樂跟我學51微控制器作業系統和IP棧》 第九部分在OSStart前開中斷引起的莫名其妙錯誤

《uCOS51移植心得》---七年前之《快快樂樂跟我學51微控制器作業系統和IP棧》 第九部分在OSStart前開中斷引起的莫名其妙錯誤

在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

KafkaController控制器詳解

作者:小程 我們的kafka原始碼分享已經進行過很多期了,主要的內容也都分享的差不多了,那麼在今後的分享中,主要集中在kafka效能優化和使用。 Kafka叢集中的其中一個Broker會被選舉為Controller,主要負責Partition管理和副本狀態管理,也會執行類似於重分配Partit

KafkaNIO通訊機制

很久沒有做技術方面的分享了,今天閒來有空寫一篇關於Kafka通訊方面的文章與大家共同學習。 一、Kafka通訊機制的整體結構 這個圖採用的就是我們之前提到的SEDA多執行緒模型,連結如下: http://www.jianshu.com/p/e184fdc0ade4 1、對於broker來說

程式碼架構設計模式--鎖執行緒

上篇講到鎖可以用來解決多執行緒同時訪問同一資源時的同步問題,即鎖可以控制多執行緒對函式關聯資源的的同步訪問。這一篇我來簡單分析下鎖如何解決同步問題的。 在講鎖之前,我們我們先來討論下wait和notify方法,這兩個方法是用來控制執行緒執行的。說白了就是控制執行緒狀態的流轉,wait控制執行

程式碼架構設計模式--LockCondition

# Condition和JDK中的Object類的wait、notify方法一樣是控制執行緒狀態的,使用Condition的前提也是必須要先獲得鎖物件。 # 之前的博文分析過鎖,這裡先來總結下鎖釋放的幾種方式: 1 呼叫鎖的unlock等方法手動釋放鎖 2 執行緒異常退出的時候虛擬機