1) Use UART1 and its Auto Direction Control. It will set/clear its
RTS/DTR line on transmit.
2) If UART1 is reserved, you may manually do it easily: On put char
always set the pin. In ISR Thre req, if there is no data in fifo, clear the
pin..
From: l... [mailto:l...] On Behalf Of
Ron
Sent: 02 March, 2010 02:20
To: l...
Subject: [lpc2000] Re: LPC17xx question - ISR driven Serial possible?
Thanks for the advice. I am working with this now, to see what kind of
results I have. The one issue I might with utilizing the FIFO is the system
that I am trying to connect to.
There is a driver on the Tx line that has to be turned on and off on a real
time comm system, so if I wanted to transmit 1234 the driver system would
have to be this:
_____1234_____ TXed characters
|____| driver !enable line
I have this working for 1 character, beyond that, not as much luck.
--- In l... , "Deniz
Can Cigsar" wrote: >
> I would recommend a software fifo that works as a carrier between sender and > ISR. You do not need a task to process TX data, its
waste of resources..
> Also you are not using 16 level fifo of the hardware..
>
> My put char code is like this:
>
> 1. Disable Thre Irq, this wont hurt, it is just thre not the whole
> interrupt system
>
> 2. Check if there is room in hardware FIFO, if there is room, push the
> data into it, goto step 5
>
> 3. If software fifo is full, register txEvent, enable Thre IRQ, wait
> for txEvent, goto step 1
>
> 4. Push data to software fifo
>
> 5. Enable Thre Irq
>
> The interrupt routin is like this:
>
> 1. Read IIR
>
> 2. for thre:
>
> a. move upto 16 bytes of data from software fifo into hardware fifo
>
> b. if registered, trigger txEvent
>
> This will use both of 16 level hardware fifo, and additional software fifo. > Also no thread to handle tx flow, interrupt driven
such that the output is
> continuous if you have more than 16 bytes to transmit.. Realy low resource
> to waste..
Thanks for the advice. I am working with this now, to see what kind of results
I have. The one issue I might with utilizing the FIFO is the system that I am
trying to connect to.
There is a driver on the Tx line that has to be turned on and off on a real time
comm system, so if I wanted to transmit 1234 the driver system would have to be
this:
_____1234_____ TXed characters
|____| driver !enable line
I have this working for 1 character, beyond that, not as much luck.
--- In l..., "Deniz Can Cigsar" wrote: >
> I would recommend a software fifo that works as a carrier between sender
and
> ISR. You do not need a task to process TX data, its waste of resources..
> Also you are not using 16 level fifo of the hardware..
>
>
>
> My put char code is like this:
>
>
>
> 1. Disable Thre Irq, this wont hurt, it is just thre not the whole
> interrupt system
>
> 2. Check if there is room in hardware FIFO, if there is room, push
the
> data into it, goto step 5
>
> 3. If software fifo is full, register txEvent, enable Thre IRQ, wait
> for txEvent, goto step 1
>
> 4. Push data to software fifo
>
> 5. Enable Thre Irq
>
>
>
> The interrupt routin is like this:
>
> 1. Read IIR
>
> 2. for thre:
>
> a. move upto 16 bytes of data from software fifo into hardware fifo
>
> b. if registered, trigger txEvent
>
>
>
> This will use both of 16 level hardware fifo, and additional software fifo.
> Also no thread to handle tx flow, interrupt driven such that the output is
> continuous if you have more than 16 bytes to transmit.. Realy low resource
> to waste..
>
>
>
>
Reply by Deniz Can Cigsar●March 1, 20102010-03-01
I would recommend a software fifo that works as a carrier between sender and
ISR. You do not need a task to process TX data, its waste of resources..
Also you are not using 16 level fifo of the hardware..
My put char code is like this:
1. Disable Thre Irq, this wont hurt, it is just thre not the whole
interrupt system
2. Check if there is room in hardware FIFO, if there is room, push the
data into it, goto step 5
3. If software fifo is full, register txEvent, enable Thre IRQ, wait
for txEvent, goto step 1
4. Push data to software fifo
5. Enable Thre Irq
The interrupt routin is like this:
1. Read IIR
2. for thre:
a. move upto 16 bytes of data from software fifo into hardware fifo
b. if registered, trigger txEvent
This will use both of 16 level hardware fifo, and additional software fifo.
Also no thread to handle tx flow, interrupt driven such that the output is
continuous if you have more than 16 bytes to transmit.. Realy low resource
to waste..
From: l... [mailto:l...] On Behalf Of
Ron
Sent: 01 March, 2010 19:17
To: l...
Subject: [lpc2000] Re: LPC17xx question - ISR driven Serial possible?
Let me know what you think about this, because I have a solution I have
tried, but it isn't quite working either. Take a look:
So I created this task to processes characters from the ISR:
void xUARTsendTask(void *pvParameter)
{
uint8_t sendChar;
vSemaphoreCreateBinary(xSendSemaphore);
xSemaphoreTake(xSendSemaphore, 0);
for( ;; ){
xQueueReceive(xCharsForTx, &sendChar, portMAX_DELAY); // block
waiting for main to send a character
UART1->THR = sendChar; // send character when
it is received
xSemaphoreTake(xSendSemaphore, portMAX_DELAY); //
block waiting for ISR signal Semaphore
}
}
The new putchar Call is this:
signed portBASE_TYPE serial_putChar(signed portCHAR cOutChar, portTickType
xBlockTime )
{
signed portBASE_TYPE xReturn = pdFAIL;
if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) == pdPASS ){
// place character into buffer - this will trigger the send task
xReturn = pdPASS;
}
return xReturn;
}
The ISR would be very simple
void serialISR(void)
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
portCHAR cChar;
if(UART1->IIR & UART_IIR_INTID_THRE){ // when there is a Transmit
Hold Register Empty Interrtupt
{
xSemaphoreGiveFromISR(xSendSemaphore, &xHigherPriorityTaskWoken);
// signal semaphore that THR is ready for char
}
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
I think the concept is right, but I am still having problems with it - the
Transmitter sends to characters and then bombs out.
--- In l..., "Deniz Can Cigsar" wrote:
>
> ". If an OS is being used, a thread on top could handle semaphore signalling > from the interrupt to control buffering, but this
puts another layer of
> processing on top of the UART - probably not justified unless whole buffer
> pointers, rather than single chars, are being passed to the tx.interrupt
> handler."
>
> I do not agree with that.. Semaphores and events are system level entities, > and they can be processed by SVC Pending SV. Here I
mean, no interrupt
> disabling. Interrupt just marks pending sv flag, so when the cpu returns
> from interrupt(s), it also process pending sv code, so updates events, and
> semaphores. This is very cheap.
>
> When I use UART as terminal -one character comes, one character goes-, I use > a middle layer FIFO, that carries out the UART
incoming and outgoing data
> between interrupt and application code. That restricts all the state machine > on app layer.. If you use C++, it is just a
declaration of variable such
> that:
>
> UartPipe myPipe;
>
> that's it.. But when I use framed transportation, here I mean, data is
> carried out in frames, I again use FIFO but this time fifo caries frame
> struct instead of char itself.. Here the state machine works at interrupt
> level, because framed transportation is structured data spread over time..
> Result is in FIFO, app code may have separate state machine..
>
> From: l... [mailto:l...] On Behalf Of > mjames_doveridge
> Sent: 01 March, 2010 16:11
> To: l...
> Subject: [lpc2000] Re: LPC17xx question - ISR driven Serial possible?
>
> --- In l... , David
> Smead david.smead@ wrote:
> >
> > I wanted to add my $.02 to the issue of state machines. States should
> > only be set inside the state machine, never from external functions
> > such as an interrupt handler, or another task. "Jamming" a state
> > machine may work 99.999% of the time. You'll spend a lot of time on
> > the .001% failures.
> >
> > Dave
> > You are correct 99.999% of the time:)
>
> Unfortunately, these cases where interrupt interaction is the primary
> function, 'nice, safe' rules sometimes have to be broken. I can
agree that
> great care has to be taken! This case is a very simple state machine, hardly > worthy of the name, and serialization of the events,
(by disabling the
> interrupt - often the only means available), is only necessary when testing > the state for NOT IDLE.
>
> There are doubtless more 'visibly secure' means of attaining the
same ends. > If an OS is being used, a thread on top could handle
semaphore signalling
> from the interrupt to control buffering, but this puts another layer of
> processing on top of the UART - probably not justified unless whole buffer
> pointers, rather than single chars, are being passed to the tx.interrupt
> handler. On these simple controllers, semaphore handling often requires a
> brief interrupt-disable anyway if the controller thread is to be set
> running.
>
> Rgds,
> Martin
>
Reply by Ron●March 1, 20102010-03-01
Let me know what you think about this, because I have a solution I have
tried, but it isn't quite working either. Take a look:
So I created this task to processes characters from the ISR:
void xUARTsendTask(void *pvParameter)
{
uint8_t sendChar;
vSemaphoreCreateBinary(xSendSemaphore);
xSemaphoreTake(xSendSemaphore, 0);
for( ;; ){
xQueueReceive(xCharsForTx, &sendChar, portMAX_DELAY); // block
waiting for main to send a character
UART1->THR = sendChar; // send character when it is
received
xSemaphoreTake(xSendSemaphore, portMAX_DELAY); // block
waiting for ISR signal Semaphore
}
}
The new putchar Call is this:
signed portBASE_TYPE serial_putChar(signed portCHAR cOutChar,
portTickType xBlockTime )
{
signed portBASE_TYPE xReturn = pdFAIL;
if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) == pdPASS ){
// place character into buffer - this will trigger the send task
xReturn = pdPASS;
}
return xReturn;
}
The ISR would be very simple
void serialISR(void)
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
portCHAR cChar;
if(UART1->IIR & UART_IIR_INTID_THRE){ // when there is a Transmit
Hold Register Empty Interrtupt
{
xSemaphoreGiveFromISR(xSendSemaphore, &xHigherPriorityTaskWoken); //
signal semaphore that THR is ready for char
}
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
I think the concept is right, but I am still having problems with it -
the Transmitter sends to characters and then bombs out.
--- In l..., "Deniz Can Cigsar" wrote: >
> ". If an OS is being used, a thread on top could handle semaphore signalling > from the interrupt to control buffering, but this
puts another layer of > processing on top of the UART - probably not
justified unless whole buffer > pointers, rather than single chars, are being passed
to the tx.interrupt > handler."
>
> I do not agree with that.. Semaphores and events are system level entities, > and they can be processed by SVC Pending SV. Here I
mean, no interrupt
> disabling. Interrupt just marks pending sv flag, so when the cpu returns > from interrupt(s), it also process pending sv code,
so updates events, and > semaphores. This is very cheap.
>
> When I use UART as terminal -one character comes, one character goes-, I use > a middle layer FIFO, that carries out the UART
incoming and outgoing data > between interrupt and application code. That
restricts all the state machine > on app layer.. If you use C++, it is just a
declaration of variable such > that:
>
> UartPipe myPipe;
>
> that's it.. But when I use framed transportation, here I mean, data is
> carried out in frames, I again use FIFO but this time fifo caries frame > struct instead of char itself.. Here the state
machine works at interrupt > level, because framed transportation is structured
data spread over time.. > Result is in FIFO, app code may have separate state
machine..
>
> From: l... [mailto:l...] On Behalf Of > mjames_doveridge
> Sent: 01 March, 2010 16:11
> To: l...
> Subject: [lpc2000] Re: LPC17xx question - ISR driven Serial possible?
>
> --- In l... , David > Smead david.smead@ wrote:
> >
> > I wanted to add my $.02 to the issue of state machines. States should > > only be set inside the state machine, never from
external functions
> > such as an interrupt handler, or another task. "Jamming" a state
> > machine may work 99.999% of the time. You'll spend a lot of time on
> > the .001% failures.
> >
> > Dave
> > You are correct 99.999% of the time:)
>
> Unfortunately, these cases where interrupt interaction is the primary
> function, 'nice, safe' rules sometimes have to be broken. I can
agree that > great care has to be taken! This case is a very
simple state machine, hardly > worthy of the name, and serialization of the events,
(by disabling the
> interrupt - often the only means available), is only necessary when testing > the state for NOT IDLE.
>
> There are doubtless more 'visibly secure' means of attaining the
same ends. > If an OS is being used, a thread on top could handle
semaphore signalling > from the interrupt to control buffering, but this
puts another layer of > processing on top of the UART - probably not
justified unless whole buffer > pointers, rather than single chars, are being passed
to the tx.interrupt > handler. On these simple controllers, semaphore
handling often requires a > brief interrupt-disable anyway if the controller
thread is to be set
> running.
>
> Rgds,
> Martin
>
Reply by Deniz Can Cigsar●March 1, 20102010-03-01
". If an OS is being used, a thread on top could handle semaphore signalling
from the interrupt to control buffering, but this puts another layer of
processing on top of the UART - probably not justified unless whole buffer
pointers, rather than single chars, are being passed to the tx.interrupt
handler."
I do not agree with that.. Semaphores and events are system level entities,
and they can be processed by SVC Pending SV. Here I mean, no interrupt
disabling. Interrupt just marks pending sv flag, so when the cpu returns
from interrupt(s), it also process pending sv code, so updates events, and
semaphores. This is very cheap.
When I use UART as terminal -one character comes, one character goes-, I use
a middle layer FIFO, that carries out the UART incoming and outgoing data
between interrupt and application code. That restricts all the state machine
on app layer.. If you use C++, it is just a declaration of variable such
that:
UartPipe myPipe;
that's it.. But when I use framed transportation, here I mean, data is
carried out in frames, I again use FIFO but this time fifo caries frame
struct instead of char itself.. Here the state machine works at interrupt
level, because framed transportation is structured data spread over time..
Result is in FIFO, app code may have separate state machine..
From: l... [mailto:l...] On Behalf Of
mjames_doveridge
Sent: 01 March, 2010 16:11
To: l...
Subject: [lpc2000] Re: LPC17xx question - ISR driven Serial possible?
--- In l... , David
Smead wrote: >
> I wanted to add my $.02 to the issue of state machines. States should
> only be set inside the state machine, never from external functions
> such as an interrupt handler, or another task. "Jamming" a state
> machine may work 99.999% of the time. You'll spend a lot of time on
> the .001% failures.
>
> Dave
>
You are correct 99.999% of the time:)
Unfortunately, these cases where interrupt interaction is the primary
function, 'nice, safe' rules sometimes have to be broken. I can agree
that
great care has to be taken! This case is a very simple state machine, hardly
worthy of the name, and serialization of the events, (by disabling the
interrupt - often the only means available), is only necessary when testing
the state for NOT IDLE.
There are doubtless more 'visibly secure' means of attaining the same
ends.
If an OS is being used, a thread on top could handle semaphore signalling
from the interrupt to control buffering, but this puts another layer of
processing on top of the UART - probably not justified unless whole buffer
pointers, rather than single chars, are being passed to the tx.interrupt
handler. On these simple controllers, semaphore handling often requires a
brief interrupt-disable anyway if the controller thread is to be set
running.
Rgds,
Martin
Reply by mjames_doveridge●March 1, 20102010-03-01
--- In l..., David Smead wrote: >
> I wanted to add my $.02 to the issue of state machines. States should
> only be set inside the state machine, never from external functions
> such as an interrupt handler, or another task. "Jamming" a state
> machine may work 99.999% of the time. You'll spend a lot of time on
> the .001% failures.
>
> Dave
>
You are correct 99.999% of the time:)
Unfortunately, these cases where interrupt interaction is the primary function,
'nice, safe' rules sometimes have to be broken. I can agree that great
care has to be taken! This case is a very simple state machine, hardly worthy
of the name, and serialization of the events, (by disabling the interrupt -
often the only means available), is only necessary when testing the state for
NOT IDLE.
There are doubtless more 'visibly secure' means of attaining the same
ends. If an OS is being used, a thread on top could handle semaphore signalling
from the interrupt to control buffering, but this puts another layer of
processing on top of the UART - probably not justified unless whole buffer
pointers, rather than single chars, are being passed to the tx.interrupt
handler. On these simple controllers, semaphore handling often requires a brief
interrupt-disable anyway if the controller thread is to be set running.
Rgds,
Martin
Reply by David Smead●March 1, 20102010-03-01
I wanted to add my $.02 to the issue of state machines. States should
only be set inside the state machine, never from external functions
such as an interrupt handler, or another task. "Jamming" a state
machine may work 99.999% of the time. You'll spend a lot of time on
the .001% failures.
Dave
On Sun, Feb 28, 2010 at 11:29 PM, mjames_doveridge
wrote: > --- In l..., "carnac100" wrote:
>>
>> --- In l..., "Ron" wrote:
>> >
>> > Is it possible to have a fully ISR driven serial driver on the LPC17xx
series of chips? One that would follow this form:
>> >
>> > serial_putChar(char ch){
>> > sendBuffer[in++] = ch;
>> > UART1->IER |= UART_IER_THREINT_EN;
>> > }
>> >
>> > serialISR(){
>> > if(UART1->IIR & UART_IIR_INTID_THRE){
>> > UART1->THR = sendBuffer[out++];
>> > if (out == in){
>> > UART1->IER &= ~UART_IER_THREINT_EN;
>> > }
>> > }
>> > }
>> >
>> > Or something similar to that.
>> >
>> > The biggest problem I am having is that it doesn't appear that it is
possible to (or I can't figure out how to) enable the THRE interrupt in the
IER and cause an immediate THRE interrupt in the IIR.
>> >
>> > Ultimately I am using FreeRTOS, so should it be needed, I can create a
serial driver task that would fill the THR register for me if needed. But I
wanted to see if this would work first.
>> >
>>
>> You will need to implement a real simple state machine for the UART. In your
putchar function check the current state. If the state is IDLE (buffer is
empty) put the first byte in the UART transmit holding register and set the
state to NOT IDLE. If the state evaluates NOT IDLE when entering the putchar
function just place the byte in the transmit buffer. In the transmit
interrupt routine set the state back to IDLE when the last byte has been
sent.
>>
>> Regards,
>>
>> Frank
>> ..and beware the race condition where the interrupt routine sets the state to
IDLE just after your putchar has tested it and found it NOT-IDLE. This can
result in single chars. being occasionally delayed until the next putchar call,
characters getting swapped or even tx fail forever if you do not precisely
follow the logic posted by Frank, (ie. if the state is tested as NOT IDLE, do
not set the state variable to NOT IDLE. This might seem obvious, but many
experienced engineers 'automatically' set state variables to an
explicit value when an action occurs, irrespective of any previous value. This
is good for clarity and debugging in most 'application' state
machines, but not when dealing with interrupt interactions:).
>
> If the race problem could affect your comms protocols, you could disable
transmit interrupts if the test evaluates as NOT IDLE and perform the test
again. Re-enable them after acting on the result.
>
> Rgds,
> Martin
> Rgds,
> Martin
>
Reply by mjames_doveridge●March 1, 20102010-03-01
--- In l..., "carnac100" wrote: >
> --- In l..., "Ron" wrote:
> >
> > Is it possible to have a fully ISR driven serial driver on the LPC17xx
series of chips? One that would follow this form:
> >
> > serial_putChar(char ch){
> > sendBuffer[in++] = ch;
> > UART1->IER |= UART_IER_THREINT_EN;
> > }
> >
> > serialISR(){
> > if(UART1->IIR & UART_IIR_INTID_THRE){
> > UART1->THR = sendBuffer[out++];
> > if (out == in){
> > UART1->IER &= ~UART_IER_THREINT_EN;
> > }
> > }
> > }
> >
> > Or something similar to that.
> >
> > The biggest problem I am having is that it doesn't appear that it is
possible to (or I can't figure out how to) enable the THRE interrupt in the
IER and cause an immediate THRE interrupt in the IIR.
> >
> > Ultimately I am using FreeRTOS, so should it be needed, I can create a
serial driver task that would fill the THR register for me if needed. But I
wanted to see if this would work first.
> > You will need to implement a real simple state machine for the UART. In
your putchar function check the current state. If the state is IDLE (buffer is
empty) put the first byte in the UART transmit holding register and set the
state to NOT IDLE. If the state evaluates NOT IDLE when entering the putchar
function just place the byte in the transmit buffer. In the transmit
interrupt routine set the state back to IDLE when the last byte has been
sent.
>
> Regards,
>
> Frank
>
..and beware the race condition where the interrupt routine sets the state to
IDLE just after your putchar has tested it and found it NOT-IDLE. This can
result in single chars. being occasionally delayed until the next putchar call,
characters getting swapped or even tx fail forever if you do not precisely
follow the logic posted by Frank, (ie. if the state is tested as NOT IDLE, do
not set the state variable to NOT IDLE. This might seem obvious, but many
experienced engineers 'automatically' set state variables to an
explicit value when an action occurs, irrespective of any previous value. This
is good for clarity and debugging in most 'application' state
machines, but not when dealing with interrupt interactions:).
If the race problem could affect your comms protocols, you could disable
transmit interrupts if the test evaluates as NOT IDLE and perform the test
again. Re-enable them after acting on the result.
Rgds,
Martin
Rgds,
Martin
Reply by carnac100●February 26, 20102010-02-26
--- In l..., "Ron" wrote: >
> Is it possible to have a fully ISR driven serial driver on the LPC17xx series
of chips? One that would follow this form:
>
> serial_putChar(char ch){
> sendBuffer[in++] = ch;
> UART1->IER |= UART_IER_THREINT_EN;
> }
>
> serialISR(){
> if(UART1->IIR & UART_IIR_INTID_THRE){
> UART1->THR = sendBuffer[out++];
> if (out == in){
> UART1->IER &= ~UART_IER_THREINT_EN;
> }
> }
> }
>
> Or something similar to that.
>
> The biggest problem I am having is that it doesn't appear that it is
possible to (or I can't figure out how to) enable the THRE interrupt in the
IER and cause an immediate THRE interrupt in the IIR.
>
> Ultimately I am using FreeRTOS, so should it be needed, I can create a serial
driver task that would fill the THR register for me if needed. But I wanted to
see if this would work first.
>
You will need to implement a real simple state machine for the UART. In your
putchar function check the current state. If the state is IDLE (buffer is
empty) put the first byte in the UART transmit holding register and set the
state to NOT IDLE. If the state evaluates NOT IDLE when entering the putchar
function just place the byte in the transmit buffer. In the transmit
interrupt routine set the state back to IDLE when the last byte has been
sent.
Regards,
Frank
Reply by mant...@compusmart.ab.ca●February 26, 20102010-02-26
Your serial_putChar routine needs to force a byte into the
FIFO (bypassing your buffer) if the FIFO is empty, and enable
the THRE interrupt. Unlike other serial implementations I've
seen, this one only generates a THRE interrupt when the FIFO
transitions to empty, rather than continuing to generate
interrupts while empty.
You don't need to disable the THRE interrupt, as it won't
generate further interrupts once the FIFO is empty. Which is
also why initiating the send process cannot be done from inside
the ISR.
Mike
Quoting Ron :
> Is it possible to have a fully ISR driven serial
driver on the
> LPC17xx series of chips? One that would follow this form:
>
> serial_putChar(char ch){
> sendBuffer[in++] = ch;
> UART1->IER |= UART_IER_THREINT_EN;
> }
>
> serialISR(){
> if(UART1->IIR & UART_IIR_INTID_THRE){
> UART1->THR = sendBuffer[out++];
> if (out == in){
> UART1->IER &= ~UART_IER_THREINT_EN;
> }
> }
> }
>
> Or something similar to that.
>
> The biggest problem I am having is that it doesn't appear that it is
> possible to (or I can't figure out how to) enable the THRE interrupt
> in the IER and cause an immediate THRE interrupt in the IIR.
>
> Ultimately I am using FreeRTOS, so should it be needed, I can create
> a serial driver task that would fill the THR register for me if
> needed. But I wanted to see if this would work first.
>