advertisement

2014年11月28日

2014/11/28 進階微控制器應用

Counting Semaphore 計數信號 (為具有長度大於一之佇列,ㄧ次可以傳好幾個)
Binary Semaphore 二元信號(是長度為一之佇列,且ㄧ次只能傳一個資料,而資料內容不care)

為什麼要用到計數信號?

因為
一開始處理工作會跟二元信號要xSemaphoreTake,若二元信號裡面沒資料,則處理工作會blocked。
若中斷xSemaphoreGive給二元信號資料後,處理工作在跟二元信號要資料,有信號則進行處理。
如下圖



若中斷頻率快於處理工作處理資料的速度時,會遺漏中斷產生的資料,這是二元信號的缺點,因為只能存放一個資料,故無法在給予中斷如下圖

當中斷產生之頻率高於處理工作處理中斷之頻率時,二元信號將會漏掉一些中斷事件。
解決上述問題之方式為使用計數信號,因其可以存放的資料較多,當處理工作處理頻率較中斷產生頻率低,可將尚未處理的中斷信號放在計數信號中如下圖


若計數信號長度為五時,其比例為五比一,當處理工作在處理信號時,最多還可以接收五個中斷信號

建立計數信號
資料型態為 xSemaphoreHandle
產生之API為xSemaphoreCreateCounting(unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount)
unsigned portBASE_TYPE uxMaxCount指位元數、指最大計數值count:即計數之長度,如8051為八位元,ARM為32位元
該API會回傳建立好的計數信號處理值,無法建立則回傳NULL
unsigned portBASE_TYPE uxInitialCount:起始計數值count(用來設定資源管理或事件同步)
當資料進入佇列count就加一,取走後就減一

計數信號主要用於:

  1. 事件同步(中斷同步處理):有中斷事件起來馬上處理完畢 取信號→處理工作→信號計數器-1(計數信號之計數之起始值=0);給信號→登記等待工作→信號計數器+1(計數信號最大值=待做處理工作之可能最大值)
  2. 資源管理:資源(記憶體、CPU時間(可以執行或不可以執行))取信號→佔用資源→信號計數器-1(計數信號之計數之起始值=資源總數);給信號→釋放資源→信號計數器+1(計數信號最大值=資源總數);

同步會造成阻斷現象,但會完成事件
非同步可以更多時間處理很多事情,而不會等待阻斷


範例:建立一個處理事件同步之計數信號

xSemaphoreHandle cntSemaphore;
cntSemaphore=xSemaphoreCreatCounting(10,0);

有一中斷產生時會給三個信號到計數信號,處理工作需處理此三個信號

中斷處理程式
void __interrupt__ __far vExampleISR(void) {void __interrupt__ __far vExampleISR(void) {
        static  portBASE_TYPE xHigherPriorityTaskWoken;
        xSemaphoreGiveFromISR(cntSemaphore,&xHigherPriorityTaskWoken);//FromISR為中斷副程式內才要加的
        if(xHigherPriorityTaskWoken==pdTRUE) {
                portSWITCH_CONTEXT();
        }
}

//處理工作
void handleTask(void *ptr) {
        while(1) {
                xSemaphoreTake(cntSemaphore,portMAX_DELAY);
                處理工作;
        }
}
xSemaphoreHandle cntSemaphore;
//主程式
int main(void) {
        cntSemaphore=xSemaphoreCreateCounting(10,0);
        if(cntSemaphore!=NULL) {
                xTaskCreate(handleTask,"...",...);
                vTaskStartScheduler();
        }
}
在中斷服務程式中使用Queue之API送資料到Queue
xQueueSendToBackFromISR(xQueueHandle...void *資料指標,portBASE_TYPE *TaskWoken(變數));//*TaskWoken(變數)為狀態回傳變數

xQueueSendToFrontFromISR();此為插隊
xQueueSendToBackFromISR();此為排隊

中斷通常是傳遞資料,很少接收資料

該APIOK會回傳pdPASS,否則Queue已滿會回傳erQUEUE_FULL

從Queue接資料
xQueueReceiveFromISR(xQueueHandle...,void *資料指標,0);
ok回傳pdPASS,Queue已空回傳erQUEUE_EMPTY

chapter 4

資源管理(Resoure Management)為了避免發生衝突,尤其在多工作業很容易造成之問題
資源包括
記憶體,CPU,週邊硬體
多工作業系統很容易造成資源衝突
1.Accessing Peripherals 
• Task A executes and starts to write the string “Hello world” to the LCD. 
• Task A is pre-empted by Task B after outputting just the beginning of the string – “Hello w”. 
• Task B writes “Abort, Retry, Fail?” to the LCD before entering the Blocked state. 
• Task A continues from the point at which it was pre-empted and completes outputting the remaining characters – “orld”. 

當Task A 執行顯示Hello Word到一半,只印出hello時工作切換到Task B,Task B正好執行列印Abort Retry,執行後工做切回Task A,此時LCD將顯示,Hello Abort Retry World.

2.讀改寫操作(不可間斷)
Read-Modify-Write(RMW)
TASKA 執行 PORTA | =1;(=>port A=port A | 1;

組合語言:讀port A到暫存器R1
改:令R2=1,R1與R2做OR運算後存到R1
寫:R1值存到port A

在組合語言讀改寫過程中,工作切換到Task B 若port A被TaskB改掉,則切回TaskA後所得之答案將會錯誤

3.Non-atomic Access to Variables (可切割存取變數)atomic原子/不可切割
結構變數
多位元組變數:八位元微控制器可以一次存取8位元資料
                                                            需二次存取16位元資料(多位元組變數)
結構變數
struct {
  資料型態1 成員變數1;
  資料型態2 成員變數2;
}結構名;

結構變數與多位元組變數接可能因工作切換造成記憶體被改掉而存取錯誤

結構變數可視為多位元組陣列變數,多位元組變數需多次存取記憶體過程中,若切換到其他工作,而其他工作也正好使用相同之記憶體時,即會造成資料毀損(data corruption)

4.Function Reentrancy函式重入性
可重入式函式(Reentrancy Funtion)
函式在不同工作或中斷服務程式中均可被呼叫使用而不出錯。
可重入函式只使用暫存器或相對local堆疊區資料

例可重入式函式
long lAddOneHundered( long lVar1 ) 
/* This function scope variable will also be allocated to the stack 
or a register, depending on compiler and optimization level. Each 
task or interrupt that calls this function will have its own copy 
of lVar2. */
long lVar2; 
 lVar2 = lVar1 + 100; 
 /* Most likely the return value will be placed in a CPU register, 
 although it too could be placed on the stack. */ 
 return lVar2; 
}

不可重複式
/* In this case lVar1 is a global variable so every task that calls 
the function will be accessing the same single copy of the variable. */ 
long lVar1; 
long lNonsenseFunction( void ) 
/* This variable is static so is not allocated on the stack. Each task 
that calls the function will be accessing the same single copy of the 
variable. */ 
static long lState = 0; 
long lReturn; 
 switch( lState ) 
 { 
 case 0 : lReturn = lVar1 + 10; 
 lState = 1; 
 break; 
 case 1 : lReturn = lVar1 + 20; 
 lState = 0; 
 break; 
 } 
全域變數、static不可重入式函式  有哪一些?
區域變數可重入式函式

如何避免資源衝突
一資源管理
主要使用:
MUTEX(Mutual Exclusive 互相排除) 保護資源,不被其他使用
Critical Section緊要區(或關鍵區)當進入此區就不能進入工作切換或中斷,進入此區一定會把工作執行完,保護CPU

Mutex主要用來保護記憶體資源
Critical Section 主要用來保證程式流程之完整


另外亦可擱置排程來保障程式流程,擱置其他程式保護自己的程式。





沒有留言:

張貼留言

文章有誤或有問題麻煩您留言告知! 謝謝您~~