⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stimer.c

📁 包括EPA协议栈
💻 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 + -