65C51 up to his old tricks again

For discussing the 65xx hardware itself or electronics projects.
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

65C51 up to his old tricks again

Post by cbmeeks »

OK, I finally got my board working again. I'm embarrassed to admit how long it took due to a stupid coding error on my part.

Anyway, I have built a small daughter card for my SBC that uses the infamous 65C51 (confirmed bug).

I started noticing it was dropping characters so I did a little research and found some code on here that puts a delay into the transmit method.

It works...mostly.

I'd say it went from 60% working to 85%.

Typing "this is a long line" yields something like "this isa lng line". Close, but no cigar.

So, my question is, should I just keep tweaking with the delay routine until I get it right or is there a bullet proof method already known by everyone?

FWIW, my machine is currently running at 1 MHz. (I took it down from 4 MHz until the dust settles).

mon.asm

Code: Select all

;-------------------------------------------------------------------------------
;       Main RESET Vector (ROM Startup)
;-------------------------------------------------------------------------------
.segment "CODE"
.org $8000

NMI_vec:
IRQ_vec:
RES_vec:
        JSR INITS


		LDY #0
@LOOP:
		LDA MSG, Y
		BEQ MAIN
		JSR ACIA_ECHO
		INY
		JMP @LOOP

;-------------------------------------------------------------------------------
;       MAIN Loop
;-------------------------------------------------------------------------------
MAIN:
		INC VIA_PORTA
		JSR ACIA_READ
		JSR ACIA_ECHO
        JMP MAIN


;-------------------------------------------------------------------------------
;       System Initialization
;-------------------------------------------------------------------------------
INITS:
        CLD                 		; Clear decimal arithmetic mode.
        CLI                 		; Clear interrupts

		JSR	VIA_INIT				; Initialize onboard VIA
		JSR ACIA_INIT				; Initialize ACIA

        RTS

MSG:
	.byte "Welcome to Potpourri6502", CR, LF, $00

;-------------------------------------------------------------------------------
;       Startup Vectors
;-------------------------------------------------------------------------------
.segment "VECTORS"
	.word NMI_vec           ; NMI Vector
	.word RES_vec           ; RESET Vector
	.word IRQ_vec           ; IRQ Vector

acia.asm

Code: Select all


;-------------------------------------------------------------------------------
;       Register Locations
;       TODO    Move $5800 to config file?  Is it worth it?
;-------------------------------------------------------------------------------
ACIA            := $5800
ACIA_CTRL       := ACIA + 3
ACIA_CMD        := ACIA + 2
ACIA_SR         := ACIA + 1
ACIA_RX         := ACIA
ACIA_TX         := ACIA


;-------------------------------------------------------------------------------
;       Name:           ACIA_INIT
;       Desc:           Configures base setup
;                       19200,N,8,1
;       Destroys:       Nothing
;-------------------------------------------------------------------------------
.byte "ACIA"                ; Tag this segment.  Remove to save four bytes.
ACIA_INIT:
        PHA                 ; Push A to stack
        LDA #$1F            ; %0001 1111 = 19200 Baud
                            ;              External receiver
                            ;              8 bit words
                            ;              1 stop bit
        STA ACIA_CTRL
        LDA #$0B            ; %0000 1011 = Receiver odd parity check
                            ;              Parity mode disabled
                            ;              Receiver normal mode
                            ;              RTSB Low, trans int disabled
                            ;              IRQB disabled
                            ;              Data terminal ready (DTRB low)
        STA ACIA_CMD
        PLA                 ; Restore A
        RTS


;-------------------------------------------------------------------------------
;       Name:           ACIA_ECHO
;       Desc:           Sends data to serial port
;       Destroys:       A
;       Note:           TODO - Add fix for 65C51 transmit bug
;                       It was recommended to use ~521 microseconds 
;                       (or a little more) delay.
;-------------------------------------------------------------------------------
ACIA_ECHO:
        PHA             ; Push A to stack
        LDA #$10        ; 16, %00010000
ACIA_TX_FULL:
        BIT ACIA_SR     ; Wait for TDRE bit = 1
        BEQ ACIA_TX_FULL
        PLA             ; Pull A from stack
        STA ACIA_TX     ; Send A
        JSR DELAY_6551
        RTS

;-------------------------------------------------------------------------------
;       Name:           ACIA_READ
;       Desc:           Reads data from serial port and return in A
;       Destroys:       A
;       Note:           Probably not compatible with EhBASIC because it is 
;                       blocking
;-------------------------------------------------------------------------------
ACIA_READ:
        LDA #$08
ACIA_RX_FULL:
        BIT ACIA_SR             ; Check to see if the buffer is full
        BEQ ACIA_RX_FULL
        LDA ACIA_RX
        RTS





; 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)
		LDY   #1    ;Get delay value (clock rate in MHz 1 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



PS, not sure why my code blocks are uneven. They are fine in my text editor...

Thanks!!!
Cat; the other white meat.
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: 65C51 up to his old tricks again

Post by Chromatix »

Does increasing the delay, say to $80 loaded in X, correct the problem?

A more reliable timing method would be to use a hardware timer, such as half of a 6522, and drive it from some division of the UART's master oscillator. This would also obviate the need to waste time in a loop after sending every character; instead you wait *before* sending until you observe the timer has expired, and reset the timer immediately after sending. You'd need to set the timer up during UART initialisation, so that you don't get stuck before sending the first byte.

Ooh - I just noticed you're running with polled receive, rather than interrupt. So you may be missing characters due to receive overrun rather than transmit corruption, if they're coming in a burst from your host machine. The 6551 doesn't have hardware control of CTS by receive status (probably because it doesn't have a FIFO, only a buffer register). I think you said you don't have the RTS/CTS lines connected anyway, otherwise I'd suggest negating CTS while sat in the timing loop. Using a hardware timer as suggested above would allow you to pick up the receive data sooner - but you should also implement a buffer in software, and at least consider servicing the UART on interrupt (receive on UART interrupt, transmit on timer interrupt).
Last edited by Chromatix on Thu Feb 14, 2019 4:02 am, edited 1 time in total.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: 65C51 up to his old tricks again

Post by GARTHWILSON »

cbmeeks wrote:
So, my question is, should I just keep tweaking with the delay routine until I get it right or is there a bullet proof method already known by everyone?
I think 6502.org forum member GaBuZoMeu has the best solution yet: Use the 51's pin 5 (if in DIP), the x16 clock, as an output to drive a VIA's PB6 for its T2 to count pulses and generate an interrupt. The T2 latch value can then remain constant in spite of changes in Φ2 rate and baud rate.

Edit: I see Chromatix alluded to it already. The link will just give some more detail, although you'll still have to examine the data sheets further and do more programming to get it all done.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: 65C51 up to his old tricks again

Post by cbmeeks »

Chromatix wrote:
Does increasing the delay, say to $80 loaded in X, correct the problem?

A more reliable timing method would be to use a hardware timer, such as half of a 6522, and drive it from some division of the UART's master oscillator. This would also obviate the need to waste time in a loop after sending every character; instead you wait *before* sending until you observe the timer has expired, and reset the timer immediately after sending. You'd need to set the timer up during UART initialisation, so that you don't get stuck before sending the first byte.

$80 had the same effect.

The 6522 idea is a nice one. But, I should say, the ACIA is just a temporary way for me to have some type of serial until I can design an NXP board. The ACIA is just all I have at the moment.

It would be nice if I can get it stable until I can finish the NXP but if it becomes too much of a headache, I may just skip it.

Thanks
Cat; the other white meat.
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: 65C51 up to his old tricks again

Post by Chromatix »

I added another potential cause to my post above; that would fit with increased delay *not* solving the problem.
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: 65C51 up to his old tricks again

Post by floobydust »

Well, the code blocks in the delay routine are uneven due to tab characters instead of spaces. I wrote that bit of code when I found the defect in the W65C51 some years ago (with Ultraedit). If you also use the transmit routine I modified for using the delay routine it should work without issue, provided the hardware itself is functioning properly and you're also running the chip at 19.2K baud rate.

As I was writing this reply, others replied as well with options on managing the W65C51. However, if you're unable to get reliable characters transmitted using the routines I posted in the link below, then you most likely have a hardware problem, so using another method is unlikely to fix it.

viewtopic.php?f=4&t=2543&start=30#p29795

Perhaps a full schematic and pictures might help diagnose the problem. Also note that you can find some older 4MHz R65C51 chips around... I bought some a few years ago and I have them running upwards of 5MHz with interrupt-driven I/O and 128-byte buffers. Overall, setting up and running a 6551 chip is very trivial.... if the chip is good, they just work.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: 65C51 up to his old tricks again

Post by GARTHWILSON »

Others posted while I was writing. I'll post this anyway.

It sounds then there's another problem besides the delay. Can you verify on the oscilloscope that there's space between the characters, and that the bit rate is not a little off? (That one should result in a framing error at the receive end, and could happen if you don't have a crystal made for the correct resonance mode. You won't have that problem if you're using an oscillator can anyway though.) The bug in WDC's '51 is the transmit-register-empty bug, which you can get around with one of several delay methods whether hardware or software.

Outside of that, it shouldn't be that hard to get going. I've been using the '51 for decades and never had any trouble with it. It has always worked on first try except when I lacked the capacitor on pin 6 as I show in the I/O ICs page of the 6502 primer. Oh, I take that back: When I tried to use the RTS\ and DTR\ outputs as general-purpose outputs (to drive status LEDs when I wasn't doing serial communications with the ACIA) with neither crystal input nor x16 clock input, I think it didn't work until I provided input on one of those. It was the last circuit shown on that page.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: 65C51 up to his old tricks again

Post by Chromatix »

I think this problem is specific to the "echo" test he's trying to run. In that *specific* case, any delay long enough to reliably avoid corrupting the stop-bit on the transmit side will be too long to avoid gradually falling behind a continuous train of receive-side traffic.

A test for this might be to eliminate the delay loop and instead set the host to transmit at 8N2 instead of 8N1. Leave the host receive and all the 6551's configuration at 8N1. You'll then get receive characters at 11-symbol intervals while being able to send them at 10-symbol intervals.
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: 65C51 up to his old tricks again

Post by cbmeeks »

OK, I think some good news.

I may have been experiencing some issues with the Windows terminal program I was using (Termite).

I switched to ExtraPutty and I can't get it to break.

I'm going to keep testing to make sure it isn't some fluke but, if it's working, then I can start my mini-monitor to grab data from my host PC and move to RAM.

Got a long weekend to boot. Fun fun. :-)

Thanks to all of those that helped.

Code: Select all


MAIN:
	INC VIA_PORTA
	JSR ACIA_READ
	JSR ACIA_ECHO

        JMP MAIN


...

ACIA_ECHO:
        PHA             ; Push A to stack
@LOOP:
        LDA ACIA_SR     ; Read ACIA Status Register
        AND #$10        ; Isolate transmit data register status bit
        BEQ @LOOP
        PLA             ; Pull A from stack
        STA ACIA_TX     ; Send A
        JSR DELAY_6551
        RTS

ACIA_READ:
        LDA #$08
ACIA_RX_FULL:
        BIT ACIA_SR             ; Check to see if the buffer is full
        BEQ ACIA_RX_FULL
        LDA ACIA_RX
        RTS

Attachments
Capture.PNG
Cat; the other white meat.
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: 65C51 up to his old tricks again

Post by Chromatix »

Are you able to generate data on the SBC and print that at full speed now?
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: 65C51 up to his old tricks again

Post by cbmeeks »

I believe so. In fact, I generated this welcome message:

Code: Select all

Bacon ipsum dolor amet biltong corned beef ham hock, drumstick turkey cupim rump kielbasa sausage turducken. Filet mignon capicola picanha, kielbasa chicken meatball rump shank. Corned beef pork belly pork chop chuck, landjaeger buffalo tenderloin. Ribeye 
Which is 256 bytes. Then, I copied the messaged echoed to my terminal and compared the string. Every byte was there.

**EDIT**

Hmm. I may have spoke too soon. Typing on the keyboard seems to work fine. But when I paste text (which the terminal simulates rapidly typing), it is all wonky. I'm hoping it's just because the terminal pastes at faster than 19.2. But I cannot confirm at the moment.
Cat; the other white meat.
cb3rob
Posts: 89
Joined: 23 Aug 2018
Location: CyberBunker

Re: 65C51 up to his old tricks again

Post by cb3rob »

are these current production chips? last batch i ordered was 2017'ish which by now is 3 years ago so i would expect them to have fixed it by now. (been using harris cpc65c51AE2's from china overstock (heck they're cheaper too ;) so far but it looks like we need to change that soon as intending to do some bus network using canbus linedrivers which implies a 250kbit/s baudrate is needed to make sure the bus drivers don't detect a permanent dominant state and thus the shift register should be clocked at 4mhz/16 which those old harris chips will never be able to do ;) (collision detction is just a matter of reading back each packet you sent and if something else also sent on the bus it falls through at the source address already.. also rxd is connected to dsr to make sure we -know- some other node sent a startbit... some 'somewhat random delay' after that so collisions are avoided.;) but either way... IS THIS PROBLEM FIXED NOW? as it's still mentioned in the datasheets from mouser but it's not mentioned in the datasheets from wdc themselves. (there it only mentions irq driven tx not working, not the tx register empty flag bug. (they never should have shipped chips that are broken like this in the first place ;) (don't care much for irq driven tx... as long as polling mode tx works without any nasty workarounds ;) original post isn't clear on wether he's got the problem with chips from 4-5 years ago or with chips from last week. (mouser can sit on their stock of broken chips for all eternity but i take it there have been production runs since that day ;)
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: 65C51 up to his old tricks again

Post by Chromatix »

AFAIK, WDC doesn't make high-volume continuous production of discrete chips. A lot of their business is IP to semi-custom and FPGA designs, for which the discrete chips (including the microcontrollers) serve as demonstration and evaluation hardware. So it's entirely probable that even WDC is still sitting on a stock of broken 65C51s.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: 65C51 up to his old tricks again

Post by BigEd »

Never will be fixed, in my opinion.
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: 65C51 up to his old tricks again

Post by Chromatix »

I think the current recommendation is still to use the 28L92 as a modern, properly functioning substitute; since it has timers and GPIO pins, it could also replace a 6522 for some people, offsetting the cost difference.

There are also some low-cost SPI-bus UARTs out there.
Post Reply