單晶片lab9結報

tags: stm32
實驗日期 : 2021/12/09

上課教材

lab1

SPEC

利用RTOS中3條以上thread完成跑馬燈,按下開發板上的按鈕切換至下一個狀態。

  1. 每隔1秒亮一顆LED,共8顆輪流亮。
  2. 每隔1秒同時亮兩顆LED。
  3. 每隔1秒亮一顆LED且每隔0.5秒亮一顆LED(同時)。
  4. LED燈全部閃爍。

實現方法

volatile int counter = 0;
volatile int counter_thread3 = 0;

使用兩個全局volatile變數,紀錄LED亮到哪一顆燈,因為是全局變數,在不同執行緒之間都可以共享。

switch (state % 4) {
    case 0:
        thread1.signal_set(0x1); break;
    case 1:
        thread2.signal_set(0x1); break;
    case 2:
        thread1.signal_set(0x1);
        thread3.signal_set(0x1); break;
    case 3:
        thread4.signal_set(0x1); break;
}

state為紀錄狀態的變數,當按鈕被按下時,state++,以state % 4判斷就會在0到3之間之間循環。使用4個執行緒,狀態1使用執行緒1、狀態2使用執行緒2、狀態3使用執行緒1與執行緒3、狀態4使用執行緒4。

實際程式測試時,發現切換至不同執行緒,一開始會執行切換後的執行緒,之後再回去執行前一個執行緒,造成LED閃爍未符合預期。推測原因是未執行完但已signal觸發的執行緒會排在queue裡面,等到執行完切換後的執行緒後,會再回去執行尚未執行的task,不過這方面原因有待商榷。

lab2

SPEC

利用RTOS中的signals。在serial monitor輸入指令控制開發板的LED。輸入'1'亮綠燈、輸入'2'亮藍燈、輸入'3'亮紅燈。

實現方法

lab1 實現方法

lab3

SPEC

利用RTOS中的signals。將超音波模組測量到的距離(cm)顯示2位於七段顯示器,並控制開發板的LED為

距離(cm) LED
d<10
紅燈
d[10,15]
藍燈
d[15,20]
綠燈
d>20
全亮

實現方法

使用別人寫好的超音波函式庫,接口使用如下

// call dist when the distance changes
ultrasonic mu(p6, p7, .1, 1, &dist); 
// start measuring the distance
mu.startUpdates();
// call checkDistance() as much as possible, as this is 
// where the class checks if dist needs to be called.
mu.checkDistance();

參照lab1 實現方法使用signal觸發讓LED亮功能的個別執行緒,再使用lab8 lab6實現方法觀念顯示2位數在七段顯示器上。

課後習題

Question 1

請詳述thread在Mbed平台中是如何運作的。

Answer 1

參照官方RTOS doc範例說明

Thread thread;

建立thread這個類的對象,也就是創建一個執行緒。

void led2_thread() {
    while (true) {
        led2 = !led2;
        Thread::wait(1000);
    }
}
thread.start(led2_thread);

開啟執行緒,並賦予其函數,led2_thread的函式可以視為是另一個int main(){}的函式入口,也就是說除了原本main function的執行緒外,又新增了1個執行緒,共有2個執行緒同時執行。


signal是用來告知process有一個event要發生,像是std::this_thread::sleep_for(2000ms);就是讓執行緒休息,2秒後收到一個signal再wake up起來,不同執行緒之間互相溝通也是需要signal。

Question 2

請解釋執行多執行緒之死結(Deadlock)的問題,以及如何避免。

Answer 2

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

當P1、P2兩個process都需要資源才能繼續執行。P1擁有資源R2、還需要額外資源R1才能執行;P2擁有資源R1、還需要額外資源R2才能執行,兩邊都在互相等待而沒有任何一個可執行,稱為死結(DeadLock)。

因此這邊可以總結deadlock必須要滿足以下四個條件

條件 說明
Mutual exclusion 一個資源一次只能被一個process所使用。
Hold and Wait process取得一個資源之後等待其他的資源。
No preemption 資源只能由process自己釋放,不能由其他方式釋放。
Circular wait 每個process都握有另一個process請求的資源,導致每一個process都在等待另一個process釋放資源。

解決方法有2個 - deadlock prevention與deadlock avoidance。

  • Deadlock prevention
    提供一組方法去確認至少一個必要的死結情況不會發生,這些方法靠著限制資源的需求來達成預防死結。
  • Deadlock avoidance
    要求作業系統給出額外的資訊,關於一個process在他的lifetime裡會要求的resource。有了這些額外的資訊,作業系統可以決定是否讓程序的要求繼續等候。為了決定現在的要求是否能滿足,作業系統必須考慮現在資源的存量、資源的分配量、和未來資源的要求與釋放。
  • ref 1 : 周志遠作業系統清大OCW影片
  • ref 2 : 周志遠作業系統上課講義
  • ref 3 : 第二十八天 死結(Deadlock)

Question 3

請解釋program、process、thread彼此之間的關係,並舉例說明。

Answer 3

  1. program是一個靜態的物件,以二進位的方式存放在disk
  2. process是一個動態的物件,是指一個正在memory執行的program,即是大家熟知的C/C++的memory layout空間。
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

    由上圖可知道data與text區域是不變的,而stack與heap區是會隨程式動態變化。
  3. thread又稱lightweight process,是OS能夠進行programmed instructions的最小單位,同一個process下可以有多個thread執行,他們彼此之間共享code section, data section, OS resource(open files, signals)。
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

不過以Linux來說,thread(light-weighted process)跟process從kernel角度看幾乎是一樣的。

心得

劉永勝

這次實作基礎的mbed OS程式,我們常需要搭載許多模組在同一個開發版上使用,若只使用一個程序性的main function,可能造成多數元件處於靜止的狀態,無法有效分配開發版的作業效能。利用這次OS的觀念,可以讓其他模組以thread的方式,保持隨時可觸發狀態,即時的操作模組,開發版資源也能被有效運用。

李宇洋

這次實驗主要是了解Thread跟Signal的概念,並且在實作Lab時實現多執行緒。一開始由於對於Thread如何使用不理解,所以卡住了將近2小時在研究他的執行流程,Thread.start()後會一直不斷處於Idle狀態並且等待Signal後執行相應Method。原本認為Signal Flag的設定是類似密碼的概念,但是其實只是讓Stm32判定是要讓哪個Thread執行動作,在Method裡面還是要自行處理後判定何時讓Thread回到Idle狀態。

陳旭祺

這次實驗只有3個實作,內容較簡單,學習創建新的thread與用signal(用來告知process有一個event發生)去觸發指定的thread運作。multi-thread programming是個寫程式很進階的topic,有很多需要注意的問題,像是2個執行緒搶同一份資源、如何解決deadlock,這部分可能未來需要修作業系統等課程比較能深刻了解,就本此實驗而言,算是對multi-thread一個很粗淺的了解,因為我們也沒有相關的知識背景。