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三种方式 ...
随机推荐
- 将本地的mongodb迁移到阿里云
首先在阿里云上安装mongodb,可以根据官方教程 https://docs.mongodb.com/manual/tutorial/install-mongodb-on-amazon/ 完成之后启动 ...
- 第7月第27天 c++11 boost
1. #include <boost/asio.hpp> #include <cstdlib> #include <memory> namespace asio = ...
- 促使团队紧密协作[高效能程序员的修炼-N1]
在Jeff看来,团队里最重要的事情,是人与人之间地协作和沟通!所有的问题,其实都是人的问题.“不管什么问题,那总是人的问题”-温伯格.即,让你和团队陷入困境的最快的方法,就是认为技术是决定性的因素,而 ...
- python多个分割符split字符串
python中string自带的split不支持多个分隔符同时切分,用正则 import re line='hello,world' lineLists = re.split('[,,..??]',l ...
- 集合类List、Set、Map的区别、联系和遍历方式
说集合之前,先说说数组和集合: 1.数组长度是固定的,当超过容量后会在内存中重新创建一个原来数组1.5倍长度的新数组,再把元素存进去:数组既可以存储基本数据类型,又可以存储引用数据类型. 2.集合长度 ...
- python实战之原生爬虫(爬取熊猫主播排行榜)
""" this is a module,多行注释 """ import re from urllib import request # B ...
- c++中的类(class)
c++的class(类)使用方法 这几天一直在调splay之类的东西,突然想转指针...qwq 于是,我就在沙华大佬的帮助下,学了下一顿乱指( $ -> $ ),也就是class(类) 首先:c ...
- Windows xp下安装sql server2005所碰到的一些问题及解决方法
之前提到的帮老板做的一个中船重工的项目,其中的一个子模块:windows下获取特定进程网络流量 一开始是用VS2010做的,后来老板把项目书拿给我看后,明确要求开发环境为VS2005和Sql serv ...
- IOC创建对象的几种方式
接上一篇IOC入门 IOC创建对象的几种方式 1)调用无参数构造器 2)带参数构造器 3)工厂创建对象 工厂类:静态方法创建对象 工厂类:非静态方法创建对象 1.对之前的User类进行一些修改,加上一 ...
- MNMP下nginx1.6开启支持pathinfo配置,支持thinkphp的URL格式
对于thinkphp框架项目的访问格式有多种,其中pathinfo是默认的基本访问格式,格式为:http://hostname:port/index.php/模块名/action名/参数1/参数1的值 ...