05 November 2018, 23:13 | #1 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
|
Spurious PORTS irq
While I was writing some code using CIA registers I came across a strange behaviour that I can not understand.
All tests done in WinUAE, latest version, bare Quickstart A500 configuration or A1200 configuration. I was undecided whether to write in support.WinUAE thread or in the Coders.Asm/Hardware section. I have finally decided to post here because maybe something obvious escapes me. I have written only the minimum parts that reproduce the problem, in the simplest way: a bare keyboard handler. This code generates spurious PORTS irq and I can not quite understand why: Code:
progstart lea $dff000,a6 lea $bfed01,a5 move.w #$7fff,($9a,a6) move.b #$7f,(a5) move.b #$89,(a5) ;SP+TA ; move.b #$8f,(a5) lea (.i2,pc),a0 move.l a0,($68).w move.w #$c008,($9a,a6) ;PORTS .la cmpi.w #$9007,($6,a6) ;keyboard raw code blo.b .la ;as colors on screen move.b (key,pc),d0 move.w d0,$180(a6) .lb cmpi.w #$0101,($6,a6) bhs.b .lb bra.b .la ;PORTS irq handler .i2 movem.l d0/a0/a1,-(SP) lea ($bfe001),a0 lea ($dff09c),a1 move.b ($d00,a0),d0 ;read IRQ source and clear btst #3,D0 ;serial (keyboard) bne.b .ik tst.b d0 ;is there really a CIA IRQ? bne.b .ix ;if==0 spurious PORTS irq .ic move.w ($6-$9c,a1),($180-$9c,a1) ;rainbow bra.b .ic .ik move.b ($c00,a0),d0 ;read raw key move.b #$48,($e00,a0) ;SPMODE=output, RUNMODE=one-shot move.b #$8E,($400,a0) ;setup ~200us delay clr.b ($500,a0) ;start timer A not.b d0 ror.b #1,d0 .il btst #0,($d00,a0) ;check if time passed beq.b .il ;and cleans IRQ ; tst.b ($d00,a0) ;* 1) ; tst.b ($d00,a0) ;* 2) clr.b ($e00,a0) ;SPMODE=input, ACK keyboard ; tst.b ($d00,a0) ;* 3) lea (key,pc),a0 move.b d0,(a0) ;store raw key .ix moveq #8,D0 move.w d0,(a1) ;cleans PORTS irq move.w d0,(a1) movem.l (sp)+,d0/a0/a1 rte key ds.b 1 pad ds.b 1 To have a working code on A500 you've to add the commented out line [* 1)], otherwise the code generates unwanted IRQs. For machines from the A1200 and up you must also add line [* 2)] or alternatively a solo line [* 3)] (with cache deactivated it's sufficient [* 1)], like A500). Attached two binary versions: the pure one (without added lines) [kbs.0] and the one with additional line [* 1)] [kbs.1]. I would be grateful to those who could try on real machines or who could help me to understand the reason for this behavior. In fact are not a problem the strange IRQs generated, it's just enough ignore them by cleaning up INTREQ(PORTS), but I would like to understand.. EDIT: removed attached files Last edited by ross; 07 November 2018 at 13:04. |
06 November 2018, 11:04 | #2 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,411
|
A silly question perhaps, but could it be that timer A is already running (through the OS for instance) when you start the program and enable it as a source for interrupts?
If I'm reading the code correctly, I don't see you disable the timer prior to setting/checking it later in the interrupt handler. |
06 November 2018, 12:25 | #3 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
|
Your question is relevant and you're right, at first I don't touch Timer A counter.
But there is a simple reason: seems that it's not used by the system, at least not at boot and I assumed that the program was launched at boot. Sorry if I did not add that to the description. At program start, if you wait, no interrupts are triggered, a confirmation that TA is unused (in code I've left active only SP and TA). When a key is pressed IRQ2 is triggered (SP source), then inside the handler I make a delay of 200us (using timer A) for the ACK. This delay triggers an IRQ but is cleared by the very same check. I could have avoided from the beginning a TA IRQ generation (not enabling it), but the point is precisely this peculiarity, which makes the spurious IRQ happens. When I release the key, an IRQ is triggered again, again due to SP: it's after this that most of the time the spurious IRQ is generated. Despite ICR being cleaned up, for some reason an IRQ2 immediately retrigger and this time the source is apparently not the CIA! You can see it because ICR on handler entrance is zeroed.. It's a possible situation if you have external devices (HDD controller, USB controller, also CD32 generates it) but I can not understand how an A500 generate it. Furthermore, the fact that adding a fictitious ICR cleanup to not incur in this situation seems strange to me, as if there were delays in the propagation of the signals. It may be that a real machine behaves like that, but it's odd, I do not know why and it's not documented. I would like to have a confirmation Thanks for your time! Last edited by ross; 06 November 2018 at 13:19. Reason: maybe a better english.. maybe.. |
06 November 2018, 14:51 | #4 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,411
|
Well, I can't really see any other issues - apart from one that seems far fetched to me. The code looks like it should work and resembles other keyboard handling code I've seen.
The only thing that might (emphasis on might) cause some issues on the A500 version is your use of the clr command. On a plain 68000 that does both a read and a write instead of just writing a zero, which might cause issues because the CIA register you clr.b is write-only AFAIK and thus should not be read from. However, the 68020 should've fixed that issue so the A1200 version ought to be OK then. |
06 November 2018, 14:54 | #5 |
Registered User
Join Date: Sep 2015
Location: Germany
Posts: 260
|
Hi ross, I saw your code and there are two things that I noticed and I got a little hint:
Code:
move.b #$48,($e00,a0) ;SPMODE=output, RUNMODE=one-shot move.b #$8E,($400,a0) ;setup ~200us delay clr.b ($500,a0) ;start timer A Code:
moveq #$48,d1 move.b d1,($e00,a0) ;SPMODE=output, RUNMODE=one-shot moveq #$-$72,d1 ;Same as $8e, but compatible to moveq command move.b d1,($400,a0) ;setup ~200us delay moveq #0,d1 move.b d1,($500,a0) ;start timer A Code:
.ix moveq #8,D0 move.w d0,(a1) ;cleans PORTS irq move.w d0,(a1) movem.l (sp)+,d0/a0/a1 rte Code:
.ix moveq #8,D0 move.w d0,(a1) ;cleans PORTS irq movem.l (sp)+,d0/a0/a1 nop rte |
06 November 2018, 15:00 | #6 | ||
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,411
|
Quote:
So while still an interesting point, a better phrase would've been "so you have the guarantee your code is executed serial in order on a 68060". No other 68k chip has a superscalar/out of order design (perhaps the Vampire does though, I don't really know anything about that chip). Quote:
Edit: or is your point purely only about a performance gain? Last edited by roondar; 06 November 2018 at 15:17. |
||
06 November 2018, 16:28 | #7 | ||||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
|
Quote:
Quote:
It is only some quick code to bring out the problem Quote:
[I'm too used to patch old code where I simply disable superscalar bit in PCR register ] Quote:
The problem in this case is that the code is executed too quickly and access to a custom register (any) slows down enough before the RTE. Is there a guarantee that the nop will do it too? (mmh, it sync the pipelines, maybe suffice in evey case.. well, the double access certainly works ) |
||||
06 November 2018, 16:30 | #8 | ||
Registered User
Join Date: Sep 2015
Location: Germany
Posts: 260
|
Quote:
Quote:
Maybe an explanation from Motorola's User Manual of what the nop command on the 68020 does makes it clearer: "The NOP instruction forces instruction and bus synchronisation by freezing instruction execution until all pending bus cycles have completed." Or for the 68060: "The following instructions perform this pipeline synchronization: ... nop..." or "... NOPs between instructions to guarantee serialization of reads and writes to I/O devices." |
||
06 November 2018, 16:37 | #9 | |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,411
|
Quote:
|
|
06 November 2018, 16:45 | #10 | |
Registered User
Join Date: Sep 2015
Location: Germany
Posts: 260
|
Quote:
|
|
06 November 2018, 16:53 | #11 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,516
|
This is getting far too off topic but in my opinion NOP is wrong and only accidental fix. Problem is Paula being slow, it needs one more CCK after INTREQ/INTENA write before it changes IPL lines (if RTE finishes during that extra CCK, CPU still sees old interrupt active and it can happen if all the stacked data is in caches). There is no guarantee NOP is slow enough (it probably is but no guarantee), only extra chip bus access guarantees it.
(and next I'll debug the actual problem..) |
06 November 2018, 17:06 | #12 | |||
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,411
|
Quote:
Quote:
Quote:
Not knowing a specific bit of info about a single 68000 opcode that is only valid for 68020+ doesn't change this*. For instance, the double move.w to acknowledge interrupts prior to RTE accomplishes the exact same thing as what you're using the extra NOP for: it prevents double interrupts on 68060/A4000. In fact, the double acknowledgement is only used to achieve just that - compatibility with the 68060/A4000. *) note that there are indeed things you do need to know, such as the VBR register and how caches can affect your code. Last edited by roondar; 06 November 2018 at 17:25. |
|||
06 November 2018, 17:09 | #13 | |
Registered User
Join Date: Sep 2015
Location: Germany
Posts: 260
|
Quote:
Code:
move.w #xxxx,INTREQ(An) nop rte |
|
06 November 2018, 17:17 | #14 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,516
|
Reading CIA interrupt register without first waiting for Paula interrupt can get tricky because there is some internal delays in CIAs. I don't remember how it exactly goes but there was some buggy games that required this kind of behavior. (Not that it may not be 100% correct but close enough).
It is much more safe to poll timer start bit than interrupt. It will also surprise you later when you use other timer and wonder why interrupts sometimes get lost.. EDIT: It probably is something emulation related because it makes no sense to get interrupt when it was cleared in Paula. Yes, as I said, NOP probably is slow enough but it is only a side effect, NOP could have been faster and still do what it is documented to do. Of course it does not matter in practice. But in theory it is wrong Last edited by Toni Wilen; 06 November 2018 at 17:29. |
06 November 2018, 17:26 | #15 | |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
Quote:
Back then I made a lot of tests regarding reliable interrupt aknowledge on my A4000/60 and the NOP/RTE solution didn't work all the time, "randomly" interrupts wouldn't be acknowledged. Hence I always used the "write twice to INTREQ" approach which never failed even once. |
|
06 November 2018, 17:29 | #16 | ||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
|
Quote:
Quote:
Thanks. Last edited by ross; 06 November 2018 at 17:44. Reason: edit |
||
06 November 2018, 17:37 | #17 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
|
Quote:
But some are different from normal memory cells because they actually contain 2 different registers (one read-only and one write-only). ICR is one of these, so 68000 clr.b is not to be used with it. (you can actually use it but you have to be aware of the consequences) |
|
06 November 2018, 17:42 | #18 | |
Registered User
Join Date: Sep 2015
Location: Germany
Posts: 260
|
Quote:
|
|
06 November 2018, 17:47 | #19 | |
Registered User
Join Date: Sep 2015
Location: Germany
Posts: 260
|
Quote:
|
|
06 November 2018, 17:48 | #20 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
|
Quote:
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Emulated A500 with Kick 1.3 generates spurious Lev6 interrupt | Kalms | Coders. Asm / Hardware | 2 | 20 March 2018 15:25 |
Irq Blitter | LeCaravage | Coders. Asm / Hardware | 9 | 16 June 2017 10:21 |
IRQ Virus | redblade | request.Apps | 8 | 01 September 2012 08:22 |
Spurious checksum errors | MagerValp | support.Hardware | 6 | 28 August 2008 17:10 |
New Ports available | DJBase | News | 1 | 26 January 2007 11:55 |
|
|