打印
[应用相关]

PendSV的触发

[复制链接]
1914|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
PendSV典型使用场合是在上下文切换时(在不同任务之间切换)。 我们先简单的写几段代码实现PendSV的中断触发,当然也会涉及到汇编指令,自从开始挑战的那天起,我不如地狱谁入地狱!

使用特权

评论回复
沙发
dingbo95|  楼主 | 2019-5-30 20:00 | 只看该作者
如何触发PendSV中断呢?从Cortex-M3权威指南手册上可以看到如下图所示,控制ICSR的28位置1便可以悬起PendSV 触发PendSV中断。

使用特权

评论回复
板凳
dingbo95|  楼主 | 2019-5-30 20:00 | 只看该作者
如何设置PendSV优先级?同样下表也来自Cortex-M3权威指南,设置地址0xE000ED22中的值既可以设置PendSV的优先级。暂且将PendSV的优先级设置为最低0xff;

使用特权

评论回复
地板
dingbo95|  楼主 | 2019-5-30 20:01 | 只看该作者
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优先级
}


使用特权

评论回复
5
dingbo95|  楼主 | 2019-5-30 20:01 | 只看该作者
主函数中调用trigger_PendSV() 便可以触发。

使用特权

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

使用特权

评论回复
7
dingbo95|  楼主 | 2019-5-30 20:02 | 只看该作者
这里用到了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;
以此类推,..........。

使用特权

评论回复
8
dingbo95|  楼主 | 2019-5-30 20:03 | 只看该作者
开启debud调试功能,按F10 单步执行到trigger_PendSV函数,接着按F11进入trigger_PendSV函数内部执行。

使用特权

评论回复
9
dingbo95|  楼主 | 2019-5-30 20:03 | 只看该作者
trigger_PendSV函数执行完毕会触发PendSv事件中断,进入PendSV_Handler函数中。

使用特权

评论回复
10
dingbo95|  楼主 | 2019-5-30 20:03 | 只看该作者
按F10 单步执行到STMDB R0!,{R4-R11} 将R4~R11寄存器的值写入到Stack_buffer缓冲区(内存)。

使用特权

评论回复
11
dingbo95|  楼主 | 2019-5-30 20:04 | 只看该作者
执行改变ADD R4, R4, #10  ADD R5, R5, #10 指令来改变R4 R5寄存器的值。

使用特权

评论回复
12
dingbo95|  楼主 | 2019-5-30 20:04 | 只看该作者
通过LDMIA R0!,{R4-R11} 来从Stack_buffer缓冲区恢复R4~R11的值。

使用特权

评论回复
13
戈卫东| | 2019-5-30 21:24 | 只看该作者
写操作系统时才需要这个指令。
在ISR里面触发它,在服务程序里面提供系统服务。

使用特权

评论回复
14
labasi| | 2019-6-18 11:38 | 只看该作者
希望楼主能进入天堂

使用特权

评论回复
评论
xiaofei558008 2020-12-29 10:15 回复TA
哈哈哈哈哈哈哈哈哈,笑死 
15
paotangsan| | 2019-6-18 12:03 | 只看该作者
请问PendSV是什么啊

使用特权

评论回复
评论
xiaofei558008 2020-12-29 10:15 回复TA
同问,PendSV 是啥缩写? 
16
renzheshengui| | 2019-6-18 12:14 | 只看该作者
paotangsan 发表于 2019-6-18 12:03
请问PendSV是什么啊

endSV指可悬起系统调用

一般用在上了操作系统的软件开发中

操作系统通常不让用户程序直接访问硬件,而是通过提供一些系统服务函数,让用户程序使用 SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就要产生一个 SVC异常,然后操作系统提供的 SVC异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。

使用特权

评论回复
17
paotangsan| | 2019-7-4 16:18 | 只看该作者
renzheshengui 发表于 2019-6-18 12:14
endSV指可悬起系统调用

一般用在上了操作系统的软件开发中

非常感谢热心解答

使用特权

评论回复
18
renzheshengui| | 2019-7-4 16:30 | 只看该作者
paotangsan 发表于 2019-7-4 16:18
非常感谢热心解答

客气   举手之劳啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

1197

帖子

5

粉丝