| /*module1.h*/ int a = 5; /* 在模塊1的.h文件中定義int a */ /*module1 .c*/ #include "module1.h" /* 在模塊1中包含模塊1的.h文件 */ /*module2 .c*/ #include "module1.h" /* 在模塊2中包含模塊1的.h文件 */ /*module3 .c*/ #include "module1.h" /* 在模塊3中包含模塊1的.h文件 */ |
| /*module1.h*/ extern int a; /* 在模塊1的.h文件中聲明int a */ /*module1 .c*/ #include "module1.h" /* 在模塊1中包含模塊1的.h文件 */ int a = 5; /* 在模塊1的.c文件中定義int a */ /*module2 .c*/ #include "module1.h" /* 在模塊2中包含模塊1的.h文件 */ /*module3 .c*/ #include "module1.h" /* 在模塊3中包含模塊1的.h文件 */ |
這樣如果模塊1、2、3操作a的話(huà),對應的是同一片內存單元。
一個(gè)嵌入式系統通常包括兩類(lèi)模塊:
?。?)硬件驅動(dòng)模塊,一種特定硬件對應一個(gè)模塊;
?。?)軟件功能模塊,其模塊的劃分應滿(mǎn)足低偶合、高內聚的要求。
多任務(wù)還是單任務(wù)
所謂"單任務(wù)系統"是指該系統不能支持多任務(wù)并發(fā)操作,宏觀(guān)串行地執行一個(gè)任務(wù)。而多任務(wù)系統則可以宏觀(guān)并行(微觀(guān)上可能串行)地"同時(shí)"執行多個(gè)任務(wù)。
多任務(wù)的并發(fā)執行通常依賴(lài)于一個(gè)多任務(wù)操作系統(OS),多任務(wù)OS的核心是系統調度器,它使用任務(wù)控制塊(TCB)來(lái)管理任務(wù)調度功能。TCB包括任務(wù)的當前狀態(tài)、優(yōu)先級、要等待的事件或資源、任務(wù)程序碼的起始地址、初始堆棧指針等信息。調度器在任務(wù)被激活時(shí),要用到這些信息。此外,TCB還被用來(lái)存放任務(wù)的"上下文"(context)。任務(wù)的上下文就是當一個(gè)執行中的任務(wù)被停止時(shí),所要保存的所有信息。通常,上下文就是計算機當前的狀態(tài),也即各個(gè)寄存器的內容。當發(fā)生任務(wù)切換時(shí),當前運行的任務(wù)的上下文被存入TCB,并將要被執行的任務(wù)的上下文從它的TCB中取出,放入各個(gè)寄存器中。
嵌入式多任務(wù)OS的典型例子有Vxworks、ucLinux等。嵌入式OS并非遙不可及的神壇之物,我們可以用不到1000行代碼實(shí)現一個(gè)針對80186處理器的功能最簡(jiǎn)單的OS內核,作者正準備進(jìn)行此項工作,希望能將心得貢獻給大家。
究竟選擇多任務(wù)還是單任務(wù)方式,依賴(lài)于軟件的體系是否龐大。例如,絕大多數手機程序都是多任務(wù)的,但也有一些小靈通的協(xié)議棧是單任務(wù)的,沒(méi)有操作系統,它們的主程序輪流調用各個(gè)軟件模塊的處理程序,模擬多任務(wù)環(huán)境。
單任務(wù)程序典型架構
?。?)從CPU復位時(shí)的指定地址開(kāi)始執行;
?。?)跳轉至匯編代碼startup處執行;
?。?)跳轉至用戶(hù)主程序main執行,在main中完成:
a.初試化各硬件設備;
b.初始化各軟件模塊;
c.進(jìn)入死循環(huán)(無(wú)限循環(huán)),調用各模塊的處理函數
用戶(hù)主程序和各模塊的處理函數都以C語(yǔ)言完成。用戶(hù)主程序最后都進(jìn)入了一個(gè)死循環(huán),其首選方案是:
| while(1) { } |
| for(;;) { } |
| printf("%d,%d",++i,i++); /* 輸出是什么?*/ c = a+++b; /* c=? */ |
| /* 存放中斷的隊列 */ typedef struct tagIntQueue { int intType; /* 中斷類(lèi)型 */ struct tagIntQueue *next; }IntQueue; IntQueue lpIntQueueHead; __interrupt ISRexample () { int intType; intType = GetSystemType(); QueueAddTail(lpIntQueueHead, intType);/* 在隊列尾加入新的中斷 */ } |
| While(1) { If( !IsIntQueueEmpty() ) { intType = GetFirstInt(); switch(intType) /* 是不是很象WIN32程序的消息解析函數? */ { /* 對,我們的中斷類(lèi)型解析很類(lèi)似于消息驅動(dòng) */ case xxx: /* 我們稱(chēng)其為"中斷驅動(dòng)"吧? */ … break; case xxx: … break; … } } } |
| /* 設置中斷向量表 */ m_myPtr = make_far_pointer(0l); /* 返回void far型指針void far * */ m_myPtr += ITYPE_UART; /* ITYPE_UART: uart中斷服務(wù)程序 */ /* 相對于中斷向量表首地址的偏移 */ *m_myPtr = &UART _Isr; /* UART _Isr:UART的中斷服務(wù)程序 */ |
| #ifndef C_Class #define C_Class struct #endif C_Class A { C_Class A *A_this; /* this指針 */ void (*Foo)(C_Class A *A_this); /* 行為:函數指針 */ int a; /* 數據 */ int b; }; |
聯(lián)系客服