--- title: ChibiOS/RT categories: embedded, arm, stm32, stm32f429 toc: yes ... 組員 ---- * 莊承翰 / vchchuang * 詹尚倫 / game * 陳祐任 / bruce30262 * 陳易駿 / alex122380 * 郭耀琮 / rbugoo131 共筆: `hackpad`_ 作業系統架構 ------------ ChibiOS/RT 是一個相當模組化的設計,部由許多主要的獨立組件構成。而每一個組件又可能細分成許多子系統 .. image:: /embedded/chibi_architecture.png * kernel : OS kernel中與平台無關的部份 * port layer :OS kernel中與結構/編譯器 相關的部份 * HAL(hardware abstraction layer) : 包含許多抽象的device drivers,提供普遍的I/O API給不同平台的應用程式 * platform layer : 包含許多device drivers的實作 * various : 提供各種額外但不包含在特定組件的工具的函式庫 * HAL 與 platform關係如下 .. image:: /embedded/chibi_HAL_plat.png 中斷(Interrupt) ^^^^^^^^^^^^^^^ * 先備知識 + 可遮罩式中斷 ( Maskable Interrupt ) : - 一種硬體中斷 - 可以透過軟體控制去設定中斷遮罩暫存器 ( Interrupt Mask Register ) 內的位元遮罩值 ( bit-mask ) 來讓CPU決定要不要回應這個中斷要求。 + 不可遮罩式中斷 ( Non-Maskable Interrupt, NMI ) : - 一種硬體中斷 - 與可遮罩式中斷不同,它無法用軟體去控制。**CPU一定要回應這個中斷要求,不可以忽略。** + 中斷遮罩暫存器 ( Interrupt Mask Registers ) : 在 ARM Cortex-M3中,可以透過設定中斷遮罩暫存器,來控制系統的中斷。共有三種: - PRIMASK : 一個只有一個 bit 的暫存器。設為1時,系統將只會處理 NMI 和 hard fault exception,其他可遮罩式中斷將被全部忽略。設為0時,則可以處理所有中斷。 - FAULTMASK: 一個只有一個 bit 的暫存器。設為1時,系統將只會處理 NMI,其他像是 hard fault exception 或是可遮罩式中斷都將被全部忽略。設為0時,則可以處理 hard fault exception。 - BASEPRI: 8個 bit 的暫存器,用來儲存優先度等級( priority level )。當這個暫存器被設為一個非0值時,系統將會忽略優先度比這個值還要大**(代表優先度等級較低) **的中斷。 * Chibi OS/RT的中斷類別 + 正常中斷 ( Regular Interrupts ): - 可遮罩式的中斷 - **在 GCC Ports / ARM Cortex-Mx / ARMv7-M 的移植版本中,優先度等級較低的中斷將被視為正常中斷** - 無法搶佔部分的 kernel code - 在此類的 interrupt handler 裡面可以呼叫 operating system APIs。 + 快速中斷 ( Fast Interrupts ): - 可遮罩式的中斷 - **在 GCC Ports / ARM Cortex-Mx / ARMv7-M 的移植版本中,優先度等級較高的中斷將被視為快速中斷** - 可以搶佔 kernel code ,也因此有較短的延遲 ( lantency ) 。 - 在此類的 interrupt handler 裡面無法呼叫任何一個 operating system API 。 + 不可遮罩式中斷 ( Non Maskable Interrupts, NMI): - 不受OS控制的中斷,擁有最短的延遲 ( lowest latency ) 執行緒(Thread)狀態 ^^^^^^^^^^^^^ .. image:: /embedded/chibiThdState.png * Start : 初始的狀態 * Suspended : * Running : 正在執行中的狀態 * Stop : 停止的狀態 * Sleeping : * Ready : 準備好的狀態 ChbiOS/RT 初始化後會建立兩個 thread + Idle thread : - priority level最低,只有在其他thread 處於sleep狀態時才會執行,通常在執行這個threaad時 系統會進入low power mode 且不會做任何事情 + Main thread : - priority=NORMALPRIO ,此thread在一開始執行main() function,且需要時可以變更自己的priority,通常其他的thread也都是由此建立的 Thread and Structure Reference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. image:: /struct_threads_list__coll__graph.png * 實線方向 : 資料結構繼承關係 * 虛線方向 : 指標指向的資料結構 Ready List ^^^^^^^^^^^^^ ChibiOS/RT 的 ready list以doubly linked list 實作 .. image:: /embedded/chibi_ready_list.png 數字愈大,優先權愈大 ( priority 相同的話,採用 round-robin strategy) * 執行序的priority level + IDLEPRIO : - value = 1 - 保留給Idle Thread的特殊priority level + LOWPRIO : - value = 2 - user thread 中 priority level 最低 + NORMALPRIO : - value = 64 - main() thread從這個level開始,通常user thread 的priority level是以此為中心 + HIGHPRIO : - value = 127 - user thread 中 priority level 最高 選出下一個可執行的thread, 並進行Context Switch `chsch.c`_ .. code-block:: c if (ntp->p_prio <= currp->p_prio) chSchReadyI(ntp); else { Thread *otp = chSchReadyI(currp); setcurrp(ntp); ntp->p_state = THD_STATE_CURRENT; chSysSwitch(ntp, otp); } 上下文交換(Context Switch) ^^^^^^^^^^^^^^^^^^^^^^^^^ | 在chibios當中,是以port_switch()來完成context switch | | /os/ports/GCC/ARMCMx/chcore_v7m.c(line:236) .. code-block:: c void _port_switch(Thread *ntp, Thread *otp) { asm volatile ("push {r4, r5, r6, r7, r8, r9, r10, r11, lr}" ←儲存舊的thread的狀態 : : : "memory"); #if CORTEX_USE_FPU asm volatile ("vpush {s16-s31}" : : : "memory"); #endif asm volatile ("str sp, [%1, #12] \n\t" ←切換stack pointer所指的位址 "ldr sp, [%0, #12]" : : "r" (ntp), "r" (otp)); ← #if CORTEX_USE_FPU asm volatile ("vpop {s16-s31}" : : : "memory"); #endif asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}" ←讀入新的thread的狀態 : : : "memory"); } 系統狀態(System States) ^^^^^^^^^^^^^^^^^^^^^^ .. image:: http://chibios.sourceforge.net/html/dot_inline_dotgraph_1.png | .. image:: http://chibios.sourceforge.net/html/dot_inline_dotgraph_2.png .. image:: http://chibios.sourceforge.net/html/dot_inline_dotgraph_3.png * Init + ChibiOS/RT 進行OS初始化之前的狀態,進行所謂的物理重置(physical reset)時也會進到這個狀態 + 呼叫chSysInit()這個函式進行初始化 + 在這個狀態裡所有可以發出Maskable Interrupt的sources全部失效 + 初始化完後進到 Normal * Normal + 初始化完後到達的狀態 + 在這裡可以執行Thread, 接收並處理任何中斷及呼叫任何system API * Suspended + 在這個狀態裡,無法接收正常中斷(IRQ),但是可以接收快速中斷(FIQ) + 除了可以呼叫chSysDisable()到達Disable狀態,以及chSysEnable()到達Normal狀態之外,其他所有system API都不能呼叫 * Disabled + 所有可遮罩式中斷資源全部失效,系統僅能處理不可遮罩式中斷(NMI) + 除了可以呼叫chSysEnable()到達Normal狀態,以及chSysSuspend()到達Suspended狀態之外,其他所有system API都不能呼叫 * Sleep + 當系統中沒有其他的Thread要跑時,此時系統會執行一個 `idle thread`_,到達這個狀態 + 此時系統將處於 low power mode,並等待一個中斷跳出這個狀態 + 接收到一個IRQ時,將會跑到 SRI 狀態去處理中斷,處理完後會回到 Normal * S-Locked * I-Locked * Serving Regular Interrupt ( SRI ) * Serving Fast Interrupt ( SFI ) * Serving Non-Maskable Interrupt ( SNMI ) * Halted 硬體驅動原理 ------------ * 以 DMA2D 為例 * 在對硬體的driver作設計時會用到很多_IO的type + 在ChibiOS-RT-Community/os/ports/common/ARMCMx/CMSIS/include/core_cm4.h裡找到相關定義 :: #define __IO volatile /*!< Defines 'read / write' permissions*/ 效能表現 -------- * 參考 ChibiOS/RT 的 test/testbmk.c 參考資料 -------- * `Building eye-catching GUIs for your embedded MCU designs`_ * `ChibiOS/RT - SourceForge`_ * `Overview of the Cortex-M3, Chapter 2`_