EmbeddedRelated.com
Forums

UART transmit problem with GNU

Started by jesperkr123 April 28, 2005
Hey

I'm trying to get the UART0 and UART1 working on my LPC2124 Olimex
board. I use the WINARM GNU toolchain.

I've wrote a simple code to test the UART. But when i send a byte to
my PC, the received byte is wrong.
This is my test program:

void SetUART(int baud){
unsigned int divisor = pCF / (16 * baud);

PINSEL0 |= 0x00050005; /* Enable UART0 & UART1 */

U0IER = 0x00; // disable all interrupts
U0IIR; // clear interrupt ID
U0RBR; // clear receive register
U0LSR; // clear line status register

U0LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit, DLAB=1*/
U0DLL = divisor;
U0DLM = (divisor >> 8);
U0LCR = 0x03; /* DLAB = 0 - no access to UART1 Div. */
U0IER = 1;

U1LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit, DLAB=1*/
U1DLL = divisor;
U1DLM = (divisor >> 8);
U1LCR = 0x03;
U1IER = 1;

U0FCR = 0x07; //enable the FIFO's
U1FCR = 0x07; //enable the FIFO's
}

void __attribute__ ((interrupt("IRQ"))) tc0(void) {
timeval--;
T0_IR = 1; // Clear interrupt flag
VICVectAddr = 0; // Acknowledge Interrupt
}

void __attribute__ ((interrupt("IRQ"))) u0(void) {
putcha(U0RBR);
U0IIR;
VICVectAddr = 0;
}

void __attribute__ ((interrupt("IRQ"))) u1(void) {
status |= (1<<UART_1);
dummy = U1RBR;
U1IIR;
VICVectAddr = 0; // Acknowledge Interrupt
}

void setInterrupt(void)
{
enableIRQ();

VICIntEnClear = ~0x000000d0;
VICIntSelect &= ~0x000000d0;
VICIntEnable = 0x000000d0;
VICVectAddr0 = (unsigned long)tc0;
VICVectCntl0 = 0x20 | TIM0;
VICVectAddr1 = (unsigned long)u0;
VICVectCntl1 = 0x20 | UART_0;
VICVectAddr2 = (unsigned long)u1;
VICVectCntl2 = 0x20 | UART_1;
}

void init(void)
{
systemInit();
ledInit();
setInterrupt();
SetUART(9600);
}

char putcha(char ch)
{
while (!(U0LSR & 0x20));
return(U0THR=ch);
}

int main (void) {
init();
while(1)
{
if (IOPIN0 & (1<<SWPIN))
{}
else
putcha(0x30);
}
}
When I run this code, I receive 0x63 on my PC?? Any suggestions ??
What am I missing...
I've tested the board with the Keil CHARM compiler, with succes.....
Almost the same code....

Regards
Jesper Kristensen
Denmark



An Engineer's Guide to the LPC2100 Series

You need to encapsulate UODLL and DODLM by setting and clearing the
DLAB

U0LCR |= 0x80; /* Set DLAB */
U0DLL = divisor;
U0DLM = (divisor>>8);
U0LCR &= ~0x80; /* Clear DLAB */ > my PC, the received byte is wrong.
> This is my test program:
>
> void SetUART(int baud){
> unsigned int divisor = pCF / (16 * baud);
>
> PINSEL0 |= 0x00050005; /* Enable UART0 & UART1 */
>
> U0IER = 0x00; // disable all interrupts
> U0IIR; // clear interrupt ID
> U0RBR; // clear receive register
> U0LSR; // clear line status
register
>
> U0LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit, DLAB=1*/
> U0DLL = divisor;
> U0DLM = (divisor >> 8);
> U0LCR = 0x03; /* DLAB = 0 - no access to UART1 Div. */
> U0IER = 1;
>
> U1LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit,
DLAB=1*/
> U1DLL = divisor;
> U1DLM = (divisor >> 8);
> U1LCR = 0x03;
> U1IER = 1;
>
> U0FCR = 0x07; //enable the FIFO's
> U1FCR = 0x07; //enable the FIFO's
> }
>
> void __attribute__ ((interrupt("IRQ"))) tc0(void) {
> timeval--;
> T0_IR = 1; // Clear interrupt
flag
> VICVectAddr = 0; // Acknowledge
Interrupt
> }
>
> void __attribute__ ((interrupt("IRQ"))) u0(void) {
> putcha(U0RBR);
> U0IIR;
> VICVectAddr = 0;
> }
>
> void __attribute__ ((interrupt("IRQ"))) u1(void) {
> status |= (1<<UART_1);
> dummy = U1RBR;
> U1IIR;
> VICVectAddr = 0; // Acknowledge
Interrupt
> }
>
> void setInterrupt(void)
> {
> enableIRQ();
>
> VICIntEnClear = ~0x000000d0;
> VICIntSelect &= ~0x000000d0;
> VICIntEnable = 0x000000d0;
> VICVectAddr0 = (unsigned long)tc0;
> VICVectCntl0 = 0x20 | TIM0;
> VICVectAddr1 = (unsigned long)u0;
> VICVectCntl1 = 0x20 | UART_0;
> VICVectAddr2 = (unsigned long)u1;
> VICVectCntl2 = 0x20 | UART_1;
> }
>
> void init(void)
> {
> systemInit();
> ledInit();
> setInterrupt();
> SetUART(9600);
> }
>
> char putcha(char ch)
> {
> while (!(U0LSR & 0x20));
> return(U0THR=ch);
> }
>
> int main (void) {
> init();
> while(1)
> {
> if (IOPIN0 & (1<<SWPIN))
> {}
> else
> putcha(0x30);
> }
> }
> When I run this code, I receive 0x63 on my PC?? Any suggestions ??
> What am I missing...
> I've tested the board with the Keil CHARM compiler, with
succes.....
> Almost the same code....
>
> Regards
> Jesper Kristensen
> Denmark



Hey

Thanks for the hint, but it did'nt work... I still got problems...

Jesper

--- In lpc2000@lpc2..., "javida13" <javida13@y...> wrote:
> You need to encapsulate UODLL and DODLM by setting and clearing the
> DLAB
>
> U0LCR |= 0x80; /* Set DLAB */
> U0DLL = divisor;
> U0DLM = (divisor>>8);
> U0LCR &= ~0x80; /* Clear DLAB */ > > my PC, the received byte is wrong.
> > This is my test program:
> >
> > void SetUART(int baud){
> > unsigned int divisor = pCF / (16 * baud);
> >
> > PINSEL0 |= 0x00050005; /* Enable UART0 & UART1 */
> >
> > U0IER = 0x00; // disable all interrupts
> > U0IIR; // clear interrupt ID
> > U0RBR; // clear receive register
> > U0LSR; // clear line status
> register
> >
> > U0LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit, DLAB=1*/
> > U0DLL = divisor;
> > U0DLM = (divisor >> 8);
> > U0LCR = 0x03; /* DLAB = 0 - no access to UART1 Div. */
> > U0IER = 1;
> >
> > U1LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit,
> DLAB=1*/
> > U1DLL = divisor;
> > U1DLM = (divisor >> 8);
> > U1LCR = 0x03;
> > U1IER = 1;
> >
> > U0FCR = 0x07; //enable the FIFO's
> > U1FCR = 0x07; //enable the FIFO's
> > }
> >
> > void __attribute__ ((interrupt("IRQ"))) tc0(void) {
> > timeval--;
> > T0_IR = 1; // Clear interrupt
> flag
> > VICVectAddr = 0; // Acknowledge
> Interrupt
> > }
> >
> > void __attribute__ ((interrupt("IRQ"))) u0(void) {
> > putcha(U0RBR);
> > U0IIR;
> > VICVectAddr = 0;
> > }
> >
> > void __attribute__ ((interrupt("IRQ"))) u1(void) {
> > status |= (1<<UART_1);
> > dummy = U1RBR;
> > U1IIR;
> > VICVectAddr = 0; // Acknowledge
> Interrupt
> > }
> >
> > void setInterrupt(void)
> > {
> > enableIRQ();
> >
> > VICIntEnClear = ~0x000000d0;
> > VICIntSelect &= ~0x000000d0;
> > VICIntEnable = 0x000000d0;
> > VICVectAddr0 = (unsigned long)tc0;
> > VICVectCntl0 = 0x20 | TIM0;
> > VICVectAddr1 = (unsigned long)u0;
> > VICVectCntl1 = 0x20 | UART_0;
> > VICVectAddr2 = (unsigned long)u1;
> > VICVectCntl2 = 0x20 | UART_1;
> > }
> >
> > void init(void)
> > {
> > systemInit();
> > ledInit();
> > setInterrupt();
> > SetUART(9600);
> > }
> >
> > char putcha(char ch)
> > {
> > while (!(U0LSR & 0x20));
> > return(U0THR=ch);
> > }
> >
> > int main (void) {
> > init();
> > while(1)
> > {
> > if (IOPIN0 & (1<<SWPIN))
> > {}
> > else
> > putcha(0x30);
> > }
> > }
> > When I run this code, I receive 0x63 on my PC?? Any
suggestions ??
> > What am I missing...
> > I've tested the board with the Keil CHARM compiler, with
> succes.....
> > Almost the same code....
> >
> > Regards
> > Jesper Kristensen
> > Denmark



--- In lpc2000@lpc2..., "jesperkr123" <jk@t...> wrote:
Hey

Well I solved my problem... I calculated a wrong divisor.

unsigned int divisor = pCF / (16 * baud); //Works in Keil, but not GNU

should be:

unsigned int divisor = (int)(((FOSC*PLL_M/VPBDIV_VAL) / ((baud) *
16.0)) + 0.5); // Works in GNU

Jesper
> Hey
>
> Thanks for the hint, but it did'nt work... I still got problems...
>
> Jesper
>
> --- In lpc2000@lpc2..., "javida13" <javida13@y...> wrote:
> > You need to encapsulate UODLL and DODLM by setting and clearing
the
> > DLAB
> >
> > U0LCR |= 0x80; /* Set DLAB */
> > U0DLL = divisor;
> > U0DLM = (divisor>>8);
> > U0LCR &= ~0x80; /* Clear DLAB */
> >
> >
> > > my PC, the received byte is wrong.
> > > This is my test program:
> > >
> > > void SetUART(int baud){
> > > unsigned int divisor = pCF / (16 * baud);
> > >
> > > PINSEL0 |= 0x00050005; /* Enable UART0 & UART1
*/
> > >
> > > U0IER = 0x00; // disable all
interrupts
> > > U0IIR; // clear interrupt ID
> > > U0RBR; // clear receive
register
> > > U0LSR; // clear line status
> > register
> > >
> > > U0LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit,
DLAB=1*/
> > > U0DLL = divisor;
> > > U0DLM = (divisor >> 8);
> > > U0LCR = 0x03; /* DLAB = 0 - no access to UART1 Div. */
> > > U0IER = 1;
> > >
> > > U1LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit,
> > DLAB=1*/
> > > U1DLL = divisor;
> > > U1DLM = (divisor >> 8);
> > > U1LCR = 0x03;
> > > U1IER = 1;
> > >
> > > U0FCR = 0x07; //enable the FIFO's
> > > U1FCR = 0x07; //enable the FIFO's
> > > }
> > >
> > > void __attribute__ ((interrupt("IRQ"))) tc0(void) {
> > > timeval--;
> > > T0_IR = 1; // Clear
interrupt
> > flag
> > > VICVectAddr = 0; // Acknowledge
> > Interrupt
> > > }
> > >
> > > void __attribute__ ((interrupt("IRQ"))) u0(void) {
> > > putcha(U0RBR);
> > > U0IIR;
> > > VICVectAddr = 0;
> > > }
> > >
> > > void __attribute__ ((interrupt("IRQ"))) u1(void) {
> > > status |= (1<<UART_1);
> > > dummy = U1RBR;
> > > U1IIR;
> > > VICVectAddr = 0; // Acknowledge
> > Interrupt
> > > }
> > >
> > > void setInterrupt(void)
> > > {
> > > enableIRQ();
> > >
> > > VICIntEnClear = ~0x000000d0;
> > > VICIntSelect &= ~0x000000d0;
> > > VICIntEnable = 0x000000d0;
> > > VICVectAddr0 = (unsigned long)tc0;
> > > VICVectCntl0 = 0x20 | TIM0;
> > > VICVectAddr1 = (unsigned long)u0;
> > > VICVectCntl1 = 0x20 | UART_0;
> > > VICVectAddr2 = (unsigned long)u1;
> > > VICVectCntl2 = 0x20 | UART_1;
> > > }
> > >
> > > void init(void)
> > > {
> > > systemInit();
> > > ledInit();
> > > setInterrupt();
> > > SetUART(9600);
> > > }
> > >
> > > char putcha(char ch)
> > > {
> > > while (!(U0LSR & 0x20));
> > > return(U0THR=ch);
> > > }
> > >
> > > int main (void) {
> > > init();
> > > while(1)
> > > {
> > > if (IOPIN0 & (1<<SWPIN))
> > > {}
> > > else
> > > putcha(0x30);
> > > }
> > > }
> > > When I run this code, I receive 0x63 on my PC?? Any
> suggestions ??
> > > What am I missing...
> > > I've tested the board with the Keil CHARM compiler, with
> > succes.....
> > > Almost the same code....
> > >
> > > Regards
> > > Jesper Kristensen
> > > Denmark