自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

從零開始構(gòu)建實(shí)時(shí)操作系統(tǒng)—任務(wù)切換

運(yùn)維 系統(tǒng)運(yùn)維
嵌入式實(shí)時(shí)操作系統(tǒng)將會(huì)部署到越來越多的設(shè)備中,這就要求工程師深入地了解嵌入式實(shí)時(shí)操作系統(tǒng)。

1、前言

隨著計(jì)算機(jī)技術(shù)和微電子技術(shù)的迅速發(fā)展,嵌入式系統(tǒng)應(yīng)用領(lǐng)域越來越廣泛,尤其是其具備低功耗技術(shù)的特點(diǎn)得到人們的重視。隨著工信部提出NB-IoT基站建設(shè)具體目標(biāo)、三大運(yùn)營(yíng)商加速建設(shè),即將迎來萬物互聯(lián)的新時(shí)代,這是信息產(chǎn)業(yè)繼移動(dòng)互聯(lián)網(wǎng)之后的下一個(gè)萬億級(jí)市場(chǎng),這些為實(shí)時(shí)操作系統(tǒng)的應(yīng)用提供了廣闊的前景。

嵌入式實(shí)時(shí)操作系統(tǒng)將會(huì)部署到越來越多的設(shè)備中,這就要求工程師深入地了解嵌入式實(shí)時(shí)操作系統(tǒng)。本系列文章將和大家一起從零開始構(gòu)建一個(gè)嵌入式實(shí)時(shí)操作系統(tǒng),我將用最簡(jiǎn)單直白的方式一步一步搭建,我將用一篇文章的方式來總結(jié)搭建中的每個(gè)節(jié)點(diǎn)階段,并開源軟件工程和源代碼。

2、嵌入式實(shí)時(shí)操作系統(tǒng)

嵌入式實(shí)時(shí)操作系統(tǒng)是一個(gè)特殊的程序,是一個(gè)支持多任務(wù)的運(yùn)行環(huán)境。嵌入式實(shí)時(shí)操作系統(tǒng)最大的特點(diǎn)就是“實(shí)時(shí)性”,如果有一個(gè)任務(wù)需要執(zhí)行,實(shí)時(shí)操作系統(tǒng)會(huì)立即執(zhí)行該任務(wù),不會(huì)有較長(zhǎng)的延時(shí)。典型的實(shí)時(shí)操作系統(tǒng)有uCOS ,RT-Thread,F(xiàn)reeRTOS ,VxWorks,WinCE等。

嵌入式實(shí)時(shí)操作系統(tǒng)是一個(gè)特殊的程序(通常稱為內(nèi)核),它可以創(chuàng)建和控制所有任務(wù)。嵌入式實(shí)時(shí)操作系統(tǒng)除了包含一個(gè)內(nèi)核以外,還提供其他服務(wù),如文件系統(tǒng),協(xié)議棧,圖形用戶界面等。本文的重點(diǎn)在于了解嵌入式實(shí)時(shí)操作系統(tǒng)內(nèi)核的工作原理和結(jié)構(gòu),因此文中提到的實(shí)時(shí)操作系統(tǒng)通常指的是操作系統(tǒng)內(nèi)核。實(shí)時(shí)操作系統(tǒng)內(nèi)核通常要占用5%左右的CPU運(yùn)行時(shí)間,另外內(nèi)核是一個(gè)軟件代碼,需要額外占用ROM空間和RAM空間。

嵌入式實(shí)時(shí)操作系主要由以下3個(gè)子系統(tǒng)組成:

  • 任務(wù)調(diào)度子系統(tǒng)
  • 任務(wù)通信子系統(tǒng)
  • 內(nèi)存管理子系統(tǒng)

3、實(shí)現(xiàn)目標(biāo)

本文講解構(gòu)建嵌入式實(shí)時(shí)操作系統(tǒng)的第一個(gè)節(jié)點(diǎn)階段:實(shí)現(xiàn)簡(jiǎn)單的任務(wù)切換功能。

代碼區(qū)的數(shù)據(jù)是不變的,處理器寄存器的值和??臻g的值決定程序運(yùn)行狀態(tài)。讓每個(gè)任務(wù)“獨(dú)享”一個(gè)??臻g,當(dāng)我們將任務(wù)運(yùn)行時(shí)的處理器寄存器的值保存起來時(shí),這樣就實(shí)現(xiàn)保存任務(wù)的運(yùn)行狀態(tài)。同樣的當(dāng)我們把保存的任務(wù)運(yùn)行時(shí)的處理器寄存器的值裝載到處理的寄存器中時(shí),這樣就恢復(fù)了任務(wù)的運(yùn)行狀態(tài),任務(wù)繼續(xù)運(yùn)行起來。

切換任務(wù)的原理是:每個(gè)任務(wù)有一個(gè)“獨(dú)享”棧空間,通過保存和裝載任務(wù)運(yùn)行時(shí)的處理器寄存器的值,實(shí)現(xiàn)任務(wù)的暫停和恢復(fù)運(yùn)行。暫停一個(gè)任務(wù)后再恢復(fù)另外一個(gè)任務(wù)就完成了一次任務(wù)切換。

任務(wù)代碼,任務(wù)??臻g和處理器狀態(tài)如下圖:

4、實(shí)驗(yàn)環(huán)境

硬件是基于意法半導(dǎo)體的STM32F401(ARM公司的Cortex-M4內(nèi)核),軟件開發(fā)使用的是KEIL V5.2 開發(fā)工具。

軟件工程如下:

軟件工程中包含:main.c ,startup_stm32f401xc.s 和 readme三個(gè)文件。startup_stm32f401xc.s文件為STM32F401的啟動(dòng)文件,main.c文件實(shí)現(xiàn)任務(wù)切換功能,readme文件用于記錄版本修改日志。

5、代碼實(shí)現(xiàn)

切換任務(wù)的原理是讓每個(gè)任務(wù)都有一個(gè)“獨(dú)享”??臻g,通過保存和裝載任務(wù)運(yùn)行時(shí)的處理器寄存器的值,實(shí)現(xiàn)任務(wù)的暫停和恢復(fù)運(yùn)行。暫停一個(gè)任務(wù)后再恢復(fù)另外一個(gè)任務(wù)就完成了一次任務(wù)切換。

因此需要實(shí)現(xiàn):

  • 每個(gè)任務(wù)的獨(dú)立??臻g。
  • 實(shí)現(xiàn)任務(wù)的暫停和恢復(fù)。
  • 實(shí)現(xiàn)任務(wù)的調(diào)度。

(1)實(shí)現(xiàn)獨(dú)立??臻g

棧空間代碼如下:

為每個(gè)任務(wù)定義一個(gè)靜態(tài)數(shù)組,當(dāng)任務(wù)運(yùn)行時(shí)將處理器的棧指針指向任務(wù)“自己的”靜態(tài)數(shù)組,從而實(shí)現(xiàn)獨(dú)立??臻g。棧空間用來存放局部變量,中斷調(diào)用和函數(shù)調(diào)用時(shí)的處理器寄存器的值。任務(wù)切換時(shí)需要將處理器寄存器的值保存到任務(wù)的獨(dú)立棧空間。

在保存任務(wù)運(yùn)行狀態(tài)時(shí)需要保存處理器寄存器值到棧空間,因此需要深入了解處理器寄存器的用途和出入棧順序,Cortex-M4內(nèi)核的寄存器和寄存器中斷自動(dòng)入棧的順序圖如下:

初始化??臻g的代碼如下:

??臻g初始化后的狀態(tài)如下:

棧是一中先入后出的數(shù)據(jù)結(jié)構(gòu),Cortex-M4內(nèi)核的棧操作方式倍設(shè)置成了向下生長(zhǎng)。psp_array用于保存任務(wù)棧指針,psp_array[0]任務(wù)0棧指針指向task0_stack[112],其中task0_stack[116]保存PC程序指針值,task0_stack[117]保存狀態(tài)寄存器(符合Cortex-M4內(nèi)核寄存器出棧順序:手動(dòng)出棧8個(gè)寄存器,硬件自動(dòng)出棧8個(gè)寄存器)。

(2)實(shí)現(xiàn)任務(wù)的暫停和恢復(fù)

代碼如下:

cortex-M4內(nèi)核有一個(gè)PendSV(可掛起的系統(tǒng)調(diào)用)異常,其異常編號(hào)為14并且具有可編程的優(yōu)先級(jí)。當(dāng)軟件將PendSV設(shè)置成掛起時(shí),程序?qū)⑦M(jìn)入PendSV異常(中斷)。

將PendSV異常優(yōu)先級(jí)設(shè)置為最低,其它中斷函數(shù)都可以得到正常響應(yīng),不會(huì)受到PendSV異常影響,在PendSV異常中執(zhí)行任務(wù)切換,時(shí)序框圖如下:

PendSV_Handler為Cortex-M4內(nèi)核中斷服務(wù)函數(shù),進(jìn)入中斷函數(shù)時(shí)處理器自動(dòng)保存了R0,R1,R2,R3, R12,LR,PC,XPSR,在PendSV_Handler中斷程序中完成R4~R11入棧保存工作,從而實(shí)現(xiàn)任務(wù)保存工作。

/* 讀取當(dāng)前進(jìn)程棧指針數(shù)值 */
MRS R0,PSP
/* 保存R4-R11八個(gè)寄存器的值到當(dāng)前任務(wù)棧中 同時(shí)將回寫的地址寫入R0 */
STMDB R0!,{R4-R11}

psp_array[0]為任務(wù)0的棧指針, psp_array[1]為任務(wù)1的棧指針。以下代碼實(shí)現(xiàn)任務(wù)棧指針切換。

/* 讀取psp_array 地址 */
LDR R3, =__cpp(&psp_array)
/* 將當(dāng)前進(jìn)程PSP指針值 寫入 相應(yīng)的 PSP_array 位置 */
STR R0,[R3,R2,LSL #2]
/* 獲取下個(gè)進(jìn)程序號(hào) */
LDR R4,=__cpp(&next_task)
LDR R4,[R4]
/* R1為&curr_task 將下個(gè)進(jìn)程序號(hào)寫入curr_task中 */
STR R4,[R1]
/* psp_array讀取更新后的curr_task的PSP指針數(shù)值 */
LDR R0,[R3,R4,LSL #2]

在PendSV_Handler中斷程序中完成R4~R11寄存器出棧,PendSV_Handler中斷程序返回時(shí)處理器自動(dòng)出棧R0,R1,R2,R3, R12,LR,PC,XPSR,從而實(shí)現(xiàn)任務(wù)恢復(fù)工作。

/* 出棧 R4-R11八個(gè)寄存器 */
LDMIA R0!,{R4-R11}
/* 設(shè)置PSP指針 */
MSR PSP,R0
/* 中斷返回 */
BX LR

(3)實(shí)現(xiàn)任務(wù)的調(diào)度

任務(wù)調(diào)度的代碼如下:

SysTick_Handler為定時(shí)器中斷程序,實(shí)現(xiàn)時(shí)間片輪流改變目標(biāo)任務(wù),并掛起PendSV_Handle中斷,退出SysTick_Handler中斷程序時(shí)進(jìn)入PendSV_Handle中斷程序。

6、運(yùn)行結(jié)果

代碼仿真運(yùn)行如下:

運(yùn)行代碼后task_num0和task_num1這兩個(gè)變量依次自加,代碼實(shí)現(xiàn)任務(wù)輪流切換功能。

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2022-04-01 08:09:03

操作系統(tǒng)嵌入式重構(gòu)

2017-02-10 09:30:33

數(shù)據(jù)化運(yùn)營(yíng)流量

2010-02-22 09:39:52

HTML 5Web

2024-08-01 11:21:52

2024-07-31 08:14:17

2024-03-01 19:53:37

PyBuilderPython開發(fā)

2024-05-17 17:29:00

CurdlingPython開發(fā)

2024-11-28 10:35:47

2025-01-09 11:14:13

2015-10-15 14:16:24

2009-04-11 15:12:24

vxworks操作系統(tǒng)

2024-02-23 09:00:00

編程語言編譯器工具

2025-01-26 16:57:02

2020-07-02 15:32:23

Kubernetes容器架構(gòu)

2024-12-06 17:02:26

2014-07-22 13:09:21

android

2015-11-17 16:11:07

Code Review

2018-04-18 07:01:59

Docker容器虛擬機(jī)

2019-01-18 12:39:45

云計(jì)算PaaS公有云

2025-02-17 07:20:00

Flutter 3Flutter開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)