Login
Back to forumReply to this topicGo to last reply

Posted By

SukkoPera
on 2025-04-06
04:09:02
 Another RS232 KERNAL Bug

I think I've found another bug in the RS-232 KERNAL routines, I would like to hear your thoughts.

The bug happens when software flow control is enabled and we hit the low watermark, meaning that a XON should be sent so that the sender will resume sending data. The code goes like this:

; get a char out of the input buffer

agetch
lda inqcnt ; got any?
beq bukbuk ; nope, inqcnt=0 then return a $00

; not empty

php ; save int enb bit

; { mut-ex begin

sei
ldx inqrpt ; do: inqrpt <- inqrpt+1 mod 64
inx
txa
and #$3f
sta inqrpt
plp

; mut-ex end }

tax
lda inpque,x ; get char from queue
pha ; save it
dec inqcnt ; one less
lda inqcnt
cmp #lowatr ; low watermark?
bne notlow ; nope

; hit low water mark

bit arstop ; is remote ~s'ed
bpl notlow ; nope, then don't ~q
lda xon
beq notlow ; x-sw is off
sta soutq ; send a ~q
sec
ror soutfg ; flag it
lsr arstop ; remote now not ~s'ed (msb cleared)

aready ; entry for chkin & chkout
bit apres ; is he there?
bpl anrdy ; no, don't even bother to look
bukbuk ; i'll just be jumping in here
pha
notlow ; here too
lda astat ; get status definition
and #$4f ; use bits 0..3, and 6
eor #$40 ; invert dsr
sta status
pla
anrdy
clc
rts


The code is correct just until the aready label: I assume that the developers wanted to recycle some code from the aready routine (which has a further bug!) in order to update the in-memory copy of the ACIA status, but this won't work:

- The received character is stored on the stack and needs to be pulled out just before returning.
- If there is no character in the incoming buffer, the code jumps to bukbuk right at the beginning. There they had to push a dummy byte to the stack just so that the pla before returning has something to pull out of it. Fair enough.
- When we don't hit the low watermark, the code jumps to notlow, skipping bukbuk and its pha. So far, so good.
- Although, when we DO hit the low watermark, the code sends the XON and then falls through to aready (which can be ignored) and bukbuk, resulting in two chars being pushed to the stack but only one pulled out, which causes the stack to get exhausted if enough data is sent.

The fix is to add a jmp notlow right before aready.

This is what was causing the +4 to hang while I was trying to add flow control to George's Tie Fighter demo.

I think there is yet another bug at the end: the current code will ALWAYS return with the carry cleared, but other parts of the code expect it to return with the carry set in case the ACIA was not ready. This also means that if this function gets called while the incoming buffer is empty, it will return bogus data and there is no way of knowing that!

What a mess!


Back to topReply to this topic


Copyright © Plus/4 World Team, 2001-2025. Support Plus/4 World on Patreon