Re: [cc65] Interrupts howto?

From: Ullrich von Bassewitz <uz1musoftware.de>
Date: 2005-05-04 10:35:59
Hi!

On Tue, May 03, 2005 at 12:31:31PM +0300, Karri Kaksonen wrote:
> I have tried to understand how callirq and condes should go together
> but it would be really helpful to get a small description of how I should
> do this.

The semantics of callirq are currently changing, and unfortunately things are
not as finished as I said in my last mail regarding this topic. I will leave
again for a few days tomorrow, so not much will happen before next week.

> If I understand correctly I can use CONDES to put my addresses into
> the _irqvecs table during the linking phase somehow.

You can use either .condes or .interruptor to export symbols that the linker
will arrange into a table, if told so by a CONDES directive in the linker
script. As with constructors and destructors, interruptors can have a priority
between 1 and 31. By default, the linker will sort these routines in order of
increasing priority.

The callirq routine walks over the table, starting from the last(!) entry, and
calls each function in the table as a normal subroutine. This means that
functions with higher numerical priority are called first. Each function must
return with the carry flag set if the interrupt was handled (which means that
it managed somehow to quieten the interrupt source), or carry clear if this is
not the case. callirq will stop calling interruptors with the first routine
that returns with carry set (assuming that the cause of the interrupt has
vanished). callirq itself will the return carry set/clear depending on the
last routine called. Note: this differs from the way, constructors and
destructors work!

The second part of interrupt handling is in calling callirq: Usually the
interrupt vector is hooked in the startup code, provided that the interruptor
table is not empty. The interrupt stub must save the CPU registers, call
callirq and (if necessary) return the "handled" flag somehow. This latter part
is platform highly dependent.

Using interruptors solves a few problems:

  * "Installing" an interrupt handler is easy - just declare it as
    .interruptor, and it is called when an interrupt occurs as soon as the
    startup code is run.

  * Interrupt handlers don't need to save any registers and can return with
    RTS as a normal subroutine.

  * If interrupt handlers are installed the "usual" way, the will hook the
    interrupt vector, saving its old value. This means that the handlers must
    be deinstalled in reverse order. If this does not happen, the machine will
    usually crash. This is a severe problem with loadable drivers that is
    solved by interruptors.

Drawbacks:

  * An interruptor is always called as long as the program runs. There is 
    no way to install it for some time and then deinstall it.

  * Since interrupt latency is unknown, highly time critical interrupt
    handlers are a problem.

Regards


        Uz


-- 
Ullrich von Bassewitz                                  uz@musoftware.de
----------------------------------------------------------------------
To unsubscribe from the list send mail to majordomo@musoftware.de with
the string "unsubscribe cc65" in the body(!) of the mail.
Received on Wed May 4 10:36:07 2005

This archive was generated by hypermail 2.1.8 : 2005-05-04 10:36:09 CEST