Hi
I am not sure if the GPT is better for your application than a Programmable Interrupt Timer - it seems like you just want to generate an interrupt every 1ms so a PIT would be easier. Of course, you may be using a part with no PIT.
I haven't used GPT, but I have included below code that will set up PITs and ISRs for them. If you need to use a GPT, then it shouldn't be too difficult to adapt this. My code is for mcf5282, but I know it also works on mcf52235.
When I looked at you code, I noticed that your set the interrupt level and priority to 7 - this level is non-maskable. Unless your ISR happens to need an NMI, a lower level may be better.
I also noticed that you haven't set a vector for the ISR, is this hardcoded in your vectors? If not, you must set the correct vector. I have included source for a C function that will both set the vector and the interrupt mask. (all code samples belowe are aimed at GCC, but should be portable to CW).
First, timer initialisation, adapt this for GPT:
Code:/* FUNCTION: PIT_Timer_Init() * * Initialise and enable a Programmable Interval Timer * * PARAM1: PIT - can be 0, 1, 2 or 3 * * PARAM2: Prescaler value - sets the tick frequency to * (system clock/2) divided by 2^PCSR * * PARAM3: Modulo counter - sets the mumber of ticks per interrupt * * PARAM4: Interrupt handler * * RETURNS: none */voidPIT_Timer_Init(uint8 timer, uint8 PCSR, uint16 PMR, void (*handler)(void)){ // At 64MHz: // PCSR = 5 gives a tick per uS // PMR = 10000 gives an interrupt every 10ms if (timer < 4) { uint8 ipl = MCF5282_INTC_ICR_IL(TIMER_NETWORK_LEVEL) | MCF5282_INTC_ICR_IP(timer); MCF5282_PIT_PCSR(timer) = 0; // Set up interrupt handler mcf5282_interrupt_init(timer + 55, ipl, handler); // Set modulo count // (= number of ticks per interrupt) MCF5282_PIT_PMR(timer) = PMR; // Tick frequency = (system clock/2) divided by 2^PCSR MCF5282_PIT_PCSR(timer) = (uint16)(MCF5282_PIT_PCSR_PRE(PCSR)); // Create and enable 'set and forget' timer MCF5282_PIT_PCSR(timer) |= MCF5282_PIT_PCSR_OVW | MCF5282_PIT_PCSR_PIE | MCF5282_PIT_PCSR_PIF | MCF5282_PIT_PCSR_RLD | MCF5282_PIT_PCSR_EN; }}/* FUNCTION: PIT_Timer_Stop() * * Disable timer interrupts for the specified PIT * * PARAM1: PIT - can be 0, 1, 2 or 3 * * RETURNS: none */voidPIT_Timer_Stop(uint8 timer){ if (timer < 4) MCF5282_PIT_PCSR(timer) &= ~( MCF5282_PIT_PCSR_PIE | MCF5282_PIT_PCSR_EN );}
Second, set up the interrupt vector and enable the interrupt in the interrupt controller:
Code:/* FUNCTION: mcf5282_interrupt_init() * * Initialise an interrupt handler for an interrupt source * for INTC0. If the handler is a NULL pointer, then mask * this interrupt. * * PARAM1: Interrupt source (1..62) * * PARAM2: Interrupt level and priority * * PARAM3: Interrupt handler * * RETURNS: none */voidmcf5282_interrupt_init(uint8 source, uint8 ipl, void (*handler)(void)){ // Only for user defined vectors in INTC0 if ((source > 0) && (source < 63)) { // Interrupts should be disabled to avoid vector problems // and to ensure that a spurious interrupt exception can't // be generated. uint8 sysint = asm_set_ipl(7); if (handler) { // Set interrupt priority level MCF5282_INTC0_ICR(source) = (ipl & 0x3F); // Set vector mcf5xxx_set_handler(source+64, (ADDRESS)handler); // Clear mask for this handler if (source < 32) MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT(source) | MCF5282_INTC_IMRL_MASKALL); else { MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_MASKALL); MCF5282_INTC0_IMRH &= ~(MCF5282_INTC_IMRH_INT(source)); } } else { // Set vector mcf5xxx_set_handler(source+64, (ADDRESS)handler); // Set mask for this handler if (source < 32) { MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT(source); } else { MCF5282_INTC0_IMRH |= MCF5282_INTC_IMRH_INT(source); } } // As you were... asm_set_ipl(sysint); }}/********************************************************************/
In case you need it, this is the assembler for the function that masks interrupts in the SR, used while the interrupt vectors and masks are being modified:
Code:/********************************************************************//* * This routines changes the IPL to the value passed into the routine. * It also returns the old IPL value back. * Calling convention from C: * old_ipl = asm_set_ipl(new_ipl); * For the Diab Data C compiler, it passes return value thru D0. * Note that only the least significant three bits of the passed * value are used. */asm_set_ipl:_asm_set_ipl: link A6,#-8 movem.l D6-D7,(SP) move.w SR,D7 /* current sr */ move.l D7,D0 /* prepare return value */ andi.l #0x0700,D0 /* mask out IPL */ lsr.l #8,D0 /* IPL */ move.l 8(A6),D6 /* get argument */ andi.l #0x07,D6 /* least significant three bits */ lsl.l #8,D6 /* move over to make mask */ andi.l #0x0000F8FF,D7 /* zero out current IPL */ or.l D6,D7 /* place new IPL in sr */ move.w D7,SR movem.l (SP),D6-D7 lea 8(SP),SP unlk A6 rts
And the interrupt handler (note that __attribute__((interrupt_handler)) is GCC specific, you need to change for CW):
Code:/******************************************************************** * FUNCTION: hz_timer_isr() * * PIT2 interrupt handler, set to be called at 1 second intervals * * PARAMS: none * * RETURNS: none * * Used for updating rate counters for bit rates, etc. */__attribute__((interrupt_handler))voidhz_timer_isr(void){ // Do something... // Clear interrupt at CSR MCF5282_PIT_PCSR(HZ_TIMER) |= MCF5282_PIT_PCSR_PIF;}
And finally, put this call somewhere to set up a timer (this is to create a timer that is called at 1 second intervals on a mcf5282 running at 64MHz, change the values to get a 1ms timer):
Code: // We are assuming that sys_clk is 64MHz // so PCSR = 11 gives 15625 ticks per second. PIT_Timer_Init(HZ_TIMER, 11, 15625, hz_timer_isr);
Cheers,
Paul.