cubemx使用freertos时用systick和TIM的区别

Posted 一剃解千愁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cubemx使用freertos时用systick和TIM的区别相关的知识,希望对你有一定的参考价值。

cube工程和生成的代码上区别

1,选择systick

Keil:

此时,中断优先级的抢占优先级是最低级的15,子优先级是0(分组4)

只有带__weak 的 HAL_InitTick

2,选择某一定时器:TIM1

Keil:

有带__weak 的 HAL_InitTick,被overwrite

也有真正被调用的HAL_InitTick

此时,中断优先级的抢占优先级是最高级的0,子优先级是0(分组4)

定时器选择TIM6或TIM7比较好

基本定时器(TIM6,TIM7)的主要功能: 只有最基本的定时功能。基本定时器TIM6和TIM7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动。
  通用定时器(TIM2~TIM5)的主要功能: 除了基本的定时器的功能外,还具有测量输入信号的脉冲长度( 输入捕获) 或者产生输出波形( 输出比较和PWM)。
  高级定时器(TIM1,TIM8)的主要功能: 高级定时器不但具有基本,通用定时器的所有的功能,还具有控制交直流电动机所有的功能,你比如它可以输出6路互补带死区的信号,刹车功能等等。

__weak void HAL_Delay(uint32_t Delay)

  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  
    wait += (uint32_t)(uwTickFreq);
  

  while((HAL_GetTick() - tickstart) < wait)
  
  

总结:systick作为操作系统时基钟,好处是方便移植,操作系统需要的是一个时基,systick又是属于内核外设(24位的倒计时定时器,也有中断服务函数,中断优先级通过设置内核寄存器SHPR3,可以设置的最低优先级为15),移植到任意的相同内核的都能使用,不需要再做修改。不好的地方就是,比如有中断服务函数中调用HAL_delay()来延时,它是通过while来判断是否达到时间,但是每次得到一个节拍数,和前面的对比不变,由于其中断优先级比systick(看上面的图片可知优先级是15)高,抢占中断,导致systick的中断服务函数无法工作(它的工作就是递减,减小tick),没“人”减小tick,而HAL_delay()又在等tick减少,又是它自己导致tick不能减少,OS调度也在等,这样就崩了,一般也不在中断中搞延时,中断都是为了尽快的执行完,实时操作系统也更加要求快速。
上下文切换是在PendSV中进行的(任务切换中断 PendSV 和系统时钟节拍中断 Systick),其优先级会被设置为最低,这样可以避免在其他中断处理过程中产生上下文切换。在PendSV异常处理中执行,该异常是由SysTick异常触发
而使用一个基本定时器来提供时基,定时器优先级设置为最高优先级(看上面的图片可知优先级是0),其他中断也无法抢占,不会影响systick工作,操作系统又得到了一个时基,不好的地方是,移植代码,需要找个相同的定时器来使用,如果被占用,还得选择其他定时器
综上,systick偏向公用,定时器偏向专用

NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
其中宏__NVIC_PRIO_BITS为4,

其他参考资料:
void SysTick_Handler(void)

if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行

xPortSysTickHandler();

sysTick属于内核外设,跟普通外设的中断优先级有些区别,并没有抢占优先级和子优先级的说法,在STM32F429中,内核外设的中断优先级由内核SCB这个外设的寄存器:SHPRx(x=1.2.3)来配置。
内核外设的中断优先级可编程为:0~15,只有16个可编程优先级,数值越小,优先级越高。如果软件优先级配置相同,那就根据他们在中断向量表里面的位置编号来决定优先级大小,编号越小,优先级越高。
SysTick定时器的计数器是向下递减计数的,计数一次的时间TDEC=1/CLKAHB,当重装载寄存器中的值VALUELOAD减到0的时候,产生中断,可知中断一次的时间TINT=VALUELOAD * TDEC中断= VALUELOAD/CLKAHB
NVIC的中断优先级分组不仅对片上外设有效,同样对内核的外设也有效。我们把systick的优先级15转换成二进制值就是1111(0b),又因为NVIC的优先级分组2,那么前两位的11(0b)就是3,后两位的11(0b)也是3。无论从抢占还是子优先级都比我们设定的外设的优先级低。如果当两个的软件优先级都配置成一样,那么就比较他们在中断向量表中的硬件编号,编号越小,优先级越高
systick虽然作为与CPU紧耦合的内核外设,但其中断优先级并不比普通外设要高,并不因为它是内核外设而特殊,它还是遵循中断优先级高低的规则来响应。
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */

延时;
void SysTick_us(uint32_t us)

uint32_t us_tick=SystemCoreClock / 1000000UL;;
uint32_t start_val,real_val,JianGe;
start_val=SysTick->VAL; //把最开始获得的计数值作为基准值
do
real_val=SysTick->VAL; //获取当前值
if(start_val>real_val) //应对计时器提前下溢

JianGe=start_val-real_val;

else

JianGe=SysTick->LOAD+start_val-real_val;

while(JianGe<us*us_tick); //判断是否到达间隔

void rt_hw_us_delay(rt_uint32_t us)

rt_uint32_t start, now, delta, reload, us_tick;
start = SysTick->VAL;
reload = SysTick->LOAD;
us_tick = SystemCoreClock / 1000000UL;
do
now = SysTick->VAL;
delta = start > now ? start - now : reload + start - now;
while(delta < us_tick * us);

其他区别:

系统的时钟

systick和定时器都可作为操作系统时基钟,这个操作系统时钟有什么作用?
时钟节拍是特定的周期性中断,这个中断可以看做是系统心跳。系统的时钟节拍周期一般使用1ms,当然这不是一个绝对的数值,只是常用的数值,这个数值过小会使得内核的负载过高(时钟节拍率越快,系统的额外开销就越大),这个值过大会影响任务的运行实时性。

参考:
1,任何操作系统都需要提供一个时钟节拍,以供系统处理诸如延时、 超时等与时间相关的事件
2,时钟的节拍中断使得内核可以将任务延迟若干个时钟节拍,以及当任务等待,事件发生时,提供等待超时等依据。
举个例子:系统中有两个同等优先级的任务:task1 和 task2,而且在就绪态队列中,它们的优先级是最高的,也就是说,此时系统中就它们兄弟俩在运行了,task1在执行的时候, 如果它不主动放弃 CPU,它就会一直执行,那么什么时候才能轮到 task2 执行呢??
所以此时需要一种机制能打断 task1 的执行,然后切换到 task2,后面在 task2 执行的时候,也能从 task2 中收回 CPU 的控制权,然后交给 task1,并且要让 task1 从上次被打断的地方开始执行。
通用的方法就是周期性的触发中断(一般称为 Tick 中断),在中断处理函数中,保存上一个任务的上下文,然后切换到下一个任务中。在 FreeRTOS 中使用一个硬件 timer 作为 Tick 中断。如果将 Tick 中断配置为 1ms 来一次,那么系统就会 1ms 进行一次任务切换。

系统时钟作用:
1,延时、 超时等与时间相关的事件
2,时间片轮转执行时,周期性的触发中断,使得优先级相同的任务轮流执行。
3,统计任务运行时间的API
4, 任务切换的实现

以上是关于cubemx使用freertos时用systick和TIM的区别的主要内容,如果未能解决你的问题,请参考以下文章

CubeMX STM32 HAL + FreeRTOS

freeRtos学习笔记 移植和CPU利用率统计

HAL STM32F407ZGT6 FreeRTOS

Cortex M3 - Systick NVIC 禁用 - 节能 FreeRTOS

STM32 使用 FreeRTOS过程记录

CubeMX使用FreeRTOS编程指南