EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

LPC2368 UART1 vs. UART0 - 115k baud issue?

Started by goodgodgivemeanaliasalready October 29, 2009
Thanks Richard, your points are well taken and I'll probably adopt some
of your recs.

Good news update:

I have a 14.7456 Mhz oscillator on board as well. I enabled it this
morning and accounted for the clock changes appropriately in the baud
setup. The receives at 115k are now working as expected. So it looks
like it was probably some kind of timing issue / ISR slowness in my
code.

Now my only problem is that my Crossworks JTAG unit won't let me debug
(it drops the JTAG connection when I select the external oscillator as
the clock source). But at least the main problem seems to be accounted
for and solved...

Thanks for all your help everyone...

--- In l..., "rtstofer" wrote:
>
> --- In l..., "goodgodgivemeanaliasalready"
spambite3444@ wrote:
>
> > And again, I'm very confused that the transmit works (and it is a
ISR
> > handled function as well!), but not the RX...
> >
> > I'll look at the timing again, but a 4MHz oscillator should be able
to
> > handle all of this. I have a nauseous feeling that I'm missing
> > something simple, but ...
> >
> > Thanks for your help...
> If I understood what you said, your setup works at 57k baud with a 4
MHz osc but not at 115k baud. Have you thought about just kicking the
osc up to 8 MHz as an experiment?
>
> I usually try to get CCLK at the max and ordinarily set PCLKK.
then again, I am not trying to use low power.
>
> I have never worked with the LPC23xx devices but with the LPC21xx
devices you have to go to a lot of effort to get interrupts to nest. For
example, I have no idea how long your interrupts are disabled.
>
> Another experiment would be to send strings shorter than the FIFO
depth.
>
> There's an oddity (in my view) in the way the FIFOs are implemented.
Basically, you wait for an THRE interrupt and then you have to fill the
FIFO. There is no way to determine whether there is an empty space in
the FIFO. So, when you get the THRE interrupt you need to fill as many
of the 16 slots as possible from the transmit queue.
>
> The receive FIFO is even more interesting as you have the opportunity
to get the interrupt for every character or at 4, 8 or 14 chars. Here
again, you KNOW that at least so many chars are available in the FIFO.
The CTI interrupt will occur if there are chars in the FIFO but not
enough to reach the FIFO level for an interrupt.
>
> So, basically, you should be processing the transmit and receive FIFO
interrupts with chunks of chars from the queues. You don't have to count
chars or loop on status bits, you just have to grab/stuff as fast as you
can because you KNOW the depth of the FIFO.
>
> Richard
>

An Engineer's Guide to the LPC2100 Series

Hello goodgodgivemeanaliasalready

I just recently read your message...

I assume somewhere in your code you have modified bits 9 and 8 of PCLKSEL0 (PCLK_UART1) from the reset value of 00 (use CCLK/4 = 1MHz) to 01 (use CCLK = 1MHz).

I really doubt the problems you are having are a result of the error in the Baud.
BR= PCLK / [16 DL (1 + DivAddVal/MulVal) ]
@00000/[16*2(1+1/12)]
5385

The error in the Buad: (115385-115200)/115200 <.2%

I would be willing to bet that the device is being overburdened. This is why the receive and transmit functions work at the lower Bauds and not the higher ones.

You can easily verify this by using the PLL to adjust the frequency of the core and thus the Baud of UART1 without modifying any of your existing UART ISR code. See what happens when you increase the frequency to 8MHz (you would have to change DLL=4). The error would still be the same as at 4Mhz but probably would cure the problems you are having.

Once you determine the device is being overburdened, it then becomes a tradeoff of either modifying and optimizing your code for execution time or increasing the CCLK.

If, for whatever reason, you don't want to raise CCLK, an alternative would be to use hardware flow control.

--- In l..., "goodgodgivemeanaliasalready" wrote:
> Hi all,
>
> I am trying to get a simple pass thru of data at 115k from uart 1 to
> uart 0 on an lpc2368. Both are enabled (powered) and if I use 9600 baud
> rates, everything is fine. I'm running the unit off the 4MHz IRC. I
> then bumped uart0 up to 115k, had to switch the fractional baud rate
> settings. No problem, have 9600 baud message coming in UART1, shooting
> out UART0 at 115k.
>
> Then, I tried getting UART1 up to 115k. Should have just been setting
> the same values for the fractional baud rate and I'd be in good shape,
> right? Not so much. The data coming in is all garbled as if the
> fractional change isn't taking.
>
> The UART code is running with receive and transmit interrupts enabled.
> I'm running a 1 millisecond timer on timer 0, PWM is active in the
> background as well. Again, at 9600 baud, the rest of the code is all
> functioning correctly.
>
> For what it is worth, here is the init code for UART1:
>
>
> /***********************************************************************\
> ******/
> void uart1Init(uint16_t baud, UCHAR mode, UCHAR fmode)
> {
> U1IER = 0x00; // disable all interrupts
> U1IIR; // clear interrupt ID
> U1RBR; // clear receive register
> U1LSR; // clear line status register
>
> // set the baudrate
> U1LCR = ULCR_DLAB_ENABLE; // select divisor latches
> U1DLL = (UCHAR)baud; // set for baud low
> byte
> U1DLM = (UCHAR)(baud >> 8); // set for baud high byte
>
> if((baud == B115200) || (baud == B57600)) //Fractional baud rate
> needed here!!! 115k and 57.6k are 8.51% error otherwise
> {
> U1FDR |= (1 << U1FDR_DIVADDVAL_BIT); //DivAddVal = 1
> U1FDR |= (12 << U1FDR_MULVAL_BIT); //MulVal = 12
> }
>
> // set the number of characters and other user specified operating
> parameters
> U1LCR = (mode & ~ULCR_DLAB_ENABLE);
> U1FCR = fmode;
>
> #ifdef UART1_TX_INT_MODE
> uart1_tx_extract_idx = uart1_tx_insert_idx = 0;
> uart1_tx_running = 0;
> #endif
>
> #ifdef UART1_RX_INT_MODE
> // initialize data queues
> uart1_rx_extract_idx = uart1_rx_insert_idx = 0;
>
> // enable receiver interrupts
> U1IER |= UIER_ERBFI;
> #endif
> }
>
> Does anyone have any ideas / suggestions to look at on this? I have
> electrically scoped the system when it is running at 115k and verified
> that the same test data is coming into the port electrically at the
> higher baud rate. I just can't seem to get the LPC to suck in the bits
> at 115k vs. 9600.
>
> Thanks!
>

Hi abrpbay12,
Thanks for the comment, I think you and Richard are right. I am using a bastardized Crossworks project from a different project, and the ISR handling has a couple levels of indirection that I think just pushed it over the edge in terms of timing.

I was expecting to have to address a higher clock speed, but thought that a simple pass thru shouldn't tax the system. However, it looks like it was.

In the other thread, I note that I bumped it up to use the 14.7456Mhz oscillator on my board, and things cleared up (though I'm losing the CrossConnect JTAG when I engage the external oscillator...but that is a different problem I'll work with them).

Thanks very much for your response...

--- In l..., "abrpbay12" wrote:
>
> Hello goodgodgivemeanaliasalready
>
> I just recently read your message...
>
> I assume somewhere in your code you have modified bits 9 and 8 of PCLKSEL0 (PCLK_UART1) from the reset value of 00 (use CCLK/4 = 1MHz) to 01 (use CCLK = 1MHz).
>
> I really doubt the problems you are having are a result of the error in the Baud.
> BR= PCLK / [16 DL (1 + DivAddVal/MulVal) ]
> @00000/[16*2(1+1/12)]
> 5385
>
> The error in the Buad: (115385-115200)/115200 <.2%
>
> I would be willing to bet that the device is being overburdened. This is why the receive and transmit functions work at the lower Bauds and not the higher ones.
>
> You can easily verify this by using the PLL to adjust the frequency of the core and thus the Baud of UART1 without modifying any of your existing UART ISR code. See what happens when you increase the frequency to 8MHz (you would have to change DLL=4). The error would still be the same as at 4Mhz but probably would cure the problems you are having.
>
> Once you determine the device is being overburdened, it then becomes a tradeoff of either modifying and optimizing your code for execution time or increasing the CCLK.
>
> If, for whatever reason, you don't want to raise CCLK, an alternative would be to use hardware flow control.
>
> --- In l..., "goodgodgivemeanaliasalready" wrote:
> >
> >
> > Hi all,
> >
> > I am trying to get a simple pass thru of data at 115k from uart 1 to
> > uart 0 on an lpc2368. Both are enabled (powered) and if I use 9600 baud
> > rates, everything is fine. I'm running the unit off the 4MHz IRC. I
> > then bumped uart0 up to 115k, had to switch the fractional baud rate
> > settings. No problem, have 9600 baud message coming in UART1, shooting
> > out UART0 at 115k.
> >
> > Then, I tried getting UART1 up to 115k. Should have just been setting
> > the same values for the fractional baud rate and I'd be in good shape,
> > right? Not so much. The data coming in is all garbled as if the
> > fractional change isn't taking.
> >
> > The UART code is running with receive and transmit interrupts enabled.
> > I'm running a 1 millisecond timer on timer 0, PWM is active in the
> > background as well. Again, at 9600 baud, the rest of the code is all
> > functioning correctly.
> >
> > For what it is worth, here is the init code for UART1:
> >
> >
> > /***********************************************************************\
> > ******/
> > void uart1Init(uint16_t baud, UCHAR mode, UCHAR fmode)
> > {
> > U1IER = 0x00; // disable all interrupts
> > U1IIR; // clear interrupt ID
> > U1RBR; // clear receive register
> > U1LSR; // clear line status register
> >
> > // set the baudrate
> > U1LCR = ULCR_DLAB_ENABLE; // select divisor latches
> > U1DLL = (UCHAR)baud; // set for baud low
> > byte
> > U1DLM = (UCHAR)(baud >> 8); // set for baud high byte
> >
> > if((baud == B115200) || (baud == B57600)) //Fractional baud rate
> > needed here!!! 115k and 57.6k are 8.51% error otherwise
> > {
> > U1FDR |= (1 << U1FDR_DIVADDVAL_BIT); //DivAddVal = 1
> > U1FDR |= (12 << U1FDR_MULVAL_BIT); //MulVal = 12
> > }
> >
> > // set the number of characters and other user specified operating
> > parameters
> > U1LCR = (mode & ~ULCR_DLAB_ENABLE);
> > U1FCR = fmode;
> >
> > #ifdef UART1_TX_INT_MODE
> > uart1_tx_extract_idx = uart1_tx_insert_idx = 0;
> > uart1_tx_running = 0;
> > #endif
> >
> > #ifdef UART1_RX_INT_MODE
> > // initialize data queues
> > uart1_rx_extract_idx = uart1_rx_insert_idx = 0;
> >
> > // enable receiver interrupts
> > U1IER |= UIER_ERBFI;
> > #endif
> > }
> >
> > Does anyone have any ideas / suggestions to look at on this? I have
> > electrically scoped the system when it is running at 115k and verified
> > that the same test data is coming into the port electrically at the
> > higher baud rate. I just can't seem to get the LPC to suck in the bits
> > at 115k vs. 9600.
> >
> > Thanks!
>


The 2024 Embedded Online Conference