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三种方式 ...
随机推荐
- HDU 4509 湫湫系列故事——减肥记II (简单模拟)
题意:一天一共有1440分钟,主人公每天有n件事要做,给出这n件事开始跟结束的时间,然后让你求出,空闲的时间的总分钟数是多少. 解题报告:简单模拟,只要开个一维数组标记那个每个分钟是否是有事的就可以了 ...
- 第11月第21天 php引用 codeigniter cakephp
1. class CI_Controller { private static $instance; /** * Constructor */ public function __construct( ...
- Django用ajax进行post请求
post请求有两种,跨域和不跨域 1.不跨域 # 不跨域的 view.py def re_json(request): print(request.POST['name']) p1 = Product ...
- perl6 中将 字符串 转成十六进制
say Blob.new('abcde'.encode('utf8')).unpack("H*"); say '0x'~'abcde'.encode('utf8').unpack( ...
- Git 使用规范流程【转】
转自:http://www.ruanyifeng.com/blog/2015/08/git-use-process.html 作者: 阮一峰 日期: 2015年8月 5日 团队开发中,遵循一个合理.清 ...
- mysql5.7 主从复制的正常切换【转】
目前环境如下: master server IP:172.17.61.131 slave server IP:172.17.61.132 mysql version: mysql-5.7.21-lin ...
- MySQL5.7 GTID在线开启与关闭【转】
当前场景 当前某些业务还有未开启GTID服务组,升级5.7后,如何检测是否符合开启GTID条件,如何在线修改切换使用GTID:已经升级5.7后,已经开启GTID,如何快速回滚后退: 线上gtid如 ...
- 【转】深入理解C++中public、protected及private用法
首先明白以下两点: 1.类的一个特征就是封装,public和private作用就是实现这一目的. 即:用户代码(类外)可以访问public成员而不能访问private成员:private成员只能由类成 ...
- 启动虚拟机报错VMware Workstation cannot connect to the virtual machine
启动虚拟机报错: VMware Workstation cannot connect to the virtual machine. Make sure you have rights to run ...
- 360加固保的dex脱壳方法
完全测试了看雪论坛的方法,发现并没有脱壳,依然无法反编译 http://bbs.pediy.com/thread-213377.htm 使用上面方法的结果是会得到16个dex文件,只有一个是与程序相关 ...