Got a problem with an external UART connected to XIRQ on a Freescale MC9S12A64 processor...
This interrupt is non-maskable; I cant change it or modify the hardware in any way due to legacy reasons. Also, the UART is connected via a couple of ports emulating an address and data bus. This makes UART register access a non-atomic operation consisting of a number of CPU instructions to set up the address \ data bits and port direction..
Foreground read\write "to the UART" is done by reading \ writing RAM based ring buffers. The XIRQ \ UART interrupt deals with read\ write from the RAM based ring buffers on the other side.
I have reduced the reasons for foreground access to the UART down to just enabling the UART Tx interrupt when data is waiting in a RAM based ring buffer. Unfortunately, this occasionally "collides" with the XIRQ interrupt routine requirement to transfer data between the UART and ring buffers, resulting in data corruption.
I know I cant mask the XIRQ - (I believe I cant even turn it off once turned on). However, if I could get the XIRQ routine to trigger and pick up a flag to indicate "enable UART Tx interrupt", then all hardware accesses would be through the one interrupt routine, removing the problem with non-atomic collision.
Question - is there a way to trigger the XIRQ interrupt routine to run (as an interrupt!) using a code-based \ software access?
For the 68HC11, there is a trick to mask the XIRQ interrupt. It may also work in the 9S12A64 MCU. Not sure though, you would have to try it. The trick is to set the saved CCR[X] flag from within the XIRQ handler and the final RTI will restore to CCR[X]=1. However, this cannot be achieved with a simple TAP instruction. Example assembly language sequence:
bset _CCR_,x,#X. ;Disable further XIRQs
>Question - is there a way to trigger the XIRQ interrupt routine to run (as an interrupt!) using a code-based \ software access?
Assuming your SWI interrupt is not used otherwise, you could move the XIRQ code to the SWI interrupt (callable with the SWI instruction), and simply use a JMP to the SWI handler from within the XIRQ handler. This way it can be called manually, and automatically, as needed.
Hi Tony, thanks for your input.
If I'm reading your asm correctly, we first get the stack pointer into x; then do an indexed "bit set" of the top of stack, which should be the CCR which is going to be pulled by the following rti...?
I wonder if simply pushing the CCR, setting the bit and then pulling it again would provide a way of masking the XIRQ without having to perform an rti (and therefore be in an int rtn in the first place..)? Ie,
I will be returning to this part of the project next week and hopefully I can try it out and offer some feedback....
Next time I'll just use the IRQ...!