📄 tc_drv.c
字号:
/****************************************************************
** *
** FILE : TC_DRV.C *
** COPYRIGHT : (c) 2004 .Xiamen Yaxon NetWork CO.LTD *
** *
** *
** 2004/10/27 *
****************************************************************/
#define TC_DRV_GLOBAL
#include "includes.h"
#include "target.h"
#include "hardware.h"
#include "aic_drv.h"
#include "TC_Drv.h"
typedef struct {
AT91PS_TC reg;
INT32U pid;
INT32U pin_tioa_mask;
INT32U pin_tiob_mask;
INT32U pin_tclk_mask;
} TC_DESC;
static TC_DESC dev_tc[3] = {
{ /* TC0 */
AT91C_BASE_TC0,
AT91C_ID_TC0,
AT91C_P1_TIOA0,
AT91C_P2_TIOB0,
AT91C_P0_TCLK0
},{/* TC1 */
AT91C_BASE_TC1,
AT91C_ID_TC1,
AT91C_P4_TIOA1,
AT91C_P5_TIOB1,
AT91C_P3_TCLK1
},{/* TC2 */
AT91C_BASE_TC2,
AT91C_ID_TC2,
AT91C_P7_TIOA2,
AT91C_P8_TIOB2,
AT91C_P6_TCLK2
}
};
/************************************************************************
* TC_Calculate - calculate TC parameters
************************************************************************/
static void TC_Calculate_Clk( INT32U delay_us, INT32U mcki, INT32U *rc, INT32U *tcclk)
{
INT32U rc_save ;
/* Adjust to us * MHz */
*rc = delay_us *(mcki / 1000000) ;
/* If period(microsec) * MCK(MHz) div 2 < 2, error */
if ((rc_save = *rc >> 1) < 2 ) {
//DEBUG_PRINT (DEBUG_ALWAYS, ("\r\n%s:%s", __FILE__, __LINE__));
//return (ERROR);
return;
}
if ( rc_save < ( 1<<16 ))
*tcclk = TC_CLKS_MCK2 ;
else
if (( rc_save = *rc >> 3 ) < ( 1 << 16 ))
*tcclk = TC_CLKS_MCK8 ;
else
if (( rc_save = *rc >> 5 ) < ( 1 << 16 ))
*tcclk = TC_CLKS_MCK32 ;
else
if (( rc_save = *rc >> 7 ) < ( 1 << 16 ))
*tcclk = TC_CLKS_MCK128 ;
else
if (( rc_save = *rc >> 10 ) < ( 1 << 16 ))
*tcclk = TC_CLKS_MCK1024 ;
else {
// DEBUG_PRINT (DEBUG_ALWAYS, ("\r\n%s:%s", __FILE__, __LINE__));
//return (ERROR);
return;
}
*rc = rc_save;
}
/*****************************************************************
* TC_Open - Initialize Timer Counter Channel and enable is clock
*****************************************************************/
void TC_Open (INT32U chan, INT32U mode, INT8U tioa, INT8U tiob, INT8U tclk)
{
TC_DESC *tc = &dev_tc[chan];
INT32U pio;
// enable TC clock
AT91F_PS_EnablePeriphClock(AT91C_BASE_PS,1 << tc->pid);
//configure PIO pin
pio = 0;
if (tioa) pio |= tc->pin_tioa_mask;
if (tiob) pio |= tc->pin_tiob_mask;
if (tclk) pio |= tc->pin_tclk_mask;
AT91C_BASE_PIO->PIO_PDR = pio; // disable pio peripheral function
// disable TC and interrupt
tc->reg->TC_CCR = AT91C_TC_CLKDIS;
tc->reg->TC_IDR = 0xffffffff;
// clear status bit
pio = tc->reg->TC_SR;
// configure TC mode
tc->reg->TC_CMR = mode;
// enable TC
tc->reg->TC_CCR = AT91C_TC_CLKEN;
}
/*****************************************************************
* TC_Close - Stop a Timer Counter Channel and disable is clock
*****************************************************************/
void TC_Close (INT32U chan)
{
TC_DESC *tc = &dev_tc[chan];
tc->reg->TC_CCR = AT91C_TC_CLKDIS;
tc->reg->TC_IDR = 0xffffffff;
AT91F_PS_DisablePeriphClock(AT91C_BASE_PS,1 << tc->pid);
}
/*******************************************************************
* TC_Read - read TC's current counter
*******************************************************************/
INT32U TC_Read (INT32U chan)
{
TC_DESC *tc = &dev_tc[chan];
return (tc->reg->TC_CV);
}
/******************************************************************
* write TC's RA,RB,RC
******************************************************************/
void TC_Write (INT32U chan, INT32U ra, INT32U rb, INT32U rc)
{
TC_DESC *tc = &dev_tc[chan];
tc->reg->TC_RA = ra;
tc->reg->TC_RB = rb;
tc->reg->TC_RC = rc;
}
/******************************************************************
* READ THE TC SR REGISTER
******************************************************************/
INT32U TC_GetStatus(INT32U chan)
{
TC_DESC *tc = &dev_tc[chan];
// Return the value of the Status Register
return ( tc->reg->TC_SR ) ;
}
/******************************************************************
* CONFIG A TC AS RC COMPARE MODE ,AND RC COMPARE TIGGER ENABLE
* FIRST CALL TC_Open;
******************************************************************/
void TC_Config (INT32U chan, INT32U us, INT32U mcki)
{
TC_DESC *tc = &dev_tc[chan];
INT32U rc, clk;
/* disable TC and interrupt */
tc->reg->TC_CCR = AT91C_TC_CLKDIS;
tc->reg->TC_IDR = 0xffffffff;
/* calc TC register value */
TC_Calculate_Clk(us, mcki, &rc, &clk);
tc->reg->TC_RA = 0;
tc->reg->TC_RB = 0;
tc->reg->TC_RC = rc;
tc->reg->TC_CMR &= 0xFFF8; // clear TCCLKS
tc->reg->TC_CMR |= clk&0x07|AT91C_TC_WAVE|AT91C_TC_CPCTRG;
/* enable TC */
tc->reg->TC_CCR = AT91C_TC_CLKEN;
}
/******************************************************************
* SET COMMAND TO TC
******************************************************************/
INT32U TC_Ioctl (INT32U chan, INT32U cmd, INT32U *arg)
{
TC_DESC *tc = &dev_tc[chan];
INT32U dummy;
switch (cmd) {
case TC_CMD_BLOCK_MODE:
AT91C_BASE_TCB0->TCB_BMR = (INT32U) arg;
break;
case TC_CMD_BLOCK_SYNC:
AT91C_BASE_TCB0->TCB_BCR = AT91C_TCB_SYNC;
break;
case TC_CMD_START:
tc->reg->TC_CCR = AT91C_TC_SWTRG;
break;
case TC_CMD_INT_ENABLE:
tc->reg->TC_IER = (INT32U) arg;
break;
case TC_CMD_INT_ACK:
dummy = tc->reg->TC_SR;
break;
case TC_CMD_MODE_CAPTURE:
case TC_CMD_MODE_WAVEFORM:
default:
return (false);
}
return (true);
}
/*************************************************************
* 初始化作为系统时基的定时器0
*************************************************************/
void AT91_TC0_Init(void (*isr_handler)(void))
{
TC_Open (SYS_TC0,TC_CLKS_MCK128|AT91C_TC_CPCTRG,0,0,0);
AIC_Install_Isolate( AT91C_ID_TC0,TC0_PRIO,AIC_LEVEL_LOW, isr_handler);
TC_Config (SYS_TC0,(1000/OS_TICKS_PER_SEC)*1000,MCK);
AIC_Int_Enable(AT91C_ID_TC0);
TC_Ioctl(SYS_TC0, TC_CMD_START, NULL);
TC_Ioctl(SYS_TC0, TC_CMD_INT_ENABLE, (INT32U *)AT91C_TC_CPCS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -