Tweaked the Atmel ARM7 MS/TP settings.

This commit is contained in:
skarg
2007-08-09 23:53:18 +00:00
parent ed5562126e
commit f1deb0b1fe
6 changed files with 301 additions and 286 deletions
+2 -2
View File
@@ -917,7 +917,7 @@ bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port)
/* The PASS_TOKEN state listens for a successor to begin using */ /* The PASS_TOKEN state listens for a successor to begin using */
/* the token that this node has just attempted to pass. */ /* the token that this node has just attempted to pass. */
case MSTP_MASTER_STATE_PASS_TOKEN: case MSTP_MASTER_STATE_PASS_TOKEN:
if (mstp_port->SilenceTimer < Tusage_timeout) { if (mstp_port->SilenceTimer <= Tusage_timeout) {
if (mstp_port->EventCount > Nmin_octets) { if (mstp_port->EventCount > Nmin_octets) {
/* SawTokenUser */ /* SawTokenUser */
/* Assume that a frame has been sent by the new token user. */ /* Assume that a frame has been sent by the new token user. */
@@ -1026,7 +1026,7 @@ bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port)
transition_now = true; transition_now = true;
} }
mstp_port->ReceivedValidFrame = false; mstp_port->ReceivedValidFrame = false;
} else if ((mstp_port->SilenceTimer >= Tusage_timeout) || } else if ((mstp_port->SilenceTimer > Tusage_timeout) ||
(mstp_port->ReceivedInvalidFrame == true)) { (mstp_port->ReceivedInvalidFrame == true)) {
if (mstp_port->SoleMaster == true) { if (mstp_port->SoleMaster == true) {
/* SoleMaster */ /* SoleMaster */
+2 -2
View File
@@ -99,13 +99,13 @@ typedef enum {
/* that a node must wait for a station to begin replying to a */ /* that a node must wait for a station to begin replying to a */
/* confirmed request: 255 milliseconds. (Implementations may use */ /* confirmed request: 255 milliseconds. (Implementations may use */
/* larger values for this timeout, not to exceed 300 milliseconds.) */ /* larger values for this timeout, not to exceed 300 milliseconds.) */
#define Treply_timeout 255 #define Treply_timeout 260
/* The minimum time without a DataAvailable or ReceiveError event that a */ /* The minimum time without a DataAvailable or ReceiveError event that a */
/* node must wait for a remote node to begin using a token or replying to */ /* node must wait for a remote node to begin using a token or replying to */
/* a Poll For Master frame: 20 milliseconds. (Implementations may use */ /* a Poll For Master frame: 20 milliseconds. (Implementations may use */
/* larger values for this timeout, not to exceed 100 milliseconds.) */ /* larger values for this timeout, not to exceed 100 milliseconds.) */
#define Tusage_timeout 20 #define Tusage_timeout 25
struct mstp_port_struct_t { struct mstp_port_struct_t {
+5 -7
View File
@@ -124,9 +124,12 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
static void dlmstp_task(void) static void dlmstp_task(void)
{ {
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
/* only do receive state machine while we don't have a frame */ /* only do receive state machine while we don't have a frame */
if ((MSTP_Port.ReceivedValidFrame == false) && if ((MSTP_Port.ReceivedValidFrame == false) &&
(MSTP_Port.ReceivedInvalidFrame == false)) { (MSTP_Port.ReceivedInvalidFrame == false)) {
/* LED OFF */
pPIO->PIO_SODR = LED2;
do { do {
RS485_Check_UART_Data(&MSTP_Port); RS485_Check_UART_Data(&MSTP_Port);
MSTP_Receive_Frame_FSM(&MSTP_Port); MSTP_Receive_Frame_FSM(&MSTP_Port);
@@ -135,13 +138,8 @@ static void dlmstp_task(void)
break; break;
} while (MSTP_Port.DataAvailable); } while (MSTP_Port.DataAvailable);
} else { } else {
/* toggle LED on Frame received */ /* LED ON */
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; pPIO->PIO_CODR = LED2;
if ((pPIO->PIO_ODSR & LED2) == LED2)
pPIO->PIO_CODR = LED2;
else
pPIO->PIO_SODR = LED2;
} }
/* only do master state machine while rx is idle */ /* only do master state machine while rx is idle */
if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE) { if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE) {
+2 -1
View File
@@ -12,7 +12,8 @@ LDSCRIPT=at91sam7s256.ld
BACNET_FLAGS = -DBACDL_MSTP=1 -DPRINT_ENABLED=0 -DBIG_ENDIAN=0 -DMAX_APDU=480 -DDLMSTP_TEST BACNET_FLAGS = -DBACDL_MSTP=1 -DPRINT_ENABLED=0 -DBIG_ENDIAN=0 -DMAX_APDU=480 -DDLMSTP_TEST
INCLUDES = -I. -I../.. -I../../demo/handler -I../../demo/object INCLUDES = -I. -I../.. -I../../demo/handler -I../../demo/object
OPTIMIZATION = -O0 #OPTIMIZATION = -O0
OPTIMIZATION = -Os
CFLAGS = -fno-common $(OPTIMIZATION) $(INCLUDES) $(BACNET_FLAGS) -Wall -g CFLAGS = -fno-common $(OPTIMIZATION) $(INCLUDES) $(BACNET_FLAGS) -Wall -g
# -Wa,<options> Pass comma-separated <options> on to the assembler # -Wa,<options> Pass comma-separated <options> on to the assembler
AFLAGS = -Wa,-ahls,-mapcs-32,-adhlns=$(<:.s=.lst) AFLAGS = -Wa,-ahls,-mapcs-32,-adhlns=$(<:.s=.lst)
+15 -16
View File
@@ -38,7 +38,7 @@
#include "board.h" #include "board.h"
/* UART */ /* UART */
static AT91S_USART *RS485_Interface = AT91C_BASE_US0; static volatile AT91S_USART *RS485_Interface = AT91C_BASE_US0;
/* baud rate */ /* baud rate */
static int RS485_Baud = 38400; static int RS485_Baud = 38400;
@@ -50,7 +50,7 @@ static int RS485_Baud = 38400;
*****************************************************************************/ *****************************************************************************/
void RS485_Set_Interface(char *ifname) void RS485_Set_Interface(char *ifname)
{ {
RS485_Interface = (AT91S_USART *)ifname; RS485_Interface = (volatile AT91S_USART *)ifname;
} }
/**************************************************************************** /****************************************************************************
@@ -63,7 +63,7 @@ void RS485_Set_Interface(char *ifname)
void RS485_Initialize(void) void RS485_Initialize(void)
{ {
// enable the USART0 peripheral clock // enable the USART0 peripheral clock
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<<AT91C_ID_US0); pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<<AT91C_ID_US0);
/* enable the peripheral by disabling the pin in the PIO controller */ /* enable the peripheral by disabling the pin in the PIO controller */
@@ -76,7 +76,7 @@ void RS485_Initialize(void)
AT91C_US_TXDIS; /* Transmitter Disable */ AT91C_US_TXDIS; /* Transmitter Disable */
RS485_Interface->US_MR = RS485_Interface->US_MR =
AT91C_US_USMODE_RS485 | /* RS-485 Mode - RTS auto asserted */ AT91C_US_USMODE_RS485 | /* RS-485 Mode - RTS auto assert */
AT91C_US_CLKS_CLOCK | /* Clock = MCK */ AT91C_US_CLKS_CLOCK | /* Clock = MCK */
AT91C_US_CHRL_8_BITS | /* 8-bit Data */ AT91C_US_CHRL_8_BITS | /* 8-bit Data */
AT91C_US_PAR_NONE | /* No Parity */ AT91C_US_PAR_NONE | /* No Parity */
@@ -146,31 +146,25 @@ void RS485_Send_Frame(
uint16_t nbytes) /* number of bytes of data (up to 501) */ uint16_t nbytes) /* number of bytes of data (up to 501) */
{ {
uint8_t turnaround_time; uint8_t turnaround_time;
uint32_t baud;
/* toggle LED on send */ /* toggle LED on send */
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
if ((pPIO->PIO_ODSR & LED1) == LED1) /* LED ON */
pPIO->PIO_CODR = LED1; pPIO->PIO_CODR = LED1;
else
pPIO->PIO_SODR = LED1;
/* delay after reception - per MS/TP spec */ /* delay after reception - per MS/TP spec */
if (mstp_port) { if (mstp_port) {
baud = RS485_Get_Baud_Rate();
/* wait about 40 bit times since reception */ /* wait about 40 bit times since reception */
if (baud == 9600) turnaround_time = (40*1000)/RS485_Baud;
turnaround_time = 4; if (!turnaround_time) {
else if (baud == 19200)
turnaround_time = 2;
else
turnaround_time = 1; turnaround_time = 1;
}
while (mstp_port->SilenceTimer < turnaround_time) { while (mstp_port->SilenceTimer < turnaround_time) {
/* do nothing - wait for timer to increment */ /* do nothing - wait for timer to increment */
}; };
} }
while (nbytes) { while (nbytes) {
while (!(RS485_Interface->US_CSR & AT91C_US_TXRDY)) { while (!(RS485_Interface->US_CSR & AT91C_US_TXRDY)) {
/* do nothing - wait for Tx buffer to get empty */ /* do nothing - wait until Tx buffer is empty */
} }
RS485_Interface->US_THR = *buffer; RS485_Interface->US_THR = *buffer;
buffer++; buffer++;
@@ -180,6 +174,11 @@ void RS485_Send_Frame(
mstp_port->SilenceTimer = 0; mstp_port->SilenceTimer = 0;
} }
} }
while (!(RS485_Interface->US_CSR & AT91C_US_TXRDY)) {
/* do nothing - wait until Tx buffer is empty */
}
/* LED OFF */
pPIO->PIO_SODR = LED1;
return; return;
} }
+262 -245
View File
@@ -2,7 +2,7 @@
// //
// Purpose: Set up the 16-bit Timer/Counter // Purpose: Set up the 16-bit Timer/Counter
// //
// We will use Timer Channel 0 to develop a 50 msec interrupt. // We will use Timer Channel 0 to develop a 1 msec interrupt.
// //
// The AT91SAM7S-EK board has a 18,432,000 hz crystal oscillator. // The AT91SAM7S-EK board has a 18,432,000 hz crystal oscillator.
// //
@@ -10,15 +10,15 @@
// PLLCK = (MAINCK / DIV) * (MUL + 1) = 18432000/14 * (72 + 1) // PLLCK = (MAINCK / DIV) * (MUL + 1) = 18432000/14 * (72 + 1)
// PLLCLK = 1316571 * 73 = 96109683 hz // PLLCLK = 1316571 * 73 = 96109683 hz
// //
// MCK = PLLCLK / 2 = 96109683 / 2 = 48054841 hz // MCK = PLLCLK / 2 = 96109683 / 2 = 48054841 hz
// //
// TIMER_CLOCK5 = MCK / 1024 = 48054841 / 1024 = 46928 hz // TIMER_CLOCK5 = MCK / 1024 = 48054841 / 1024 = 46928 hz
// //
// TIMER_CLOCK5 Period = 1 / 46928 = 21.309239686 microseconds // TIMER_CLOCK5 Period = 1 / 46928 = 21.309239686 microseconds
// //
// A little algebra: .050 sec = count * 21.3092396896*10**-6 // A little algebra: .001 sec = count * 21.3092396896*10**-6
// count = .050 / 21.3092396896*10**-6 // count = .001 / 21.3092396896*10**-6
// count = 2346 // count = 46.928
// //
// //
// Therefore: set Timer Channel 0 register RC to 9835 // Therefore: set Timer Channel 0 register RC to 9835
@@ -31,11 +31,14 @@
// disable all the other timer 0 interrupts // disable all the other timer 0 interrupts
// //
// Author: James P Lynch May 12, 2007 // Author: James P Lynch May 12, 2007
// Modified by Steve Karg
// Changed timer to 1ms.
// Encapsulated the intialization
// ***************************************************************************** // *****************************************************************************
/********************************************************** /**********************************************************
Header files Header files
**********************************************************/ **********************************************************/
#include "AT91SAM7S256.h" #include "AT91SAM7S256.h"
#include "board.h" #include "board.h"
@@ -43,268 +46,282 @@
// global variable counts interrupts // global variable counts interrupts
volatile unsigned long Timer_Milliseconds = 0; volatile unsigned long Timer_Milliseconds = 0;
void TimerSetup(void) { void Timer0_Setup(int milliseconds) {
// TC Block Control Register TC_BCR (read/write)
//
// |------------------------------------------------------------------|------|
// | SYNC |
// |------------------------------------------------------------------|------|
// 31 1 0
//
// SYNC = 0 (no effect) <===== take default
// SYNC = 1 (generate software trigger for all 3 timer channels simultaneously)
//
AT91PS_TCB pTCB = AT91C_BASE_TCB; // create a pointer to TC Global Register structure
pTCB->TCB_BCR = 0; // SYNC trigger not used
// TC Block Control Register TC_BCR (read/write) // TC Block Mode Register TC_BMR (read/write)
// //
// |------------------------------------------------------------------|------| // |-------------------------------------|-----------|-----------|-----------|
// | SYNC | // | TC2XC2S TCXC1S TC0XC0S |
// |------------------------------------------------------------------|------| // |-------------------------------------|-----------|-----------|-----------|
// 31 1 0 // 31 5 4 3 2 1 0
// //
// SYNC = 0 (no effect) <===== take default // TC0XC0S Select = 00 TCLK0 (PA4)
// SYNC = 1 (generate software trigger for all 3 timer channels simultaneously) // = 01 none <===== we select this one
// // = 10 TIOA1 (PA15)
AT91PS_TCB pTCB = AT91C_BASE_TCB; // create a pointer to TC Global Register structure // = 11 TIOA2 (PA26)
pTCB->TCB_BCR = 0; // SYNC trigger not used //
// TCXC1S Select = 00 TCLK1 (PA28)
// TC Block Mode Register TC_BMR (read/write) // = 01 none <===== we select this one
// // = 10 TIOA0 (PA15)
// |-------------------------------------|-----------|-----------|-----------| // = 11 TIOA2 (PA26)
// | TC2XC2S TCXC1S TC0XC0S | //
// |-------------------------------------|-----------|-----------|-----------| // TC2XC2S Select = 00 TCLK2 (PA29)
// 31 5 4 3 2 1 0 // = 01 none <===== we select this one
// // = 10 TIOA0 (PA00)
// TC0XC0S Select = 00 TCLK0 (PA4) // = 11 TIOA1 (PA26)
// = 01 none <===== we select this one //
// = 10 TIOA1 (PA15) pTCB->TCB_BMR = 0x15; // external clocks not used
// = 11 TIOA2 (PA26)
//
// TCXC1S Select = 00 TCLK1 (PA28)
// = 01 none <===== we select this one
// = 10 TIOA0 (PA15)
// = 11 TIOA2 (PA26)
//
// TC2XC2S Select = 00 TCLK2 (PA29)
// = 01 none <===== we select this one
// = 10 TIOA0 (PA00)
// = 11 TIOA1 (PA26)
//
pTCB->TCB_BMR = 0x15; // external clocks not used
// TC Channel Control Register TC_CCR (read/write) // TC Channel Control Register TC_CCR (read/write)
// //
// |----------------------------------|--------------|------------|-----------| // |----------------------------------|--------------|------------|-----------|
// | SWTRG CLKDIS CLKENS | // | SWTRG CLKDIS CLKENS |
// |----------------------------------|--------------|------------|-----------| // |----------------------------------|--------------|------------|-----------|
// 31 2 1 0 // 31 2 1 0
// //
// CLKEN = 0 no effect // CLKEN = 0 no effect
// CLKEN = 1 enables the clock <===== we select this one // CLKEN = 1 enables the clock <===== we select this one
// //
// CLKDIS = 0 no effect <===== take default // CLKDIS = 0 no effect <===== take default
// CLKDIS = 1 disables the clock // CLKDIS = 1 disables the clock
// //
// SWTRG = 0 no effect // SWTRG = 0 no effect
// SWTRG = 1 software trigger aserted counter reset and clock starts <===== we select this one // SWTRG = 1 software trigger aserted counter reset and clock starts <===== we select this one
// //
AT91PS_TC pTC = AT91C_BASE_TC0; // create a pointer to channel 0 Register structure AT91PS_TC pTC = AT91C_BASE_TC0; // create a pointer to channel 0 Register structure
pTC->TC_CCR = 0x5; // enable the clock and start it pTC->TC_CCR = 0x5; // enable the clock and start it
// TC Channel Mode Register TC_CMR (read/write) // TC Channel Mode Register TC_CMR (read/write)
// //
// |-----------------------------------|------------|---------------| // |-----------------------------------|------------|---------------|
// | LDRB LDRA | // | LDRB LDRA |
// |-----------------------------------|------------|---------------| // |-----------------------------------|------------|---------------|
// 31 19 18 17 16 // 31 19 18 17 16
// //
// |----------|---------|--------------|------------|---------------| // |----------|---------|--------------|------------|---------------|
// |WAVE = 0 CPCTRG ABETRG ETRGEDG | // |WAVE = 0 CPCTRG ABETRG ETRGEDG |
// |----------|---------|--------------|------------|---------------| // |----------|---------|--------------|------------|---------------|
// 15 14 13 11 10 9 8 // 15 14 13 11 10 9 8
// //
// |----------|---------|--------------|------------|---------------| // |----------|---------|--------------|------------|---------------|
// | LDBDIS LDBSTOP BURST CLKI TCCLKS | // | LDBDIS LDBSTOP BURST CLKI TCCLKS |
// |----------|---------|--------------|------------|---------------| // |----------|---------|--------------|------------|---------------|
// 7 6 5 4 3 2 0 // 7 6 5 4 3 2 0
// //
// CLOCK SELECTION // CLOCK SELECTION
// TCCLKS = 000 TIMER_CLOCK1 (MCK/2 = 24027420 hz) // TCCLKS = 000 TIMER_CLOCK1 (MCK/2 = 24027420 hz)
// 001 TIMER_CLOCK2 (MCK/8 = 6006855 hz) // 001 TIMER_CLOCK2 (MCK/8 = 6006855 hz)
// 010 TIMER_CLOCK3 (MCK/32 = 1501713 hz) // 010 TIMER_CLOCK3 (MCK/32 = 1501713 hz)
// 011 TIMER_CLOCK4 (MCK/128 = 375428 hz) // 011 TIMER_CLOCK4 (MCK/128 = 375428 hz)
// 100 TIMER_CLOCK5 (MCK/1024 = 46928 hz) <===== we select this one // 100 TIMER_CLOCK5 (MCK/1024 = 46928 hz) <===== we select this one
// 101 XC0 // 101 XC0
// 101 XC1 // 101 XC1
// 101 XC2 // 101 XC2
// //
// CLOCK INVERT // CLOCK INVERT
// CLKI = 0 counter incremented on rising clock edge <===== we select this one // CLKI = 0 counter incremented on rising clock edge <===== we select this one
// CLKI = 1 counter incremented on falling clock edge // CLKI = 1 counter incremented on falling clock edge
// //
// BURST SIGNAL SELECTION // BURST SIGNAL SELECTION
// BURST = 00 clock is not gated by any external system <===== take default // BURST = 00 clock is not gated by any external system <===== take default
// 01 XC0 is anded with the clock // 01 XC0 is anded with the clock
// 10 XC1 is anded with the clock // 10 XC1 is anded with the clock
// 11 XC2 is anded with the clock // 11 XC2 is anded with the clock
// //
// COUNTER CLOCK STOPPED WITH RB LOADING // COUNTER CLOCK STOPPED WITH RB LOADING
// LDBSTOP = 0 counter clock is not stopped when RB loading occurs <===== take default // LDBSTOP = 0 counter clock is not stopped when RB loading occurs <===== take default
// = 1 counter clock is stopped when RB loading occur // = 1 counter clock is stopped when RB loading occur
// //
// COUNTER CLOCK DISABLE WITH RB LOADING // COUNTER CLOCK DISABLE WITH RB LOADING
// LDBDIS = 0 counter clock is not disabled when RB loading occurs <===== take default // LDBDIS = 0 counter clock is not disabled when RB loading occurs <===== take default
// = 1 counter clock is disabled when RB loading occurs // = 1 counter clock is disabled when RB loading occurs
// //
// EXTERNAL TRIGGER EDGE SELECTION // EXTERNAL TRIGGER EDGE SELECTION
// ETRGEDG = 00 (none) <===== take default // ETRGEDG = 00 (none) <===== take default
// 01 (rising edge) // 01 (rising edge)
// 10 (falling edge) // 10 (falling edge)
// 11 (each edge) // 11 (each edge)
// //
// TIOA OR TIOB EXTERNAL TRIGGER SELECTION // TIOA OR TIOB EXTERNAL TRIGGER SELECTION
// ABETRG = 0 (TIOA is used) <===== take default // ABETRG = 0 (TIOA is used) <===== take default
// 1 (TIOB is used) // 1 (TIOB is used)
// //
// RC COMPARE TRIGGER ENABLE // RC COMPARE TRIGGER ENABLE
// CPCTRG = 0 (RC Compare has no effect on the counter and its clock) // CPCTRG = 0 (RC Compare has no effect on the counter and its clock)
// 1 (RC Compare resets the counter and starts the clock) <===== we select this one // 1 (RC Compare resets the counter and starts the clock) <===== we select this one
// //
// WAVE // WAVE
// WAVE = 0 Capture Mode is enabled <===== we select this one // WAVE = 0 Capture Mode is enabled <===== we select this one
// 1 Waveform Mode is enabled // 1 Waveform Mode is enabled
// //
// RA LOADING SELECTION // RA LOADING SELECTION
// LDRA = 00 none) <===== take default // LDRA = 00 none) <===== take default
// 01 (rising edge of TIOA) // 01 (rising edge of TIOA)
// 10 (falling edge of TIOA) // 10 (falling edge of TIOA)
// 11 (each edge of TIOA) // 11 (each edge of TIOA)
// //
// RB LOADING SELECTION // RB LOADING SELECTION
// LDRB = 00 (none) <===== take default // LDRB = 00 (none) <===== take default
// 01 (rising edge of TIOA) // 01 (rising edge of TIOA)
// 10 (falling edge of TIOA) // 10 (falling edge of TIOA)
// 11 (each edge of TIOA) // 11 (each edge of TIOA)
// //
pTC->TC_CMR = 0x4004; // TCCLKS = 1 (TIMER_CLOCK5) pTC->TC_CMR = 0x4004; // TCCLKS = 1 (TIMER_CLOCK5)
// CPCTRG = 1 (RC Compare resets the counter and restarts the clock) // CPCTRG = 1 (RC Compare resets the counter and restarts the clock)
// WAVE = 0 (Capture mode enabled) // WAVE = 0 (Capture mode enabled)
// TC Register C TC_RC (read/write) Compare Register 16-bits // TC Register C TC_RC (read/write) Compare Register 16-bits
// //
// |----------------------------------|----------------------------------------| // |----------------------------------|----------------------------------------|
// | not used RC | // | not used RC |
// |----------------------------------|----------------------------------------| // |----------------------------------|----------------------------------------|
// 31 16 15 0 // 31 16 15 0
// //
// Timer Calculation: What count gives 1 msec time-out? // Timer Calculation: What count gives 1 msec time-out?
// //
// TIMER_CLOCK5 = MCK / 1024 = 48054841 / 1024 = 46928 hz // TIMER_CLOCK5 = MCK / 1024 = 48054841 / 1024 = 46928 hz
// //
// TIMER_CLOCK5 Period = 1 / 46928 = 21.309239686 microseconds // TIMER_CLOCK5 Period = 1 / 46928 = 21.309239686 microseconds
// //
// A little algebra: .001 sec = count * 21.3092396896*10**-6 // A little algebra: .001 sec = count * 21.3092396896*10**-6
// count = .001 / 21.3092396896*10**-6 // count = .001 / 21.3092396896*10**-6
// count = 46.928 // count = 46.928
// //
pTC->TC_RC = 47; // STK: Even Simpler, let the compiler do the work:
//
// TIMER_CLOCK5 = (MCK / 1024) / 1000
// = 48054841 / 1024 / 1000 = 46.928
pTC->TC_RC = ((MCK/1024/1000)+1)*milliseconds;
// TC Interrupt Enable Register TC_IER (write-only)
//
//
// |------------|-------|-------|-------|-------|--------|--------|--------|--------|
// | ETRGS LDRBS LDRAS CPCS CPBS CPAS LOVRS COVFS |
// |------------|-------|-------|-------|-------|--------|--------|--------|--------|
// 31 8 7 6 5 4 3 2 1 0
//
// COVFS = 0 no effect <===== take default
// 1 enable counter overflow interrupt
//
// LOVRS = 0 no effect <===== take default
// 1 enable load overrun interrupt
//
// CPAS = 0 no effect <===== take default
// 1 enable RA compare interrupt
//
// CPBS = 0 no effect <===== take default
// 1 enable RB compare interrupt
//
// CPCS = 0 no effect
// 1 enable RC compare interrupt <===== we select this one
//
// LDRAS = 0 no effect <===== take default
// 1 enable RA load interrupt
//
// LDRBS = 0 no effect <===== take default
// 1 enable RB load interrupt
//
// ETRGS = 0 no effect <===== take default
// 1 enable External Trigger interrupt
//
pTC->TC_IER = 0x10; // enable RC compare interrupt
// TC Interrupt Enable Register TC_IER (write-only) // TC Interrupt Disable Register TC_IDR (write-only)
// //
// //
// |------------|-------|-------|-------|-------|--------|--------|--------|--------| // |------------|-------|-------|-------|-------|--------|--------|--------|--------|
// | ETRGS LDRBS LDRAS CPCS CPBS CPAS LOVRS COVFS | // | ETRGS LDRBS LDRAS CPCS CPBS CPAS LOVRS COVFS |
// |------------|-------|-------|-------|-------|--------|--------|--------|--------| // |------------|-------|-------|-------|-------|--------|--------|--------|--------|
// 31 8 7 6 5 4 3 2 1 0 // 31 8 7 6 5 4 3 2 1 0
// //
// COVFS = 0 no effect <===== take default // COVFS = 0 no effect
// 1 enable counter overflow interrupt // 1 disable counter overflow interrupt <===== we select this one
// //
// LOVRS = 0 no effect <===== take default // LOVRS = 0 no effect
// 1 enable load overrun interrupt // 1 disable load overrun interrupt <===== we select this one
// //
// CPAS = 0 no effect <===== take default // CPAS = 0 no effect
// 1 enable RA compare interrupt // 1 disable RA compare interrupt <===== we select this one
// //
// CPBS = 0 no effect <===== take default // CPBS = 0 no effect
// 1 enable RB compare interrupt // 1 disable RB compare interrupt <===== we select this one
// //
// CPCS = 0 no effect // CPCS = 0 no effect <===== take default
// 1 enable RC compare interrupt <===== we select this one // 1 disable RC compare interrupt
// //
// LDRAS = 0 no effect <===== take default // LDRAS = 0 no effect
// 1 enable RA load interrupt // 1 disable RA load interrupt <===== we select this one
// //
// LDRBS = 0 no effect <===== take default // LDRBS = 0 no effect
// 1 enable RB load interrupt // 1 disable RB load interrupt <===== we select this one
// //
// ETRGS = 0 no effect <===== take default // ETRGS = 0 no effect
// 1 enable External Trigger interrupt // 1 disable External Trigger interrupt <===== we select this one
// //
pTC->TC_IER = 0x10; // enable RC compare interrupt pTC->TC_IDR = 0xEF; // disable all except RC compare interrupt
// TC Interrupt Disable Register TC_IDR (write-only)
//
//
// |------------|-------|-------|-------|-------|--------|--------|--------|--------|
// | ETRGS LDRBS LDRAS CPCS CPBS CPAS LOVRS COVFS |
// |------------|-------|-------|-------|-------|--------|--------|--------|--------|
// 31 8 7 6 5 4 3 2 1 0
//
// COVFS = 0 no effect
// 1 disable counter overflow interrupt <===== we select this one
//
// LOVRS = 0 no effect
// 1 disable load overrun interrupt <===== we select this one
//
// CPAS = 0 no effect
// 1 disable RA compare interrupt <===== we select this one
//
// CPBS = 0 no effect
// 1 disable RB compare interrupt <===== we select this one
//
// CPCS = 0 no effect <===== take default
// 1 disable RC compare interrupt
//
// LDRAS = 0 no effect
// 1 disable RA load interrupt <===== we select this one
//
// LDRBS = 0 no effect
// 1 disable RB load interrupt <===== we select this one
//
// ETRGS = 0 no effect
// 1 disable External Trigger interrupt <===== we select this one
//
pTC->TC_IDR = 0xEF; // disable all except RC compare interrupt
} }
// ***************************************************************************** // *****************************************************************************
// //
// Timer 0 Interrupt Service Routine // Timer 0 Interrupt Service Routine
// //
// entered when Timer0 RC compare interrupt asserts (200 msec period) // Entered when Timer0 RC compare interrupt asserts
// blinks LED2 (pin PA2)
// //
// Author: James P Lynch May 12, 2007 // Author: James P Lynch May 12, 2007
// Modified by Steve Karg
// simplified and changed to a millisecond count-up timer
// ***************************************************************************** // *****************************************************************************
void Timer0IrqHandler (void) { void Timer0IrqHandler (void) {
volatile AT91PS_TC pTC = AT91C_BASE_TC0; // pointer to timer channel 0 register structure volatile AT91PS_TC pTC = AT91C_BASE_TC0; // pointer to timer channel 0 register structure
unsigned int dummy; // temporary unsigned int dummy; // temporary
dummy = pTC->TC_SR; // read TC0 Status Register to clear interrupt // read TC0 Status Register to clear interrupt
Timer_Milliseconds++; // increment the tick count dummy = pTC->TC_SR;
// increment the tick count
Timer_Milliseconds++;
} }
void TimerInit(void) { void TimerInit(void) {
// enable the Timer0 peripheral clock // enable the Timer0 peripheral clock
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<<AT91C_ID_TC0); pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<<AT91C_ID_TC0);
// Set up the AIC registers for Timer 0 // Set up the AIC registers for Timer 0
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; // pointer to AIC data structure volatile AT91PS_AIC pAIC = AT91C_BASE_AIC;
pAIC->AIC_IDCR = (1<<AT91C_ID_TC0); // Disable timer 0 interrupt in AIC Interrupt Disable Command Register // Disable timer 0 interrupt
pAIC->AIC_SVR[AT91C_ID_TC0] = // Set the TC0 IRQ handler address in AIC Source // in AIC Interrupt Disable Command Register
(unsigned int)Timer0IrqHandler; // Vector Register[12] pAIC->AIC_IDCR = (1<<AT91C_ID_TC0);
pAIC->AIC_SMR[AT91C_ID_TC0] = // Set the interrupt source type and priority // Set the TC0 IRQ handler address in
(AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 0x4 ); // in AIC Source Mode Register[12] // AIC Source Vector Register[12]
pAIC->AIC_ICCR = (1<<AT91C_ID_TC0); // Clear the TC0 interrupt in AIC Interrupt Clear Command Register pAIC->AIC_SVR[AT91C_ID_TC0] =
pAIC->AIC_IDCR = (0<<AT91C_ID_TC0); // Remove disable timer 0 interrupt in AIC Interrupt Disable Command Reg (unsigned int)Timer0IrqHandler;
pAIC->AIC_IECR = (1<<AT91C_ID_TC0); // Enable the TC0 interrupt in AIC Interrupt Enable Command Register // Set the interrupt source type and priority
// in AIC Source Mode Register[12]
// Setup timer0 to generate a 10 msec periodic interrupt pAIC->AIC_SMR[AT91C_ID_TC0] =
TimerSetup(); (AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 0x4 );
// Clear the TC0 interrupt
// in AIC Interrupt Clear Command Register
pAIC->AIC_ICCR = (1<<AT91C_ID_TC0);
// Remove disable timer 0 interrupt
// in AIC Interrupt Disable Command Reg
pAIC->AIC_IDCR = (0<<AT91C_ID_TC0);
// Enable the TC0 interrupt
// in AIC Interrupt Enable Command Register
pAIC->AIC_IECR = (1<<AT91C_ID_TC0);
// Setup timer0 to generate a 1 msec periodic interrupt
Timer0_Setup(1);
} }