6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 12:33 pm

All times are UTC




Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: Thu Feb 14, 2019 3:26 am 
Offline
User avatar

Joined: Wed Aug 17, 2005 12:07 am
Posts: 1250
Location: Soddy-Daisy, TN USA
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:
;-------------------------------------------------------------------------------
;       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:

;-------------------------------------------------------------------------------
;       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.


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 14, 2019 3:44 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.

Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 14, 2019 3:49 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8545
Location: Southern California
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?


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 14, 2019 3:50 am 
Offline
User avatar

Joined: Wed Aug 17, 2005 12:07 am
Posts: 1250
Location: Soddy-Daisy, TN USA
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.


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 14, 2019 4:04 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
I added another potential cause to my post above; that would fit with increased delay *not* solving the problem.


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 14, 2019 4:04 am 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1385
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.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 14, 2019 4:13 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8545
Location: Southern California
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?


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 14, 2019 4:19 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 16, 2019 12:06 am 
Offline
User avatar

Joined: Wed Aug 17, 2005 12:07 am
Posts: 1250
Location: Soddy-Daisy, TN USA
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:

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
Capture.PNG [ 18.86 KiB | Viewed 4249 times ]

_________________
Cat; the other white meat.
Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 16, 2019 12:08 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
Are you able to generate data on the SBC and print that at full speed now?


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 16, 2019 12:16 am 
Offline
User avatar

Joined: Wed Aug 17, 2005 12:07 am
Posts: 1250
Location: Soddy-Daisy, TN USA
I believe so. In fact, I generated this welcome message:

Code:
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.


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 02, 2020 8:21 pm 
Offline

Joined: Thu Aug 23, 2018 7:10 am
Posts: 89
Location: CyberBunker
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 ;)


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 02, 2020 8:34 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 02, 2020 8:39 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Never will be fixed, in my opinion.


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 02, 2020 8:44 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 34 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron