Arlet wrote:
floobydust wrote:
It shouldn't be a problem... I also use a pair of circular buffers for driving a UART as a console via IRQ. It uses head/tail pointers and a count variable.
The count variable would be a problem, because it's updated both in the main program and in the interrupt handler. What I usually do is remove the count variable, and just compare head/tail pointers to see how much data is in the buffer. To avoid ambiguity between completely full and completely empty, you can either reserve 1 space in buffer, or use more bits in head/tail than necessary.
Well, it's true that the ISR decrements the count variable as it sends another byte of data. And of course, the output routine increments the count each time another byte of data is placed into the buffer. As the 65C02 is only processing in a single thread, you can't get the count out of sync with the two routines.
I've been using this type of buffer code since the 80's without an issue. The latest version has over 30K hours of non-stop execution on a few SBC boards without a single glitch.
Code:
;
;Character Output routine: puts the character in the A reg into the xmit buffer, character in
; A Reg is preserved on exit. Transmit is IRQ driven/buffered with a size of 128 bytes.
CHROUT PHY ;save Y reg
OUTCH LDY OCNT ;get character output count in buffer
BMI OUTCH ;check against limit, loop back if full
;
LDY OTAIL ;Get the buffer tail pointer
STA OBUF,Y ;Place character in the buffer
INC OTAIL ;Increment Tail pointer
RMB7 OTAIL ;Strip off bit 7, 128 bytes only
INC OCNT ;Increment character count
;
LDY #%00000100 ;Get mask for xmit on
STY UART_COMMAND ;Turn on xmt
;
PLY ;Restore Y reg
RTS ;Return to caller
;
and the ISR specific routine:
Code:
;
UART_XMT LDA OCNT ;Any characters to xmit?
BEQ NODATA ;No, turn off xmit
;
LDY OHEAD ;Get the head pointer to buffer
LDA OBUF,Y ;Get the next character
STA UART_TRANSMIT ;Send the character to 2691
INC OHEAD ;Increment head pointer
RMB7 OHEAD ;Strip off bit 7, 128 bytes only
DEC OCNT ;Decrement counter
BNE REGEXT0 ;If not zero, exit and continue normal stuff
;
;No more buffer data to send, check 2691 status and disable transmit if it's finished
NODATA LDA UART_STATUS ;Get status register
BIT #%00001000 ;Check for THR empty
BNE REGEXT0 ;Exit if character still loaded
BIT #%00000100 ;Check for TxRDY active
BEQ REGEXT0 ;Exit if not active, another character in THR
LDY #%00001000 ;Else, get mask for xmit off
STY UART_COMMAND ;Turn off xmit
REGEXT0A BRA REGEXT0 ;Exit IRQ handler
;