Again, as a follow up, the basic problem is that the Xmit bit is stuck on in the status register. So, depending on how you Xmit routine works, you may need to go thru some other code rewrite:
Polled I/O:
- Which is what I'm using right now. Most polled I/O routines loop on reading the status register, mask off the Xmit bit and loop back to reading/testing until it can handle another byte. This is where you can substitute the delay routine. in the Xmit routine.
IRQ-driven I/O:
- This would be much uglier... as the problem with the chip will endlessly generate IRQs due to the Xmit being stuck on. Putting a delay routine in the IRQ driven code likely won't work and will probably cause other code failures.
So, here's the base Xmit routine from SyMon (which I've change quite a bit lately):
Code:
COUT PHA ;Save ACCUMULATOR on STACK
COUTL LDA SIOSTAT ;Read ACIA status register
AND #$10 ;Isolate transmit data register status bit
BEQ COUTL ;LOOP back to COUTL IF transmit data register is full
PLA ;ELSE, restore ACCUMULATOR from STACK
STA SIODAT ;Write byte to ACIA transmit data register
RTS ;Done COUT subroutine, RETURN
I edited the above to:
Code:
COUTL LDA SIOSTAT ;Read ACIA status register
; AND #$10 ;Isolate transmit data register status bit
; BEQ COUTL ;LOOP back to COUTL IF transmit data register is full
PLA ;ELSE, restore ACCUMULATOR from STACK
STA SIODAT ;Write byte to ACIA transmit data register
JSR DELAY_6551 ;Required delay - Comment out for working 6551/65C51!
RTS ;Done COUT subroutine, RETURN
And the simple delay routine to be called:
Code:
; Latest WDC 65C51 has a bug - Xmit bit in status register is stuck on
; IRQ driven transmit is not possible as a result - interrupts are endlessly triggered
; Polled I/O mode also doesn't work as the Xmit bit is polled - delay routine is the only option
; The following delay routine kills time to allow W65C51 to complete a character transmit
; 0.523 milliseconds required loop time for 19,200 baud rate
; MINIDLY routine takes 524 clock cycles to complete - X Reg is used for the count loop
; Y Reg is loaded with the CPU clock rate in MHz (whole increments only) and used as a multiplier
;
DELAY_6551 PHY ;Save Y Reg
PHX ;Save X Reg
DELAY_LOOP LDY #2 ;Get delay value (clock rate in MHz 2 clock cycles)
;
MINIDLY LDX #$68 ;Seed X reg
DELAY_1 DEX ;Decrement low index
BNE DELAY_1 ;Loop back until done
;
DEY ;Decrease by one
BNE MINIDLY ;Loop until done
PLX ;Restore X Reg
PLY ;Restore Y Reg
DELAY_DONE RTS ;Delay done, return
;
Hope this helps.