Application Note: Interrupt Routines for the CFV2-40

This application note covers the external interrupt capabilities. Examples are given for the NetBurner CFV2-40 platform, which is based on the 5206e processor. Please reference the ColdFire user's manual that was included in your installation for more detailed information. The available external interrupt inputs are dependant on your platform:

CFV2-40 (ColdFire 5206e): The 3 external interrupt pins are configured to be predefined interrupt request pins, which means the 3 pins represent interrupt priority level signals IRQ1, IRQ4, and IRQ7.

CFV2-66 (ColdFire 5272): The 2 external interrupt pins are configured to be predefined interrupt request pins, which means the 2 pins represent interrupt priority level signals IRQ2 and IRQ4.

Pull-up resistors are provided for each active-low interrupt input. If you are working on your own custom design, other interrupt signals may be available.

To create an interrupt routine you need to do the following:
1. Add the required #include files to your source code
2. Create your interrupt routine using the INTERRUPT( ) macro
3. Add the address of your interrupt service routine to the Vector Base Table
4. Configure the Interrupt Control Register (ICR) for your interrupt
5. Enable your specific interrupt in the Interrupt Mask Register (IMR)

 

Step 1: Add the following #include files to your source code:

#include <sim5206.h>  // or sim5272.h
#include <ucos.h> 
#include <cfinter.h>

Step 2: Create your interrupt service routine using the INTERRUPT( ) macro

The following macro is used to configure interrupts:

INTERRUPT(isr_address, interrupt_priority_mask);

where
isr_address = address of your interrupt service routine
interrupt_priority_mask = The current interrupt priority. Interrupt requests are
inhibited for all priority levels less than or equal to the current priority, except the
edge-sensitive level 7 request, which cannot be masked.

The following examples are for interrupt levels 1, 4, and 7. The IPM is set to mask
all interrupt requests less than or equal to the current interrupt level. You can set higher
mask levels for interrupts 1 and 4 if you prefer.

INTERRUPT(ISR_Level1, 0x2100)
{
   // Interrupt processing code goes here
}

INTERRUPT(ISR_Level4, 0x2400)
{
   // Interrupt processing code goes here
}
      

Note: The unmaskable interrupt 7 cannot use the INTERRUPT macro. This interrupt is designed to be the highest priority, cannot be masked, and does not interface with the RTOS.

 

Step 3: Add the address of your interrupt service routine to the Vector Base Table

The following examples are for interrupt levels 1, 4, and 7.

vector_base.table[24+1]=(long)&ISR_Level1;
vector_base.table[24+4]=(long)&ISR_Level4;
vector_base.table[24+7]=(long)&ISR_Level7;

 

Step 4: Configure the Interrupt Control Register (ICR) for your interrupt

The ICR contains the interrupt levels and priorities assigned to each interrupt. There is one ICR for each interrupt. Each interrupt must have a unique interrupt level and priority. You must program the ICR for each interrupt before programming the IMR. See pages 8-9 through 8-12 of the Freescale 5206e User's Manual for more details.

The following values for interrupts 1, 4, and 7 are recommended:

sim.icr1 = 0x87;
sim.icr4 = 0x93;
sim.icr7 = 0x9F;

 

Step 5: Enable your specific interrupt in the Interrupt Mask Register (IMR)

You mask an interrupt by setting the corresponding bit in the IMR and enable an interrupt by clearing the corresponding bit in the IMR. The following #defines are provided. See pages 8-10 through 8-12 of the Freescale 5206e User's Manual for more details.

#define IMR_INT1 (0x0002)
#define IMR_INT4 (0x0010)
#define IMR_INT7 (0x0080)

To enable interrupts 1, 4, or 7 you need to clear the bit for the interrupt you are using:

sim.imr &= ~IMR_INT1; // enable IRQ 1
sim.imr &= ~IMR_INT4; // enable IRQ 4
sim.imr &= ~IMR_INT7; // enable IRQ 7

Example Program

The following example program demonstrates the use of interrupts.
The source code and make file are available here:
IntAppNote.cpp
makefile

/*---------------------------------------------------------
The following program uses the ColdFire's 8 bit parallel 
port to generate continuous level 4 interrupt requests.  
The CFV2-40's LED bank is used to display the number of 
interrupts received.

To run the program, a jumper wire is needed from JP1 pin19
the Debug Connector) to JP2 pin 5 (/IRQ4 on the Interface
Connector).

The program was tested on a CFV2-40 Revision 1.2 board.

Code Revision 1.0, 2/10/2000
----------------------------------------------------------*/
#include "predef.h" 
#include <basictypes.h> 
#include <sim5206.h> 
#include <ucos.h> 
#include <cfinter.h> 
#include <stdio.h> 
#include <utils.h>

#define IMR_INT1 (0x0002)
#define IMR_INT4 (0x0010)
#define IMR_INT7 (0x0080)
#define ICR_INT1 (0x87)
#define ICR_INT4 (0x93)
#define ICR_INT7 (0x9F)

// Needed for C++ 
extern "C"
{
void UserMain(void * pd);
}

volatile BYTE IntCtr = 0;

// Interrupt service routine
INTERRUPT(ISR_Level4, 0x2400)
{
   sim.ppdat= 0xFF; // Clear cause of IRQ
   putleds(IntCtr++); 
}

// Main function
void UserMain(void *pd)
{
   // Configure the 8 5206e parallel port pins as outputs
   sim.par &= ~0x0030; // Assign the PP pins as functional 
   sim.ppddr= 0xFF; // Assign the PP dir as output
   sim.ppdat= 0xFF; // Set all outputs high

   // Set up the interrupt
   vector_base.table[24+4]=(long)&ISR_Level4;
   sim.icr4 = ICR_INT4;    // configure control register
   sim.imr &= ~IMR_INT4;   // enable IRQ 4
   putleds(0);
   printf("Waiting for IRQ 4\r\n");
   while(1)
   {
      OSTimeDly(1);
      sim.ppdat= 0; // Generate an interrupt
      printf(".");
   }
}