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三种方式 ...
随机推荐
- MacOS 下提示APP 损坏 无法安装 解决方法
sudo spctl --master-disable
- C型USB能阻止危险充电器通过USB传播恶意软件
C型USB能阻止危险充电器通过USB传播恶意软件 C型USB设备(USB Type-C)的新型身份验证协议可以保护用户免受潜在的充电器损坏的风险,这种新型的USB还能减少被恶意软件的风险.基于密码的认 ...
- deeplearning.ai学习seq2seq模型
一.seq2seq架构图 seq2seq模型左边绿色的部分我们称之为encoder,左边的循环输入最终生成一个固定向量作为右侧的输入,右边紫色的部分我们称之为decoder.单看右侧这个结构跟我们之前 ...
- if 语句 写了return 报错
- 第一篇:初始Golang
Golang简介 编程语言已经非常多,偏性能敏感的编译型语言有 C.C++.Java.C#.Delphi和Objective-C 等,偏快速业务开发的动态解析型语言有PHP.Python.Perl.R ...
- java 组合接口时的名字冲突
重载方法仅通过返回类型是区分不开的,在打算组合的不同接口中,尽量使用不同的方法名,否则可能导致混乱 //: interfaces/InterfaceCollision.java package obj ...
- CentOS 6 安装chromium
由于centos 6对C++11支持不足的缘故,目前chromium已经不再支持CentOS 6系列. 这里介绍如何在centos 6系列安装chromium. 1.添加chromium源 cd /e ...
- MySQL 数据库性能优化之SQL优化【转】
优化目标 减少 IO 次数IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO 次数是 SQL 优化中需要第一优先考虑, ...
- /dev/null和/dev/zero的区别
/dev/null,外号叫无底洞,你可以向它输出任何数据,它通吃,并且不会撑着!/dev/zero,是一个输入设备,你可你用它来初始化文件. /dev/null------它是空设备,也称为位桶(bi ...
- VirtualBox 安装 Gentoo 小记
因为需求,尝试了一下在 VirtualBox 安装 Gentoo.虽然多年前就折腾过多次 LFS,但 Gentoo 并没有太多尝试.这次确实也经历了种种波折,到最后总算成功了,大致跨度为3天.本来手上 ...