On Mar 22, 12:24=EF=BF=BDam, Chris Carlen
<crcarleREMOVET...@BOGUSsbcglobal.net> wrote:
> Greetings:
>
> I am writing driver code for the serial communications interface (SCI)
> of the TI TMS320F2812.
>
> So far I have been developing a set of functions analagous to C stdio
> stream IO calls that allow me to communicate via a RS232 link to a PC.
> The 16-byte receive and transmit FIFOs are utilized by the lowest level
> getc/putc functions. =EF=BF=BDThe other functions merely call getc/putc:
>
> These functions work Ok:
>
> int SCIb_getc(void);
> int SCIb_putc(int);
>
> int SCIb_gets(char *s, int size);
> int SCIb_puts(const char *s);
>
> These are not yet implemented, but will be for binary block transfer:
>
> uint16 SCIb_write(const void *ptr, uint16 size, uint16 count);
> uint16 SCIb_read(void *ptr, uint16 size, uint16 count);
>
> There are some other functions for initialization, setting baud, control
> char handling, echoing, etc.
>
> My next task is to make this driver codebase interrupt driven. =EF=BF=BDI =
am
> first trying to understand all of the reasons for using interrupts, and
> what the range of implementation possiblities might be.
>
> So far I can see the following reasons to use interrupts:
>
> 1. =EF=BF=BDTo implement flow control at the driver level. =EF=BF=BDFor ex=
., the
> simplest case would be to have the FIFO threshold interrupt handler
> deassert CTS so that the DTE would stop sending when the FIFO is full.
> The SCIx_getc() code could then reassert CTS when the FIFO has fallen
> below some threshold.
>
> Interestingly, I have just learned that the RS232 standard does not
> provide for hardware flow control in the RxD direction. =EF=BF=BDIt would =
seem
> highly non-standard to use the DTR/DSR pair here. =EF=BF=BDThus, the trans=
fer
> protocol level would have to ensure that the DTE doesn't get overrun.
> For my devices, this shouldn't be an issue. =EF=BF=BDThey will do much mor=
e
> receiving than transmitting.
>
> 2. =EF=BF=BDTo increase the effective size of the FIFO buffer. =EF=BF=BDBy=
having the
> interrupt handler for the receiver put the data into a larger buffer
> than the 16 byte FIFO, and base the CTS state on the condition of the
> larger buffer rather than the FIFO then the user code can process data
> in larger chunks and less frequently.
>
> This might increase throughput somewhat, but doesn't solve the
> fundamental problem of needing flow control. =EF=BF=BDIt just trnasfers th=
e
> problem of buffer overrun from the hardware FIFO to the software buffer.
> =EF=BF=BD Thus, either hardware must still do this via CTS or the protocol=
needs
> to be able to stop the DTE. =EF=BF=BDIf the protocol is XMODEM for instanc=
e, and
> the buffer is >=3D132 bytes, then I suppose this would guarantee no overru=
ns.
>
> One application will have a mixture of binary file transfer from
> DTE->DCE which will be XMODEM-like so this will be fine. =EF=BF=BDHowever,=
it
> will also have a text command language, so it is conceivable that the
> buffer could overflow before the command processor had a chance to
> digest commands, if a machine was sending the commands rapidly. =EF=BF=BDT=
hus,
> hardware flow control would be needed here, or limiting the data rate.
>
> 3. =EF=BF=BDIt is possible for the SCI interrupts to call user code. =EF=
=BF=BDIe, the
> user can "register" a user function with the driver. =EF=BF=BDThen the use=
r
> could be "forced" to process data before the buffer overflows.
>
> I don't particularly like this, nor do I think it is typical.
>
> What can I expect of typical PC serial port drivers, on Windows and
> Linux? =EF=BF=BDWhat do they do with the RTS/CTS and DTR/DSR lines?
>
> Obviously I am learning about this by doing and for the first time.
> Comments regarding the direction I am taking and my understanding of the
> purpose for interrupts in a serial driver are welcome.
>
> --
> Good day!
>
> ____________________________________
> CRC
> crobcREMOVET...@BOGUSsbcglobal.net
> NOTE, delete texts: "REMOVETHIS" and
> "BOGUS" from email address to reply.
Hi, I have some serial routines, not for your chip though. Uses a
software buffer instead of a FIFO, it's interrupt driven and uses XON/
XOFF comands for flow control. You may not be able to use them
directly but it should show you how to go about it. Email me if you
want them.
Reply by Bubba●March 25, 20082008-03-25
If you want to do something else during sending or receiving of data then
it's best to use a interrupt driven FIFO for rx and tx.
But if your aplication can sit and wait for rx or tx then it's ok not to use
FIFOs.
:-)
"Chris Carlen" <crcarleREMOVETHIS@BOGUSsbcglobal.net> skrev i meddelandet
news:fsb48j07of@news4.newsguy.com...
> Bubba wrote:
>> Look at this example from Atmel. It should be very similar for the
>> TMS320F2812 except for the hardware register. It should be easy to adapt
>> for the TMS320F2812.
> [edit]
>
>
> Thanks for the reply.
>
> That's a pretty simple example. There isn't much going on there that I
> hadn't already inferred was the point of it all. I guess I'll just keep
> forging ahead.
>
>
>
>
> --
> Good day!
>
> ____________________________________
> CRC
> crobcREMOVETHIS@BOGUSsbcglobal.net
> NOTE, delete texts: "REMOVETHIS" and
> "BOGUS" from email address to reply.
Reply by Chris Carlen●March 25, 20082008-03-25
Bubba wrote:
> Look at this example from Atmel. It should be very similar for the
> TMS320F2812 except for the hardware register. It should be easy to adapt
> for the TMS320F2812.
[edit]
Thanks for the reply.
That's a pretty simple example. There isn't much going on there that I
hadn't already inferred was the point of it all. I guess I'll just keep
forging ahead.
--
Good day!
____________________________________
CRC
crobcREMOVETHIS@BOGUSsbcglobal.net
NOTE, delete texts: "REMOVETHIS" and
"BOGUS" from email address to reply.
Reply by Keith M●March 24, 20082008-03-24
Chris Carlen wrote:
> Interestingly, I have just learned that the RS232 standard does not
> provide for hardware flow control in the RxD direction.
While I don't have the EIA/TIA standard in front of me, there is always
flow control support in both directions AVAILABLE using normal signal
lines on RS-232. For instance, if the DTE side of the 232 connection
wants to stop the DCE from sending, it can drop any of its outputs to
communicate this fact.
So it can drop DTR or RTS. RTS is definitely more common, but DTR is
definitely used in some circles and supported. Microsoft, through their
COMM api (I can get the details if you need this) can be configured for
DTR/DSR flow control.
If its the DCE side you are talking about, then the DCE can drop CTS or
DSR. Certainly CTS is more popular, but DSR works too.
> It would seem
> highly non-standard to use the DTR/DSR pair here.
There's a difference between non-standard, and not popular. See above.
I use DTR/DSR flow control in my embedded hobby application because
the particular implementation of the USB->serial converter chip I am
using only supports DTR/DSR (and not rts/cts. and hence an example
where a manufacturer chose to support dtr/dsr over rts/cts)
> What can I expect of typical PC serial port drivers, on Windows and
> Linux? What do they do with the RTS/CTS and DTR/DSR lines?
I don't think Linux has support for DTR/DSR flow control, at least not
in any common recent major released/supported kernel. I searched for
this awhile ago, and I forget the exact hangup on why or what the
problem was in supporting it.
But for Windows, DTR/DSR is definitely common enough that it's supported
in the base API's without hacks/additions.
As far as what they DO with it, you have to configure what mode you want
the serial port to operate in. Dunno how specific you want, but if the
receive buffer of PC fills, it drops RTS/DTR until that buffer has been
emptied. Then it raises it again.
> Obviously I am learning about this by doing and for the first time.
> Comments regarding the direction I am taking and my understanding of the
> purpose for interrupts in a serial driver are welcome.
Dunno how much I've helped. My application is a async TTL-level 2mbps
serial stream where the bulk of the conversation is microcontroller ->
windows PC. The windows PC issues commands, and the uC responds with
about 12K bytes of traffic -- with multiple commands / responses per
second. Upwards of about 3 requests/responses second, if I'm doing the
math right after a long day of Easter travel. :)
I've got a blog at http://www.techtravels.org/amiga/amigablog
that has covered some issues that you might run into. It's a
rambling-style brain-dump, but if you can get past the format, you might
find it interesting.
Thanks
Keith
Reply by Bubba●March 23, 20082008-03-23
Look at this example from Atmel. It should be very similar for the
TMS320F2812 except for the hardware register. It should be easy to adapt for
the TMS320F2812.
// AVR306: Using the AVR UART in C
// Routines for interrupt controlled UART
// Last modified: 02-06-21
// Modified by: AR
/* Includes */
#include <io8515.h>
#include <ina90.h>
/* UART Buffer Defines */
#define UART_RX_BUFFER_SIZE 128 /* 2,4,8,16,32,64,128 or 256 bytes */
#define UART_TX_BUFFER_SIZE 128
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 )
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
#error RX buffer size is not a power of 2
#endif
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1 )
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
#error TX buffer size is not a power of 2
#endif
/* Static Variables */
static unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART_RxHead;
static volatile unsigned char UART_RxTail;
static unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;
/* Prototypes */
void InitUART( unsigned char baudrate );
unsigned char ReceiveByte( void );
void TransmitByte( unsigned char data );
/* Main - a simple test program*/
void main( void )
{
InitUART( 11 ); /* Set the baudrate to 19,200 bps using a 3.6864MHz
crystal */
_SEI(); /* Enable interrupts => enable UART interrupts */
for( ; ; ) /* Forever */
{
TransmitByte( ReceiveByte() ); /* Echo the received character */
}
}
/* Initialize UART */
void InitUART( unsigned char baudrate )
{
unsigned char x;
UBRR = baudrate; /* Set the baud rate */
/* Enable UART receiver and transmitter, and receive interrupt */
UCR = ( (1<<RXCIE) | (1<<RXEN) | (1<<TXEN) );
x = 0; /* Flush receive buffer */
UART_RxTail = x;
UART_RxHead = x;
UART_TxTail = x;
UART_TxHead = x;
}
/* Interrupt handlers */
#pragma vector=UART_RX_vect
__interrupt void UART_RX_interrupt( void )
{
unsigned char data;
unsigned char tmphead;
data = UDR; /* Read the received data */
/* Calculate buffer index */
tmphead = ( UART_RxHead + 1 ) & UART_RX_BUFFER_MASK;
UART_RxHead = tmphead; /* Store new index */
if ( tmphead == UART_RxTail )
{
/* ERROR! Receive buffer overflow */
}
UART_RxBuf[tmphead] = data; /* Store received data in buffer */
}
#pragma vector=UART_UDRE_vect
__interrupt void UART_TX_interrupt( void )
{
unsigned char tmptail;
/* Check if all data is transmitted */
if ( UART_TxHead != UART_TxTail )
{
/* Calculate buffer index */
tmptail = ( UART_TxTail + 1 ) & UART_TX_BUFFER_MASK;
UART_TxTail = tmptail; /* Store new index */
UDR = UART_TxBuf[tmptail]; /* Start transmition */
}
else
{
UCR &= ~(1<<UDRIE); /* Disable UDRE interrupt */
}
}
/* Read and write functions */
unsigned char ReceiveByte( void )
{
unsigned char tmptail;
while ( UART_RxHead == UART_RxTail ) /* Wait for incomming data */
;
tmptail = ( UART_RxTail + 1 ) & UART_RX_BUFFER_MASK;/* Calculate buffer
index */
UART_RxTail = tmptail; /* Store new index */
return UART_RxBuf[tmptail]; /* Return data */
}
void TransmitByte( unsigned char data )
{
unsigned char tmphead;
/* Calculate buffer index */
tmphead = ( UART_TxHead + 1 ) & UART_TX_BUFFER_MASK; /* Wait for free space
in buffer */
while ( tmphead == UART_TxTail );
UART_TxBuf[tmphead] = data; /* Store data in buffer */
UART_TxHead = tmphead; /* Store new index */
UCR |= (1<<UDRIE); /* Enable UDRE interrupt */
}
unsigned char DataInReceiveBuffer( void )
{
return ( UART_RxHead != UART_RxTail ); /* Return 0 (FALSE) if the receive
buffer is empty */
}
Reply by Chris Carlen●March 21, 20082008-03-21
Greetings:
I am writing driver code for the serial communications interface (SCI)
of the TI TMS320F2812.
So far I have been developing a set of functions analagous to C stdio
stream IO calls that allow me to communicate via a RS232 link to a PC.
The 16-byte receive and transmit FIFOs are utilized by the lowest level
getc/putc functions. The other functions merely call getc/putc:
These functions work Ok:
int SCIb_getc(void);
int SCIb_putc(int);
int SCIb_gets(char *s, int size);
int SCIb_puts(const char *s);
These are not yet implemented, but will be for binary block transfer:
uint16 SCIb_write(const void *ptr, uint16 size, uint16 count);
uint16 SCIb_read(void *ptr, uint16 size, uint16 count);
There are some other functions for initialization, setting baud, control
char handling, echoing, etc.
My next task is to make this driver codebase interrupt driven. I am
first trying to understand all of the reasons for using interrupts, and
what the range of implementation possiblities might be.
So far I can see the following reasons to use interrupts:
1. To implement flow control at the driver level. For ex., the
simplest case would be to have the FIFO threshold interrupt handler
deassert CTS so that the DTE would stop sending when the FIFO is full.
The SCIx_getc() code could then reassert CTS when the FIFO has fallen
below some threshold.
Interestingly, I have just learned that the RS232 standard does not
provide for hardware flow control in the RxD direction. It would seem
highly non-standard to use the DTR/DSR pair here. Thus, the transfer
protocol level would have to ensure that the DTE doesn't get overrun.
For my devices, this shouldn't be an issue. They will do much more
receiving than transmitting.
2. To increase the effective size of the FIFO buffer. By having the
interrupt handler for the receiver put the data into a larger buffer
than the 16 byte FIFO, and base the CTS state on the condition of the
larger buffer rather than the FIFO then the user code can process data
in larger chunks and less frequently.
This might increase throughput somewhat, but doesn't solve the
fundamental problem of needing flow control. It just trnasfers the
problem of buffer overrun from the hardware FIFO to the software buffer.
Thus, either hardware must still do this via CTS or the protocol needs
to be able to stop the DTE. If the protocol is XMODEM for instance, and
the buffer is >=132 bytes, then I suppose this would guarantee no overruns.
One application will have a mixture of binary file transfer from
DTE->DCE which will be XMODEM-like so this will be fine. However, it
will also have a text command language, so it is conceivable that the
buffer could overflow before the command processor had a chance to
digest commands, if a machine was sending the commands rapidly. Thus,
hardware flow control would be needed here, or limiting the data rate.
3. It is possible for the SCI interrupts to call user code. Ie, the
user can "register" a user function with the driver. Then the user
could be "forced" to process data before the buffer overflows.
I don't particularly like this, nor do I think it is typical.
What can I expect of typical PC serial port drivers, on Windows and
Linux? What do they do with the RTS/CTS and DTR/DSR lines?
Obviously I am learning about this by doing and for the first time.
Comments regarding the direction I am taking and my understanding of the
purpose for interrupts in a serial driver are welcome.
--
Good day!
____________________________________
CRC
crobcREMOVETHIS@BOGUSsbcglobal.net
NOTE, delete texts: "REMOVETHIS" and
"BOGUS" from email address to reply.