實驗室項目.md
1 嵌入式操作系統
- 為什麽要用嵌入式操作系統
普通的單片機編程:程序(軟件)——單片機硬件;
嵌入式操作系統開發:程序(軟件)——操作系統——嵌入式硬件(包括單片機等);
我們平時普通所學的單片機編程開發,一般情況下都需要對單片機的片載資源進行了解,了解IO口、PWM發生器、中斷、定時器、串口等常用的內部資源,然後一般采用C編程的面向過程編程,程序的運行過程從進入入口函數開始運行,是順序執行的。單片機的開發,相對來說比較簡單,但是不同的單片機,要實現相同的功能,其內部程序必然存在差別,也就是所說的移植性較差,另外在開發單片機時,必然要閱讀芯片手冊,對可用的資源有一定的硬件上的了解
嵌入式開發,也就是在已有的硬件基礎上移植操作系統,開發者所寫的軟件程序運行在操作系統中,通過調用操作系統提供的 API 接口等調用硬件資源,實現想要實現的功能。操作系統某種程度上屏蔽了底層的硬件,可以暫時不去考慮操作系統是如何調用硬件資源問題,這其中涉及到驅動等知識。
當然,想要實現移植操作系統的單片機,相對來說其性能就要求高一些,像普通的51芯片,即使移植剪裁到很小的Linux系統,運行起來也很吃力。
開發者所寫的程序是與操作系統相關,與硬件無關,只要運行在相同的操作系統中即可,因此嵌入式開發具有較好的移植性,對底層硬件也不強制要求熟悉,此外嵌入式系統通常是並發式執行任務,因此執行效率要好。比如要說得us/Os II 可同時管理64個任務,多個任務的處理在同時間段內同步完成。(這裏涉及到多線程以及CPU時間片的概念)。
總結來說,與單片機開發相比,嵌入式開發有如下優點:
- 移植性好;
- 屏蔽硬件,不要求對硬件資源的熟悉性;
- 多任務實時性高,效率高;
除此之外,嵌入式操作系統還具備很多優越性:精簡的內核,高實時性,多任務的操作系統;高可靠性;可裁剪性好;
百度百科的解釋還是很有道理的:
嵌入式操作系統(Embedded Operating System,簡稱:EOS)是指用於嵌入式系統的操作系統。嵌入式操作系統是一種用途廣泛的系統軟件,通常包括與硬件相關的底層驅動軟件、系統內核、設備驅動接口、通信協議、圖形界面、標準化瀏覽器等。嵌入式操作系統負責嵌入式系統的全部軟、硬件資源的分配、任務調度,控制、協調並發活動。它必須體現其所在系統的特征,能夠通過裝卸某些模塊來達到系統所要求的功能。目前在嵌入式領域廣泛使用的操作系統有:嵌入式實時操作系統μC/OS-II、嵌入式Linux、Windows Embedded、VxWorks等,以及應用在智能手機和平板電腦的Android、iOS等。
2 μC/OS-II系統
2.1 μC/OS-II特點
- 小巧的實時操作系統,整個代碼分為內核層和移植層,方便移植和裁剪
- 搶占式調度策略,保證任務的實時性
- 可管理多達64個任務
- 提供了用於任務通信的事件(信號量,消息隊列,郵箱等)管理,內存管理,時間管理等系統服務
2.2 內核結構
- 臨界段(Critical Sections):臨界區,指處理是不可分割的代碼,一旦這部分代碼開始執行了,則不允許任何中斷打斷
- 實現資源共享
- 處理臨界段代碼是需要關中斷,處理完畢後再打開中斷,系統定義了兩個宏(macros)來開關中斷
c OS_ENTER_CRITICAL() OS_EXIT_CRITCAL() //宏定義的具體實現取決於移植所用的微處理器,每種微處理器都要自己的OS_CPU.H文件
- 任務:
- 任務通常是無限循環
- 系統可管理多達64個任務,但保留了0,1,2,3,OS_LOWEST_PRIO-3,OS_LOWEST_PRIO-2,OS_LOWEST_PRIO-1,OS_LOWEST_PRIO這8個任務以備系統使用,其中包括系統空閑任務,和系統CPU效率使用計算等任務
- 用戶可使用多達56個任務,在創建任務時需要給任務賦予不同的優先級,優先級號越低,任務優先級越高。μC/OS-II系統的任務調度是基於優先級的。
- OS_LOWEST_PRO 該變量可以在中OS_CFG.H 中定義,說明應用程序中任務優先級別的數目
- 中斷處理:
- 中斷服務子程序框架:保存全部CPU寄存器 -- 調用OSIntEnter或者OSIntNesting直接加1 -- 執行用戶代碼中斷服務(匯編或者C編譯器支持在線匯編) -- 調用OSIntExit -- 恢復CPU寄存器 -- 執行中斷返回命令
- 註意:中斷服務子程序運行結束後會發生一次任務調度,所以並不一定會繼續運行被中斷的任務
- 時鐘節拍:
- 時鐘節拍是一種特殊得中斷,操作系統的心臟,對任務列表進行掃描,判斷是否有延時任務應該處於準備就緒狀態,進行上下文切換,也就是切換任務
- μC/OS-II系統需要用戶提供周期性信號源,系統在多任務系統啟動以後再開啟時鐘節拍器
OSTickISR():硬件定時器以時鐘節拍為周期定時產生中斷,該中斷服務程序為OSTickISR,該函數中主要調用了OSTIMETick()函數來完成系統在每個時鐘節拍需要完成的工作。
保存處理器寄存器的值 調用OSIntEnter()或是OSIntNesting加1 調用OSTimeTick() 調用OSIntExit() 恢復處理器寄存器的值 執行中斷返回指令
OSTimeTick():時鐘節拍服務函數做的工作包括:記錄節拍樹,任務延時減一,其任務時在每個時鐘節拍了解任務的延時狀態,使得其中延時結束的非掛起任務進入就緒狀態。
- μC/OS-II系統初始化
- OSInit():建立空閑任務idle task,這個任務總是處於就緒態,空閑任務OSTaskIDLE()的優先級總是設成最低
- 初始化4個空數據結構緩沖區:OS_MAX_TASKS(OSTCBFreeList)任務控制塊鏈表,OS_MAX_EVENTS(OSEventFreeList)ECB時間控制塊鏈表,OS_MAX_QS(OSQFreeList),OS_MAX_MEM_PART(OSMemFreeList)
- OSStart()啟動:開始多任務執行,啟動之前,至少要調用OSTaskCreate()創建一個應用任務
2.3 任務管理
任務狀態:OSTCBStat 任務狀態字
任務控制塊OS_TCB:用來記錄任務的堆棧指針,任務的當前狀態,任務的優先級等一些與任務管理有關的屬性的表,叫做任務控制塊TCB。系統初始化時會按照用戶提供的任務數(OS_MAX_TASKS)為任務創建相應數量的任務控制塊鏈表,也就是空任務塊鏈表,當創建一個任務後,會調用OSTCBInit來為任務控制塊進行初始化,從鏈表中獲取一個任務控制塊,並利用屬性對各個成員賦值,最後將該塊鏈入鏈表頭部。
任務就緒表:ready List:包含兩個變量,OSRdyGrp和OSRdyTb1[],每個任務的就緒標誌都會放入就緒表中,任務按照優先級分組,8個任務為一組(64個任務),OSRdyGrp中的每一位表示8組任務中每一組中是否有進入就緒狀態的任務。
任務堆棧:保存CPU寄存器中的內容及存儲私有數據的需要,每個任務都應該分配有自己的堆棧,任務堆棧是任務的重要組成部分,在應用程序中定義任務堆棧方法為:OS_TSK TaskStk[TASK_STK_SIZE]定義一個OS_STK類型數組並在創建一個任務時將數組地址賦給該任務。
任務創建:創建函數:OSTaskCreate + 創建函數:OSTaskCreateExt 創建任務時傳遞任務的堆棧指針,任務的指針,任務參數以及任務優先級等,OSTaskCreate()在創建任務時會調用任務堆棧初始化函數OSTaskStkInit()來完成任務堆棧的初始化工作,這個函數在OS_CPU.C根據處理器移植時編寫
- 任務調度(Task Scheduling):
- 搶占式多任務內核,優先級最高的任務一旦準備就緒,就擁有CPU的所有權開始運行,uc/OS 不支持時間片輪轉,任務調度是指:查找準備就緒的最高優先級的任務並進行上下文的切換。(任務調度的所花費時間是常數)
- 任務就緒表:ready List:任務調度的依據,包含兩個變量,OSRdyGrp和OSRdyTb1[],每個任務的就緒標誌都會放入就緒表中,任務按照優先級分組,8個任務為一組(64個任務),OSRdyGrp中的每一位表示8組任務中每一組中是否有進入就緒狀態的任務。
- 系統在RAM中設立一個記錄表,每個任務在表中占據一個位置,用這個位置1/0的狀態判斷任務是否處於就緒狀態,可使用相關代碼將相關任務設為就緒狀態或者脫離就緒狀態,以及獲取到優先級別最高的就緒任務
- 任務切換:OS_TASK_SW()任務切換宏:中止正在運行的任務,轉而去運行另外一個任務的操作,這個任務時就緒任務中優先級別最高的那個任務。簡單說,就是將掛起的任務寄存器入棧,將較高優先級任務的寄存器出棧
2.4 內存管理
- μC/OS-II系統中將連續的大塊的內存按分區來管理,每個分區包含有整數個大小相同的內存塊
- 內存控制塊OS_MEM: memory control blocks 系統的每個內存分區都有它自己的內存控制塊
- 使用內存管理:需要在OS_CFG.H文件中將開關量OS_MEM_EN 置1
- 創建內存分區:OSMEMCreate()
- 分配一個內存塊:OSMemGet()
- 釋放一個內存塊:OSMEMPut()
2.5 時間管理:系統服務
- 時鐘節拍:定時中斷來實現延時和超時控制,這個中斷叫做時鐘節拍,每秒發生10 -100次,頻率越高,系統負荷越重
- OSTimeDlY():系統規定:除了空閑任務之外所有任務必須在任務中合適位置調用OSTIMEDly,使得當前任務運行延時一段時間,並進行一次任務調度,以讓出CPU使用權。其中操作包括:取消當前任務就緒狀態,延時節拍數存入TCB,調用調度函數。
- OSTimeDlyResume:取消任務延時
- OSTimeGet:獲取系統時間
- OSTimeSet:設置系統時間等
2.6 任務間的通信:數據共享與通信
- 臨界段:臨界資源保護
- 操作系統通信方法 -- 事件Event:信號量,郵箱,消息隊列,信號量集
OSSchedLock() 禁止調度保護任務級的共享資源
事件(ECB 事件控制塊)OS_EVENT:
typedef struct { INT8U OSEventType; //事件的類型 INT16U OSEventCnt; //信號量計數器 void *OSEventPtr; //消息或消息隊列的指針 INT8U OSEventGrp; //等待事件的任務組 INT8U OSEventTbl[OS_EVENT_TBL_SIZE];//任務等待表 } OS_EVENT;
- 信號量(Semaphore):控制共享資源的使用權,標誌事件的發生,使得兩個任務的行為同步,信號量包括信號量計數值和等待該信號任務的等待任務表,操作:OSSEMCreate(創建一個信號量,這個時候系統從空事件控制塊鏈表中獲取一個控制塊,對它初始化並描述該事件),OSSEemPend(OS_Event pevent,INT16U timeout,INTU err)請求信號量,pevent是被請求信號量的指針, OSSemPost(OS_EVENT pevent)釋放信號量,如果不需要某信號量了可以調用OssDel(OS_EVENT pevent,INT8U opt,INT8U *err),註意互斥信號量與優先級反轉的問題
- 消息郵箱:OS_EVENT_TYPE_MBOX:在兩個需要通信的任務之間通過傳遞數據緩沖區指針的方法來通信
- 消息隊列:OS_EVENT_TYPE_Q:相當於是共用一個任務等待列表的消息郵箱數組
- 信號量集
2.7 移植 μC/OS-II系統
- 移植的條件
- 處理器的C編譯器能產生並可重入代碼
- 在程序中可以打開或者關閉中斷
- 處理器支持定時中斷(10-1000Hz)
- 處理器能夠容納一定量的數據硬件堆棧,因為每個任務都有自己的任務堆棧,在調度時用於將當前任務的CPU寄存器存放到此任務的堆棧中,再從另一個任務中恢復原來的工作寄存器,繼續運行另一個任務,這是多任務調度的基礎。
- 處理器有將堆棧指針和其他CPU寄存器存儲或者獨處到堆棧/內存的指令
- 移植文件
設置OS_CPU.H與處理器和編譯器相關的代碼:包括定義數據類型INT8U,INT8S等,使用OS_ENTER_CRITICAL等宏開啟中斷關閉中斷等,定義堆棧增長方向(要註意)
用C語言編寫與操作系統相關的函數 OS_CPU_C.C:OSTaskStkInit(初始化任務堆棧),OSTaskCreateHook,OSTaskDelHook,OSTaskSwHoOK,OSTaskStatHook,OSTimeTickHooK,比較重要的是第一個,後面五個一般可置空
用匯編語言編寫四個與處理器相關的函數 OS_CPU.ASM:OSStartHighRdy,OSCtxSw(上下文切換)OSIntCtxSw(中斷級任務切換),OSTickISR
- 系統體系: OS_CFG.H 系統配置
3 通信接口:SPI,SCI,IIC
3.1 SPI:serial peripheral interface
- 串行外圍設備接口,Motorola公司推出的一種同步串行接口,SPI總線是一種三線同步總線,硬件功能很強,CPU有更多時間處理其他事務
- 同步需要多出一條時鐘線
- 常用於擴展外設:AD,DA,FRAM,DSP等
- SPI總線由三條信號線組成:串行時鐘(SCLK/SPSCK)、串行數據輸出(SDO/MOSO)、串行數據輸入(SDI/MOSI)。SPI總線可以實現多個SPI設備互相連接。提供SPI串行時鐘的SPI設備為SPI主機或主設備(Master),其他設備為SPI從機或從設備(Slave)。主從設備間可以實現全雙工通信,當有多個從設備時,還可以增加一條從設備選擇線(Slave Select)。
- 寄存器:SPI數據寄存器,SPI控制寄存器,狀態控制寄存器
3.2 SCI:serial communication interface
- 串行通信接口,motorola公司推出的一種通用的異步通信接口UART,異步只需要發送和接收兩根線
- 常用於串行通信:RS422,RS485,RS232
- 波特率:每秒內傳送的位數 bps
- MCU內引腳的輸入輸出通常采用TTL電平,適合板內數據傳輸,為了信號傳輸更遠,可以轉化成RS232,RS485總線標準
- 寄存器:SCI數據寄存器(接收移位寄存器,發送移位寄存器),SCI控制寄存器,SCI狀態寄存器,SCI波特率寄存器
- UART:UART(Universal Asynchronous Receiver & Transmitter)即通用異步收發器,是串行通信的一種協議,它規定串行通信的波特率、起始/停止位、數據位、校驗位等格式,以及各種異步握手信號。
3.3 I2C:I2C總線
- Philips公司開發的一種簡單的雙向二進制同步串行總線,只需要兩根線即可連接於總線上的在器件之間傳送信息,具備多主機系統所需要的包括總線裁決和高低速器件同步功能的高性能串行總線
- 兩根線:SDA(串行數據線) SCL(串行時鐘線),連接在總線上的IC數量受總線最大電容限制,兩根線都是雙向數據線,
- 每個接到I2C總線上的器件都有唯一地址,I2C有存在總線仲裁機制,以確定哪一臺主機控制總線,發送數據到其他器件
4 XGATE
4.1 什麽是xgate
飛思卡爾9s12X系列雙核中的協處理器XGATE
雙核架構,增加了一個RISC核的高效協處理器,XGATE模塊,專門用於處理中斷任務,可以將主核CPU從執行耗時的中斷處理程序工作中解放出來,專註於執行與應用有關的任務,實現更好的實時事件處理,XGATE采用RISC指令核,代碼高效,主頻運行速率可達到主核的2倍。
4.2 xgate配置與使用
- xgate.cxgate文件為XGATE的主文件,在其中編寫需要的中斷服務子程序
- xgate.h 是對XGATE用到的一些聲明
在Main.c文件中定義CPU與XGate共享的數據
#pragma DATA_SEG_SHARED_DATA volatile int shared_counter;// 定義XGATE與主核共享RAM的變量 #pragma DATA_SEG DEFAULT
在Main.c 文件中設置SetupXGATE:定義xgate的中斷向量表的偏移地址,以及中斷權限的分配,決定是主CPU還是XGATE響應中斷
#define ROUTE_INTERRUPT(vec_adr, cfdata) \
INT_CFADDR= (vec_adr) & 0xF0; \
INT_CFDATA_ARR[((vec_adr) & 0x0F) >> 1]= (cfdata)
//channel id 需要到xgate.cxgate文件向量列表中查找
//自定義向量名
#define RTI_VEC 0xF0 /* vector address= 2 * channel id */
#define MSCAN0_VEC 0xB2 /* vector address= 2 * channel id */
#define SCI2_VEC 0x8A /* vector address= 2 * channel id */
#define SCI0_VEC 0xD6
static void SetupXGATE(void)
{
//初始化Xgate向量表模塊並將XGVBR 寄存器設置到初始地址
XGVBR= (unsigned int)(void*__far)(XGATE_VectorTable - XGATE_VECTOR_OFFSET);
// RTI_VEC 為自定義中斷名 設置xgate中斷以及中斷優先級
ROUTE_INTERRUPT(RTI_VEC, 0x86); /* RQST=1 and PRIO=1 */ //實時時鐘中斷
ROUTE_INTERRUPT(MSCAN0_VEC, 0x81); /* RQST=1 and PRIO=1 */ //CAN接收中斷
ROUTE_INTERRUPT(SCI2_VEC, 0x84); /* RQST=1 and PRIO=1 */
ROUTE_INTERRUPT(SCI0_VEC, 0x83); /* RQST=1 and PRIO=1 */
XGMCTL= 0xFBC1; /* XGE | XGFRZ | XGIE */
}
- xgate.cxgate中實現中斷函數,同時修改中斷向量表vectorTable
interrupt void SCI2_Handler(void){
}
const XGATE_TableEntry XGATE_VectorTable[] ={
...
{(XGATE_Function)SCI2_Handler}, // Channel 45 - SCI2
...
}
5 CAN總線
5.1 什麽是CAN總線:controller Area Network
can總線是一種串行數據通信協議,特點包括:多主機方式工作,任意節點可以在任意時刻主動向網絡上其他節點發送信息;串行,同步,半雙工,CRC
節點信息分成不同的優先級:仲裁總線結構機制,節點同時傳送信息時,優先級低的節點主動停止數據發送,優先級高的節點不受影響繼續傳送數據。CAN總線系統:由多個電子控制單元EMU同時控制多個工作裝置或系統,各控制單元ECU的共用信息通過總線互相傳遞。
傳輸速度快;相關控制單元可共用傳感器;更少的線束,更小的控制單元,節省了空間。
- CAN-BUS系統的組成:CAN收發器(控制器內部,接收和發送數據),數據傳輸終端,數據傳輸線(雙向數據線)
參考:https://wenku.baidu.com/view/bab35fb765ce0508763213cf.html
5.2 CAN總線的特點
- Can總線是一種實時應用的串行通信協議總線,可以使用雙絞線來傳輸信號,是應用最廣泛的現場總線之一。
- 實時性強,傳輸距離遠,抗電磁幹擾強,成本低,通信速度最高可達40M
- 雙線串行通信,檢錯能力強
- 具有優先權和仲裁功能,多個模塊通過can控制器掛在can-bus上,形成多主機局部網絡
- 根據報文ID決定接收或屏蔽報文
- 報文使用標識符來指示功能信息,優先級信息
- 短幀結構,出錯時可自動關閉節點
5.3 工作原理
- 當CAN總線上的一個節點(站)發送數據時,它以報文形式廣播給網絡中所有節點。對每個節點來說,無論數據是否是發給自己的,都對其進行接收。
每組報文開頭的11位字符為標識符,定義了報文的優先級,這種報文格式稱為面向內容的編址方案。標識符在網絡中是唯一的,描述了數據的特定含義,也決定報文優先級(標識符數值越小,優先級越高)。註意:最高優先級的報文獲得總線訪問權,低優先級報文在下一個總線周期自動重發。
當一個站要向其它站發送數據時,該站的CPU將要發送的數據和自己的標識符傳送給本站的CAN芯片,並處於準備狀態;當它收到總線分配時,轉為發送報文狀態。CAN芯片將數據根據協議組織成一定的報文格式發出,這時網上的其它站處於接收狀態。每個處於接收狀態的站對接收到的報文進行檢測,判斷這些報文是否是發給自己的,以確定是否接收它。
- CAN 總線組成:
- 傳輸線:雙絞線,兩條導線為CAN-High和CAN-Low線,減少幹擾,差分電壓傳輸,信號 = CAN_H - CAN_L
- 數據傳輸終端:傳輸線的兩頭,兩個終端電阻
- 分支線:連接主機或者通信結點的分支線,不能太長,不超過6m
- CAN控制器和CAN收發器
- CAN 總線幀結構:
實驗室項目.md