Interrupts

Started by Allen, Nick November 6, 2002
Hello All--
this is my first time transmitting to this group.
I'm trying to get CAN interrupts working on HC12BC32
using ImageCraft ICC12

I've added these to vectors.c
#pragma interrupt_handler CAN_RX_int
extern void CAN_RX_int(void);

I've extended the vector table:
#pragma abs_address:0xffc4
void (*interrupt_vectors[])(void) =
{
DUMMY_ENTRY, //CAN transmit ffc4
CAN_RX_int, //CAN receive ffc6
DUMMY_ENTRY, //CAN error ffc8
DUMMY_ENTRY, //reserved ffca
DUMMY_ENTRY, //reserved ffcc
DUMMY_ENTRY, //reserved ffce
DUMMY_ENTRY, /* BDLC */ /* Key Wakeup J */
etc.......

I've enabled receive interrupt:
CRIER=0x1;
INTCR=0xe0; I suspect isn't applicable

Is this the only way to clear the I bit in the CCR?
asm ("TAP\n"
"ANDA #$ef\n"
"TAP\n");

and a dummey interrupt routine:
void CAN_RX_int(void)
{
printf("Received an interrupt!\n");
} No work-----what am I missing??

Nick Allen




In a message dated 11/22/03 4:20:20 PM Eastern Standard Time,
writes:
I'm having diffuculties differentiating between Interrupts and subroutines.
I understand how to program an interrupt (more or less) but I'm not quiet sure
how to activate it. How can I use my interrupt once I've set it into the the
vector table???
=========================================
You 'call' a subroutine... it saves the return address on the stack. A
subroutine ends in a 'ret' and pops the return address off the stack and resumes
execution there. Anything you do more than once could probably be put in a
subroutine. The interrupt can get invoked in between any two assembler instructions,
so it needs to push and pop all the registers it uses as well as save the
return address. Interrupt handlers end in 'reti'. The hardware timers and
interrupt flags invoke the interrupts.


Subroutines are called by the normal stream of software execution. A return
address (address of the instruction following the BSR/JSR/CALL instruction)
is saved on the stack, and the subroutine returns to the calling sequence
via an RTS instruction. Tasks which are needed in multiple places in a
program are normally coded as subroutines, reducing the volume of the inline
code but costing the call/return instruction overhead.

Interrupts are a hardware function (except for SWI...) whereby some element
of the CPU hardware (timer, serial I/O, A/D, external IRQ hardware input,
etc.) can request immediate attention. An interrupt occurs between two
sequential machine instructions. All processor status (return address,
condition codes, any registers used in the interrupt service routine [ISR])
must be saved either by the hardware or by the first few instructions of the
ISR. The ISR will take care of the hardware necessities and return to the
background code via an RTI instruction.

...make any more sense?

/s/jar ()
http://www.mtritter.org
Bausch & Lomb
150 Years of Perfecting Vision, Enhancing Life
EMAIL DISCLAIMER

Please Note: The information contained in this message may be privileged and
confidential, protected from disclosure, and/or intended only for the use of
the individual or entity named above. If the reader of this message is not
the intended recipient, or an employee or agent responsible for delivering
this message to the intended recipient, you are hereby notified that any
disclosure, distribution, copying or other dissemination of this
communication is strictly prohibited. If you received this communication in
error, please immediately reply to the sender, delete the message and
destroy all copies of it.

Thank You


Thanks for all the feedback,

Its becomming a little more clear to me, but the one thing that I have not understood is how to invoke these interrupts. What if I create my own interrupt in which case I would use the "setuservector" subroutine, would it be activated when the flag is set? I'm also having difficulties understanding which flags are used here. When are TCx's used, and in the vector table why would I use address 19 for my created isr for example. I know that I may not have any logical pattern in my questions but this is how all this information appears to me.

thanks again
joe

Sydney Faria <> wrote:
the vector table associates a predetermined address (the vector) with a
"function name", when the interrupt is generated the table goes to the
associated vector address and sees the "function name" and calls that
function. That function is the interrupt and has to end with rti and not
rts since an interrupt stores many items on the stack to return back to the
machine state before the int was initiated. If you are having problems with
this sort of concept I highly recommend Han-way Huang's book on the 68HC12
microcontroller as he covers these issues very well along with many other
concepts that you will need. It has much assembler and c code to show his
examples. It is published by Delmar but I got a second hand copy for $35
when I started 68HC12 assembly programming and still consider it the best of
the 6 books that I bought!! SCF
----- Original Message -----
From:
To:
Sent: Saturday, November 22, 2003 5:56 PM
Subject: Re: [68HC12] Interrupts In a message dated 11/22/03 4:20:20 PM Eastern Standard Time,
writes:
I'm having diffuculties differentiating between Interrupts and
subroutines.
I understand how to program an interrupt (more or less) but I'm not quiet
sure
how to activate it. How can I use my interrupt once I've set it into the
the
vector table???
=========================================
You 'call' a subroutine... it saves the return address on the stack. A
subroutine ends in a 'ret' and pops the return address off the stack and
resumes
execution there. Anything you do more than once could probably be put in a
subroutine. The interrupt can get invoked in between any two assembler
instructions,
so it needs to push and pop all the registers it uses as well as save the
return address. Interrupt handlers end in 'reti'. The hardware timers and
interrupt flags invoke the interrupts.

-------------------- --------------------

---------------------------------
Post your free ad now! Yahoo! Canada Personals



the vector table associates a predetermined address (the vector) with a
"function name", when the interrupt is generated the table goes to the
associated vector address and sees the "function name" and calls that
function. That function is the interrupt and has to end with rti and not
rts since an interrupt stores many items on the stack to return back to the
machine state before the int was initiated. If you are having problems with
this sort of concept I highly recommend Han-way Huang's book on the 68HC12
microcontroller as he covers these issues very well along with many other
concepts that you will need. It has much assembler and c code to show his
examples. It is published by Delmar but I got a second hand copy for $35
when I started 68HC12 assembly programming and still consider it the best of
the 6 books that I bought!! SCF
----- Original Message -----
From:
To:
Sent: Saturday, November 22, 2003 5:56 PM
Subject: Re: [68HC12] Interrupts In a message dated 11/22/03 4:20:20 PM Eastern Standard Time,
writes:
I'm having diffuculties differentiating between Interrupts and
subroutines.
I understand how to program an interrupt (more or less) but I'm not quiet
sure
how to activate it. How can I use my interrupt once I've set it into the
the
vector table???
=========================================
You 'call' a subroutine... it saves the return address on the stack. A
subroutine ends in a 'ret' and pops the return address off the stack and
resumes
execution there. Anything you do more than once could probably be put in a
subroutine. The interrupt can get invoked in between any two assembler
instructions,
so it needs to push and pop all the registers it uses as well as save the
return address. Interrupt handlers end in 'reti'. The hardware timers and
interrupt flags invoke the interrupts.

--------------------



One more comment on this subject: once you have defined the interrupt
routine, you do not call it! That is all done for you in the background and
depends on the type of interrupt that you have programmed. I have a CAN
module with 5 different interrupts - one for receive a CAN message, one for
transmitting a CAN message etc. When I set up a message frame in memory and
then want to transmit the message frame all I do is set a flag in one of the
CAN registers - the interrupt will be generated for me by the CAN module and
the transmit int routine will be called. likewise, when a CAN message is
received, the CAN module generates the appropriate int for me and the
receive int routine is called.
You could also set up a timer that works off an int or maybe you could
use an input or output line to generate an int signal as when you sense a
key wake up, an event coming through a port, or an output compare. Again,
I suggest example code is easier to understand so again I recommend
Professor Han-way 68HC12 assembly book published by Delmar. SCF
----- Original Message -----
From: Joseph
To:
Sent: Saturday, November 22, 2003 3:54 PM
Subject: [68HC12] Interrupts
I'm having diffuculties differentiating between Interrupts and
subroutines. I understand how to program an interrupt (more or less) but
I'm not quiet sure how to activate it. How can I use my interrupt once I've
set it into the the vector table???

joe
---------------------------------
Post your free ad now! Yahoo! Canada Personals

--------------------



these ideas mentionned are very helpful although I'm a little unclear on the term "message" used.

>>You could also set up a timer that works off an int or maybe you could
use an input or output line to generate an int signal as when you sense a
key wake up, an event coming through a port, or an output compare.

I have been using the 68HC12 and I believe that I have set up an input line generating an int signal, but the problem is I have encountered until now is that the interrupt is invoked on a high when I am using:

brclr PORTA,$01,* ; check pin 0 of port A
How do pull up registers play a role here...I have disabled them in case

joe (file attached)

Sydney Faria <> wrote:
One more comment on this subject: once you have defined the interrupt
routine, you do not call it! That is all done for you in the background and
depends on the type of interrupt that you have programmed. I have a CAN
module with 5 different interrupts - one for receive a CAN message, one for
transmitting a CAN message etc. When I set up a message frame in memory and
then want to transmit the message frame all I do is set a flag in one of the
CAN registers - the interrupt will be generated for me by the CAN module and
the transmit int routine will be called. likewise, when a CAN message is
received, the CAN module generates the appropriate int for me and the
receive int routine is called.
You could also set up a timer that works off an int or maybe you could
use an input or output line to generate an int signal as when you sense a
key wake up, an event coming through a port, or an output compare. Again,
I suggest example code is easier to understand so again I recommend
Professor Han-way 68HC12 assembly book published by Delmar. SCF
----- Original Message -----
From: Joseph
To:
Sent: Saturday, November 22, 2003 3:54 PM
Subject: [68HC12] Interrupts
I'm having diffuculties differentiating between Interrupts and
subroutines. I understand how to program an interrupt (more or less) but
I'm not quiet sure how to activate it. How can I use my interrupt once I've
set it into the the vector table???

joe
---------------------------------
Post your free ad now! Yahoo! Canada Personals

-------------------- -------------------- ---------------------------------
Post your free ad now! Yahoo! Canada Personals

----------

;Intctr: equ $001E
;Irqe: equ %10000000
;Irqnum: equ $19
;SetUserVector: equ $F69A
;#include "C:\Program Files\MGTEK\MiniIDE\HC12.inc"
printf equ $F686
PORTA equ $00
DDRA equ $01
CR equ $0D
LF equ $0A

;SetUserVector Subroutine ;Stack equ $0A00

; Main prog
org $0800
;movb #$00,PORTA
movb $00,DDRA

;lds #Stack
;Ldd #myISR
;pshd
;ldd #irqnum
;ldx SetUserVector
;jsr 0,x
;puld ;clean up stack ldd #msg_wait
jsr [printf,PCR]
here nop
brclr PORTA,#$01,here ; check pin 0 of port A
ldd #msg_count
jsr [printf,PCR]
swi msg_wait db "Waiting for P0 to be 1 !",CR,LF,0
msg_count db "Beginning Countdown",CR,LF,0
count db "987654321"

end



I don't remember all the vector address definitions. Go to the motorola
developer site and get a copy of the documentation and search for vector
table or interrupts to see the complete listing of the interrupt table. TCx
refers to the predetermined set of timer interrupts, timer channel 0 - 7,
timer overflow, pulse accumulator overflow and PA edge. That's just the
timer module! you also have IRQ and XIRQ, reset of course, SPI, SCIO, ATD,
KWI, MSCAN etc. Check out http://www.ece.utexas.edu/~valvano/
where you will find some very interesting stuff, including C code.
While we are on the subject, there are other methods of processing
interrupts, and the 68HC122 is just one way.
BTW, since you mentioned SetUserVector(), I would assume that you are
familiar with what D-Bug 12 is since you are trying to call a D-Bug 12
routine but just to remind you if you do not know what I am talking about,
D-Bug 12 is a monitor program installed in memory and SetUserVector() is
just one of the C funcions that you can call in this monitor program. If
you really want to understand the interrupt mechanism, I would suggest not
using this! you can go to a place like valvano's site or www.axiom.com and
choose which microprocessor, A4, B32, D60 etc, to download a simple hello
world type of assembly code to inspect. The code file will have a nice
DEFINE file for the definition you will always use for the particular
microcontroller and there will also be a vector DEFINE file for your use.
If you haven't done so, do go to Motorola.com and download a copy of the
reference manual. You might also want to check out all the AN's
(application notes) as they have many examples of code that are very good
although there might be some typos. They had one on computed GOTOs that
really helped me a while back. Some of these ANs are about using the D-Bug
12 monitor program!
Sydney
----- Original Message -----
From: Joseph
To:
Sent: Sunday, November 23, 2003 10:16 AM
Subject: Re: [68HC12] Interrupts Thanks for all the feedback,

Its becomming a little more clear to me, but the one thing that I have not
understood is how to invoke these interrupts. What if I create my own
interrupt in which case I would use the "setuservector" subroutine, would it
be activated when the flag is set? I'm also having difficulties
understanding which flags are used here. When are TCx's used, and in the
vector table why would I use address 19 for my created isr for example. I
know that I may not have any logical pattern in my questions but this is how
all this information appears to me.

thanks again
joe

Sydney Faria <> wrote:
the vector table associates a predetermined address (the vector) with a
"function name", when the interrupt is generated the table goes to the
associated vector address and sees the "function name" and calls that
function. That function is the interrupt and has to end with rti and not
rts since an interrupt stores many items on the stack to return back to
the
machine state before the int was initiated. If you are having problems
with
this sort of concept I highly recommend Han-way Huang's book on the 68HC12
microcontroller as he covers these issues very well along with many other
concepts that you will need. It has much assembler and c code to show his
examples. It is published by Delmar but I got a second hand copy for $35
when I started 68HC12 assembly programming and still consider it the best
of
the 6 books that I bought!! SCF
----- Original Message -----
From:
To:
Sent: Saturday, November 22, 2003 5:56 PM
Subject: Re: [68HC12] Interrupts In a message dated 11/22/03 4:20:20 PM Eastern Standard Time,
writes:
I'm having diffuculties differentiating between Interrupts and
subroutines.
I understand how to program an interrupt (more or less) but I'm not
quiet
sure
how to activate it. How can I use my interrupt once I've set it into
the
the
vector table???
=========================================
You 'call' a subroutine... it saves the return address on the stack. A
subroutine ends in a 'ret' and pops the return address off the stack and
resumes
execution there. Anything you do more than once could probably be put in
a
subroutine. The interrupt can get invoked in between any two assembler
instructions,
so it needs to push and pop all the registers it uses as well as save
the
return address. Interrupt handlers end in 'reti'. The hardware timers
and
interrupt flags invoke the interrupts.

-------------------- --------------------

---------------------------------
Post your free ad now! Yahoo! Canada Personals

--------------------


I am using message in the context of a CAN message frame which is sent via a
CAN Tx flag to enable the CAN Tx int. It was just one of the types of ints
that I was referring to. I will look again at your code this evening, but at
first glance I see you are using what is called a polling method: here
nop
brclr PORTA,#$01,here
which can be written in shorthand as brclr portA, #$01 *
The other way to do this is have the port itself be configured to sense the
change and generate an interrupt for you to process. That saves CPU wasted
cycles that in inherent in the polling method. Heres an example in assembly
and in C from Huang's book
Sydney
----- Original Message -----
From: Joseph
To:
Sent: Sunday, November 23, 2003 10:32 AM
Subject: Re: [68HC12] Interrupts these ideas mentionned are very helpful although I'm a little unclear on
the term "message" used.

>>You could also set up a timer that works off an int or maybe you could
use an input or output line to generate an int signal as when you sense a
key wake up, an event coming through a port, or an output compare.

I have been using the 68HC12 and I believe that I have set up an input
line generating an int signal, but the problem is I have encountered until
now is that the interrupt is invoked on a high when I am using:

brclr PORTA,$01,* ; check pin 0 of port A
How do pull up registers play a role here...I have disabled them in case

joe (file attached)

Sydney Faria <> wrote:
One more comment on this subject: once you have defined the interrupt
routine, you do not call it! That is all done for you in the background
and
depends on the type of interrupt that you have programmed. I have a CAN
module with 5 different interrupts - one for receive a CAN message, one
for
transmitting a CAN message etc. When I set up a message frame in memory
and
then want to transmit the message frame all I do is set a flag in one of
the
CAN registers - the interrupt will be generated for me by the CAN module
and
the transmit int routine will be called. likewise, when a CAN message is
received, the CAN module generates the appropriate int for me and the
receive int routine is called.
You could also set up a timer that works off an int or maybe you could
use an input or output line to generate an int signal as when you sense a
key wake up, an event coming through a port, or an output compare.
Again,
I suggest example code is easier to understand so again I recommend
Professor Han-way 68HC12 assembly book published by Delmar. SCF
----- Original Message -----
From: Joseph
To:
Sent: Saturday, November 22, 2003 3:54 PM
Subject: [68HC12] Interrupts
I'm having diffuculties differentiating between Interrupts and
subroutines. I understand how to program an interrupt (more or less) but
I'm not quiet sure how to activate it. How can I use my interrupt once
I've
set it into the the vector table???

joe
---------------------------------
Post your free ad now! Yahoo! Canada Personals

-------------------- -------------------- ---------------------------------
Post your free ad now! Yahoo! Canada Personals

----------

;Intctr: equ $001E
;Irqe: equ %10000000
;Irqnum: equ $19
;SetUserVector: equ $F69A
;#include "C:\Program Files\MGTEK\MiniIDE\HC12.inc"
printf equ $F686
PORTA equ $00
DDRA equ $01
CR equ $0D
LF equ $0A

;SetUserVector Subroutine ;Stack equ $0A00

; Main prog
org $0800
;movb #$00,PORTA
movb $00,DDRA

;lds #Stack
;Ldd #myISR
;pshd
;ldd #irqnum
;ldx SetUserVector
;jsr 0,x
;puld ;clean up stack ldd #msg_wait
jsr [printf,PCR]
here nop
brclr PORTA,#$01,here ; check pin 0 of port A
ldd #msg_count
jsr [printf,PCR]
swi msg_wait db "Waiting for P0 to be 1 !",CR,LF,0
msg_count db "Beginning Countdown",CR,LF,0
count db "987654321"

end

Yahoo! Groups Sponsor
--------------------



--- In , Joseph <el_kora11@y...> wrote:

> Thanks for all the feedback,
>
> Its becomming a little more clear to me, but the one thing that I have not understood is how to invoke these interrupts. What if I create my own interrupt in which case I would use the "setuservector" subroutine, would it be activated when the flag is set? I'm also having difficulties understanding which flags are used here. When are TCx's used, and in the vector table why would I use address 19 for my created isr for example. I know that I may not have any logical pattern in my questions but this is how all this information appears to me.

Hi Joe,

It seems you missed the previous explanations.
With one exception Interrupts are hardware functions.

A common one is say receiving chars from a terminal connected to a serial port.

The procedure to do this is to first to set up the ports the way you want it, i.e RTFM and identify the registers associated with the spcific hardware.

The control register(s) allow you to specify say desired Baud rates and if you do want to have interrupts or not and of course there is also a register where the character comes in.

Having chosen interrupts by setting the relavant bit in the register, as soon as say a character is received in the ports buffer, the hardware invokes the interrupt.

That means the processor put all its registers into Ram at the current Stack location and fetches the interrupt vector associated with, in this case, the serial receive port, it then continues its operation at the Vector address you specified.

Of course it expects to find your input routine there, say to get the character out of the port and save it somewhere, normally in an input buffer.

When you are done doing that, you end your routine with an RTI, the processor retrieves all its registers from Ram and continues from where it got interrupted.

You see the effect of this, as far as the main program is concerned, it doesn't have to check continuously if any characters are received, as far as "it" is concerned they magically appear in an input buffer.

That also means if it is busy doing something else, no input characters are lost.

One of the things to watch is not to have more interrupts then you have time to service, you get a condition where they keep piling on the stack, you will find this easily happens say when you try to service a couple of 100.000 interrupts/sec say from a pulse generator.

Oh, yeah, also be sure the RTI finds the same stack as it left behind...

Hope this helps, now buy the book:-) Cheers, Theo