How to Use Interrupts In CW for HCS12

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

How to Use Interrupts In CW for HCS12

Jump to solution
5,715 Views
mouka
Contributor II

I am trying to setup a very simple program that uses interrupts in CW, but I seem to be chasing windmills.

I keep receiving some kind of error or another.

I am absolutely new to CW. I have been using GCC for some time now but wanted to take advantage of code debugging. I installed the serial monitor program and have successfully coded some simple prpograms.

But I got extremely frustrated when I tried using some very simple interrupt programs.

The project I used is extremely simple, it consists of:

main.c => I defined myinterrupt servicer routine here prepended with "interrupt 16", as I am interested in timer overflow interrupts

start_up.c => This is where I have my interrupt vector table, all of it except a couple are unimplemented ISR. I just placed Timer_Ovf_ISR in the prope place.

When I try building my project I get the following error message:

Here are my functions:

First: main.c: Don't wast your time with syntax errors, I couldn't build it. It compiles fine

but I get the following linker error:

 

Link Error: L1119: Vector Allocated at absolute address 0xFFFE overlaps with secions placed in segment .absSeg525

 

// main.c

#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */

int count = 366;
int dummy;

#pragma CODE_SEG __NEAR_SEG NON_BANKED
__interrupt void Timer_Overflow_ISR(void){
  if( count > 0) {
    count--;
  }else {
    count = 266;
    PORTB ^= 0x01;
  }
  dummy = TCNT; 
}
void main(void) {  
    EnableInterrupts;
  for(;:smileywink: {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}


And here's my isr_vectors.c. All I did was copy it from the examples that came with CW and modify it to add my own interrupt.

 

 // isr_vectors.c

extern void near _Startup(void);       /* Startup routine */
extern void near Timer_Overflow_ISR(void);

#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Interrupt section for this module. Placement will be in NON_BANKED area. */
__interrupt void UnimplementedISR(void)
{
   /* Unimplemented ISRs trap.*/
   asm BGND;
}


typedef void (*near tIsrFunc)(void);
const tIsrFunc _vect[] @0xFF80 = {     /* Interrupt table */
        UnimplementedISR,                 /* vector 63 */
        UnimplementedISR,                 /* vector 62 */
        UnimplementedISR,                 /* vector 61 */
        UnimplementedISR,                 /* vector 60 */
        UnimplementedISR,                 /* vector 59 */
        UnimplementedISR,                 /* vector 58 */
        UnimplementedISR,                 /* vector 57 */
        UnimplementedISR,                 /* vector 56 */
        UnimplementedISR,                 /* vector 55 */
        UnimplementedISR,                 /* vector 54 */
        UnimplementedISR,                 /* vector 53 */
        UnimplementedISR,                 /* vector 52 */
        UnimplementedISR,                 /* vector 51 */
        UnimplementedISR,                 /* vector 50 */
        UnimplementedISR,                 /* vector 49 */
        UnimplementedISR,                 /* vector 48 */
        UnimplementedISR,                 /* vector 47 */
        UnimplementedISR,                 /* vector 46 */
        UnimplementedISR,                 /* vector 45 */
        UnimplementedISR,                 /* vector 44 */
        UnimplementedISR,                 /* vector 43 */
        UnimplementedISR,                 /* vector 42 */
        UnimplementedISR,                 /* vector 41 */
        UnimplementedISR,                 /* vector 40 */
        UnimplementedISR,                 /* vector 39 */
        UnimplementedISR,                 /* vector 38 */
        UnimplementedISR,                 /* vector 37 */
        UnimplementedISR,                 /* vector 36 */
        UnimplementedISR,                 /* vector 35 */
        UnimplementedISR,                 /* vector 34 */
        UnimplementedISR,                 /* vector 33 */
        UnimplementedISR,                 /* vector 32 */
        UnimplementedISR,                 /* vector 31 */
        UnimplementedISR,                 /* vector 30 */
        UnimplementedISR,                 /* vector 29 */
        UnimplementedISR,                 /* vector 28 */
        UnimplementedISR,                 /* vector 27 */
        UnimplementedISR,                 /* vector 26 */
        UnimplementedISR,                 /* vector 25 */
        UnimplementedISR,                 /* vector 24 */
        UnimplementedISR,                 /* vector 23 */
        UnimplementedISR,                 /* vector 22 */
        UnimplementedISR,                 /* vector 21 */
        UnimplementedISR,                         /* vector 20 */
        UnimplementedISR,                 /* vector 19 */
        UnimplementedISR,                 /* vector 18 */
        UnimplementedISR,                 /* vector 17 */
        Timer_Overflow_ISR,                 /* vector 16 */
        UnimplementedISR,                 /* vector 15 */
        UnimplementedISR,                 /* vector 14 */
        UnimplementedISR,                 /* vector 13 */
        UnimplementedISR,                 /* vector 12 */
        UnimplementedISR,                 /* vector 11 */
        UnimplementedISR,                 /* vector 10 */
        UnimplementedISR,                 /* vector 09 */
        UnimplementedISR,                 /* vector 08 */
        UnimplementedISR,                          /* vector 07 */
        UnimplementedISR,                 /* vector 06 */
        UnimplementedISR,                 /* vector 05 */
        UnimplementedISR,                 /* vector 04 */
        UnimplementedISR,                 /* vector 03 */
        UnimplementedISR,                 /* vector 02 */
        UnimplementedISR,                 /* vector 01 */
        _Startup                          /* Reset vector */
   };

Labels (1)
Tags (1)
0 Kudos
1 Solution
1,540 Views
mouka
Contributor II

I was able to find out what's wrong with it.

I did fix it, but I still need some information on what the linker map script does and why.

View solution in original post

0 Kudos
10 Replies
1,541 Views
mouka
Contributor II

I was able to find out what's wrong with it.

I did fix it, but I still need some information on what the linker map script does and why.

0 Kudos
1,540 Views
CrasyCat
Specialist III

Hello

 

Do you still need help?

On what? 

 

CrasyCat

0 Kudos
1,540 Views
mouka
Contributor II

I found out that simply by commenting out the line: VECTORS _Startup in the .prm file, everything compiles just fine.

The issue I now have is this: Whenever I use interrupts in my code, something funny happens with the startup code or the reset, main() function is not called.

My only solution to run my code is to use the serial monitor and starting main() manually.

Is there a workaround for this issue?

Thanks in advance.

0 Kudos
1,540 Views
CrasyCat
Specialist III

Hello

 

This should work. I assume there is something wrong in the application.

I would recommend you to submit a service request for that.

Click here to submit a service request.

Make sure to attach a reproducible project and installed product information to the service request.
To generate the required information:
- Start CodeWarrior
- Open the project
- Select "Help" -> "Pack and Go" and follow instructions on the screen.

Attach the generated .zip file to the SR.

 

CrasyCat

0 Kudos
1,540 Views
slarti
Contributor I

I think he runs into the same problem on which I lost two days: the smartlinker will drop the interrupt table as it sees no reference to it. Worse, the IDE will not give you (at least in V4.6 it will not) any way to turn off smart linking, much less for a single file. I resorted to an assembler interrupt table. There are ways to force the linker to not drop the table, but it all looks ugly and doing something clever like a small jump table that lets you trace back to the source of the illegal interrupt (which is impossible with your anonymous vector) will require things that the inline assembler can't do as it is way too restricted to be useful.

 

regards,

Mark

 

0 Kudos
1,540 Views
mouka
Contributor II

Is there a way to deal with this "smart linker" issue?

I am an absolute beginner in CW and haven't had much time to learn its subtleties.

If there's another thread or posts related to this issue, just point me that way.

Thanks

 

0 Kudos
1,540 Views
slarti
Contributor I

You could somehow fake an access to the interrupt table from C code BUT this code must not be identifiable as "dead code", so you should have this code be called from your main() in some way (or better, make the compiler believe that it could be called one day). I think it should suffice to do something like:

 

int foo(void)

{ return 0; }

 

int main(void)

{

   if (foo()) touch_isr_table(); // a dirty hack with a call-interface 8)

}

 

If someone knows a better method, I'm all ears...

 

regards,

Mark

 

0 Kudos
1,540 Views
Lundin
Senior Contributor IV
You have to either use the vectors in the .prm file or your own vector table in C (array of function pointers). In case of the latter, you need to add the array name below ENTRIES in the .prm file, so that the vector table will be linked. Check the code I posted in this recent thread for an example:

http://forums.freescale.com/freescale/board/message?board.id=CW816COMM&thread.id=5880

0 Kudos
1,540 Views
CompilerGuru
NXP Employee
NXP Employee

The linker does link objects with absolute address, therefore using @0xFF?? is sufficient.

If the table is placed with a user defined section then referencing it in the ENTRIES is necessary though.

Another alternative is also the "interrupt 0 void name(void)" syntax, for those the compiler

generates an absolute object at the corresponding address and those are automatically linked, just like user defined @ objects.

 

I would think that placing the array with the @ is the readables solution. Yes it is not plain ANSI-C, but interrupt vectors are inherently architecture specific.

 

Daniel

0 Kudos
1,540 Views
Lundin
Senior Contributor IV
I'd strongly suggest to use ENTRIES in the .prm file and nothing else. I'd also strongly suggest using #pragma TRAP PROC for interrupts instead of the interrupt keyword. Sticking to ISO C as far as possible is always the best choise. It will save you lots of headache when using static code analyzers, if nothing else.
0 Kudos