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, 任务切换的实现

  • 11
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
stm32cubemx是一个用于生成STM32微控制器初始化代码的工具,而FreeRTOS是一个实时操作系统,串口DMA(直接存储器访问)是一种在数据传输时减少CPU负荷和提高效率的方式。当使用STM32CubeMX结合FreeRTOS来接收不定长数据时,可以按照以下步骤进行操作。 首先,在CubeMX中配置串口和DMA的初始化参数,使其支持不定长数据接收。可以选择需要的串口和对应的DMA通道,配置串口的波特率、数据位和停止位等参数。然后,配置DMA以支持循环传输和变化长度的数据接收。 其次,生成初始化代码并在FreeRTOS中集成。CubeMX可以生成针对FreeRTOS的初始化代码,将配置好的串口和DMA初始化函数添加到FreeRTOS任务中,并在任务中实现数据接收的逻辑。可以利用FreeRTOS提供的任务管理和事件控制功能,让串口DMA在后台接收数据,同时不影响其他任务的运行。 最后,根据实际需求处理不定长数据。在串口DMA接收到数据后,根据数据长度进行相应的处理,可以通过消息队列或者信号量将数据传递给其他任务进行后续处理,也可以在接收完成后发送一个事件信号通知其他任务进行处理。需要根据具体需求来设计数据处理的流程,确保数据能够被准确地接收和处理。 总之,在使用STM32CubeMXFreeRTOS进行串口DMA接收不定长数据时,需要合理配置串口和DMA参数,并在FreeRTOS任务中实现数据接收和处理的逻辑,以实现高效、稳定地数据传输和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值