我的自定义上下文切换在ARM的内联汇编中无法正常工作
我已经为我的上下文切换项目工作了一段时间,但在ARM内联汇编方面遇到了麻烦。我不知道如何用调试器逐步跟踪每一个汇编上下文,也不确定自己是否看懂了内联汇编。就这方面来说,我基本上是新手。如果你们能帮帮我,我会非常感激。完整的代码在下面的部分。
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"
volatile int32_t TimeDelay = 0;
void Delay(uint32_t nTime);
uint32_t stack_Blink_1[9]= {0};
uint32_t *sp_Blink_1 = &stack_Blink_1[8];
uint32_t stack_Blink_2[9]= {0};
uint32_t *sp_Blink_2 = &stack_Blink_2[8];
uint32_t curr_Task = 0;
uint32_t next_Task = 0;
uint32_t *PSP_Array[2]={0};
void GPIO_SETUP(void);
void EXTI_SETUP(void);
void Blink_1(void);
void Blink_2(void);
int main(void){
SysTick_Config(7200000);
GPIO_SETUP();
EXTI_SETUP();
NVIC_EnableIRQ(EXTI2_IRQn);
SCB->CCR |= SCB_CCR_STKALIGN_Msk;
sp_Blink_1--;
*(sp_Blink_1--) = (1U << 24); //xPSR
sp_Blink_1--;
sp_Blink_1--;
*sp_Blink_1 = (uint32_t)&Blink_1; //PC
sp_Blink_1-= 4;
sp_Blink_2--;
*(sp_Blink_2--) = (1U << 24); //xPSR
sp_Blink_2--;
sp_Blink_2--;
*sp_Blink_2 = (uint32_t)&Blink_2; //PC
sp_Blink_2-= 4;
PSP_Array[0]=sp_Blink_1;
PSP_Array[1]=sp_Blink_2;
Blink_1();
while(1){
}
}
void PendSV_Handler(void){
__ASM volatile(
//save current context
"MRS R0, PSP\n\t" // Get current process stack pointer value
"ISB\n\t"
"STMDB R0!, {R4-R11}\n\t" // Save R4 to R11 in task stack (8 regs)
"LDR R1, %[curr_Task]\n\t"
"LDR R2, [R1]\n\t" // Get current task ID
"LDR R3, %[psp_array]\n\t"
"STR R0,[R3, R2, LSL #2]\n\t" // Save PSP value into PSP_array
//-----------------------------------------------------------------
//load next context
"LDR R4, %[next_task]\n\t"
"LDR R4, [R4]\n\t" // Get next task ID
"STR R4, [R1]\n\t" // Set curr_task = next_task
"LDR R0,[R3, R4, LSL #2]\n\t" // Load PSP value from PSP_array
"LDMIA R0!, {R4-R11}\n\t" // Load R4 to R11 from task
"MSR PSP, R0\n\t" // Set PSP to next task
"ISB\n\t"
"BX LR\n\t" // Return
//"ALIGN 4\n\t"
: // Output Operands
: [curr_Task] "m" (curr_Task),
[psp_array] "m" (PSP_Array),
[next_task] "m" (next_Task) // Input Operands
);
}
void SysTick_Handler(void){
if(TimeDelay > 0)
TimeDelay--;
}
void EXTI2_IRQHandler(void){
if(curr_Task == 0){
EXTI_ClearITPendingBit(EXTI_Line2);
curr_Task = 1;
}else{
EXTI_ClearITPendingBit(EXTI_Line2);
curr_Task =0;
}
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
void Delay(uint32_t nTime){
TimeDelay = nTime;
while(TimeDelay != 0);
}
void Blink_1(void){
while(1){
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
Delay(10);
GPIO_SetBits(GPIOB,GPIO_Pin_1);
Delay(10);
}
}
void Blink_2(void){
while(1){
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay(10);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay(10);
}
}
void GPIO_SETUP(void){
GPIO_InitTypeDef GPIO_InitStruct_A2;
GPIO_InitStruct_A2.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStruct_A2.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct_A2.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitTypeDef GPIO_InitStruct_B0;
GPIO_InitStruct_B0.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct_B0.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct_B0.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitTypeDef GPIO_InitStruct_B1;
GPIO_InitStruct_B1.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct_B1.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct_B1.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitTypeDef GPIO_InitStruct_C13;
GPIO_InitStruct_C13.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStruct_C13.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct_C13.GPIO_Mode = GPIO_Mode_Out_PP;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_Init(GPIOA,&GPIO_InitStruct_A2);
GPIO_Init(GPIOB,&GPIO_InitStruct_B0);
GPIO_Init(GPIOB,&GPIO_InitStruct_B1);
GPIO_Init(GPIOC,&GPIO_InitStruct_C13);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, 2);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
GPIO_SetBits(GPIOB,GPIO_Pin_1);
GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
void EXTI_SETUP(void){
EXTI_InitTypeDef EXTI_InitStruct_2;
EXTI_InitStruct_2.EXTI_Line = EXTI_Line2;
EXTI_InitStruct_2.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct_2.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStruct_2.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct_2);
}
解决方案
问题之所以出现,是因为我让PSP寄存器指向了任务栈。这样会导致数据损坏,处理器也无法切换到这些任务。不是让PSP指向任务栈,而是在PendSV触发后,把任务栈中的数据取出,放到PSP指向的位置。
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"
volatile int32_t TimeDelay = 0;
void Delay(uint32_t nTime);
uint32_t stack_Blink_1[18]= {0};
uint32_t *sp_Blink_1 = &stack_Blink_1[17];
uint32_t stack_Blink_2[18]= {0};
uint32_t *sp_Blink_2 = &stack_Blink_2[17];
uint32_t curr_Task = 0;
uint32_t next_Task = 1;
uint32_t *pCurr_Task = 0;
uint32_t *pNext_Task = 0;
uint32_t *PSP_Array[2]={0};
uint32_t **pPSP_Array = 0;
uint32_t tmp = 0;
void GPIO_SETUP(void);
void EXTI_SETUP(void);
void Blink_1(void);
void Blink_2(void);
int main(void){
SysTick_Config(7200000);
GPIO_SETUP();
EXTI_SETUP();
NVIC_EnableIRQ(EXTI2_IRQn);
NVIC_SetPriority(PendSV_IRQn, 0xEF);
NVIC_SetPriority(EXTI2_IRQn, 0xFF);
SCB->CCR |= SCB_CCR_STKALIGN_Msk;
sp_Blink_1--;
*(sp_Blink_1--) = (1U << 24); //xPSR
*sp_Blink_1 = (uint32_t)&Blink_1; //PC
sp_Blink_2--;
*(sp_Blink_2--) = (1U << 24); //xPSR
*sp_Blink_2 = (uint32_t)&Blink_2; //PC
pCurr_Task = &curr_Task;
pNext_Task = &next_Task;
sp_Blink_1 = (uint32_t *)((((uint32_t)stack_Blink_1 / 8) * 8) + 8);
sp_Blink_2 = (uint32_t *)((((uint32_t)stack_Blink_2 / 8) * 8) + 8);
PSP_Array[0]=sp_Blink_1;
PSP_Array[1]=sp_Blink_2;
pPSP_Array = &PSP_Array[0];
tmp = __get_MSP();
__set_PSP(tmp);
__set_CONTROL(0x3);
__ISB();
Blink_1();
while(1){
}
}
void PendSV_Handler(void){
__ASM volatile(
//save current context
"CPSID I \n\t" //__disable_irq()
"MRS R0, PSP \n\t"
"LDR R1, %[pPSP_Array] \n\t" //loadin the address of PSP_Array
"LDR R3, %[curr_Task] \n\t"
"LDR R1, [R1, R3, LSL #2] \n\t" //getting the stack value from array (&stack_Blink_x)
"ADD R1, #32 \n\t" //stack_Blink_x[8](
"STMDB R1!, {R4-R11} \n\t" // Save R4 to R11 in task stack (8 regs) after saving the r1 goes back to stack_Blink_1[0]
"LDR R1, %[curr_Task] \n\t"
"LDR R2, %[pCurr_Task] \n\t"
//load next context
"LDR R3, %[next_task] \n\t"
"STR R3, [R2] \n\t" // Set curr_task = next_task
"LDR R2, %[pNext_Task] \n\t"
"STR R1, [R2] \n\t" // set next_task = curr_task (we are toggling)
"LDR R1, %[pPSP_Array] \n\t"
"LDR R1, [R1, R3, LSL #2] \n\t" // Load PSP value from PSP_array (&stack_Blink_x)
"LDMIA R1!, {R4-R11} \n\t" // Load R4 to R11 from stack
"MOV R2, R0 \n\t"
"ADD R2, #24 \n\t"
"ADD R1, #24 \n\t"
"LDR R3, [R1] \n\t"
"STM R2, {R3} \n\t"
"ADD R2, #4 \n\t"
"ADD R1, #4 \n\t"
"LDR R3, [R1] \n\t"
"STM R2, {R3} \n\t"
"CPSIE I \n\t" //__enable_irq()
"BX R14 \n\t" // Return
: // Output Operands
: [curr_Task] "m" (curr_Task),
[pPSP_Array] "m" (pPSP_Array),
[next_task] "m" (next_Task),
[pCurr_Task] "m" (pCurr_Task),
[pNext_Task] "m" (pNext_Task) // Input Operands
:"memory","r0","r1","r2","r3"
);
}
void SysTick_Handler(void){
if(TimeDelay > 0)
TimeDelay--;
}
void EXTI2_IRQHandler(void){
EXTI_ClearITPendingBit(EXTI_Line2);
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
void Delay(uint32_t nTime){
TimeDelay = nTime;
while(TimeDelay != 0);
}
void Blink_1(void){
while(1){
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay(10);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay(10);
}
}
void Blink_2(void){
while(1){
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
Delay(10);
GPIO_SetBits(GPIOB,GPIO_Pin_1);
Delay(10);
}
}
void GPIO_SETUP(void){
GPIO_InitTypeDef GPIO_InitStruct_A2;
GPIO_InitStruct_A2.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStruct_A2.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct_A2.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitTypeDef GPIO_InitStruct_B0;
GPIO_InitStruct_B0.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct_B0.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct_B0.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitTypeDef GPIO_InitStruct_B1;
GPIO_InitStruct_B1.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct_B1.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct_B1.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitTypeDef GPIO_InitStruct_C13;
GPIO_InitStruct_C13.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStruct_C13.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct_C13.GPIO_Mode = GPIO_Mode_Out_PP;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_Init(GPIOA,&GPIO_InitStruct_A2);
GPIO_Init(GPIOB,&GPIO_InitStruct_B0);
GPIO_Init(GPIOB,&GPIO_InitStruct_B1);
GPIO_Init(GPIOC,&GPIO_InitStruct_C13);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, 2);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
GPIO_SetBits(GPIOB,GPIO_Pin_1);
GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
void EXTI_SETUP(void){
EXTI_InitTypeDef EXTI_InitStruct_2;
EXTI_InitStruct_2.EXTI_Line = EXTI_Line2;
EXTI_InitStruct_2.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct_2.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStruct_2.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct_2);
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。