SysTick Software Timer
#ifndef __SYSTEM_H__
#define __SYSTEM_H__ #include <stdint.h>
#include <stddef.h> #include "bsp.h" extern void sys_srand( unsigned int seed );
extern int sys_rand( void ); extern uint32_t g_SysTick_Counter; typedef void (*SYS_TIMER_CALLBACK_T)( void * pContext ); typedef struct SYS_TIMER_T
{
// set before SysTick_Start()
uint32_t Period;
SYS_TIMER_CALLBACK_T callback;
void * pContext;
uint32_t Periodical;
// set after SysTick_Start()
uint32_t Active;
uint32_t Time; // Delta value relative to prev timer
struct SYS_TIMER_T *pNext;
} SYS_TIMER_T; //------------------------------------------------------------------------------
void SysTick_DelayTicks( uint32_t ticks ); void SysTick_DelayUs( uint32_t usec ); void SysTick_DelayMs( uint32_t msec ); uint32_t SysTick_Get( void ); void SysTick_DelayUnitl( uint32_t time ); void SysTick_Init( void ); //------------------------------------------------------------------------------
void SysTick_Start( SYS_TIMER_T * pTimer ); void SysTick_Stop( SYS_TIMER_T * pTimer ); //------------------------------------------------------------------------------
uint32_t SysInt_Enable( void ); uint32_t SysInt_Disable( void ); void SysInt_Init( void ); #endif /* __SYSTEM_H__ */
#include "system.h" #define SysTick_CLKSource_HCLK_Div8_Used ( 0 )
#define SysTick_IRQ_Priority ( SYSTICK_PRIORITY ) static uint32_t g_Ticks_In_Ms;
static uint32_t g_Ticks_In_1us;
static uint32_t g_Ticks_In_10us;
static uint32_t g_Ticks_In_100us;
static SYS_TIMER_T *g_TimerHead = ;
uint32_t g_SysTick_Counter = ;
uint32_t g_SysInt_Counter = ; static unsigned int g_Next = ; //------------------------------------------------------------------------------
/// Initialize the seed for rand generator.
/// \param seed rand initiation seed -- g_SysTick_Counter ?
//------------------------------------------------------------------------------
void sys_srand( unsigned int seed )
{
g_Next = seed;
} //------------------------------------------------------------------------------
/// Return a random number, maxinum assumed to be 65535
//------------------------------------------------------------------------------
int sys_rand( void )
{
g_Next = g_Next * + ;
return (unsigned int) ( g_Next / ) % ;
} /*
* Configures the priority grouping: pre-emption priority and subpriority.
* 4 bits for pre-emption priority
* 0 bits for subpriority
*/
void SysInt_Init( void )
{
NVIC_PriorityGroupConfig( NVIC_PRIORITY_GROUP );
} uint32_t SysInt_Disable( void )
{
__disable_interrupt( );
if ( g_SysInt_Counter < UINT32_MAX )
g_SysInt_Counter++; return g_SysInt_Counter;
} uint32_t SysInt_Enable( void )
{
if ( g_SysInt_Counter > )
g_SysInt_Counter--; if ( g_SysInt_Counter == )
__enable_interrupt( );
return g_SysInt_Counter;
} //------------------------------------------------------------------------------
void SysTick_DelayTicks( uint32_t ticks )
{
uint32_t SysTickVal = SysTick->VAL; // from VAL downto 0
while ( ticks >= SysTickVal ) // SysTick->VAL <= SysTick->LOAD
{
ticks -= SysTickVal;
while ( !( SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk ) )
{
}
SysTickVal = SysTick->LOAD; // from LOAD downto 0
} if ( ticks > ) // LOAD >= VAL > ticks > 0
{
uint32_t SysTickValMarker = SysTick->LOAD - ticks;
while ( SysTick->VAL > SysTickValMarker )
{
}
}
} static void SysTick_DelayTicks_64( uint64_t totalTicks )
{
while ( totalTicks > 0xFFFFFFFF )
{
SysTick_DelayTicks( 0xFFFFFFFF );
totalTicks -= 0xFFFFFFFF;
}
SysTick_DelayTicks( totalTicks );
} void SysTick_DelayUs( uint32_t usec )
{
uint64_t totalTicks; totalTicks = (uint64_t) g_Ticks_In_1us * usec;
if ( totalTicks == )
{
usec /= ;
totalTicks = (uint64_t) g_Ticks_In_10us * usec; if ( totalTicks == )
{
usec /= ;
totalTicks = (uint64_t) g_Ticks_In_100us * usec;
}
}
SysTick_DelayTicks_64( totalTicks );
} void SysTick_DelayMs( uint32_t msec )
{
uint64_t totalTicks; totalTicks = (uint64_t) g_Ticks_In_Ms * msec;
SysTick_DelayTicks_64( totalTicks );
} void SysTick_DelayUnitl( uint32_t time )
{
while ( time > g_SysTick_Counter )
{
}
} uint32_t SysTick_Get( void )
{
return g_SysTick_Counter;
}
/*------------------------------------------------------------------------------
Setup SysTick Timer for 1 msec interrupts.
-------------------------------------------------------------------------------
1. The SysTick_Config() function is a CMSIS function which configure:
- The SysTick Reload register with value passed as function parameter.
- Configure the SysTick IRQ priority to the lowest value (0x0F).
- Reset the SysTick Counter register.
- Configure the SysTick Counter clock source to be Core Clock Source (HCLK).
- Enable the SysTick Interrupt.
- Start the SysTick Counter. 2. You can change the SysTick Clock source to be HCLK_Div8 by calling the
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8) just after the
SysTick_Config() function call.
The SysTick_CLKSourceConfig() is defined inside the misc.c file. 3. You can change the SysTick IRQ priority by calling the
NVIC_SetPriority(SysTick_IRQn, n)
just after the SysTick_Config() function call.
The NVIC_SetPriority() is defined inside the core_cm3.h file. 4. To adjust the SysTick time base, use the following formula: Reload Value = SysTick Counter Clock (Hz) x Desired Time base (s) - Reload Value is the parameter to be passed for SysTick_Config() function
- Reload Value should not exceed 0xFFFFFF 5. SysTick_CLKSource: specifies the SysTick clock source. SysTick_CLKSource_HCLK
AHB clock selected as SysTick clock source. SysTick_CLKSource_HCLK_Div8
AHB clock divided by 8 selected as SysTick clock source. */
void SysTick_Init( void )
{
#if ( RTOS_USED > 0 )
return;
#else
SysTick_Config( SystemCoreClock / );
NVIC_SetPriority( SysTick_IRQn, SYSTICK_PRIORITY ); #if (SysTick_CLKSource_HCLK_Div8_Used > 0 )
uint32_t SysTick_Clock = SystemCoreClock / ;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
#else
uint32_t SysTick_Clock = SystemCoreClock;
#endif g_TimerHead = ;
g_SysTick_Counter = ;
g_Ticks_In_1us = ( SysTick_Clock + ) / ; // 168/21, 72/9
g_Ticks_In_10us = ( SysTick_Clock + ) / ;
g_Ticks_In_100us = ( SysTick_Clock + ) / ;
g_Ticks_In_Ms = ( SysTick_Clock + ) / ; // 168000/21000, 72000/9000
#endif
} #if (RTOS_USED > 0 )
__weak
#endif
//------------------------------------------------------------------------------
// The hook function is called directly from the interrupt handler
// The callback therefore should execute as fast as possible.
// The callback called must not re-enable interrupts.
//
void SysTick_Handler( void )
{
SysInt_Disable( ); g_SysTick_Counter++; SYS_TIMER_T * pTimerHead = g_TimerHead;
SYS_TIMER_T * pTimerNext = pTimerHead->pNext;
if ( pTimerHead ) // at least one timer is Active ...
{
pTimerHead->Time--; // There might be more than one timeout pr. tick ( with same Period )
while ( pTimerHead )
{
if ( pTimerHead->Time > )
break; // The callback may place new/same items in the queue !!!
if ( pTimerHead->callback ) // execute as fast as possible
{
( pTimerHead->callback )( pTimerHead->pContext ); if ( pTimerHead->Periodical > )
SysTick_Start( pTimerHead );
else
SysTick_Stop( pTimerHead );
} pTimerHead = pTimerNext;
pTimerNext = pTimerHead->pNext;
}
} SysInt_Enable( );
} //------------------------------------------------------------------------------
// place timer in the queue
// If the timer is already Active, it will be restarted with new configuration
//
void SysTick_Start( SYS_TIMER_T * pTimer )
{
uint32_t accumulated;
SYS_TIMER_T *this, **last;
if ( ( pTimer->callback == ) || ( pTimer->Period == ) )
return; SysInt_Disable( ); if ( pTimer->Active )
SysTick_Stop( pTimer ); pTimer->Active = ;
pTimer->pNext = ; if ( g_TimerHead == ) /* Queue empty ? */
{
pTimer->Time = pTimer->Period;
g_TimerHead = pTimer;
}
else /* Do a sorted insert */
{
this = g_TimerHead;
last = &g_TimerHead;
accumulated = ; while ( this )
{
/* Insert before "this" ? */
if ( pTimer->Period < accumulated + this->Time )
{
pTimer->pNext = this;
pTimer->Time = pTimer->Period - accumulated;
this->Time -= pTimer->Time; /* Adjust timeout */
*last = pTimer;
break;
}
else if ( this->pNext == ) /* At end of queue ? */
{
pTimer->Time = //
pTimer->Period - accumulated - this->Time;
this->pNext = pTimer;
break;
}
accumulated += this->Time;
last = &this->pNext;
this = this->pNext;
}
} SysInt_Enable( );
} void SysTick_Stop( SYS_TIMER_T * pTimer )
{
if ( pTimer == )
return; if ( g_TimerHead == ) /* Queue empty ? */
return; SYS_TIMER_T *this, **last; SysInt_Disable( ); this = g_TimerHead;
last = &g_TimerHead;
pTimer->Active = ; while ( this )
{
if ( this == pTimer ) /* Correct timer ? */
{
pTimer->Period = ;
pTimer->Active = ;
if ( this->pNext ) /* Adjust timeout */
this->pNext->Time += pTimer->Time;
*last = this->pNext;
break;
}
last = &this->pNext;
this = this->pNext;
} SysInt_Enable( );
}
SysTick Software Timer的更多相关文章
- Microsecond and Millisecond C# Timer[转]
文章转至:http://www.codeproject.com/Articles/98346/Microsecond-and-Millisecond-NET-Timer IntroductionAny ...
- Implementing Software Timers - Don Libes
在看APUE习题10.5的时候提示了这篇文章,讲的非常清晰,设计也非常巧妙,所以把原文放在这里.值得自己去实现. Title: Implementing Software Timers By ...
- rt-thread的定时器管理源码分析
1 前言 rt-thread可以采用软件定时器或硬件定时器来实现定时器管理的,所谓软件定时器是指由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务.而硬件 ...
- FreeRTOS相关转载-(朱工的专栏)
FreeRTOS系列第1篇---为什么选择FreeRTOS? 1.为什么学习RTOS? 作为基于ARM7.Cortex-M3硬件开发的嵌入式工程师,我一直反对使用RTOS.不仅因为不恰当的使用RTOS ...
- FREERTOS 手册阅读笔记
郑重声明,版权所有! 转载需说明. FREERTOS堆栈大小的单位是word,不是byte. 根据处理器架构优化系统的任务优先级不能超过32,If the architecture optimized ...
- 了解FreeRTOS源文件目录结构
参考文献: Understanding the FreeRTOS directory structure. 从官网下载下来的FreeRTOS源文件包,对于每一个已经移植完成的处理器,都有一个与之对应的 ...
- Cstyle的札记,Freertos内核具体解释,第0篇
Freertos是一个硬实时内核,支持众多的微处理器架构,我们能够从它的官网(www.freertos.ort)下载它的sourcecode,同一时候也能够看出它支持了几十种的微处理器架构,这 ...
- Linux时间子系统之(十四):tick broadcast framework
专题文档汇总目录 Notes:BroadcastTick作为cpuidle的waker,硬件基础.BroadcastTick嵌入在当前系统Tick框架中.BroadcastTick设备初始化:周期性T ...
- Linux kernel的中断子系统之(八):softirq
返回目录:<ARM-Linux中断系统>. 总结:中断分为上半部和下半部,上半部关中断:下半部开中断,处理可以延迟的事情.下半部有workqueue/softirq/tasklet三种方式 ...
随机推荐
- 第8月第21天 django lbforum项目记录
1. django-admin.py startproject lbforum01 ls cd lbforum01/ ls python manage.py startapp forum sudo p ...
- 无法执行该操作,因为链接服务器 "xxxxx" 的 OLE DB 访问接口 "SQLNCLI" 无法启动分布式事务
在存储过程中使用事务,并且使用链接服务器时,报类似下面的错误 链接服务器"****"的 OLE DB 访问接口 "SQLNCLI10" 返回了消息 " ...
- word技巧
1.插入注解(脚注和尾注) 2.复制的图片显示不全怎么办? 横向显示,或者图片另存为然后保存为PPT 3.word修订标记的添加和删除(最终版) 4.word中表格样式调整 5.修改标题的样式和标题的 ...
- j2ee组件简介
- Linux中断(interrupt)子系统之四:驱动程序接口层 & 中断通用逻辑层【转】
转自:http://blog.csdn.net/droidphone/article/details/7497787 在本系列文章的第一篇:Linux中断(interrupt)子系统之一:中断系统基本 ...
- update-rc.d使用
在Linux系统下,一个Services的启动.停止以及重启通常是通过/etc/init.d目录下的脚本来控制的.然而,在启动或改变运行级别时,是在/etc/rcX.d中来搜索脚本.其中X是运行级别的 ...
- 测试开发之Django——No1.介绍以及引申
前言 > 测试行业发展飞速,自动化测试兴起,由此对测试人员的要求与日俱增.随时而来的,就是职能的增加. > 首先需要学习的,就是自动化测试.而由自动化测试引申而来的,就是另外几个新增的岗位 ...
- linux上jdk管理
查看CentOS自带JDK是否已安装. yum list installed |grep java. 若有自带安装的JDK,卸载CentOS系统自带Java环境? yum -y remove java ...
- #Plugin 环形loading插件
CircleLoader 环形loading插件 1.原生JS,不依赖jquery,zepto 2.前端学习交流群:814798690 案例展示 下载地址 https://github.com/cha ...
- 【转载】【收藏】Github上免费的编程教程【作者Victor Felder】
原链接:https://github.com/EbookFoundation/free-programming-books/blob/master/free-programming-books-zh. ...