怎么redis实现延时队列Systick做一秒钟延时不占用CPU

stm32中的Systick与delay有什么区别? systick是否一致占用CPU?_百度知道
stm32中的Systick与delay有什么区别? systick是否一致占用CPU?
我有更好的答案
除非任务很简单,而systick一般都采用中断方式,(不会有人在程序里一直查询标志位的),不占用cpu。还可以级联systick是m3内核内置的用于时钟节拍的定时器(要看m3的手册,stm32手册里面没有,包括nvic也是)。和stm32的其他外设定时器相比非常简单。定时时间也不算长。想要输出个pwm等就别想了。delay?莫非是用for或者while循环做的延时程序,只有溢出中断可选,只想简单定时应用没啥问题。否则实际项目不会使用循环的延时?这两个就是delay一直占用cpu。不过因为stm32上面有更强大的外设定时器的。定时的范围也比systick要大,所以一般不用systick
为您推荐:
其他类似问题
您可能关注的内容
stm32的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。ucosii在stm32上的移植详解(4)
详解3中有一个问题还没解释,就是stm32f10x_it.c中已经有SysTick中断函数的定义SysTick_Handler(),为什么官方版非要弄个OS_CPU_SysTickHandler()。答案就在启动文件上,一般我们自己开发基于stm32芯片的软件,都会使用标准外设库CMSIS中提供的启动文件,而官方移植的启动文件却是自己写的,在两个文件init.s,vectors.s中(Micrium\Software\EvalBoards\ST\STM3210B-EVAL\RVMDK)。init.s负责进入main(),vectors.s设置中断向量。OS_CPU_SysTickHandler和OS_CPU_PendSVHandler就是在vectors.s中被设置的。
我的移植是使用标准外设库CMSIS中startup_stm32f10x_hd.s作为启动文件的,那该怎么在这个文件中设置OS_CPU_SysTickHandler呢,事实上在startup_stm32f10x_hd.s文件中,PendSV中断向量名为PendSV_Handler,所以只需用OS_CPU_PendSVHandler把所有出现PendSV_Handler的地方替换掉就可以了。
那么为什么OS_CPU_SysTickHandler不用这种方式处理呢,这样也就不用注释os_cpu.c中的OS_CPU_SysTickHandler(),这主要是基于两个原因:
1. startup_stm32f10x_hd.s尽量少该,能不改就不改。
如果保留OS_CPU_SysTickHandler(),在以后开发过程中,改动OS_CPU_SysTickHandler()中的内容可能性是非常大的,如果一不小把该文件其他部分改了造成了问题,这个bug就非常难查了,所以我一般移植好后就把
osii的这些文件设置为只读。
对于上面的原因1,一开始移植时,我曾做过在PendSV_Handler()中调用OS_CPU_PendSVHandler(),后来发现这样不行,这是为什么呢?问题出在LR寄存器上。
PendSV_Handler()
OS_CPU_PendSVHandler();
汇编出来的代码会是这样:
PendSV_Handler PROC
OS_CPU_PendSVHandler
这样在进入OS_CPU_PendSVHandler之后,LR寄存器中存放的是指令POP
{r4,pc}的地址+1。在OS_CPU_PendSVHandler中的ORR
LR, LR, #0x04就不会起作用,也就无法使用PSP,移植因此失败。其实在AN-1018.pdf的3.04.06中也有强调OS_CPU_PendSVHandler必须被放置在中断向量表中。一开始我也没注意。
到这里移植的大部分工作都做完了,下面剩下的就是把工程配置好,SysTick中断处理好。
在工程中建立 osii组,把
osii下的文件都加进该组。这里别忘了把os_cpu_a.asm加入。
在工程的Options中,c/c++选项卡的Include
Paths中添加.\src\ osii\.\src\ osii\port。
编译工程,会发现缺少app_cfg.h和os_cfg.h文件,app_cfg.h是用来配置应用软件的,主要是任务的优先级和堆栈大小,中断优先级等信息。目前还没有基于
osii开发应用软件,所以只需在include文件夹中创建一个空的app_cfg.h文件即可。os_cfg.h是用来配置
osii系统的。拷贝Micrium\Software\EvalBoards\ST\STM3210B-EVAL\RVMDK\OS-Probe\os_cfg.h到template\include,对其做如下修改:
#define OS_APP_HOOKS_EN
#define OS_DEBUG_EN
#define OS_EVENT_MULTI_EN
#define OS_SCHED_LOCK_EN
#define OS_TICK_STEP_EN
#define OS_TASK_CHANGE_PRIO_EN
#define OS_TASK_QUERY_EN
#define OS_TASK_STAT_EN
#define OS_TASK_STAT_STK_CHK_EN
#define OS_TASK_SUSPEND_EN
#define OS_FLAG_EN
#define OS_MBOX_EN
#define OS_TIME_DLY_HMSM_EN
#define OS_TIME_DLY_RESUME_EN
#define OS_TIME_GET_SET_EN
#define OS_TIME_TICK_HOOK_EN
所做的修改主要是把一些功能给去掉,减少内核大小,也利于调试。等移植完成后,如果需要该功能,再做开启。
接下来就剩下处理好SysTick中断和启动任务了。SysTick是系统的“心跳”,本质上来说就是一个定时器。先把原来main.c中的内容删除,添加如下代码:
#include " os_ii.h"
#include "stm32f10x.h"
static OS_STK startup_task_stk[STARTUP_TASK_STK_SIZE];
static void systick_init(void)
RCC_ClocksTypeDef rcc_
RCC_GetClocksFreq(&rcc_clocks);
SysTick_Config(rcc_clocks.HCLK_Frequency / OS_TICKS_PER_SEC);
static void startup_task(void *p_arg)
systick_init();
#if (OS_TASK_STAT_EN & 0)
OSStatInit();
OSTaskDel(OS_PRIO_SELF);
int main(void)
OSTaskCreate(startup_task, (void *)0,
&startup_task_stk[STARTUP_TASK_STK_SIZE - 1],
STARTUP_TASK_PRIO);
OSStart();
systick_init()用来初始化并启动SysTick定时器。
RCC_GetClocksFreq()用来获取系统时钟。
SysTick_Config()初始化并使能SysTick定时器。
这里要注意的是OS_TICKS_PER_SEC,它是每秒钟的ticks数,如果为1000,就是1s中1000个ticks,也就是说1ms就会产生一个SysTick中断。系统的时间片为1ms。
在邵老师的书中3.11节已有明确说明,必须在调用OSStart()之后,才能开启时钟节拍器(SysTick)。一般会把它放在第一个任务(启动任务)中。
startup_task()用来创建其他应用任务,创建完其他任务后,就会自己删除自己。
文件中的STARTUP_TASK_STK_SIZE,STARTUP_TASK_PRIO需要在app_cfg.h中定义。代码如下:
#define STARTUP_TASK_PRIO
#define STARTUP_TASK_STK_SIZE
在stm32f10x_it.c中,还需要添加SysTick中断的处理代码:
void SysTick_Handler(void)
OSIntEnter();
OSTimeTick();
OSIntExit();
这个代码是仿照OS_CPU_SysTickHandler()中代码的,在邵老师书的3.11节亦有说明。这里就不解释。
至此 osii在stm32上的移植已全部完成。
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。怎么实现Systick做一秒钟延时不占用CPU-STM32-F0/F1/F2专区_百度知道
怎么实现Systick做一秒钟延时不占用CPU-STM32-F0/F1/F2专区
我有更好的答案
总不能让cpu发起延时以后? 如果要是这样 还不如用os了?还是处理完现在的 再返回原来的?扔下不管了,去干别的,等延时结束,那现在干的活干一半了怎么返回
信任、共进、卓越
电脑装机/选购
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。STM32学习记录13 ucosII移植
12:08:04来源: eefocus
关于如何移植,建立工程的问题已经有很多文档说明了,此处只是说明一下需要修改的文件及修改的原因。
1:os_cpu.h&
我们需要对此文件进行修改:&
1) &void OS_CPU_PendSVHandler(void) 需替换成 void PendSV_Handler(void) 一般我们自己开发基于 stm32 芯片的软件,都会使用标准外设库 CMSIS 中提供的启动文件,比如 stap_stm32f10x_hd.s,而 Micrium 官方没有用 ST 的标准启动文件,而且分开写成了两个.s 文件,即 &init.s 和 vectors.s
(Micrium\Software\EvalBoards\ST\10B-EVAL\RVMDK) init.s 负责进入 main(),vectors.s 设置中断向量 由于 OS_CPU_PendSVHandler 这个中断向量就是在 vectors.s 中被设置的,且我们使用的是startup_stm32f10x_hd.s 作为启动文件的,而在 startup_stm32f10x_hd.s 文件中,PendSV 的中断向量名为 PendSV_Handler,所以只需用 PendSV_Handler 替换掉相应文件的OS_CPU_PendSVHandler,其中函数声明在 OS_CPU_C.h 中,具体的中断服务函数原型在OS_CPU_A.ASM 中,后面也将对其进行修改。 这样子,替换后的 PendSV_Handler 函数在 OS_CPU_C.h 中有声明,在 OS_CPU_A.ASM 中有具体的中断服务函数代码,与 startup_stm32f10x_hd.s 中的向量地址就对应上了。&
2) &注释掉最后三个关于 SysTick 服务函数&
void &OS_CPU_SysTickHandler(void); &&
void &OS_CPU_SysTickInit(void); & &
INT32U &OS_CPU_SysTickClkFreq(void);&
其中,OS_CPU_SysTickHandler 函数在 ST 标准库 stm32f10x_it.c 中已定义,此处不需要;
其中,OS_CPU_SysTickInit 定义在 os_cpu_c.c 中,依赖于 OS_CPU_SysTickClkFreq,用于初始化 SysTick 定时器,需注释掉;其中,OS_CPU_SysTickClkFreq 定义在官方 EvalBoards 的 BSP.c中,需解除依赖,若需要,我们可以在 bsp.c 中实现。
2: stm32f10x_it.c
由于1.2的原因,需要修改
SysTick 作为 OS 的&心跳&,可称为滴答时钟,本质上来说就是一个定时器,和 PendSV 中断一样,在 startup_stm32f10x_hd.s 中 SysTick 的中断向量名为 SysTick_Handler,且因为 ST标准库已经有相关库函数,所以我们只需作如下修改:&
& 打开 os_cpu_c.c 文件,找到 void OS_CPU_SysTickHandler(void)的内容代码&
& OS_CPU_SR &cpu_&
& OS_ENTER_CRITICAL(); & & & & & & & & & & & & &
& OSIntNesting++;&
& OS_EXIT_CRITICAL();&
& OSTimeTick(); & & & & & & & & & & & & & & & &&
& & OSIntExit(); & &&
复制到 stm32f10x_it.c 文件中的 SysTick_Handler (void)函数内; &
& void SysTick_Handler(void)&
& & OS_CPU_SR &cpu_&
& & OS_ENTER_CRITICAL(); & & & & & & & & & & & & &
& & OSIntNesting++;&
& & OS_EXIT_CRITICAL();&
& & OSTimeTick(); & & & & & & & & & & & & & & & & & & & & & & & &
& & OSIntExit(); & & & & & & & & & & & & & & & & &
并且在文件头部添加:#include &&
3:os_cup_a.asm
由于1.1的原因,OS_CPU_PendSVHandler 中断服务函数的原型在此文件中,我们需要用PendSV_Handler 将其替换,以实现在 startup_stm32f10x_hd.s 中的中断向量的匹配。&
1) &注释掉 EXPORT OS_CPU_PendSVHandler,并修改成 EXPORT &PendSV_Handler,&
2) &找到 OS_CPU_PendSVHandler 程序原型,并重命名为 PendSV_Handler &
这样 PendSV_Handler 中断服务函数就成功建立了,同时,我们需要注释掉 stm32f10x_it.h 和stm32f10x_it.c 中的相关 PendSV_Handler 的声明和定义,以防止冲突。
4:os_cpu_c.c&
由于1.2做一下修改:
1) &把最后 OS_CPU_SysTickHandler(), OS_CPU_SysTickInit()这两个函数的内容代码注释掉;&
2) &禁用以下宏定义,因为他们涉及到上一步注释的 Systick 服务函数&
#define &OS_CPU_CM3_NVIC_ST_CTRL & &(*((volatile INT32U *)0xE000E010))&
#define &OS_CPU_CM3_NVIC_ST_RELOAD &(*((volatile INT32U *)0xE000E014)) &&
#define &OS_CPU_CM3_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018))&
#define &OS_CPU_CM3_NVIC_ST_CAL & & (*((volatile INT32U *)0xE000E01C))&
#define &OS_CPU_CM3_NVIC_ST_CTRL_COUNT & &0x & & &
#define &OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC & 0x & & &
#define &OS_CPU_CM3_NVIC_ST_CTRL_INTEN & & 0x & & &
#define &OS_CPU_CM3_NVIC_ST_CTRL_ENABLE & &0x & &
5:os_cfg.h&
此文件为配置内核的头文件,在这个文件,我们可以禁用、互斥信号量、邮箱、队列、信号量集、定时器、内存管理,调试模式: &
#define OS_FLAG_EN & &0 & //禁用信号量集 & &&
#define OS_MBOX_EN & &0 & //禁用邮箱 & &&
#define OS_MEM_EN & & &0 & //禁用内存管理 & &&
#define OS_MUTEX_EN & 0 & //禁用互斥信号量 & &&
#define OS_Q_EN & & 0 & //禁用队列 & &&
#define OS_SEM_EN & & &0 & //禁用信号量 & &&
#define OS_TMR_EN & & &0 & //禁用定时器 & &&
#define OS_DEBUG_EN & 0 & //禁用调试 &&
也可以禁用应用软件的钩子函数和多重事件控制
#define OS_APP_HOOKS_EN & 0 &
#define OS_EVENT_MULTI_EN &0 &
这些所做的修改主要是把一些功能给去掉,减少内核大小,也利于编译调试。等用到的时候,再开启相应的功能。
关键字:&&&&
编辑:什么鱼
引用地址:
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
微信扫一扫加关注 论坛活动 E手掌握
微信扫一扫加关注
芯片资讯 锐利解读
大学堂最新课程
汇总了TI汽车信息娱乐系统方案、优质音频解决方案、汽车娱乐系统和仪表盘参考设计相关的文档、视频等资源
热门资源推荐
频道白皮书
何立民专栏
北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。1671人阅读
UC/OS(20)
UCOS是一个实时的多任务任务基于优先级的操作系统,要运行多任务的话,在启动多任务之后,需要在每隔一段时间(一个滴答)内进行任务调度和相关数据的更新,以确保满足运行要求的最高优先级任务以便在下一次任务调度切换的时候能够得到一个及时的响应。
这个时间间隔是由时间中断来实现,而且每个中断的中断函数需要对相关的数据进行一个周期性更新。
在STM32中时间的中断由SysTick定时器(是cortexM3内核的定时器)实现。
系统时间中断函数OS_CPU_SysTickHandle 函数实现。
系统时钟中断
SysTick定时器被捆绑在NVIC中,用于产生SysTick异常(详情请见《CM3权威指南》8.7节)。
在SysTick定时器开始工作之前,需要对定时器进行初始化,确定其中断时间间隔,以及相关寄存器的配置。其功能由OS_CPU_SysTickInit(os_cpu_c.c)函数实现。
这里配置没有用到st的官方库,而是直接使用的寄存器操作。
代码如下:
//对应寄存器的地址
#define& OS_CPU_CM3_NVIC_ST_CTRL&&& (*((volatile INT32U *)0xE000E010))&& /* SysTick Ctrl & Status Reg. */
#define& OS_CPU_CM3_NVIC_ST_RELOAD& (*((volatile INT32U *)0xE000E014))&& /* SysTick Reload& Value Reg. */
#define& OS_CPU_CM3_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018))&& /* SysTick Current Value Reg. */
#define& OS_CPU_CM3_NVIC_ST_CAL&&&& (*((volatile INT32U *)0xE000E01C))&& /* SysTick Cal&&&& Value Reg. */
#define& OS_CPU_CM3_NVIC_PRIO_ST&&& (*((volatile INT8U& *)0xE000ED23))&& /* SysTick Handler Prio& Reg. */
#define& OS_CPU_CM3_NVIC_ST_CTRL_COUNT&&&&&&&&&&&&&&&&&&& 0x&&&& /* Count flag.&&&&&&&&&&&&&&& */
#define& OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC&&&&&&&&&&&&&&&&& 0x&&&& /* Clock Source.&&&&&&&&&&&&& */
#define& OS_CPU_CM3_NVIC_ST_CTRL_INTEN&&&&&&&&&&&&&&&&&&& 0x&&&& /* Interrupt enable.&&&&&&&&& */
#define& OS_CPU_CM3_NVIC_ST_CTRL_ENABLE&&&&&&&&&&&&&&&&&& 0x&&&& /* Counter mode.&&&&&&&&&&&&& */
#define& OS_CPU_CM3_NVIC_PRIO_MIN&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0xFF&&&& /* Min handler prio.&&&&&&&&& */
void& OS_CPU_SysTickInit (void)
&&& INT32U&
&&& cnts = OS_CPU_SysTickClkFreq() / OS_TICKS_PER_SEC; //OS_CPU_SysTickClkFreq()是得到systick的时钟频率。则也就是说,计数器一秒钟能计数的次数。OS_TICKS_PER_SEC(os_cfg.h)表示的是一秒钟计数器需要清零的次数,这里配置为1000(可以根据系统的需求进行配置),也就是说1s/1000 = 1ms进行一次systick时间中断。那么1ms内定时器需要计数次数为OS_CPU_SysTickClkFreq()
/ OS_TICKS_PER_SEC
&&& OS_CPU_CM3_NVIC_ST_RELOAD = (cnts - 1);//将cnts的值填进RELOAD寄存器中
& & & & & & & & & & & & & & & & & & & & & & & &&
&&& OS_CPU_CM3_NVIC_PRIO_ST&& = OS_CPU_CM3_NVIC_PRIO_MIN; //设置systick中断的优先级
&&& OS_CPU_CM3_NVIC_ST_CTRL& |= OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC | OS_CPU_CM3_NVIC_ST_CTRL_ENABLE;//定时器使能,开启内核时钟
& & & & & & & & & & & & & & & & & & &&
&&& OS_CPU_CM3_NVIC_ST_CTRL& |= OS_CPU_CM3_NVIC_ST_CTRL_INTEN; & //定时器中断使能
系统时钟中断中断函数
在系统时间中断后,便会执行相应的中断函数void& OS_CPU_SysTickHandler (void)(os_cpu_c.c)
该函数的主要功能就是将中断状态标志全局变量OSIntNesting加1,然后调用OSTimeTick()进行调度。
在退出中断程序之前,调用OSIntExit,完成退出之前的最后处理。该函数在之后的中断管理说明。
时间中断任务调度器OSTimeTick
OSTimeTick函数(os_core.c)的主要作用是在系统时钟中断的时候,由中断程序调用,对任务的时延、任务的状态进行修改,设置就绪状态,但是不会实现任务的切换。
函数的核心代码部分如下:
ptcb = OSTCBL&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //指向就绪任务控制块链表
&&&&&&& while (ptcb-&OSTCBPrio != OS_TASK_IDLE_PRIO) {&&&& //遍历链表
&&&&&&&&&&& OS_ENTER_CRITICAL();
&&&&&&&&&&& if (ptcb-&OSTCBDly != 0u) {&&&&&&&&&&&&&&&&&&& //如果设置了任务时延或者等待事件时延
&&&&&&&&&&&&&&& ptcb-&OSTCBDly--;&&&&&&&&&&&&&&&&&&&&&&&&& //将时延时间减1
&&&&&&&&&&&&&&& if (ptcb-&OSTCBDly == 0u) {&&&&&&&&&&&&&&& //若是时延时间为0
&&&&&&&&&&&&&&&&&&& if ((ptcb-&OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) { &//如果任务等待事件有一个发生了
&&&&&&&&&&&&&&&&&&&&&&& ptcb-&OSTCBStat& &= (INT8U)~(INT8U)OS_STAT_PEND_ANY;&&&&&&&&& //清除事件等待标志,因为时间已经到了,不管有没有事件发生,都得清零
&&&&&&&&&&&&&&&&&&&&&&& ptcb-&OSTCBStatPend = OS_STAT_PEND_TO;&&&&&&&&&&&&&&&& //表示等待事件以为时间超时不在等待
&&&&&&&&&&&&&&&&&&& } else {
&&&&&&&&&&&&&&&&&&&&&&& ptcb-&OSTCBStatPend = OS_STAT_PEND_OK; &//任务等待完成,或是因为是简单的任务延时,或者是因为任务等待事件已经发生
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&& if ((ptcb-&OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {& //任务处于就绪状态,而不是阻塞状态(就绪链表中的任务状态只有三种,就绪,阻塞和运行态)
&&&&&&&&&&&&&&&&&&&&&&& OSRdyGrp&&&&&&&&&&&&&& |= ptcb-&OSTCBBitY;&&&&&&&&&&&& //更新就绪任务表和就绪任务数组
&&&&&&&&&&&&&&&&&&&&&&& OSRdyTbl[ptcb-&OSTCBY] |= ptcb-&OSTCBBitX;
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&&&&&& ptcb = ptcb-&OSTCBN&&&&&&&&&&&&&&&&&&&&&&& /* Point at next TCB in TCB list&&&&&&&&&&&&&&& */
&&&&&&&&&&& OS_EXIT_CRITICAL();
在就绪任务链表中,若ptcb-&OSTCBDly != 0u,说明该任务处于时延状态(任务时延或者等待时间时延),为阻塞态。(两者等价)
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:71220次
积分:1194
积分:1194
排名:千里之外
原创:48篇
(2)(1)(1)(4)(3)(1)(4)(3)(20)(2)(3)(3)(2)(1)(2)
(window.slotbydup = window.slotbydup || []).push({
id: '4740890',
container: s,
size: '250,250',
display: 'inlay-fix'}

我要回帖

更多关于 redis实现延时队列 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信