Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
12/28/06 09:07
Read: times


 
#130209 - Question about my interrupt driven UART
Responding to: ???'s previous message
Hi There-
Thanks to advice from Russell/Erik/Others i've gone ahead and started to tinker with interrupt driven serial I/O routines. I have two fifos in internal ram that are each 32 bytes long, one for receive and one for xmit. My receive routines work very well and I have no problems. My xmit routines are, however, struggling a bit and I was hoping to seek some advice. The basic data structure is:

dseg AT 21h
TX_BUF_HEAD: ds 1
TX_BUF_TAIL: ds 1
RX_BUF_HEAD: ds 1
RX_BUF_TAIL: ds 1

RX_BUF: ds 32
TX_BUF: ds 32

TX_DB: ds 1 //temp byte for xmit data

I have a routine called do_message that moves the data pointer to some fixed spot (#messsage) and gets each character from the message till it hits a "0". do_message calls tx_push_byte for each character. push_byte checks to see if the the fifo is empty/full/wrap around etc and then places the new data byte appropriatley in the fifo and adjusts the TX_BUF_HEAD as needed. My xmit UART ISR also checks for fifo empty/not empty and if not empty writes the byte at the tail of the fifo and incs the tail. If it is empty it just clears TI0 and does reti.

My question boils down to: what is the best way to "kick start" the ISR process. Obviously the only way to get into the ISR is if TI0 is set. In tx_push_byte when the fifo is empty I need to somehow say "ok, ISR, start." I could do mov SBUF0, Data in the tx_push_byte fifo empty area, but that seems ugly and leads to problems with transmitting an extra byte etc. I'd like to do setb TI0 and have the ISR go, but if I use that method, I run into the problem that I set TI0 (in tx_push_byte fifo empty area) before the previous data byte has completed a UART transmission. The only fix I could think of was to add a bit called FIFO_START which initializes cleared. tx_push_byte only sets TI0 if the fifo is empty AND FIFO_START is cleared. push_byte then sets FIFO_START and the bit is only cleared in the ISR's TX FIFO empty check. Seems a little ugly and unnecessary. How do people typically "kick start" the ISR? Once it's running without any race conditions it makes sense, but I'm having trouble getting it there. I've pasted my code thus far below. I realize that this code is pretty ugly...it's a first attempt with lots of debugging nonsense and can be really optimized...right now I'm just trying for functionality and I'll deal with making it elegant later. This currently uses the FIFO_START semaphore... THANKS!!

D



;-----------------------------------------------------------------------------
; CODE SEGMENT
;-----------------------------------------------------------------------------


Blink segment CODE

rseg Blink ; Switch to this code segment.
using 0 ; Specify register bank for the
; following program code.

Main:
;call init_device - config file generation
call init_device

; Disable the WDT.
anl PCA0MD, #NOT(040h) ; clear Watchdog Enable bit

; Initialize LED to OFF

clr GREEN_LED

//enable timer 1 for UART xmissions
orl TCON, #1000000b

clr TI0
clr RI0

//init this stuff
mov RX_BUF_HEAD, #RX_BUF
mov RX_BUF_TAIL, #RX_BUF

mov TX_BUF_HEAD, 0
mov TX_BUF_TAIL, 0

mov TX_BUF_HEAD, #TX_BUF
mov TX_BUF_TAIL, #TX_BUF

clr FIFO_START


loop2:

mov a, 0
mov r7, a
call do_a_message

nops: nop
nop
nop
nop

JB SW, nops

nop

JNB SW, $
jmp loop2

do_a_message:
mov dptr, #MESSAGE
msg1: clr a
movc a, @a+dptr
inc dptr
mov TX_DB, a
mov R7, a
cjne R7, #0, msg2
ret
msg2: call tx_push_byte
jmp msg1

tx_push_byte:
//NEED TO CHECK FOR BUFFER Full etc
mov a, TX_BUF_HEAD

//CHECK BUFFER FULL

//CHECK BUFFER WRAP AROUND

//CHECK BUFFER EMPTY
xrl a, TX_BUF_TAIL
JZ TX_BUF_EMPTY_TEST

TX_BUF_NOT_EMPTY:
mov R0, TX_BUF_HEAD
mov @R0, TX_DB
inc TX_BUF_HEAD
ret
TX_BUF_EMPTY_TEST:
JNB FIFO_START, TX_BUF_EMPTY
jmp TX_BUF_NOT_EMPTY
TX_BUF_EMPTY:
mov R0, TX_BUF_HEAD
mov @R0, TX_DB
inc TX_BUF_HEAD
//HOW SHOULD I START THE ISR? Mov to SBU0? SET TI0? HELP!!!
setb FIFO_START
setb TI0
ret

UART_ISR: JB TI0, TX_INT
JB RI0, RX_INT

TX_INT: mov a, TX_BUF_HEAD
xrl a, TX_BUF_TAIL
JZ TX_BUF_EMPTY_ISR

TX_BUF_NOT_EMPTY_ISR:
clr TI0
mov R0, TX_BUF_TAIL
mov A, @R0
inc TX_BUF_TAIL
mov SBUF0, a
setb GREEN_LED
reti

TX_BUF_EMPTY_ISR:
clr TI0
reti


RX_INT: clr RI0
mov R0, RX_BUF_HEAD
mov A, SBUF0
mov @R0, A
inc RX_BUF_HEAD
reti


MESSAGE: db "123456789", 0
MESSAGE2: db "sadkjsad", 0
MESSAGE3: db "ujlksajdlkasd", 0
NEWLINE: db 13,10,0


List of 21 messages in thread
TopicAuthorDate
the nature of the UART/steping through interrupts            01/01/70 00:00      
   Uart is full duplex            01/01/70 00:00      
      Thanks Russell            01/01/70 00:00      
   UART Question Part 2            01/01/70 00:00      
      You can not do both            01/01/70 00:00      
         In response to Neil            01/01/70 00:00      
            go with the bit            01/01/70 00:00      
         In response to Neil            01/01/70 00:00      
         In response to Neil            01/01/70 00:00      
            Sorry for teh tripple post...            01/01/70 00:00      
      More...            01/01/70 00:00      
         Search and Read            01/01/70 00:00      
         Thanks Russell            01/01/70 00:00      
         I hope Russell did not lead you down the garden pa            01/01/70 00:00      
            Erik - garden path indeed!            01/01/70 00:00      
               I'm using interrupts            01/01/70 00:00      
   Question about my interrupt driven UART            01/01/70 00:00      
      You know the answer.            01/01/70 00:00      
         Thanks Russell            01/01/70 00:00      
         answer is partially incorrect            01/01/70 00:00      
   Can't single step on UART            01/01/70 00:00      

Back to Subject List