Interrupt Vectors

Started by Paul Williams February 19, 2008
Hi,

I am have problems with a MC9S12DP512, I am using ICC12 and using TwinPeeks
to load the programs.

My question relates to the operation of the timer interrupts. I can get TC7
working correctly.

But if I try and use TC0 nothing appears to happen. I believe it has
something to do with the redirected interrupt vectors. Mainly because of the
redirect vector that works for TC7 is actually that of TC0 in the manual.

Here is a sample of my code just in case something is incorrect:

// Setup

void SetTimer(unsigned int Ticks){
asm("sei");

TIOS = 0x81;
TIE = 0x81;
TSCR2 = 0x8c;//0x88;
TC0=Ticks-1;
TC7 = Ticks - 1;
TSCR1 = 0x80;
// Clear Timer Flag
TFLG1 = 0x81;
// Make the timer 7 the highest priority interrupt
HPRIO = 0xEE;
asm("cli");
}

// ISR for timer 0 this is the same for timer 7
#pragma interrupt_handler Timer0
void Timer0(void){
PTM^=0x01; // Pulse LED
//putstring("abcd\n\r");
// Clear timer interrupt flag
TFLG1 = 0x01;
}

Within the main() function:

//TC7

*((unsigned char *)0x3FE8) = 0x06; // JMP opcode
*((void (**)(void))0x3FE9) = Timer7;

// TC0
*((unsigned char *)0x3FFD) = 0x06; // JMP opcode
*((void (**)(void))0x3FFE) = Timer0;

Any help would be greatly appreciated

Paul
Hi Paul,

I haven't slavishly checked your register settings so maybe that is part
of your problem. I didn't see the TSCR1 reg with TEN bit set.

In ICC the easiest way to setup the isr vectors is via a vector file
with the following example for a c32:

#define DUMMY_ENTRY (void (*)(void))0xFFFF

//#pragma nonpaged_function _start sci0Handler //banked code
extern void _start (void);
#ifdef EN_SCI
extern void sci0Handler (void);
#endif

#pragma abs_address:0xFF80
void (*interrupt_vectors[])(void) {
DUMMY_ENTRY, /*Reserved $FF80*/
DUMMY_ENTRY, /*Reserved $FF82*/
DUMMY_ENTRY, /*Reserved $FF84*/
DUMMY_ENTRY, /*Reserved $FF86*/
DUMMY_ENTRY, /*PWM Emerg Shutdown*/
DUMMY_ENTRY, /*VREG LVI*/
DUMMY_ENTRY, /*PWM Emerg Shutdown*/
DUMMY_ENTRY, /*Port P*/
DUMMY_ENTRY, /*Reserved $FF90*/
DUMMY_ENTRY, /*Reserved $FF92*/
DUMMY_ENTRY, /*Reserved $FF94*/
DUMMY_ENTRY, /*Reserved $FF96*/
DUMMY_ENTRY, /*Reserved $FF98*/
DUMMY_ENTRY, /*Reserved $FF9A*/
DUMMY_ENTRY, /*Reserved $FF9C*/
DUMMY_ENTRY, /*Reserved $FF9E*/
DUMMY_ENTRY, /*Reserved $FFA0*/
DUMMY_ENTRY, /*Reserved $FFA2*/
DUMMY_ENTRY, /*Reserved $FFA4*/
DUMMY_ENTRY, /*Reserved $FFA6*/
DUMMY_ENTRY, /*Reserved $FFA8*/
DUMMY_ENTRY, /*Reserved $FFAA*/
DUMMY_ENTRY, /*Reserved $FFAC*/
DUMMY_ENTRY, /*Reserved $FFAE*/
DUMMY_ENTRY, /*CAN Transmit*/
DUMMY_ENTRY, /*CAN Receive*/
DUMMY_ENTRY, /*CAN Errors*/
DUMMY_ENTRY, /*CAN Wake-up*/
DUMMY_ENTRY, /*Flash*/
DUMMY_ENTRY, /*Reserved $FFBA*/
DUMMY_ENTRY, /*Reserved $FFBC*/
DUMMY_ENTRY, /*Reserved $FFBE*/
DUMMY_ENTRY, /*Reserved $FFC0*/
DUMMY_ENTRY, /*Reserved $FFC2*/
DUMMY_ENTRY, /*SCME*/
DUMMY_ENTRY, /*CRG Lock*/
DUMMY_ENTRY, /*Reserved $FFC8*/
DUMMY_ENTRY, /*Reserved $FFCA*/
DUMMY_ENTRY, /*Reserved $FFCC*/
DUMMY_ENTRY, /*Port J*/
DUMMY_ENTRY, /*Reserved $FFD0*/
DUMMY_ENTRY, /*ATD */
DUMMY_ENTRY, /*Reserved $FFD4*/
#ifdef EN_SCI
sci0Handler, /*SCI*/
#else
DUMMY_ENTRY, /*SCI*/
#endif //EN_SCI
DUMMY_ENTRY, /*SPI*/
DUMMY_ENTRY, /*Pulse Accumulator A Input Edge*/
DUMMY_ENTRY, /*Pulse Accumulator A Overflow*/
DUMMY_ENTRY, /*Timer Overflow*/
DUMMY_ENTRY, /*Timer Channel 7*/
DUMMY_ENTRY, /*Timer Channel 7*/
DUMMY_ENTRY, /*Timer Channel 5*/
DUMMY_ENTRY, /*Timer Channel 4*/
DUMMY_ENTRY, /*Timer Channel 3*/
DUMMY_ENTRY, /*Timer Channel 2*/
DUMMY_ENTRY, /*Timer Channel 1*/
DUMMY_ENTRY, /*Timer Channel 0*/
DUMMY_ENTRY, /*Real Time Interrupt*/
DUMMY_ENTRY, /*IRQ*/
DUMMY_ENTRY, /*XIRQ*/
DUMMY_ENTRY, /*SWI*/
_start, /*Unimplement Intruction Trap*/
_start, /*COP failure reset*/
_start, /*Clock monitor fail reset*/
_start, /*Reset*/
};
#pragma end_abs_address

Note that the abs_address at the start of the vector array has to be
calculated so that the reset vector lies at 0xFFFE. If you have a
bootloader inside the protected block where the real vector table
resides, then it should take on the responsibility of building a pseudo
jump table from real values sent during download (as is the case in my
example). If not then the programmer will have to know exactly where
the bootloader expects to see the pseudo table and hardcode the vector
array to that location.

Note too the nonpaged_function pragma. Here it isn't required because
the C32 can fit all code into a linear space, however in your case you
are probably doing a banked build and will need to use it.

-rob

Paul Williams wrote:
> Hi,
>
> I am have problems with a MC9S12DP512, I am using ICC12 and using TwinPeeks
> to load the programs.
>
> My question relates to the operation of the timer interrupts. I can get TC7
> working correctly.
>
> But if I try and use TC0 nothing appears to happen. I believe it has
> something to do with the redirected interrupt vectors. Mainly because of the
> redirect vector that works for TC7 is actually that of TC0 in the manual.
>
> Here is a sample of my code just in case something is incorrect:
>
> // Setup
>
> void SetTimer(unsigned int Ticks){
> asm("sei");
>
> TIOS = 0x81;
> TIE = 0x81;
> TSCR2 = 0x8c;//0x88;
> TC0=Ticks-1;
> TC7 = Ticks - 1;
> TSCR1 = 0x80;
> // Clear Timer Flag
> TFLG1 = 0x81;
> // Make the timer 7 the highest priority interrupt
> HPRIO = 0xEE;
> asm("cli");
> }
>
> // ISR for timer 0 this is the same for timer 7
> #pragma interrupt_handler Timer0
> void Timer0(void) {
> PTM^=0x01; // Pulse LED
> //putstring( "abcd\n\r" );
> // Clear timer interrupt flag
> TFLG1 = 0x01;
> }
>
> Within the main() function:
>
> //TC7
>
> *((unsigned char *)0x3FE8) = 0x06; // JMP opcode
> *((void (**)(void))0x3FE9) = Timer7;
>
> // TC0
> *((unsigned char *)0x3FFD) = 0x06; // JMP opcode
> *((void (**)(void))0x3FFE) = Timer0;
>
> Any help would be greatly appreciated
>
> Paul
>
>
The TSCR1 = 0x80 will do the trick.

As TwinPeeks is residing within the MCU the use of a vector table is
irrelevant. TwinPeeks actually redirects all vectors to RAM.

To utilize this feature in C the following code is used and works for
timer7:

*((unsigned char *)0x3FE8) = 0x06; // JMP opcode
*((void (**)(void))0x3FE9) = Timer7;

Note that the value 0x3FE8 is the RAM location for the TC7 interrupt

The problem seems to be that this value (used for TC7) is the same as that
defined for TC0.

A list of the redirected vectors are provided on page 30 of the Cards12
manual.

Thanks

Paul

From: 6... [mailto:6...] On Behalf Of
Rob Milne
Sent: Wednesday, 20 February 2008 1:46 AM
To: 6...
Subject: Re: [68HC12] Interrupt Vectors

Hi Paul,

I haven't slavishly checked your register settings so maybe that is part
of your problem. I didn't see the TSCR1 reg with TEN bit set.

In ICC the easiest way to setup the isr vectors is via a vector file
with the following example for a c32:

#define DUMMY_ENTRY (void (*)(void))0xFFFF

//#pragma nonpaged_function _start sci0Handler //banked code
extern void _start (void);
#ifdef EN_SCI
extern void sci0Handler (void);
#endif

#pragma abs_address:0xFF80
void (*interrupt_vectors[])(void) {
DUMMY_ENTRY, /*Reserved $FF80*/
DUMMY_ENTRY, /*Reserved $FF82*/
DUMMY_ENTRY, /*Reserved $FF84*/
DUMMY_ENTRY, /*Reserved $FF86*/
DUMMY_ENTRY, /*PWM Emerg Shutdown*/
DUMMY_ENTRY, /*VREG LVI*/
DUMMY_ENTRY, /*PWM Emerg Shutdown*/
DUMMY_ENTRY, /*Port P*/
DUMMY_ENTRY, /*Reserved $FF90*/
DUMMY_ENTRY, /*Reserved $FF92*/
DUMMY_ENTRY, /*Reserved $FF94*/
DUMMY_ENTRY, /*Reserved $FF96*/
DUMMY_ENTRY, /*Reserved $FF98*/
DUMMY_ENTRY, /*Reserved $FF9A*/
DUMMY_ENTRY, /*Reserved $FF9C*/
DUMMY_ENTRY, /*Reserved $FF9E*/
DUMMY_ENTRY, /*Reserved $FFA0*/
DUMMY_ENTRY, /*Reserved $FFA2*/
DUMMY_ENTRY, /*Reserved $FFA4*/
DUMMY_ENTRY, /*Reserved $FFA6*/
DUMMY_ENTRY, /*Reserved $FFA8*/
DUMMY_ENTRY, /*Reserved $FFAA*/
DUMMY_ENTRY, /*Reserved $FFAC*/
DUMMY_ENTRY, /*Reserved $FFAE*/
DUMMY_ENTRY, /*CAN Transmit*/
DUMMY_ENTRY, /*CAN Receive*/
DUMMY_ENTRY, /*CAN Errors*/
DUMMY_ENTRY, /*CAN Wake-up*/
DUMMY_ENTRY, /*Flash*/
DUMMY_ENTRY, /*Reserved $FFBA*/
DUMMY_ENTRY, /*Reserved $FFBC*/
DUMMY_ENTRY, /*Reserved $FFBE*/
DUMMY_ENTRY, /*Reserved $FFC0*/
DUMMY_ENTRY, /*Reserved $FFC2*/
DUMMY_ENTRY, /*SCME*/
DUMMY_ENTRY, /*CRG Lock*/
DUMMY_ENTRY, /*Reserved $FFC8*/
DUMMY_ENTRY, /*Reserved $FFCA*/
DUMMY_ENTRY, /*Reserved $FFCC*/
DUMMY_ENTRY, /*Port J*/
DUMMY_ENTRY, /*Reserved $FFD0*/
DUMMY_ENTRY, /*ATD */
DUMMY_ENTRY, /*Reserved $FFD4*/
#ifdef EN_SCI
sci0Handler, /*SCI*/
#else
DUMMY_ENTRY, /*SCI*/
#endif //EN_SCI
DUMMY_ENTRY, /*SPI*/
DUMMY_ENTRY, /*Pulse Accumulator A Input Edge*/
DUMMY_ENTRY, /*Pulse Accumulator A Overflow*/
DUMMY_ENTRY, /*Timer Overflow*/
DUMMY_ENTRY, /*Timer Channel 7*/
DUMMY_ENTRY, /*Timer Channel 7*/
DUMMY_ENTRY, /*Timer Channel 5*/
DUMMY_ENTRY, /*Timer Channel 4*/
DUMMY_ENTRY, /*Timer Channel 3*/
DUMMY_ENTRY, /*Timer Channel 2*/
DUMMY_ENTRY, /*Timer Channel 1*/
DUMMY_ENTRY, /*Timer Channel 0*/
DUMMY_ENTRY, /*Real Time Interrupt*/
DUMMY_ENTRY, /*IRQ*/
DUMMY_ENTRY, /*XIRQ*/
DUMMY_ENTRY, /*SWI*/
_start, /*Unimplement Intruction Trap*/
_start, /*COP failure reset*/
_start, /*Clock monitor fail reset*/
_start, /*Reset*/
};
#pragma end_abs_address

Note that the abs_address at the start of the vector array has to be
calculated so that the reset vector lies at 0xFFFE. If you have a
bootloader inside the protected block where the real vector table
resides, then it should take on the responsibility of building a pseudo
jump table from real values sent during download (as is the case in my
example). If not then the programmer will have to know exactly where
the bootloader expects to see the pseudo table and hardcode the vector
array to that location.

Note too the nonpaged_function pragma. Here it isn't required because
the C32 can fit all code into a linear space, however in your case you
are probably doing a banked build and will need to use it.

-rob

Paul Williams wrote:
> Hi,
>
> I am have problems with a MC9S12DP512, I am using ICC12 and using
TwinPeeks
> to load the programs.
>
> My question relates to the operation of the timer interrupts. I can get
TC7
> working correctly.
>
> But if I try and use TC0 nothing appears to happen. I believe it has
> something to do with the redirected interrupt vectors. Mainly because of
the
> redirect vector that works for TC7 is actually that of TC0 in the manual.
>
> Here is a sample of my code just in case something is incorrect:
>
> // Setup
>
> void SetTimer(unsigned int Ticks){
> asm("sei");
>
> TIOS = 0x81;
> TIE = 0x81;
> TSCR2 = 0x8c;//0x88;
> TC0=Ticks-1;
> TC7 = Ticks - 1;
> TSCR1 = 0x80;
> // Clear Timer Flag
> TFLG1 = 0x81;
> // Make the timer 7 the highest priority interrupt
> HPRIO = 0xEE;
> asm("cli");
> }
>
> // ISR for timer 0 this is the same for timer 7
> #pragma interrupt_handler Timer0
> void Timer0(void) {
> PTM^=0x01; // Pulse LED
> //putstring( "abcd\n\r" );
> // Clear timer interrupt flag
> TFLG1 = 0x01;
> }
>
> Within the main() function:
>
> //TC7
>
> *((unsigned char *)0x3FE8) = 0x06; // JMP opcode
> *((void (**)(void))0x3FE9) = Timer7;
>
> // TC0
> *((unsigned char *)0x3FFD) = 0x06; // JMP opcode
> *((void (**)(void))0x3FFE) = Timer0;
>
> Any help would be greatly appreciated
>
> Paul
>
>