天天看点

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

      PendSV典型使用场合是在上下文切换时(在不同任务之间切换)。 我们先简单的写几段代码实现PendSV的中断触发,当然也会涉及到CM3内核汇编指令,自从开始挑战的那天起,你不如地狱谁入地狱!

      如何触发PendSV中断呢?从Cortex-M3权威指南手册上可以看到如下图所示,控制ICSR的28位置1便可以悬起PendSV 触发PendSV中断。

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

         如何设置PendSV优先级?同样下表也来自Cortex-M3权威指南,设置地址0xE000ED22中的值既可以设置PendSV的优先级。暂且将PendSV的优先级设置为最低0xff;

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

main.c加入如下代码用于触发PendSV中断异常。

#define  NVIC_INT_CTRL      0xE000Ed04 //PendSV中断控制器地址
#define  NVIC_PENDSV_SET    0x10000000 //PendSV触发的值
#define  NVIC_SYSPRI2       0xE000Ed22 //PendSV优先级控制地址
#define  NVIC_PENDSV_PRI    0x000000ff //PendSV设置为最低优先值
#define  MEM32(addr)        *(volatile unsigned long *)(addr)
#define  MEM8(addr)         *(volatile unsigned char *)(addr)
// 触发PendSV中断异常
void trigger_PendSV(void)
{
  MEM32(NVIC_INT_CTRL) = NVIC_PENDSV_SET;  //触发PendSV
  MEM8(NVIC_SYSPRI2) =  NVIC_PENDSV_PRI;   //设置PendSV优先级
}
           

主函数中调用trigger_PendSV() 便可以触发。

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

         真实的情况是,我们看不到任何现象,我们没有在 PendSV_Hander()做任何处理,一般的PendSV异常处理都是使用汇编代码,我们先尝试使用C文件采用文件内嵌套汇编的形式来在C文件中加入汇编,添加switch.c文件,将其添加到工程中,用来存放PendSV触发后中断处理的函数。__asm__ 表明要在C文件中嵌套汇编,该函数主要是将R4~R11寄存器的值保存到block结构体内定义的指针所指向的数据缓冲区buffer中。人为改变R4 R5寄存器的值,最后再从buffer中恢复原来R4~R11的值,看下是否发生改变。

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

这里用到了STMDB和LDMIA指令,这里先简单介绍一下。

stmdb:db(decrease before)表示先减后存。

指令 stmdb sp!, { fp, ip, lr, pc}  %% "!”表示sp等于最终被修改的sp的值。

假设 sp=4096,此条指令的执行过程如下:

1.先减:sp=sp-4=4092;

2.后存:4092-4095处存放pc的值;

3.先减:sp=sp-4=4088;

4.后存:4088-4091处存放lr寄存器的值;

以此类推,..........。

ldmia:ia(increase after)表示先读后增。

指令ldmia sp, {fp,sp, pc}

假设 sp=4080,此条指令的执行过程如下:

1.先读:fp位于4080-4083处存放原来保存的fp;

2.后增:sp=sp+4=4084;

3.先读:sp位于4084-4087处存放原来保存的ip;

4.后增:sp=sp+4;

以此类推,..........。

开启debud调试功能,按F10 单步执行到trigger_PendSV函数,接着按F11进入trigger_PendSV函数内部执行。

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

trigger_PendSV函数执行完毕会触发PendSv事件中断,进入PendSV_Handler函数中。

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

按F10 单步执行到STMDB R0!,{R4-R11} 将R4~R11寄存器的值写入到Stack_buffer缓冲区(内存)。

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

执行改变ADD R4, R4, #10  ADD R5, R5, #10 指令来改变R4 R5寄存器的值。

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

通过LDMIA R0!,{R4-R11} 来从Stack_buffer缓冲区恢复R4~R11的值。

从0到1写嵌入式操作系统---------------------------2.PendSV的触发

继续阅读