Writing drivers for an SC16IS752 dual UART, need some help

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Writing drivers for an SC16IS752 dual UART, need some help

1,167 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by skyjumper on Sat Mar 21 13:16:34 MST 2015
Hi All...

Like the subject says, I'm writing some serial drivers for an SC16IS752 dual UART and having some trouble.

To send data, my application utilizes a ring buffer where data to be sent goes. The serial ISR is supposed to read data from the ring buffer and send it to the UART's THR. As the TX FIFO empties, the interrupt is triggered so the ISR can go get more data from the ring buffer and give it to the UART.

All well and good, but how do I generate the first interrupt to get the entire thing started? The data sheet does not seem to tell me how to force the UART to generate an interrupt.

Thanks...

Labels (1)
0 Kudos
5 Replies

1,028 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by skyjumper on Mon Mar 23 09:48:35 MST 2015
Thanks Mike, I'm trying all that...
0 Kudos

1,028 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MikeSimmonds on Sun Mar 22 03:45:35 MST 2015
Hi there Mr Jumper.

I was hinting at my reply (#3) to this thread. But that is to do with a stuff-up with the design on the internal UART.

I have written code (many years ago now) for an external Philips (now NXP) dual uart on an embedded 80x6 board.

The setup there specifically does not enable the THRE (tx holding register empty) interrupt because it will be firing all the time.
We also disabled FIFO, preferring single characters, because of rx char (and status) looping in the FIFO on multiple reads.

The Output routine:
1: Add character or string or block to ring buffer
2: Update buffer tail (with wrap) of the ring buffer NB: only the output routines touch the tail pointer.
3: Enable the THRE interrupt for the UART. [On every UART implementation other than the NXP on-chip ones, this causes an immediate interrupt.]
My reply in the thread I mentioned was about how to force the NXP UART's to comply!


In the ISR:
1: Handle Rx -- copy character (and status if required) to to output ring buffer
2: THEN update Rx tail (Only the ISR touches the Rx tail.)

3: If THRE bit active ...
4: Check if Tx head = Tx Tail. 
5: If not equal then copy character from Tx head to TxOut register and increment Tx Head (only the ISR touches Tx Head).
    And DO NOT disable the THRE interrupt on the UART.
6: Otherwise (head = tail) the queue is empty, so disable the THRE interrupt at the UART.

7: This is important, loop back to 1 (actually re-read the interrupt status!) so that if any Rx came in while you were outputting or vice versa, we catch all activity. Only when all of the desired UART interrupts are quiet do we exit.


Note: Provided that the various head and tail pointers are a single variable, you need not disable/enable interrupts around accesses.

If this is not entirely clear, I could post my 80x6 assembler -- maybe the comments would explain things.

Cheers, Mike



0 Kudos

1,028 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MikeSimmonds on Sun Mar 22 03:41:39 MST 2015
Re searching ...

Sometimes a Google search yields better results because of the exclude term etc.
Just use the "site" option to limit to the forums.

E.g. Google "UART transmit FIFO -LPCOpen site:www.lpcware.com" and similar.

Cheers, Mike

0 Kudos

1,028 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by skyjumper on Sat Mar 21 20:45:52 MST 2015
Hi Mike, thanks for your reply...

Actually, I have spent days on this problem and coded/tested the unsatisfactory solution described below.  I did search the forum, first for the specific part number which yielded relatively few threads, and none on point, and then for something much more generic, I think "serial UART driver" which yielded a bazillion results.  The most useful thread I found was this one:

http://www.lpcware.com/content/forum/cant-get-uart-tx-fifo-to-work

This thread basically says you have to write a byte directly to the UART's THR so it can send the byte and signal when empty. But that is talking about a different part with different capabilities. I have reviewed the data sheet for the part I am sing and some of it is as clear as mud. I don't do much embedded work so I am thinking I am misunderstanding or missing the way to do this.

I did write code to send, it works as follows:
(1) From the main body of my code, disable interrupts,
(2) write data to my ring buffer,
(3) set a volatile, global flag
(4) manually call the ISR like another function
(5) enable interrupts

The top of the ISR checks to see if the global flag is set and if so reads data from the ring buffer and sends it to the UART, then returns. At this point the interrupt fires when the number of bytes in the TX FIFO falls below the set threshold, and the ISR is called and the process repeats until the ring buffer is empty. 

My logic analyzer does confirm that the THR interrupt is firing.

I view this as a poor solution. First, I have to have duplicate code in the ISR to put data into the TX FIFO, some at the top that checks and clears my global flag and then again where the IIR is read to see what triggered the interrupt. I could encapsulate this into a function but then I incur the overhead of the function call in my ISR. Also, the flag is a pain as is putting interrupts down and up.

Worst of all, when I am receiving data on channel 0 and sending data on channel 1 with this ISR I have written, at some point in time (usually about an hour later) the UART stops generating interrupts entirely. I don't know why but I suspect it may be related to my manually setting interrupts on and off to send data. The problem does not occur if I am not sending and receiving at the same time.

I could take the approach described in the thread I posted above, but I would at least like to first confirm that there is no way for me to force the UART to fire a THR empty / TX FIFO low interrupt manually. Plus, I'm not sure that its any better than what I have done.

I really am happy to do my own homework, if there is something else I should have done I'm happy to accept suggestions. I'm just pulling my hair out at this point, and my next step is to set a watchdog timer that resets the UART completely in the event of data loss for 1,000 ms or more. That would truly suck.

0 Kudos

1,028 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MikeSimmonds on Sat Mar 21 14:28:28 MST 2015
I see this is your first post.

Step 1 Search the forum(s) [fora] . I know this has been asked before because I have replied to a similar
question.

Note 2 When and if you post code examples or snippets, use code tags!

Note 3 If someone's reply helps you out - let them know. Nothing discourages (me) replies more than silence.

Most important note:  Do not expect anyone to "do your homework" for you. Show that you have made an
effort to look into the issue yourself before asking for a quick fix.

With that in mind, I leave you to step one.  I'll check back after a bit to see how you got on.

Regards, Mike

0 Kudos