a problem in "Clocking the UART" on P2010 SoC

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

a problem in "Clocking the UART" on P2010 SoC

Jump to solution
989 Views
esode
Contributor III

Hello all,

I initialized p2010 by gdb and I wrote a .c code to configure the DUART by register level.

I checked that writing/reading on UART registers is working e.g. : I changed the SB bit of UARt Line Control Register(ULCR) and saw the

SOUT pin changing on the oscilloscope. Up to here, everything is ok. However, I try to write "A" character in a while loop and I look

at the SOUT pin, and it is always in high voltage; so UART is not sending anything. I guess UART cannot get its clock from

the platform bus(CCB), because changing divisor value doesn't affect test1(,which is dummy variable to count how many times "A" is sent).

I appreciate your any help. I wonder maybe to enable the UART clock.

Here is the my main.c function. It is very simple and readable:

/*  uart registers configuration - THE ADDRESSES   */

#define UART0_1  0x100 // 0x0 for UART0 and 0x100 for UART1

#define URBR_ADDR  (0xE0004500 + UART0_1) // read-only

#define UTHR_ADDR  (0xE0004500 + UART0_1) // Transmit Holding Register

#define UDLB_ADDR  (0xE0004500 + UART0_1) // Divisior LeastSignificant Byte Register

#define UIER_ADDR  (0xE0004501 + UART0_1)

#define UDMB_ADDR  (0xE0004501 + UART0_1) // Divisior MostSignificant Byte Register

#define UIIR_ADDR  (0xE0004502 + UART0_1) // read-only

#define UFCR_ADDR  (0xE0004502 + UART0_1)

#define UAFR_ADDR  (0xE0004502 + UART0_1)

#define ULCR_ADDR  (0xE0004503 + UART0_1) // Line Control Register

#define UMCR_ADDR  (0xE0004504 + UART0_1)

#define ULSR_ADDR  (0xE0004505 + UART0_1) // read-only

#define UMSR_ADDR  (0xE0004506 + UART0_1) // read-only

#define USCR_ADDR  (0xE0004507 + UART0_1)

#define UDSR_ADDR  (0xE0004510 + UART0_1) // read-only

/*  uart registers configuration - THE VALUES   */

#define ULCR_DLAB1 0x83    // the value for Line Control Register

#define ULCR_DLAB0 0x03    // the value for Line Control Register

unsigned int ulsr;

unsigned int test1;

unsigned int test2;

/***************************** MAIN ******************************************/

int main()

{  

  test1 = 1;

  *((char *)ULCR_ADDR) =  ULCR_DLAB1;

  *((char *)UDLB_ADDR) =  0x01;

  *((char *)UDMB_ADDR) =  0x10;

  *((char *)UAFR_ADDR) =  0x00;

  test1 = 2;

  *((char *)UMCR_ADDR) =  0x00;

  *((char *)USCR_ADDR) =  0x75;  // the value is not important

  test1 = 3;

  *((char *)ULCR_ADDR) =  ULCR_DLAB0;

  *((char *)UIER_ADDR) =  0x00;

  *((char *)UFCR_ADDR) =  0x00;

  test1 = 0;

  while(1)

  {

       ulsr = *((char *)ULSR_ADDR);

       if (   ulsr & 0x0020 )  // check the 'THRE' bit of ULSR

       {

            *((char *)UTHR_ADDR) =  0x41;  // send "A"    

            test1++;    

       }

       else

            test2++;

  }

  return 0;

}

Labels (1)
1 Solution
764 Views
esode
Contributor III

Actually, we find the problem , now UART is working. I realized that the software code (C code) cannot write on the Uart registers but gdb codes can. So, we thought that the executable code from .elf file must be in a cache-inhibited region of the memory map. So, we changed the TLB entry on MMU to  be cache-inhibited. Now, it is working. The solution  seems to come from a very interesting point, but I wanted it to share with you.

Thanks.

View solution in original post

0 Kudos
8 Replies
765 Views
esode
Contributor III

Actually, we find the problem , now UART is working. I realized that the software code (C code) cannot write on the Uart registers but gdb codes can. So, we thought that the executable code from .elf file must be in a cache-inhibited region of the memory map. So, we changed the TLB entry on MMU to  be cache-inhibited. Now, it is working. The solution  seems to come from a very interesting point, but I wanted it to share with you.

Thanks.

0 Kudos
764 Views
marius_grigoras
NXP Employee
NXP Employee

Thanks for sharing this!

Btw, you setup the CCSR and PIXIS spaces non-cacheable, right?

I just want to be sure, in CW we also setup these areas non-cacheable and the DDR cacheable.

Marius

0 Kudos
764 Views
esode
Contributor III

CCSR space is non-cacheable (cache inhibited). I loaded my code  to SRAM, which is converted to SRAM

from L2 cache. This boot-rom loaction (SRAM) is also  non-cacheable and guarded.

In our custom board, we didnot use PIXIS, so there is no memory map for PIXIS.

In the example gdb project for p2020 (for Freescale ds or rdb),  there is a  memory map space for

PIXIS(non cacheable, guarded) and DDR(cacheable, not guarded). I am not using CW, I have brought-up

the p2010 by gdb. Probably, making the boot-rom location  "non-cacheable and guarded" is good idea.

Eser

764 Views
marius_grigoras
NXP Employee
NXP Employee

Quoting from e500v2 RM:

"The instruction and data caches are enabled and disabled with the cache enable (CE) bits in

L1CSR1 and L1CSR0, respectively. Disabling a cache does not cause all memory accesses to be

performed as caching inhibited. When caching-inhibited accesses are desired, the pages must be

marked as caching inhibited in the MMU pages."

Maybe this is applicable also for L2 cache (which was configured as SRAM memory in your case).

Marius

0 Kudos
764 Views
lunminliang
NXP Employee
NXP Employee

There is serial exmaple project in CW10.3 maybe you can refer to.

Go to: File->Import...->General->Existing Projects into Workspace and press "Next". Select the folder in the Import Projects root directory: C:\Program Files\Freescale\CW PA v10.3\PA\PA_Support\Serial\P2010DS_serial\ and press "Next".


0 Kudos
764 Views
esode
Contributor III

I use Ubuntu and I checked the proper path according to Windows, however I could not find the project. Actually, I use CW to open a new  project, where there is a default "Hello world!" project. The project writes "Hello world" to the serial port by Uart. I went through the Uart related .c and .h files in the .elf file, which is compiled by CW. I didn't get enough information about whether clocking is necessary to the UART. A reference manual says that Uart controller on SOC gets its clock from CCB on P2010 core. However, I do not know whether a programmer should configure a register for clocking.   I am trying to use a similar code to the duart.c file, where you may see the configuration of UART registers. Now, I am just trying to write on Uart and see it on SOUT pin by using scope.

0 Kudos
764 Views
marius_grigoras
NXP Employee
NXP Employee

On linux you can find the above files on next relative path (relative to your install directory): PA/PA_Support/Templates/Sources/P2010DS/P2010DS_init.c

PA/PA_Support/Serial/P2010DS_serial

The initialization code from init.c (the PIXIS part) and the serial code from Serial project should help you.

Let's describe a little bit the "serial" flow:

Basically the printf routine implemented in compiler libs (libc_E500V2.a) is calling the GetClockDivider() function implemented in UART* lib. Based on the hardware PIXIS input, GetClockDivider calculates the systemClock (sysclk).

You can see the source EWL libs in: PA/PA_Support/ewl and you can find information about how these can be re-build in PA/Help/PDF/Power Arch Build Tools Reference.pdf ("How to Rebuild the EWL Libraries" chapter).

Regards,

Marius

0 Kudos
764 Views
marius_grigoras
NXP Employee
NXP Employee

If you'll use the serial code from P2010DS_serial project is mandatory to initialize the PIXIS module:

     - TLB init

     - LAW init

     - eLBC regs init for CS3

You can take a look in the PA\PA_Support\Templates\Sources\P2010\P2010DS\P2010DS_init.c if you want to see how CW set up this part.

Regards,

Marius

0 Kudos