Disabling interrupts during an interrupt

bbc micro/electron/atom/risc os coding queries and routines
Post Reply
User avatar
archie456
Posts: 132
Joined: Sat Sep 07, 2019 4:22 pm
Location: Chelmsford
Contact:

Disabling interrupts during an interrupt

Post by archie456 »

Hi,

As part of the ongoing quest to write some sort of Citadel like game, I have some code which builds a room from sprites, and then a character plotted by interrupt which can move around it, pick up objects, clash against things and move from room to room.

This works fine, but I've noticed an issue whereby the character will suddenly jump for no reason - this is because the keyboard checking routine is picking up the jump key has been pressed.

I modified the routines to display via ORWRCH the keypresses on screen and indeed one of the five keyboard keys that I use is being pressed occasionally - this seems to happen at random times mostly around a minute and sometimes a few seconds.

The keyboard checks for keypresses OSBYTE &81:

Code: Select all

    LDY #&FF            ; Perform keyboard scan
    LDA #&81            ; Select OSBYTE &81
    JSR osbyte          ; Call OSBYTE to check keyboard
    CPX #0
    BEQ keynotpressed
    LDA keycollector
    ORA #1
    STA keycollector
I suspected it was the interrupt character plotter corrupting something, the interrupt checks for Vsync and determines when to plot.

Indeed, if I remove the interrupt plotter, the keypresses don't happen.

When the interrupt sprite plotter is called I immediately disable interrupts to plot the character and reenable them when plotting is finished, I've found that if I remove the interrupt disable from this code, the random keypresses don't appear to happen.

I thought it a good idea to disable interrupts when the interrupt character plotter runs... but perhaps it isn't - maybe this has something to do with the keypresses.

I also disable interrupts when drawing a new room - this stops the character being plotted during the drawing process - this seems to work fine.

Can I get some advise on this, does it matter whether interrupts are disabled or enabled during an interrupt?

(I'm not sure why disabling interrupts during an interrupt causes the keypresses - maybe the keypresses are nothing to do with the interrupt...?)

Thanks.
User avatar
tricky
Posts: 6280
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Disabling interrupts during an interrupt

Post by tricky »

When an interrupt happens, further interrupts are disabled as of a SEI had executed and the she the RTI executes, the old processor status flags are restored and interrupts can happen again.
Some of maybe all OS routines have a warning that they may enable interrupts.
If you are allowing an interrupt within an interrupt, you need to make them renterent by pushing A and pulling it again and storing it at &FC where the OS stored it before calling the interrupt. If you aren't continuing with the OS chain then you can do it differently.
I would read the keys manually as it is faster and hopefully means that you won't be allowing interrupts within yours.
User avatar
archie456
Posts: 132
Joined: Sat Sep 07, 2019 4:22 pm
Location: Chelmsford
Contact:

Re: Disabling interrupts during an interrupt

Post by archie456 »

When you say 'read keys manually' do you mean this process:

viewtopic.php?f=4&t=22271&p=316767&hili ... rd#p316767

Thanks.
User avatar
arg
Posts: 701
Joined: Tue Feb 16, 2021 2:07 pm
Location: Cambridge
Contact:

Re: Disabling interrupts during an interrupt

Post by arg »

archie456 wrote:
Tue May 10, 2022 10:31 pm
Can I get some advise on this, does it matter whether interrupts are disabled or enabled during an interrupt?
As Tricky mentioned, if you are entered directly from an interrupt then interrupts have already been disabled for you (by hardware), and will automatically be re-enabled afterwards (by the RTI instruction). In principle, you can re-enable interrupts within an interrupt handler - at the cost of making the worst-case stack usage much bigger, and the risk of your own code being re-entered which it must therefore cope with.

However, you almost certainly aren't being directly called from the interrupt and instead are hooking some OS facility such that OS code runs before and after yours in what hardware views as the complete IRQ handler. Probably interrupts are still disabled when your code runs, since the OS doesn't generally re-enable them in its own interrupt handling, and it is entitled to assume that they are still disabled after calling your code.

If you have code that wants to be sure interrupts are disabled but don't know if they already are, then you MUST write it as:

Code: Select all

PHP
SEI
... code guaranteed not to be interrupted
PLP
and never:

Code: Select all

SEI
... code
CLI
because, if you were entered with interrupts already disabled, then you have left them enabled on exit. In your case, being called from the OS, you are now returning into the OS with interrupt enabled which it is not expecting and can cause its datastructures to get corrupted since it will make updates assuming it can't be interrupted when that assumption is false.

The PHP;SEI;PLP version is always safe to use anytime, but the SEI;CLI version is only safe to use if you are certain that interrupts are already enabled - ie. in main program foreground code, but not on anything called via an OS vector.
User avatar
archie456
Posts: 132
Joined: Sat Sep 07, 2019 4:22 pm
Location: Chelmsford
Contact:

Re: Disabling interrupts during an interrupt

Post by archie456 »

Excellent arg, that's a really useful explanation... enabling interrupts at the end of my interrupt code looks to be exactly what I've been doing wrong.

Thanks for your help!
User avatar
tricky
Posts: 6280
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Disabling interrupts during an interrupt

Post by tricky »

Reading keys "manually" means (to me) set the slow data bus to read the top but and write the rest, write a key value and get the to bit too see if it was pressed, repeat for each key.

I want suggesting that the OS would call your routine with interrupts enabled, but that if you called call OS routines from within your interrupt handler that they may be temporarily enabled inside that routine.
Post Reply

Return to “programming”