RTI problem--Processor mc9s12dt256b

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

RTI problem--Processor mc9s12dt256b

3,673 Views
leeen82
Contributor I
I am trying to setup an interrupt and having problems.  I think that the problem is regarding the vector address, which I am a bit unclear about.  I used processor expert to get the interrupt to turn on and off an LED and it was successful.  By looking in the vectors.c file from processor expert I can see that the vector address is 0xFFF0 but I cant seem to get the interrupt to work without using processor expert.  I should note that maybe there is some other problem that I am missing, but I am pretty sure that I need to define a vector address for the interrupt.  Any code examples or suggestions would be greatly appreciated.  The code for the program is listed below.  Thanks in advance.

#include <hidef.h>      /* common defines and macros */
#include <mc9s12dt256.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dt256b"

//VECTOR ADDRESS 0xFFF0 MY_Int; 
#pragma TRAP_PROC
void MY_Int(void){
  CRGFLG = 128;
    DDRB=0xF0; //sets to output
    if (PORTB == 0x10){
      PORTB = 0;
    }else{
      PORTB = 0x10;
    }
}


void main(void) {
  /* put your own code here */
  RTICTL=63;
  CRGFLG=128;
  CRGINT=128;
  //INTCR=191;
  EnableInterrupts;
  for(;:smileywink:{
  }
 
 
                      /* Enable interrupt */
  //EnableInterrupts;

  for(;:smileywink: {} /* wait forever */
  /* please make sure that you never leave this function */
}

Labels (1)
Tags (1)
0 Kudos
5 Replies

575 Views
CrasyCat
Specialist III
Hello
 
In order to get working interrupts you need to:
 1 - tell the compiler the function is an interrupt function. This is done specifying
    #pragma TRAP_PROC prior to the function implementation if using the interrupt keyword.
    Example
 #pragma TRAP_PROC
void MY_Int(void){
}
or
__interruptvoid MY_Int(void){
}
You also need to make sure the function is allocated in NON_BANKED memory.
 
  In this purpose enclose the function implementation between
#pragma CODE_SEG __SHORT_SEG NON_BANKED
  and
#pragma CODE_SEG DEFAULT
 
  2-initialize the vector table entry with the address of the function.
    This is done in the .prm file using command VECTOR ADDRESS.
    Example:
VECTOR ADDRESS 0xFFF0 MY_Int
  3- Initialize the peripheral appropriately and add code to enable the interrupt for the device.
 
  4- Make sure to enable the interrupts in your main function (you can use macro
      EnabelInterrupts from hidef.h in that purpose)
CrasyCat


Message Edited by CrasyCat on 2007-12-20 01:42 PM
0 Kudos

575 Views
leeen82
Contributor I
Thanks for the reply.  I followed the steps in the above email and am still getting an error.  The error I am getting is "Link Error: L1106 : Object Timer_Int_ELEE not found."  I have pasted in the main.cpp file and the P&E_MultiLink_Cyclonepro_linker.prm, which will hopefully help in determining the problem.  I am having the same problem with setting up ATD hence I assume it is something to do with the .prm file.  Thanks in advance.  -Erik-
 
Main.cpp file:
#include <hidef.h>      /* common defines and macros */
#include <mc9s12dt256.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dt256b"
#pragma CODE_SEG __SHORT_SEG NON_BANKED
#pragma TRAP_PROC
void Timer_Int_ELEE(void){
    DDRB=0xF0; //sets to output
    if (PORTB == 0x10){
      PORTB = 0;
    }else{
      PORTB = 0x10;
    }
CRGFLG = 129;
}
#pragma CODE_SEG DEFAULT
void main(void) {
  /* put your own code here */
  EnableInterrupts;
    //VECTOR ADDRESS 0xFFF0 MY_Int; placed in the prm file
  RTICTL=63;
  PLLCTL=32;//2^5;
  CRGFLG=129;//
  CRGINT=130;//2^1+2^7;//
  CLKSEL=0;//
  INTCR=191;
  //EnableInterrupts;
  for(;:smileywink: {} /* wait forever */
  /* please make sure that you never leave this function */
}
 
 
 
 
linker file:
 
/* This is a linker parameter file for the MC9S12DT256 */
NAMES END /* CodeWarrior will pass all the needed files to the linker by command line. But here you may add your own files too. */
SEGMENTS /* here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */
    RAM = READ_WRITE 0x1000 TO 0x3FFF;
    /* unbanked FLASH ROM */
    ROM_4000 = READ_ONLY  0x4000 TO 0x7FFF;
    ROM_C000 = READ_ONLY  0xC000 TO 0xFEFF;
    /* banked FLASH ROM */
    PAGE_30 = READ_ONLY  0x308000 TO 0x30BFFF;
    PAGE_31 = READ_ONLY  0x318000 TO 0x31BFFF;
    PAGE_32 = READ_ONLY  0x328000 TO 0x32BFFF;
    PAGE_33 = READ_ONLY  0x338000 TO 0x33BFFF;
    PAGE_34 = READ_ONLY  0x348000 TO 0x34BFFF;
    PAGE_35 = READ_ONLY  0x358000 TO 0x35BFFF;
    PAGE_36 = READ_ONLY  0x368000 TO 0x36BFFF;
    PAGE_37 = READ_ONLY  0x378000 TO 0x37BFFF;
    PAGE_38 = READ_ONLY  0x388000 TO 0x38BFFF;
    PAGE_39 = READ_ONLY  0x398000 TO 0x39BFFF;
    PAGE_3A = READ_ONLY  0x3A8000 TO 0x3ABFFF;
    PAGE_3B = READ_ONLY  0x3B8000 TO 0x3BBFFF;
    PAGE_3C = READ_ONLY  0x3C8000 TO 0x3CBFFF;
    PAGE_3D = READ_ONLY  0x3D8000 TO 0x3DBFFF;
/*    PAGE_3E = READ_ONLY  0x3E8000 TO 0x3EBFFF; not used: equivalent to ROM_4000 */
/*    PAGE_3F = READ_ONLY  0x3F8000 TO 0x3FBFFF; not used: equivalent to ROM_C000 */
  //OSVECTORS = READ_ONLY    0xFF8C TO 0xFFFF;  /* OSEK interrupt vectors (use your vector.o) */
END
PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */
    _PRESTART,                   /* Used in HIWARE format: jump to _Startup at the code start */
    STARTUP,                     /* startup data structures */
    ROM_VAR,                     /* constant variables */
    STRINGS,                     /* string literals */
    VIRTUAL_TABLE_SEGMENT,       /* C++ virtual table segment */
  //.ostext,                     /* OSEK */
    NON_BANKED,                  /* runtime routines which must not be banked */
    COPY                         /* copy down information: how to initialize variables */
                                 /* in case you want to use ROM_4000 here as well, make sure
                                    that all files (incl. library files) are compiled with the
                                    option: -OnB=b */
                                 INTO  ROM_C000/*, ROM_4000*/;
    DEFAULT_ROM                  INTO  PAGE_30,PAGE_31,PAGE_32,PAGE_33,PAGE_34,PAGE_35,PAGE_36,PAGE_37,
                                       PAGE_38,PAGE_39,PAGE_3A,PAGE_3B,PAGE_3C,PAGE_3D;
                                             
  //.stackstart,               /* eventually used for OSEK kernel awareness: Main-Stack Start */
    SSTACK,                    /* allocate stack first to avoid overwriting variables on overflow */
  //.stackend,                 /* eventually used for OSEK kernel awareness: Main-Stack End */
    DEFAULT_RAM                  INTO  RAM;
  //.vectors                     INTO OSVECTORS; /* OSEK */
END
ENTRIES /* keep the following unreferenced variables */
    /* OSEK: always allocate the vector table and all dependent objects */
  //_vectab OsBuildNumber _OsOrtiStackStart _OsOrtiStart
END
STACKSIZE 0x100
VECTOR ADDRESS 0xFFF0 Timer_Int_ELEE
VECTOR 0 _Startup /* reset vector: this is the default entry point for a C/C++ application. */
//VECTOR 0 Entry  /* reset vector: this is the default entry point for an Assembly application. */
//INIT Entry      /* for assembly applications: that this is as well the initialization entry point */
0 Kudos

575 Views
CompilerGuru
NXP Employee
NXP Employee
That's a different issue.
If you use C++ you either have to explicitly use the "C" calling convention to avoid the C++ name mangling, or you have to use C++ name mangled name in the prm file.
I suggest to use the "C" calling convention.
E.g.

Code:
#pragma LINK_INFO DERIVATIVE "mc9s12dt256b"#pragma CODE_SEG __SHORT_SEG NON_BANKED#pragma TRAP_PROC#ifdef __cplusplusextern "C"#endifvoid Timer_Int_ELEE(void){    DDRB=0xF0; //sets to output    if (PORTB == 0x10){      PORTB = 0;    }else{      PORTB = 0x10;    }CRGFLG = 129;}#pragma CODE_SEG DEFAULT

(when only targeting C++, the #ifdef __cplusplus can be obviously dropped with the corresponding #endif)

Note that the C++ name mangling is a common issue to all C++ usages and not different for CW than for any other compiler I know.

Daniel
 

0 Kudos

575 Views
leeen82
Contributor I
Thanks again for the help. That fixed the problem and now the interrupt is working properly.  I have hit another wall that I simply can't get past.  I know that an interrupt service routine should perform few operations and then return to the main function to perform the bulk of the operations.  With that in mind I am trying to increment a variable each time the interrupt occurs.  The problem is the variable's value doesnt seem to change inside the main function, but when looking at the value of the variable after compiling and running the program I can see that it's value changes as each interrupt occurs.  I have pasted the code below. Since each interrupt is 64 microseconds I should be able to use the while loop in the main function to wait 3 seconds then turn on the leds.  For some reason the program never gets past the while loop in the main function.  I have stored the 64*counter into a variable and looked at its value and it always reads 0...meaning counter must always be reading zero.  But when I look at the value of counter it has incremented to a large number.  Not sure what has happened here but clearly I am missing something.  I can get it to work by placing the code directly into the interrupt, but would rather keep the isr small.  I am sure that it is something easy so please excuse my inability to solve this problem.  Thanks again for all the help.   -Erik-



#include <hidef.h>      /* common defines and macros */
#include <mc9s12dt256.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dt256b"

global long counter; //variable used to increment each interrupt
int timer_period;
#define T (*(volatile long*) counter)
#pragma CODE_SEG __SHORT_SEG NON_BANKED
#pragma TRAP_PROC
#ifdef __cplusplus
  extern "C"
#endif
void Timer_Interrupt(void){
    //CRGINT = 0;  //disable interrupt
    counter=counter + 1;
    //CRGINT=128; //enable interrupt
 
     
    /
}
#pragma CODE_SEG DEFAULT




//this function will initialize the rti timer.
//the function expects a timer period value in microseconds.
//ONLY the listed periods can be achieved.
void Timer_Initialize(int period_in_us){
/*  Possible interrupt periods
    64    us
    128   us
    192   us
    256   us
    320   us
    384   us
    448   us
*/
if (period_in_us == 64){ RTICTL = 16;}
else if (period_in_us == 128){ RTICTL = 17;}
else if (period_in_us == 192){ RTICTL = 18;}
else if (period_in_us == 256){ RTICTL = 19;}
else if (period_in_us == 320){ RTICTL = 20;}
else if (period_in_us == 384){ RTICTL = 21;}
else if (period_in_us == 448){ RTICTL = 22;}
timer_period = period_in_us; 
}


void Start_Timer(void){
//turn on timer
Timer_Initialize(timer_period);//this ensures that the timer is reset
//at the begining of the timing period.  For example the timer could
//be at 32 us and then when we set the counter=0 will get a value of
//counter = 1 but only 32us will have elapsed. 
CRGINT = 128;//set RTIE flag.
counter = 0;
 
}



void Stop_Timer(void){
//turn off timer
RTICTL=0;
CRGINT=0; 
}


long Read_Timer(void){
//returns the current timer value 
long buffer;
buffer = timer_period * counter;
return buffer; 
}



void Delay_us(long delay_time){
Start_Timer();
long Time_2_Delay;
//Time_2_Delay = delay_time*counter;
  while (Time_2_Delay < delay_time){
    Time_2_Delay= delay_time*counter; 
  }
Stop_Timer();
}



volatile static long temp;

void main(void) {
  /* put your own code here */
counter = 0;

i=0;
EnableInterrupts;
Timer_Initialize(64);


//delay
Start_Timer();
//should wait for 3 seconds then turn on the leds with ddrb and portb below.
while ((counter*64) < 3000000){
}


DDRB=0xF0;
PORTB=0x10;

for(;:smileywink: {} /* wait forever */
  /* please make sure that you never leave this function */
}

0 Kudos

575 Views
kef
Specialist I
You forgot to clear RTI flag in your RTI ISR. Add this to your Timer_Interrupt routine.
 
    CRGFLG = 0x80;
You exit from ISR but flag is still set, interrupt is pending, and ISR is called again and again, foreground task is frozen.
0 Kudos