26 July 2024, 23:27 | #1 |
Registered User
Join Date: May 2022
Location: Canada
Posts: 145
|
Serial communication reliability
Hi coders, I am having some trouble trying to identify a rare random occurrence of a lost byte during serial communication, and I would like your lights and guidance.
Question 1) I often see code with a double-write to INTREQ to clear the relevant interrupt flag, for example in my serial receive buffer full interrupt routine, at the end: move.w #$0800, CHIP_BASE+INTREQ move.w #$0800, CHIP_BASE+INTREQ This appears to be apparently for "68040 compatibility": is that a fact or a myth? Question 2) The reason I am asking is to validate the tiny possibility that in between these two writes to INTREQ, would it be possible that another byte could have been received on the serial port, with this second write potentially clearing out the flag too soon. Since the interrupt code here didn't reach RTE yet, would the interrupt be ignored and lost? Question 3) Might be directly for Toni / WinUAE, but any insights would be appreciated: On WinUAE when testing two Amiga with a serial link connection (using the option -s win32.serial_port=INTERNAL_SERIAL), I saw in WinUAE code that when using this internal serial emulation, winUAE runs in "safe_receive" mode, which we can see it the function: static bool canreceive(void) { // don't replace data in SERDATR until interrupt is cleared in safe receive mode if (safe_receive) { if (intreq & (1 << 11)) { return false; } ... My question is, based on that behavior, if I understand properly, it should be "impossible" to lose a byte since WinUAE politely waits until INTREQ is cleared before injecting a new byte. I cannot explain would I seen to be losing a byte occasionnally. Perhaps it is on writing instead of receiving. But in order to diagnose better I would need to have a WinUAE compiled with SERIALDEBUG=2 probably :| Thanks! |
27 July 2024, 13:06 | #2 |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,654
|
1) yes, this is normally required if you clear intreq just before rte (see 2).. also add a nop after the intreq writes to make sure instructions execute in-order on 060 (otherwise it could 'rte' before the writes are commited to the bus.
2) I would try clearing intreq at the start of the isr in order not to miss interrupt requests that arrive while you process the interrupt.. so the very first thing to do in your isr is to read the received byte, then clear the intreq bit.. then probably also check if the irf is set again before exiting your isr, and process the byte there instead of having to fire the isr again immediately.. If your isr takes a bit of time, the double write to intreq is probably not needed then (as paula will have processed it before your isr reaches rte).. How much of an effect this change effectively has depends on the size/runtime of your isr, of course.. Edit: you can check for overrun using bit 15 in SERDATR, btw.. Last edited by hooverphonique; 27 July 2024 at 21:48. |
27 July 2024, 20:37 | #3 | |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,282
|
Quote:
I don't know exactly which models require the "double ack" (and can't find the thread right now unfortunately), but I'm pretty sure it's sufficient to EITHER ack int + nop OR ack int + do other custom reg access. I.e. it's not that first ack is lost, but rather RTE could exit too quickly and still see old (non-acked) IPL value. nop fully guaranteeing bus transfer is done or another custom access providing extra delay should both be fine. On my B1260/50 single ack + RTE works 100% of the time. @OP: One thing to note is that despite WinUAE generally working very well, I found that it didn't behave similar enough to a real machine when debugging corner cases of "high speed" serial transfer (maybe things have improved or my setup was wrong) Also you mentioning interrupt routines and lost bytes makes me a bit suspicious. Are you sure the routine is called and completes in time? hooverphonique suggestion of monitoring of OVRUN is good. |
|
27 July 2024, 21:21 | #4 | ||
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,654
|
Quote:
Quote:
I know the ack isn't lost, I was just playing along with the OP's suggested way of overcoming this problem - I'm not sure just adding a nop between clearing the irf and rte is enough on the A4000 though.. |
||
27 July 2024, 21:35 | #5 | |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,282
|
Quote:
Probably whole NOP thing is cargo cult. I've just seen it a lot, and assumed it would fix it. 100% sure way should be to ack interrupt early, and ensure >2CCKs have passed before RTE - usually "free" by other work but double ack would work if interrupt routine isn't doing anything else. |
|
Today, 13:55 | #6 |
Registered User
Join Date: May 2022
Location: Canada
Posts: 145
|
I think I just discovered something very wrong in my code, and it happens during writing to the serial port, not during the read. Here's my writing function:
.label In summary it means: while bit 13 in SERDATR (TBE TRANSMIT BUFFER EMPTY) is zero, wait; then write my data to SERDAT. The problem is that the act of reading SERDATR can in fact EAT the data that could has just been received, apparently before the RBF (READ BUFFER FULL) interrupt code gets the chance to be triggered ! So randomly I lose one byte here. Could someone help me figure out how serial writing is supposed to be done on the Amiga without risking losing a byte, since SERDATR is used both for reading and for writing? |
Today, 16:42 | #7 |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,654
|
As far as I can gather from the description of SERDATR, reading it doesn't have any side effects.
|
Today, 17:41 | #8 |
Registered User
Join Date: May 2022
Location: Canada
Posts: 145
|
Ah perhaps then this is WinUAE emulation issue: reading SERDATR might signal to WinUAE that a byte has been received.
I tried using a workaround by checking INTREQR bit 0 instead. This flag is set to 1 when the transmit buffer is empty. The only caveat is that it is not set to one on startup. I needed to send a dummy byte to SERDAT. And also that disabling interrupts on INTREQ appears to clear out this bit. So I had to replace the 'disable all': move.w #$7fff, INTREQ(a1) to move.w #$7ffe, INTREQ(a1) in order to not touch the TBE bit. But this seems a bit hackish. |
Today, 19:13 | #9 |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,282
|
What serial protocol are you implementing, and at what rate (and target)? Is it for a generic library of some sorts? Are you running with the OS suspended or enabled?
If it's not an interactive terminal application you're making, you'll usually not be making use of the A part of UART, and would not expect to be receiving characters while you're trying to transmit. Also how are you testing? Like I wrote previously, I didn't find winuae (with serial over TCP and a host windows program) to be a good guide for tricky stuff. |
Currently Active Users Viewing This Thread: 2 (1 members and 1 guests) | |
remz |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Serial communication? | MickGyver | Coders. Blitz Basic | 4 | 10 April 2020 16:40 |
serial communication between Amiga and PC | TCH | support.Amiga Forever | 6 | 24 March 2020 00:00 |
CD32 Accelerator reliability .. | leonk | support.Hardware | 4 | 30 April 2019 19:35 |
Serial Port <--> Tablet: no communication | ral-clan | support.WinUAE | 0 | 02 February 2011 19:51 |
Supercars 2 communication screens | jotd | Retrogaming General Discussion | 11 | 04 December 2006 18:06 |
|
|