??? 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 |
Topic | Author | Date |
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 |