P4080 UART setting of baudrate

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

P4080 UART setting of baudrate

Jump to solution
1,357 Views
sumanthmushiger
Contributor III

Hello All,

I am trying to set the buudrate of P4080 UART0, to 115200 for 333Khz DUART INPUT CLOCK.

But the Uboot upon bootup as set UDLB & UMLB  to  115,200  as   "00D9" i.e.,  for 400KHz configuration.

I can change every other DUART register value except for (UDLB & UMLB) and also send & receive data 'perfectly' using a "waiit" function ..

Please can any one tell me, where am I going wrong in it? 

If I remove this "waiit", then I won't have proper communication, I can see something like 1st character and then 6th ..randomly.

P.S : THROUGH T32 debugger have a checked the value of UDLB1 = D9 & UMLB1 = 00.

And also the communicator computer is set to 115200 as standard & is tested many a times.

Here is my code

int write(int file, char *ptr, int len) {

        unsigned int i;

        int de =1;                                  // de = 1 for write & de = 0 for read function

        initialize_Uart(de);

        /* Transmitting a char from UART */

        for (i = 0; i < len; ++i, ++ptr)

        {

                    OUT_8(DUART1_UTHR, *ptr);

//                   waiit(); //TODO: frequency matching is not happening so, either the buffer is getting over written or the receiver is too slow.

        }

    return len;

}

void waiit(){

    int i;

    for(i=0;i<99999;i++);

}

void initialize_Uart(int);

void initialize_Uart(int de)

{

#define DUART1_UTHR  0xFE11C500 //transmitter buffer register

#define DUART1_UDLB  0xFE11C500 // to set the baud rate

#define DUART1_UMLB  0xFE11C501 // higher bite of baud rate

#define DUART1_UIER1 0xFE11C501 //  Modem interrupt register  00001111

#define DUART1_UFCR1 0xFE11C502 //FIFO control register  1,0,0,0,0,1,1,1

#define DUART1_ULCR1 0xFE11C503 // Line control register, for parity and other checks

#define DUART1_UMCR1 0xFE11C504    // modem control register  0x12 for loop back & ready to send 0x00 to clear these two

#define DUART1_ULSR1 0xFE11C505 // Line status register

#define DUART1_UMSR1 0xFE11C506 // modem status register -> to check if the peripheral device is ready to transmit.

#define DUART1_UDSR1 0xFE11C510 // Check if the buffer is ready to transmit or receive

#if !defined( OUT_8 )

                #define    OUT_8(p,d)        (*(volatile char *)(p) = (char)(d))

            #endif

            #if !defined( IN_8 )

                #define    IN_8(p)            ((*(volatile char *)(p)))

            #endif

    if(de==1)                                                /* Initialization of UART port 1 for writing */

    {

                OUT_8(DUART1_UIER1, 0x00);                         //disable interrupts

                //OUT_8(DUART1_ULCR1, 0x80);                         // Bank select enable

                                                                /*You can change the BAUD RATE HERE, but using default baudrate set by >U-boot is error free */

//                OUT_8(DUART1_UDLB, (baud_rate & 0xff));

//                OUT_8(DUART1_UMLB, ((baud_rate>>8)& 0xff));     //set the baud rate to 115200

                OUT_8(DUART1_UDLB, 0x0000);  // VALUE for 00B5

                OUT_8(DUART1_UMLB, 0xB500);

                OUT_8(DUART1_ULCR1, 0x03);                         // 8 bit data, 1stop, no parity

                OUT_8(DUART1_UMCR1, 0x02);                         // Ready to send/receive

                OUT_8(DUART1_UFCR1, 0x07);                         // FIFO enable | receiver soft reset | transmitter soft reset

                //OUT_8(DUART1_UIER1, 0x0f);                        // enable interrupts

                /* End of Initialization of UART port 1 */

    }

    if(de==0)                                                    /* Initialization of UART port 1 for reading */

    {

                OUT_8(DUART1_UIER1, 0x00);                                 //disable interrupts

                OUT_8(DUART1_UDLB, 0x0000);

                OUT_8(DUART1_UMLB, 0xB500);

                //OUT_8(DUART1_ULCR1, 0x80);                             // Bank select enable

                //OUT_8(DUART1_UDLB, (baud_rate & 0xff));

                //OUT_8(DUART1_UMLB, ((baud_rate>>8)& 0xff));             //set the baud rate to 115200

                OUT_8(DUART1_ULCR1, 0x03);                                 // 8 bit data, 1stop, no parity

                OUT_8(DUART1_UMCR1, 0x02);                                 // Ready to receive

    }

}


Regards,

Sumanth

Labels (1)
Tags (2)
0 Kudos
1 Solution
658 Views
marius_grigoras
NXP Employee
NXP Employee

Hi Sumanth,

I investigated your flow and I can successfully read the new values of UDLB/UMLB after a write operation (using CW). In our code, firstly, we read ULCR1 - you can make a try (in the  P4080 reference manual, also, there is a note about the order register UART programming - "Set data attributes and control bits in the ULCR, UFCR, UAFR, UMCR, UDLB, and UDMB.").

Regarding the wait() function, from our experience, this is mandatory for some boards (included P4080DS). In our code we make a single read from IVPR register for simulating the wait(). Below, you have our wait() code - we're calling this function with time=1. You can try to make something similar, your for() that simulates the wait() is very time consuming.

void
wait(int time)
{
    short x, *rom_read;
    /* Just use IVPR */
    long ivpr = 0;
    asm ("mfspr %0, 63" : "=r" (ivpr));
    rom_read = (short *)ivpr;
    while (time-- > 0) {
x = *rom_read;
    }
    return;
}

Regards,

Marius

View solution in original post

0 Kudos
4 Replies
658 Views
marius_grigoras
NXP Employee
NXP Employee

Hi Sumanth,

I'm not sure if I understood your problem, but in our CW UART project for P4080DS we're making the same wait() after writing UDLB, UMLB registers -> you can take a look in duart.c file from ${CW_PA}\PA\PA_Support\Serial\Common\duart.c.

...

cnt = GetClockDivider(baud_rate);

    /* set divisor latch count */

    OUT8(port + OFFS_LCR, LCR_DBIT8|LCR_STOP1|LCR_PARDIS|LCR_DIVLAT);

    IOWAIT();

    OUT8(port + OFFS_DLM, cnt >> 8);

    IOWAIT();

    OUT8(port + OFFS_DLL, cnt     );

IOWAIT();

...

You can debug this setting up a bp in GetClockDivider using debugger shell after you started the DebugDownload stationary P4080DS project:

bp GetClockDivider

Regards,

Marius

0 Kudos
658 Views
sumanthmushiger
Contributor III

Thank You Marius,

Probably, I didn't describe the problem properly. But, here I'll do it.

The Problem is :

1) Inspite of updating the ULB & MLB registers like this :

OUT_8(DUART1_UDLB, 0x0000);
OUT_8(DUART1_UMLB, 0xB500);

where DUART1_UDLB = 0xFE11C500

and    DUART1_UMLB = 0xFE11C501

I am not able to see the value changed in the register on my debugger.

But, When I change the values of other registers I can see the change in the registor value for their respective register.

WHY ONLY THE UDLB & UMLB registers are NOT getting updated ??? Should they be set only in the boot process? 

2) I want to remove that wait() function, boz, it is consuming more time than the TICK rate of my RTOS.

How can I do it?  is the wait() function very necessary ?  I don't think so, if the buad rate is set perfectly.

Regards,

Sumanth

659 Views
marius_grigoras
NXP Employee
NXP Employee

Hi Sumanth,

I investigated your flow and I can successfully read the new values of UDLB/UMLB after a write operation (using CW). In our code, firstly, we read ULCR1 - you can make a try (in the  P4080 reference manual, also, there is a note about the order register UART programming - "Set data attributes and control bits in the ULCR, UFCR, UAFR, UMCR, UDLB, and UDMB.").

Regarding the wait() function, from our experience, this is mandatory for some boards (included P4080DS). In our code we make a single read from IVPR register for simulating the wait(). Below, you have our wait() code - we're calling this function with time=1. You can try to make something similar, your for() that simulates the wait() is very time consuming.

void
wait(int time)
{
    short x, *rom_read;
    /* Just use IVPR */
    long ivpr = 0;
    asm ("mfspr %0, 63" : "=r" (ivpr));
    rom_read = (short *)ivpr;
    while (time-- > 0) {
x = *rom_read;
    }
    return;
}

Regards,

Marius

0 Kudos
658 Views
sumanthmushiger
Contributor III

Hello Marius,

Thank You very much. I realise the I did the mistake in the order of addressing the registers.

And also, thanks for the wait() function. I really believe this function is logically true & will solve my problem.

Thanking you,

Regards,

Sumanth

0 Kudos