Interrupt and timer on MCF52235RM

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Interrupt and timer on MCF52235RM

2,230 Views
kedja
Contributor I
Hi all,
I have some issue about timer and interrupt on a MCF52235RM µC.
I need to blink a LED every second (or ms or µs).
My code (inspirate of this code):
Code:
#ifndef __TIMER_H__#define __TIMER_H__voidmcf52235_interrupt_init(uint8 source, uint8 ipl, void (*handler)(void));/* FUNCTION: GPTA_Timer_Init() * * Initialise and enable General Purpose Timer A0 to work like * a PIT. * * 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 */#include "MCF52235.h"#define ADDRESS   uint32voidGPTA_Timer_Init(uint8 PCSR, uint16 PMR, void (*handler)(void)){  uint8 ipl = MCF_INTC_ICR_IL(2)     | MCF_INTC_ICR_IP(0); // Disable timer A MCF_GPTA_GPTSCR2 = 0; // Set up interrupt handler mcf52235_interrupt_init(44, ipl, handler);   // Set modulo count // (= number of ticks per interrupt) MCF_GPTA_GPTC0 = PMR;   // Tick frequency = (system clock/2) divided by 2^PCSR MCF_GPTA_GPTSCR2  = 0x87;//(uint8)(MCF_GPTA_GPTSCR2_PR(PCSR)); MCF_GPTA_GPTIOS = MCF_GPTA_GPTIOS_IOS0;  MCF_GPTA_GPTIE = MCF_GPTA_GPTIE_CI0;  // Enable timer A MCF_GPTA_GPTSCR2 = MCF_GPTA_GPTSCR2_TOI; MCF_GPTA_GPTSCR1 = MCF_GPTA_GPTSCR1_GPTEN;}/* FUNCTION: mcf52235_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 */voidmcf52235_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 =(uint8) asm_set_ipl(7);  if (handler)  {   // Set interrupt priority level   MCF_INTC0_ICR(source) =(uint8)(ipl & 0x3F);   // Set vector   mcf5xxx_set_handler(source+64, (ADDRESS)handler);   // Clear mask for this handler   /*if (source < 32)    MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT(source);          | MCF_INTC_IMRL_MASKALL);   else   {*/    MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_MASKALL);    MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK44);//MCF_INTC_IMRH_INT(source)   //}  }  else  {   // Set vector   mcf5xxx_set_handler(source+64, (ADDRESS)handler);   // Set mask for this handler   /*if (source < 32)   {    MCF_INTC0_IMRL |= MCF_INTC_IMRL_INT(source);   }   else   {*/    MCF_INTC0_IMRH |= MCF_INTC_IMRH_INT_MASK44;   //}  }  // As you were...  //asm_set_ipl(sysint); }}/********************************************************************/#endif

My main:
Code:
/* * main implementation: use this sample to create your own application * */#define __interrupt__   __declspec(interrupt)#include "support_common.h" /* include peripheral declarations and more */#include "MCF52235.h"#include "timer.h"#if (CONSOLE_IO_SUPPORT || ENABLE_UART_SUPPORT) /* Standard IO is only possible if Console or UART support is enabled. */#include <stdio.h>#endif__interrupt__voidtimer_handler(void){ MCF_GPIO_PORTUB^=0x01;//Blink LED // Clear interrupt MCF_GPTA_GPTFLG2 = MCF_GPTA_GPTFLG2_TOF; }int main(void){ MCF_CLOCK_SYNCR=0x0705;//PLL bypass MCF_CLOCK_SYNSR=0x80;//External clock systeme  GPTA_Timer_Init(5, 65535, timer_handler); mcf5xxx_irq_enable(); MCF_GPIO_PORTUB=0; MCF_GPIO_DDRUB=0x07; while(1) {  MCF_GPIO_PORTUB^=0x02;  }}

 These code don't work, i can't set time of interrupt (second,milisecond,µs,etc) and when i change value of prescaler, this have no effect

Thanks for help





Message Edited by kedja on 2008-06-19 10:31 AM
Labels (1)
0 Kudos
5 Replies

527 Views
mjbcswitzerland
Specialist V
Hi

I would avoid the GPT for generating periodic interrupts. It is more useful for generating waveforms.

The M5223X has 2 PITs, which are designed for this purpose and are very easy to use. Rich's code shows how much simpler it is.

The M5223X also has 4 DMA timers which are very powerful - they can easily be configured to generate periodic interrupts from us region up to many days with very high resolution.

Here are extracts from the user interface for these timer in the uTasker project, which will also simulate these timers to allow easy testing of code:

Eg of configuring a PIT with a single shot interrupt of 3245us - it calls back the user handler test_timer_int() when it fires. It will power itself up and automatically power itself down when finished with its work.

Code:
static void fnConfigurePIT(void){    PIT_SETUP pit_setup;                                                 // interrupt configuration parameters    pit_setup.int_type = PIT_INTERRUPT;    pit_setup.int_handler = test_timer_int;    pit_setup.int_priority = PIT1_INTERRUPT_PRIORITY;    pit_setup.count_delay = PIT_US_DELAY(3245);                          // 3245us delay    pit_setup.mode = PIT_SINGLE_SHOT;                                    // one-shot interrupt    fnConfigureInterrupt((void *)&pit_setup);                            // enter interrupt for PIT1 test}

Here is an example of using a DMA timer (these are interesting because they can also be used to cause DMA transfers to take place) rather than interrupting..
In this case it also performs a single shot interrupt with 6345us timeout

Code:
static void fnConfigure_DMA_Timer(void){    DMA_TIMER_SETUP dma_timer_setup;                                     // interrupt configuration parameters    dma_timer_setup.int_type = DMA_TIMER_INTERRUPT;    dma_timer_setup.int_handler = DMA_timer_int;    dma_timer_setup.channel = 1;                                         // DMA timer channel 1    dma_timer_setup.int_priority = DMA_TIMER1_INTERRUPT_PRIORITY;        // define interrupt priority    dma_timer_setup.mode = (DMA_TIMER_INTERNAL_CLOCK | DMA_TIMER_SINGLE_SHOT_INTERRUPT);    dma_timer_setup.count_delay = DMA_TIMER_US_DELAY(1,1,6345);          // 6345us delay using no dividers    fnConfigureInterrupt((void *)&dma_timer_setup);                      // enter interrupt for DMA timer test}

 To generate periodic interrupts or control output signals the parameters can be simply modified:

eg. periodic interrupt:
        dma_timer_setup.mode = (DMA_TIMER_INTERNAL_CLOCK | DMA_TIMER_PERIODIC_INTERRUPT);

or an output on its TOUT pin:
        dma_timer_setup.mode = (DMA_TIMER_RESTART_ON_MATCH | DMA_TIMER_TOGGLE_OUTPUT);
        dma_timer_setup.count_delay = DMA_TIMER_US_DELAY(1,1,(1000000/2/1500)); // 1500Hz signal

Regards

Mark

www.uTasker.com


0 Kudos

527 Views
RichTestardi
Senior Contributor II
If it helps, this is the code I use to blink a heartbeat LED:
 
Code:
#include "main.h"// *** timer ****************************************************************int volatile ticks;  // incremented by pit0 isr every millisecondint volatile seconds;  // incremented by pit0 isr every second// called by pit0 every millisecondstatic__declspec(interrupt)voidtimer_isr(void){    int halves;    MCF_PIT0_PCSR |= MCF_PIT_PCSR_PIF;    ticks++;    if (ticks%500 == 0) {        halves = ticks/500;            led_set(3, halves&1);        if ((halves&1) == 0) {            seconds++;        }    }}voidtimer_initialize(void){    // enable pit0 timer interrupt    __VECTOR_RAM[119] = (uint32)timer_isr;    MCF_INTC0_ICR55 = MCF_INTC_ICR_IL(SPL_PIT0)|MCF_INTC_ICR_IP(SPL_PIT0);    MCF_INTC0_IMRH &= ~MCF_INTC_IMRH_INT_MASK55;  // pit0    MCF_INTC0_IMRL &= ~MCF_INTC_IMRL_MASKALL;    // configure pit0 to interrupt every 1 ms    MCF_PIT0_PCSR = 0;    MCF_PIT0_PMR = 24000;  // 1 ms @ 48 MHz    MCF_PIT0_PCSR = MCF_PIT_PCSR_PRE(0)|MCF_PIT_PCSR_OVW|MCF_PIT_PCSR_PIE|MCF_PIT_PCSR_RLD|MCF_PIT_PCSR_EN;}

 
0 Kudos

527 Views
kedja
Contributor I
Thanks a bunch men,
That was very helpfull for me.
I have take the Rich T methode (more comprehensible for me :smileywink:)
C u later for another issue :smileywink:
0 Kudos

527 Views
kedja
Contributor I
Hi again,
I'm allready back :smileysad:....
When i change PMR value (2500 for 1 sec), i obtain some bug when i check with oscillograme
Representation of oscillogram screen in attachment
0 Kudos

527 Views
kedja
Contributor I
It's ok I've fix it!
0 Kudos