OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6653|回复: 9

Systick中断优先级问题

[复制链接]

1

主题

1

帖子

0

精华

新手入门

积分
25
金钱
25
注册时间
2015-12-7
在线时间
0 小时
发表于 2015-12-8 09:44:52 | 显示全部楼层 |阅读模式
5金钱
void delay_init()
{
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 
    fac_us=SystemCoreClock/8000000;
    fac_ms=(u16)fac_us*1000;
}

void BSP_Delay_us(u32 nus)
{
    u32 temp;      
    SysTick->LOAD=nus*fac_us; 
    SysTick->VAL=0x00;     
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;
    do
   {
       temp=SysTick->CTRL;
   }while((temp&0x01)&&!(temp&(1<<16)));
   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; 
   SysTick->VAL =0X00;       
}
主频为72M,延时us函数。
问题:这样写的中断优先级是多少,没有设置SysTick_Handler,并且没有在中断服务函数里中任何事?
假设定义里一个定时器4,优先级如下,是否会抢断systick中断。即谁的优先级高
void TIM4_NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);  
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

最佳答案

查看完整内容[请看2#楼]

systick的优先级最低,所以,如果在定时器中断里面调用延时,结果就是死了,出不来了。。。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-12-8 09:44:53 | 显示全部楼层
systick的优先级最低,所以,如果在定时器中断里面调用延时,结果就是死了,出不来了。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

3

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
373
金钱
373
注册时间
2015-3-7
在线时间
43 小时
发表于 2015-12-8 11:04:10 | 显示全部楼层
你这个systick用的是查询的方式,计数器减一次,就在后面的while里判断一次。
直到这个while((temp&0x01)&&!(temp&(1<<16)));不成立跳出,就定时完~

关于这个中断的优先级,看下core_cm3.h这个头文件,里面有关于这个优先级的配置~
为人莫作千年计,三十河东四十西,莫欺少年穷。
回复

使用道具 举报

2

主题

14

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
245
金钱
245
注册时间
2015-7-28
在线时间
85 小时
发表于 2015-12-11 13:59:17 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
不对吧,原子哥,在你的例程当中,跑裸机的话,SysTick是没有开启中断的,只有在ucos操作系统中才是开启了SysTick中断的。况且,如果调用了延时,SysTick中断也是优先级最低的,最多也是不会进入中断,怎么会死在里面呢
回复

使用道具 举报

8

主题

124

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
212
金钱
212
注册时间
2015-8-1
在线时间
7 小时
发表于 2015-12-13 00:29:22 | 显示全部楼层

尽量不要用这种查询的方式延迟。

我发现,当某一个地方进行延迟,被另一个中断打断,而这个中断服务程序里也有延迟等待时,就会把刚才那个延迟等待的时间给覆盖。有时候,明明主函数里两秒循环一次亮灯,结果就是灯狂闪。

所以,个人还是建议用 SysTick 中断的方式,对一个数计数,比如 uint64_t 类型的,1us 中断一次,对该数加 1,这样就提供了一个全局的微秒级时间可以用,然后延迟时,先计算延迟的结束时间,之后等那个结束时间到时即可。这样所有的延迟互相是不干扰的。

这种方式下,一定要将 SysTick 的中断优先级可以设成最高且唯一,比如0,其他所有的中断从 1 开始排。

有软件开发经验,从0硬件基础学习STM32开发。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-12-16 23:34:52 | 显示全部楼层
回复【5楼】dragon7799:
---------------------------------
那你用中断方式试试所有的例程,就会发现问题了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-12-16 23:35:12 | 显示全部楼层
回复【5楼】dragon7799:
---------------------------------
那你试试。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

8

主题

124

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
212
金钱
212
注册时间
2015-8-1
在线时间
7 小时
发表于 2015-12-17 15:46:58 | 显示全部楼层
回复【6楼】正点原子:
---------------------------------
我这种方法,所有例程确实不保证能用,只是在我自己的系统里,是这么实现的,所有延时都很准确。

因为一开始,确实因为其他地方的中断(接的外部的连续信号,每次做了一些防抖的延时),导致main函数里本来两秒切换一次状态的led灯在不断的闪烁。
有软件开发经验,从0硬件基础学习STM32开发。
回复

使用道具 举报

8

主题

124

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
212
金钱
212
注册时间
2015-8-1
在线时间
7 小时
发表于 2015-12-17 15:56:31 | 显示全部楼层

这是我自己的实现方法,其实很多系统也是这么干的,延时最准确的方式就是有一个不断递增的统一的时钟。如果大家都共用一个以倒计数来实现延时,必然会因为设置初值导致互相干扰。

头文件

[mw_shl_code=c,true]extern uint64_t gGlobalTotalTicks; #define TICK_GetFutureTick(aTicks) (gGlobalTotalTicks + (aTicks)) #define TICK_IsTimeForTick(aTicks) ((gGlobalTotalTicks >= (aTicks)) ? TRUE : FALSE)[/mw_shl_code]


具体实现

[mw_shl_code=c,true]////////////////////////////////////////////////////////////////////////////////// // 用于延时的计时器 SysTick // 初始化延迟函数 // SYSTICK的时钟固定为HCLK时钟 uint64_t gGlobalTotalTicks; void TIMER_Delay_Init() { gGlobalTotalTicks = 0; SysTick_Config(216); // 每 3 us 一次中断 SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); // 选择外部时钟 72MHz NVIC_SetPriority(SysTick_IRQn, 0); } void SysTick_Handler (void) { // gGlobalTotalTicks 从 0 - 18446744073709551615 。1 us 递增 1。3 us 一次性增加 3。 gGlobalTotalTicks += 3; } void Delay_us(uint64_t aMicroSeconds) { uint64_t lTimeoutTick = TICK_GetFutureTick(aMicroSeconds); while(TICK_IsTimeForTick(lTimeoutTick) == FALSE) { ;} } [/mw_shl_code]


另外,在程序中,也可以利用类似 Delay_us 中的方法,自己设置一段超时时间,在这段时间内可以继续工作。例如下面的这个代码段,用于定时检查 WIFI 模块

[mw_shl_code=c,true]uint64_t _WIFI_NextCheckTick = 30000000llu; // 从 30 秒开始检测 bool _IsWifiConnected = FALSE; void TIMER_Cycle_Act(void) { if (TICK_IsTimeForTick(_WIFI_NextCheckTick) == TRUE) { _IsWifiConnected = WIFI_CheckState(); if (_IsWifiConnected == TRUE) { UI_DrawWifiState(TRUE); _WIFI_NextCheckTick = TICK_GetFutureTick(10000000); // 10 秒后再次查看 } else { UI_DrawWifiState(FALSE); _WIFI_NextCheckTick = TICK_GetFutureTick(2000000); // 2 秒后再次查看 } } if (_IsWifiConnected) { .... } } [/mw_shl_code]
有软件开发经验,从0硬件基础学习STM32开发。
回复

使用道具 举报

8

主题

124

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
212
金钱
212
注册时间
2015-8-1
在线时间
7 小时
发表于 2015-12-17 20:14:33 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------

今天学习 uC/OS III,正好在官方下载的用户手册 3.05 版 115 页最上面一段是这么写的:

OSTickCtr is incremented by OS_TickTask() each time the task is signaled by the tick
ISR. OSTickCtr simply keeps track of the number of ticks since startup and its value can
be ready by calling OSTimeGet() or changed by calling OSTimeSet().

当然,我看了他的源代码,远比我的要复杂,因为由于多任务调度,需要有临界区管理,以及对等待队列进行额外操作。
有软件开发经验,从0硬件基础学习STM32开发。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-21 10:06

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表