色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何設定PendSV優(yōu)先級?

技術讓夢想更偉大 ? 來源:技術讓夢想更偉大 ? 作者:技術讓夢想更偉大 ? 2022-12-05 11:38 ? 次閱讀

先了解下如何使用PendSV異常。(為何要使用PendSV而不是其他的異常,請參考《cortex-M3權威指南》)

1,如何設定PendSV優(yōu)先級?

37b73aaa-7432-11ed-8abf-dac502259ad0.png
NVIC_SYSPRI14EQU0xE000ED22
NVIC_PENDSV_PRIEQU0xFF
LDRR0,=NVIC_SYSPRI14LDRR1,=NVIC_PENDSV_PRI
STRBR1,[R0]

2,如何觸發(fā)PendSV異常?

37c38d64-7432-11ed-8abf-dac502259ad0.png

ICSR第28位寫1,即可將PendSV異常掛起。若是當前沒有高優(yōu)先級中斷產生,那么程序將會進入PendSV handler

NVIC_INT_CTRLEQU0xE000ED04
NVIC_PENDSVSETEQU0x10000000

LDRR0,=NVIC_INT_CTRL
LDRR1,=NVIC_PENDSVSET
STRR1,[R0]

3,編寫PendSV異常handler

這里用PendSV_Handler來觸發(fā)LED點亮,以此證明PendSV異常觸發(fā)的設置是正確的。

#include"stm32f10x_conf.h"

#defineLED0*((volatileunsignedlong*)(0x422101a0))//PA8

unsignedcharflag=0;
voidLEDInit(void)
{
RCC->APB2ENR|=1<<2;
GPIOA->CRH&=0XFFFFFFF0;
GPIOA->CRH|=0X00000003;
GPIOA->ODR|=1<<8;
}

__asmvoidSetPendSVPro(void)
{
NVIC_SYSPRI14EQU0xE000ED22
NVIC_PENDSV_PRIEQU0xFF
LDRR1,=NVIC_PENDSV_PRI
LDRR0,=NVIC_SYSPRI14
STRBR1,[R0]
BXLR
}

__asmvoidTriggerPendSV(void)
{
NVIC_INT_CTRLEQU0xE000ED04
NVIC_PENDSVSETEQU0x10000000
LDRR0,=NVIC_INT_CTRL
LDRR1,=NVIC_PENDSVSET
STRR1,[R0]
BXLR
}

intmain(void)
{
SetPendSVPro();
LEDInit();
TriggerPendSV();
while(1);
}

voidPendSV_Handler(void)
{
LED0=0;
}

上述代碼可以正常點亮LED,說明PendSV異常是正常觸發(fā)了。

OK,是時候挑戰(zhàn)任務切換了。

如何實現(xiàn)任務切換?三個步驟:

步驟一:在進入中斷前先設置PSP。

curr_task=0;

設置任務0為當前任務:

__set_PSP((PSP_array[curr_task]+16*4));

設置PSP指向task0堆棧的棧頂位置:

__set_CONTROL(0x3);

設置為用戶級,并使用PSP堆棧:

__ISB();

指令同步隔離。

步驟二:將當前寄存器的內容保存到當前任務堆棧中。進入ISR時,cortex-m3會自動保存八個寄存器到PSP中,剩下的幾個需要我們手動保存。

步驟三:在Handler中將下一個任務的堆棧中的內容加載到寄存器中,并將PSP指向下一個任務的堆棧。這樣就完成了任務切換。

要在PendSV 的ISR中完成這兩個步驟,我們先需了解下在進入PendSV ISR時,cortex-M3做了什么?

1,入棧。會有8個寄存器自動入棧。入棧內容及順序如下:

37caed20-7432-11ed-8abf-dac502259ad0.pngimg

在步驟一中,我們已經(jīng)設置了PSP,那這8個寄存器就會自動入棧到PSP所指地址處。

2,取向量。找到PendSV ISR的入口地址,這樣就能跳到ISR了。,

3,更新寄存器內容

做完這三步后,程序就進入ISR了。

進入ISR前,我們已經(jīng)完成了步驟一,cortex-M3已經(jīng)幫我們完成了步驟二的一部分,剩下的需要我們手動完成。

在ISR中添加代碼如下:

MRSR0,PSP

保存PSP到R0。為什么是PSP而不是MSP。因為在OS啟動的時候,我們已經(jīng)把SP設置為PSP了。這樣使得用戶程序使用任務堆棧,OS使用主堆棧,不會互相干擾。不會因為用戶程序導致OS崩潰。

STMDBR0!,{R4-R11}

保存R4-R11到PSP中。C語言表達是*(--R0)={R4-R11},R0中值先自減1,然后將R4-R11的值保存到該值所指向的地址中,即PSP中。

STMDB Rd!,{寄存器列表} 連續(xù)存儲多個字到Rd中的地址值所指地址處。每次存儲前,Rd先自減一次。

若是ISR是從從task0進來,那么此時task0的堆棧中已經(jīng)保存了該任務的寄存器參數(shù)。保存完成后,當前任務堆棧中的內容如下(假設是task0)

37d21abe-7432-11ed-8abf-dac502259ad0.png

左邊表格是預期值,右邊是keil調試的實際值。可以看出,是一致的。在任務初始化時(步驟一),我們將PSP指向任務0的棧頂0x20000080。在進入PendSV之前,cortex-M3自動入棧八個值,此時PSP指向了0x20000060。然后我們再保存R4-R11到0x20000040~0x2000005C。

這樣很容易看明白,如果需要下次再切換到task0,只需恢復R4~R11,再將PSP指向0x20000060即可。

所以切換到另一個任務的代碼:

LDRR1,=__cpp(&curr_task)
LDRR3,=__cpp(&PSP_array)
LDRR4,=__cpp(&next_task)
LDRR4,[R4]

獲取下一個任務的編號:

STRR4,[R1]
Curr_task=next_task
LDRR0,[R3,R4,LSL#2]

獲得任務堆棧地址,若是task0,那么R0=0x20000040( R0=R3+R4*4)

LDMIAR0!,{R4-R11}

恢復堆棧中的值到R4~R11。R4=*(R0++)。執(zhí)行完后,R0中值變?yōu)?x20000060

LDMIA Rd! {寄存器列表} 先將Rd中值所指地址處的值送出寄存器中,Rd再自增1.*

MSRPSP,R0
PSP=R0。
BXLR

中斷返回。

完整代碼

#include"stm32f10x.h"
#include"stm32f10x_usart.h"
#include"stm32f10x_gpio.h"
#include"stm32f10x_rcc.h"
#include"stdio.h"
#include"misc.h"

#defineHW32_REG(ADDRESS)(*((volatileunsignedlong*)(ADDRESS)))
#defineLED0*((volatileunsignedlong*)(0x422101a0))//PA8
voidUSART1_Init(void);
voidtask0(void);
unsignedcharflag=1;

uint32_tcurr_task=0;//當前執(zhí)行任務
uint32_tnext_task=1;//下一個任務
uint32_ttask0_stack[17];
uint32_ttask1_stack[17];
uint32_tPSP_array[4];

u8task0_handle=1;
u8task1_handle=1;

voidtask0(void)
{
while(1)
{
if(task0_handle==1)
{
printf("task0
");
task0_handle=0;
task1_handle=1;
}
}
}

voidtask1(void)
{
while(1)
{
if(task1_handle==1)
{
printf("task1
");
task1_handle=0;
task0_handle=1;
}
}
}

voidLEDInit(void)
{
RCC->APB2ENR|=1<<2;
GPIOA->CRH&=0XFFFFFFF0;
GPIOA->CRH|=0X00000003;
GPIOA->ODR|=1<<8;
}

__asmvoidSetPendSVPro(void)
{
NVIC_SYSPRI14EQU0xE000ED22
NVIC_PENDSV_PRIEQU0xFF

LDRR1,=NVIC_PENDSV_PRI
LDRR0,=NVIC_SYSPRI14
STRBR1,[R0]
BXLR
}

__asmvoidTriggerPendSV(void)
{
NVIC_INT_CTRLEQU0xE000ED04
NVIC_PENDSVSETEQU0x10000000

LDRR0,=NVIC_INT_CTRL
LDRR1,=NVIC_PENDSVSET
STRR1,[R0]
BXLR
}

intmain(void)
{
USART1_Init();

SetPendSVPro();
LEDInit();

printf("OStest
");

PSP_array[0]=((unsignedint)task0_stack)+(sizeoftask0_stack)-16*4;
//PSP_array中存儲的為task0_stack數(shù)組的尾地址-16*4,即task0_stack[1023-16]地址
HW32_REG((PSP_array[0]+(14<<2)))=(unsignedlong)task0;/*PC*/
//task0的PC存儲在task0_stack[1023-16]地址+14<<2中,即task0_stack[1022]中
HW32_REG((PSP_array[0]+(15<<2)))=0x01000000;/*xPSR*/

PSP_array[1]=((unsignedint)task1_stack)+(sizeoftask1_stack)-16*4;
HW32_REG((PSP_array[1]+(14<<2)))=(unsignedlong)task1;/*PC*/
HW32_REG((PSP_array[1]+(15<<2)))=0x01000000;/*xPSR*/

/*任務0先執(zhí)行*/
curr_task=0;

/*設置PSP指向任務0堆棧的棧頂*/
__set_PSP((PSP_array[curr_task]+16*4));

SysTick_Config(9000000);
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//72/8=9MHZ
/*使用堆棧指針,非特權級狀態(tài)*/
__set_CONTROL(0x3);

/*改變CONTROL后執(zhí)行ISB(architecturalrecommendation)*/
__ISB();

/*啟動任務0*/
task0();
//LED0=0;
while(1);
}

__asmvoidPendSV_Handler(void)
{
//保存當前任務的寄存器內容
MRSR0,PSP//得到PSPR0=PSP
//xPSR,PC,LR,R12,R0-R3已自動保存
STMDBR0!,{R4-R11}//保存R4-R11共8個寄存器得到當前任務堆棧

//加載下一個任務的內容
LDRR1,=__cpp(&curr_task)
LDRR3,=__cpp(&PSP_array)
LDRR4,=__cpp(&next_task)
LDRR4,[R4]//得到下一個任務的ID
STRR4,[R1]//設置curr_task=next_task
LDRR0,[R3,R4,LSL#2]//從PSP_array中獲取PSP的值
LDMIAR0!,{R4-R11}//將任務堆棧中的數(shù)值加載到R4-R11中
//ADDSR0,R0,#0x20
MSRPSP,R0//設置PSP指向此任務
//ORRLR,LR,#0x04
BXLR//返回
//xPSR,PC,LR,R12,R0-R3會自動的恢復
ALIGN4
}

voidSysTick_Handler(void)
{
flag=~flag;
LED0=flag;
if(curr_task==0)
next_task=1;
else
next_task=0;
TriggerPendSV();
}

voidUSART1_Init(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
USART_InitTypeDefUSART_InitStructure;

/*configUSART1clock*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);

/*USART1GPIOconfig*/
/*ConfigureUSART1Tx(PA.09)asalternatefunctionpush-pull*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
/*ConfigureUSART1Rx(PA.10)asinputfloating*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);

/*USART1modeconfig*/
USART_InitStructure.USART_BaudRate=9600;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);
}

intfputc(intch,FILE*f)
{
USART_SendData(USART1,(unsignedchar)ch);
while(!(USART1->SR&USART_FLAG_TXE));

return(ch);
}

測試后結果如圖:

37e621e4-7432-11ed-8abf-dac502259ad0.png

可以看出,兩個任務可以切換了。

上述代碼參考《cortex-M3權威指南》和《安富萊_STM32-V5開發(fā)板_μCOS-III教程》得來。

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • led
    led
    +關注

    關注

    242

    文章

    23297

    瀏覽量

    661373
  • 程序
    +關注

    關注

    117

    文章

    3788

    瀏覽量

    81130

原文標題:例說OS前的任務切換(附代碼)

文章出處:【微信號:技術讓夢想更偉大,微信公眾號:技術讓夢想更偉大】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    freertos中斷優(yōu)先級在哪設置

    FreeRTOS是一個流行的實時操作系統(tǒng),它廣泛應用于嵌入式系統(tǒng)開發(fā)。在FreeRTOS中,中斷優(yōu)先級是一個重要的概念,因為它決定了中斷處理的順序和響應時間。 1. 理解中斷優(yōu)先級 在討論如何設置
    的頭像 發(fā)表于 09-02 14:17 ?709次閱讀

    APS智能優(yōu)化排產軟件的優(yōu)先級應用

    資源、訂單需求和約束條件,自動計算出最優(yōu)的生產計劃。在這個過程中,訂單排產的優(yōu)先規(guī)則起著至關重要的作用。1.交期優(yōu)先級交期優(yōu)先級是訂單排產中最基本的優(yōu)先規(guī)則。根據(jù)
    的頭像 發(fā)表于 06-26 17:43 ?409次閱讀
    APS智能優(yōu)化排產軟件的<b class='flag-5'>優(yōu)先級</b>應用

    ESP32S2如何設置中斷優(yōu)先級

    ESP32S2有六中斷, 如何設置中斷優(yōu)先級? 比如在GPIO例程里 ,這種中斷優(yōu)先級是如何設置的呢? 中斷寄存器列表里 ,只有簡稱,哪里能獲取這個名稱所對應的功能??
    發(fā)表于 06-21 07:59

    請問有什么方法降低WIFI中斷的優(yōu)先級

    因為項目對時序輸出要求比較嚴格,WIFI中斷優(yōu)先級比硬件定時器中斷優(yōu)先級要高,在定時器中斷里面對GPIO管腳控制被延長執(zhí)行,請問有什么方法降低WIFI中斷的優(yōu)先級
    發(fā)表于 06-19 07:37

    如何在不同優(yōu)先級安裝相同的處理程序?

    在不同的優(yōu)先級中安裝相同的處理程序? 我需要一個解決方案,在不同的優(yōu)先級中安裝相同的處理程序(ISR),以便在我的項目中處理 CAT2 中斷,但我不能上傳項目,因為我簽署了 NDA。
    發(fā)表于 05-28 08:13

    systick的中斷優(yōu)先級是否應該設置為最高優(yōu)先級的嵌套中斷?

    最近在學習ucosii有這樣一個疑問,關于stm32的systick作為ucosii的基準時鐘,systick的中斷優(yōu)先級是否應該設置為最高優(yōu)先級的嵌套中斷。理由是什么?各位大俠求指教!!!
    發(fā)表于 05-16 06:44

    stm32的中斷優(yōu)先級分組了之后還能改分組嗎?

    如標題所示,stm32的中斷優(yōu)先級分組了之后還能改分組嗎? 比如我要使用外部中斷EXIT2,3,我在配置的時候配置了優(yōu)先級分組2組,然后配置了EXIT2,3,如果我下面又想開外部中斷的EXIT4,5的話,我是不是必須還的要使用優(yōu)先級
    發(fā)表于 05-13 08:40

    創(chuàng)建了兩個task如果一個優(yōu)先級高 一個優(yōu)先級低,高優(yōu)先級的那個一直在做,什么時候會調度到低優(yōu)先級的呢?

    創(chuàng)建了兩個task如果一個優(yōu)先級高一個優(yōu)先級低, 我看到任務的函數(shù)都是用死循環(huán)做的,那個高優(yōu)先級的那個一直在做,什么時候會調度到低優(yōu)先級的呢?
    發(fā)表于 05-13 07:13

    求助,關于stm32F4中斷優(yōu)先級0無法搶占的問題求解

    使用F407遇到一個搶占優(yōu)先級的問題: 現(xiàn)設置優(yōu)先級分組 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);也就是15個優(yōu)先級分組。按照手冊說明0
    發(fā)表于 04-23 07:26

    求助,是否可以不用pendSV中斷做任務切換?

    freeRTOS的任務切換我的理解是:通過SysTick中斷去觸發(fā)pendSV中斷去做任務切換,因為pendSV中斷優(yōu)先級最低,所以任務切換只會發(fā)生在沒有中斷的時候產生。那是不是也可以不用pe
    發(fā)表于 04-16 07:59

    STM32F103的寄存器NVIC_IPRx搶占優(yōu)先級和子優(yōu)先級是怎么設置的?

    STM32F103的寄存器NVIC_IPRx有些不明白,搶占優(yōu)先級和子優(yōu)先級是怎么設置的? 如果,中斷分組2,搶占優(yōu)先級3,子優(yōu)先級3 那下面這樣寫對嗎? SCB->AIR
    發(fā)表于 03-27 07:48

    Hightec對芯片中斷優(yōu)先級分配時,中斷號越高中斷優(yōu)先級越高嗎?

    請問大佬,Hightec對芯片中斷優(yōu)先級分配時,中斷號越高中斷優(yōu)先級越高嗎?看網(wǎng)上的帖子說中斷號越低優(yōu)先級越高。
    發(fā)表于 02-27 06:13

    RTTnano的用戶main函數(shù)中的優(yōu)先級是多少?

    RTTnano 的用戶main函數(shù)中的優(yōu)先級是多少?為什么會出現(xiàn)創(chuàng)建新的task之后,main函數(shù)會搶占掉低優(yōu)先級的task,例如RT_THREAD_PRIORITY_MAX設置為8 ,低于3
    發(fā)表于 02-26 08:01

    華為和思科默認路由優(yōu)先級

    優(yōu)先級值不同,則優(yōu)先級值最小的為最優(yōu)路由(無論開銷值是否相同,另一種理解就是對不同路由來源或路由協(xié)議之間的比較)。
    的頭像 發(fā)表于 01-11 10:47 ?1268次閱讀

    GD32如何配置中斷優(yōu)先級分組以及中斷優(yōu)先級

    使用GD32 MCU的過程中,大家可能會有以下疑問:中斷優(yōu)先級如何配置和使用?
    的頭像 發(fā)表于 01-10 10:30 ?3123次閱讀
    GD32如何配置中斷<b class='flag-5'>優(yōu)先級</b>分組以及中斷<b class='flag-5'>優(yōu)先級</b>
    主站蜘蛛池模板: 亚洲国产成人爱AV在线播放丿| 动漫人物差差差30分钟免费看| 国产不卡视频在线| 一个吃奶两个添下面H| 日日日夜夜在线视频| 久久精品亚洲热综合一本| 国产精品一区二区AV交换| avtt天堂网2014| 2022久久精品国产色蜜蜜麻豆| 歪歪爽蜜臀AV久久精品人人槡| 欧美.亚洲.日韩.天堂| 精品久久久久久久国产潘金莲| 嘟嘟嘟影院免费观看视频| 高清毛片一区二区三区| 国产精品亚洲二线在线播放| 果冻传媒免费观看| 一个人HD在线观看免费高清视频| 征服艳妇后宫春色| 小莹的性荡生活40章| 日本艳妓BBW高潮一19| 美国大臿蕉香蕉大视频| 狠狠插狠狠干| 别插我B嗯啊视频免费| 91精选国产| 在线免费观看国产精品| 一个色综合久久| 97人妻精品全国免费视频| 69精品人妻一区二区三区蜜桃| 被窝伦理午夜电影网| 国产伦精品一区二区三区免费 | 日本黄色官网| 亚洲成 人a影院青久在线观看| 2022精品福利在线小视频| 妇少水多18P蜜泬17P亚洲乱| 九九视频在线观看视频6| 九九热伊人| 强奸美女老师| 秋霞伦理手机在线看片| 亚洲精品www久久久久久| 亚洲欧美一区二区久久| 亚洲欧美另类无码专区|