1 #ifndef __SYSTEM_H__
2 #define __SYSTEM_H__
3
4 #include <stdint.h>
5 #include <stddef.h>
6
7 #include
"bsp.h"
8
9 extern void sys_srand( unsigned
int seed );
10 extern int sys_rand(
void );
11
12 extern uint32_t g_SysTick_Counter;
13
14 typedef
void (*SYS_TIMER_CALLBACK_T)(
void *
pContext );
15
16 typedef
struct SYS_TIMER_T
17 {
18 // set before SysTick_Start()
19 uint32_t Period;
20 SYS_TIMER_CALLBACK_T callback;
21 void *
pContext;
22 uint32_t Periodical;
23 // set after SysTick_Start()
24 uint32_t Active;
25 uint32_t Time;
// Delta value relative to prev timer
26 struct SYS_TIMER_T *
pNext;
27 } SYS_TIMER_T;
28
29 //------------------------------------------------------------------------------
30 void SysTick_DelayTicks( uint32_t ticks );
31
32 void SysTick_DelayUs( uint32_t usec );
33
34 void SysTick_DelayMs( uint32_t msec );
35
36 uint32_t SysTick_Get(
void );
37
38 void SysTick_DelayUnitl( uint32_t time );
39
40 void SysTick_Init(
void );
41
42 //------------------------------------------------------------------------------
43 void SysTick_Start( SYS_TIMER_T *
pTimer );
44
45 void SysTick_Stop( SYS_TIMER_T *
pTimer );
46
47 //------------------------------------------------------------------------------
48 uint32_t SysInt_Enable(
void );
49
50 uint32_t SysInt_Disable(
void );
51
52 void SysInt_Init(
void );
53
54 #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 =
0;
uint32_t g_SysTick_Counter =
0;
uint32_t g_SysInt_Counter =
0;
static unsigned
int g_Next =
1;
//------------------------------------------------------------------------------
/// 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 *
1103515245 +
12345;
return (unsigned
int) ( g_Next /
131072 ) %
65536;
}
/*
* 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 >
0 )
g_SysInt_Counter--
;
if ( g_SysInt_Counter ==
0 )
__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 >
0 )
// 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 ==
0 )
{
usec /=
10;
totalTicks = (uint64_t) g_Ticks_In_10us *
usec;
if ( totalTicks ==
0 )
{
usec /=
10;
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 /
1000 );
NVIC_SetPriority( SysTick_IRQn, SYSTICK_PRIORITY );
#if (SysTick_CLKSource_HCLK_Div8_Used > 0 )
uint32_t SysTick_Clock = SystemCoreClock /
8;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
#else
uint32_t SysTick_Clock =
SystemCoreClock;
#endif
g_TimerHead =
0;
g_SysTick_Counter =
0;
g_Ticks_In_1us = ( SysTick_Clock +
500000 ) /
1000000;
// 168/21, 72/9
g_Ticks_In_10us = ( SysTick_Clock +
50000 ) /
100000;
g_Ticks_In_100us = ( SysTick_Clock +
5000 ) /
10000;
g_Ticks_In_Ms = ( SysTick_Clock +
500 ) /
1000;
// 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 >
0 )
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 >
0 )
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 ==
0 ) || ( pTimer->Period ==
0 ) )
return;
SysInt_Disable( );
if ( pTimer->
Active )
SysTick_Stop( pTimer );
pTimer->Active =
1;
pTimer->pNext =
0;
if ( g_TimerHead ==
0 )
/* Queue empty ? */
{
pTimer->Time = pTimer->
Period;
g_TimerHead =
pTimer;
}
else /* Do a sorted insert */
{
this =
g_TimerHead;
last = &
g_TimerHead;
accumulated =
0;
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 ==
0 )
/* 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 ==
0 )
return;
if ( g_TimerHead ==
0 )
/* Queue empty ? */
return;
SYS_TIMER_T *
this, **
last;
SysInt_Disable( );
this =
g_TimerHead;
last = &
g_TimerHead;
pTimer->Active =
0;
while (
this )
{
if (
this == pTimer )
/* Correct timer ? */
{
pTimer->Period =
0;
pTimer->Active =
0;
if (
this->pNext )
/* Adjust timeout */
this->pNext->Time += pTimer->
Time;
*last =
this->
pNext;
break;
}
last = &
this->
pNext;
this =
this->
pNext;
}
SysInt_Enable( );
}
转载于:https://www.cnblogs.com/shangdawei/p/4651357.html