📄 stimer.c
字号:
#include "AT91R40008.h"
#include "tc.h"
#include "stimer.h"
#include "ptimer.h"
#include "list.h"
#include "eb40a.h"
#define ST_TC_MODE (AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ASWTRG_CLEAR | AT91C_TC_BSWTRG_CLEAR | AT91C_TC_TCCLKS_MCK128 | AT91C_TC_CPCDIS | AT91C_TC_WAVE)
#define ST_AMOUNT_ALL (0x10)
#define ST_TICKS_MS (625) // 625 ticks per millisecond
#define ST_NASECS_TICKS (1600) // 1600 nanosecond per ticks
#define ST_CRITICAL_TICKS (62500)
typedef struct {
uint32 para;
void* pdata;
STHDLR phdlr;
Foo node;
}Stimer, *PStimer;
static Foo StList;
static void* StMsgTbl[MSG_AMOUNT_ST];
static Stimer StPool[ST_AMOUNT_ALL];
static OS_STK StStack[STACK_SIZE_ST];
static OS_MEM* pStMCB;
static OS_EVENT* pStMsgQ;
static OS_EVENT* pStSem;
void TC1IntHandler(void);
static void StTask(void* pdata);
/*------------------------------------------------------------------------------*
*- Function name: StInit
*- Parameter: void
*- Return value: void
*- Brief: Initialize soft timer module
*------------------------------------------------------------------------------*/
void StInit(void) {
uint8 err;
LIST_INIT(StList);
pStMsgQ = OSQCreate(StMsgTbl, MSG_AMOUNT_ST);
OSTaskCreate(StTask, (void*)0, (void*)(&StStack[STACK_SIZE_ST]), TASK_PRIORITY_ST);
pStSem = OSSemCreate(ST_AMOUNT_ALL);
pStMCB = OSMemCreate(StPool, ST_AMOUNT_ALL, sizeof(Stimer), &err);
TimerInit(AT91C_BASE_TC1,
AT91C_TC_CPCTRG|TC_CLKS_MCK1024,
AT91C_AIC_PRIOR_HIGHEST - 3,
AT91C_ID_TC1,
AT91C_ID_TC1,
AT91C_TC_CPCS,
TC1IntHandler);
}
__inline PStimer GetStimer(uint32 para, void* pdata, STHDLR phdlr) {
CpuSr sr;
uint8 err;
PStimer ptimer;
SpinLock(sr);
OSSemPend(pStSem, 0, &err);
ptimer = (PStimer)OSMemGet(pStMCB, &err);
SpinUnLock(sr);
ptimer->para = para;
ptimer->pdata = pdata;
ptimer->phdlr = phdlr;
return (ptimer);
}
__inline void PutStimer(PStimer ptimer) {
CpuSr sr;
SpinLock(sr);
OSSemPost(pStSem);
OSMemPut(pStMCB, (void*)ptimer);
SpinUnLock(sr);
}
/*------------------------------------------------------------------------------*
*- Function name: AddSt -*
*- Parameter: interval, When should the timer went out, time = 32ms*interval -*
*- pdata, Parameter to over timer handler -*
*- hdlr, Handler to be call back went time went over -*
*- Return value: ID of the new added soft timer, if failed returns 0 -*
*- Brief: Add a soft timer -*
*------------------------------------------------------------------------------*/
uint32 AddSt(uint32 interval, uint32 para, void* pdata, STHDLR phdlr) {
PFoo pnode;
CpuSr sr;
uint32 id, ticks;
PStimer ptimer;
TCStop(AT91C_BASE_TC1);
ptimer = GetStimer(para, pdata, phdlr);
ptimer->para = para;
ptimer->pdata = pdata;
ptimer->phdlr = phdlr;
SpinLock(sr);
if(LIST_IS_EMPTY(StList)) {
ticks = interval * ST_TICKS_MS;
id = Push(&StList, &(ptimer->node), ticks);
if(ticks >= ST_CRITICAL_TICKS) {
ticks = ST_CRITICAL_TICKS;
}
TCStart(AT91C_BASE_TC1, (uint16)ticks);
}
else {
ticks = TCGetCV(AT91C_BASE_TC1);
pnode = LIST_TAIL(StList);
id = LIST_CNT(StList);
pnode->next->tag -= ticks;
ticks = interval * ST_TICKS_MS;
while(ticks > pnode->next->tag && id > 0) {
ticks -= pnode->next->tag;
pnode = pnode->next;
id--;
}
id = InsertBehind(&StList, pnode, &(ptimer->node), ticks, !id);
ticks = LIST_HEAD(StList)->tag;
if(ticks >= ST_CRITICAL_TICKS) {
ticks = ST_CRITICAL_TICKS;
}
TCReload(AT91C_BASE_TC1, (uint16)ticks);
}
SpinUnLock(sr);
return (id);
}
/*------------------------------------------------------------------------------*
*- Function name: DelSt
*- Parameter: id, timerid
*- ptimer, pointer of an soft timer struct
*- Return value: Pointer of timer that was moved out from timer link-list
*- Brief: Delete soft timer indicated by parameter id
*------------------------------------------------------------------------------*/
void* DelSt(uint32 id) {
PFoo pnode;
CpuSr sr;
void* pdata;
PStimer ptimer;
SpinLock(sr);
pnode = DeleteByID(&StList, id);
if(pnode == (PFoo)0) {
return ((void *)0);
}
ptimer = LIST_ENTRY(pnode, Stimer, node);
if(LIST_CNT(StList)) {
TCStop(AT91C_BASE_TC1);
}
SpinUnLock(sr);
pdata = ptimer->pdata;
PutStimer(ptimer);
return (pdata);
}
/*------------------------------------------------------------------------------*
*- Function name: TC1Int
*- Parameter: void
*- Return value: void
*- Brief: C handler of soft timer interrupt, manage the soft timer list when
*- soft timer interrupt occurs.
*------------------------------------------------------------------------------*/
void TC1Int(void) {
PFoo pnode;
uint32 ticks, status;
status = AT91C_BASE_TC1->TC_SR;
ticks = TCGetRC(AT91C_BASE_TC1);
while(LIST_CNT(StList)) {
if(ticks >= LIST_HEAD(StList)->tag) {
pnode = Pop(&StList);
OSQPost((void*)pStMsgQ, (void*)LIST_ENTRY(pnode, Stimer, node));
}
else {
LIST_HEAD(StList)->tag -= ticks;
break;
}
}
if(LIST_CNT(StList)) {
ticks = LIST_HEAD(StList)->tag;
if(ticks > ST_CRITICAL_TICKS) {
ticks = ST_CRITICAL_TICKS;
}
TCReload(AT91C_BASE_TC1, ticks);
}
}
/*------------------------------------------------------------------------------*
*- Function name: StTask -*
*- Parameter: void -*
*- Return value: void -*
*- Brief: Call soft timer handler when msg arrives -*
*------------------------------------------------------------------------------*/
static void StTask(void* pdata) {
uint8 err;
PStimer ptimer;
while(1) {
ptimer = (PStimer)OSQPend(pStMsgQ, 0, &err);
((STHDLR)ptimer->phdlr)(ptimer->para, ptimer->pdata);
PutStimer(ptimer);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -