This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/PROCESSOR-SDK-AM437X: PRU UART register access

Part Number: PROCESSOR-SDK-AM437X

Tool/software: TI-RTOS

In example PRU_Hardware_UART(AM437x,  PRU Software Support Package release 3.0) , we can acccess the pro_uart0 registers like this:

 /* Set up UART to function at 115200 baud - DLL divisor is 104 at 16x oversample
  * 192MHz / 104 / 16 = ~115200 */
 CT_UART.DLL = 104;
 CT_UART.DLH = 0;
 CT_UART.MDR = 0x0;
 /* Enable Interrupts in UART module. This allows the main thread to poll for
  * Receive Data Available and Transmit Holding Register Empty */
 CT_UART.IER = 0x7;
 /* If FIFOs are to be used, select desired trigger level and enable
  * FIFOs by writing to FCR. FIFOEN bit in FCR must be set first before
  * other bits are configured */
 /* Enable FIFOs for now at 1-byte, and flush them */
 CT_UART.FCR = (0x8) | (0x4) | (0x2) | (0x1);
 //CT_UART.FCR = (0x80) | (0x4) | (0x2) | (0x01); // 8-byte RX FIFO trigger
 /* Choose desired protocol settings by writing to LCR */
 /* 8-bit word, 1 stop bit, no parity, no break control and no divisor latch */
 CT_UART.LCR = 3;
 for (cnt = 0; cnt < MAX_CHARS; cnt++){
    /* Load character, ensure it is not string termination */
    if ((tx = hostBuffer.data[cnt]) == '\0')
        break;
    CT_UART.THR = tx;
     /* Because we are doing loopback, wait until LSR.DR == 1
      * indicating there is data in the RX FIFO */
    while ((CT_UART.LSR & 0x1) == 0x0);
     /* Read the value from RBR */
     buffer[cnt] = CT_UART.RBR;
     /* Wait for TX FIFO to be empty */
     while (!((CT_UART.FCR & 0x2) == 0x2));
 }
but if we want to access the pr1_uart0 registers in PRU_ICSS0, how to get it?
  • The RTOS team have been notified. They will respond here.
  • Hi zhuangbin,

    The CT_UART is mapped to PRU_UART with originated address 0x00028000 which is PRU-ICSS 0/1 UART0 local address, see pru_uart.h and AM437x_PRU_SS1.cmd:

    PRU_UART : org = 0x00028000 len = 0x00000038 CREGISTER=7
    volatile __far pruUart CT_UART __attribute__((cregister("PRU_UART", near), peripheral));

    To access the pr1_uart0 registers from PRU_ICSS0, have you tried to modify the PRU_UART local address to global address? see the footnote of
    Table 2-1. L3 Memory Map in TRM:
    For PRU-ICSS0/1, the PRU can access the other PRU-ICSS memory space through internal expansion ports. The PRU can
    access the neighbor PRU-ICSS memory starting at 256KB/0x0004_0000 range. The address seen by the 2nd PRU-ICSS will
    get translated by hardware logic in PRU-ICSS, 0x0004_0000 will get subtracted.

    And 30.3.2 Global Memory Map.

    Regards,
    Garrett
  • Yes,I know this principle, but how should I implement it ? Can I use  the pattern like this:

    PRU_UART_1 : org = 0x00068000 len = 0x00000038 CREGISTER=7
    volatile __far pruUart CT_UART_1 __attribute__((cregister("PRU_UART_1", near), peripheral));

  • zuangbin,

    The global memory address approach should enable the access to pr1_uart0 registers from PRU_ICSS0. Were you able to make progress on this?

    Regards,
    Garrett
  • I try to use :
    PRU_UART_1 : org = 0x00068000 len = 0x00000038 CREGISTER=7
    volatile __far pruUart CT_UART_1 __attribute__((cregister("PRU_UART_1", near), peripheral));
    but it does not work.
    and how to use the global memory?
  • zhuangbin,

    I was out of office and just back. Have you tired to use 0x54468000 as the global address of PRU_UART_1 when accessing to pr1_uart0 registers from PRU_ICSS0? see clarification of global and local address map - e2e.ti.com/.../282147

    Regards,
    Garrett
  • Hi,

    I am drawing a new PCB board for the application requirements. after that, I will try it and tell the result.

    thanks.

  • Hi,

    I had try as follow:

    in the file AM437x_PRU_SS1.cmd, add a line : PRU_UART_1  : org = 0x54428000 len = 0x00000038 CREGISTER=7

    in the file pru_uart.h, add a line: volatile __far pruUart CT_UART_1 __attribute__((cregister("PRU_UART_1", near), peripheral));

    change the PRU_Hardware_UART.c in the Project PRU_Hardware_UART the CT_UART to the CT_UART_1. the code as follow:

    void main(){
     uint8_t tx;
     uint8_t cnt;
     /* TODO: If modifying this to send data through the pins then PinMuxing
      * needs to be taken care of prior to running this code.
      * This is usually done via a GEL file in CCS or by the Linux driver */

     /*** INITIALIZATION ***/
     /* Set up UART to function at 115200 baud - DLL divisor is 104 at 16x oversample
      * 192MHz / 104 / 16 = ~115200 */
     CT_UART_1.DLL = 104;
     CT_UART_1.DLH = 0;
     CT_UART_1.MDR = 0x0;
     /* Enable Interrupts in UART module. This allows the main thread to poll for
      * Receive Data Available and Transmit Holding Register Empty */
     CT_UART_1.IER = 0x7;
     /* If FIFOs are to be used, select desired trigger level and enable
      * FIFOs by writing to FCR. FIFOEN bit in FCR must be set first before
      * other bits are configured */
     /* Enable FIFOs for now at 1-byte, and flush them */
     CT_UART_1.FCR = (0x8) | (0x4) | (0x2) | (0x1);
     //CT_UART.FCR = (0x80) | (0x4) | (0x2) | (0x01); // 8-byte RX FIFO trigger
     /* Choose desired protocol settings by writing to LCR */
     /* 8-bit word, 1 stop bit, no parity, no break control and no divisor latch */
     CT_UART_1.LCR = 3;
     /* Enable loopback for test */
    // CT_UART.MCR = 0x10;
     /* Choose desired response to emulation suspend events by configuring
      * FREE bit and enable UART by setting UTRST and URRST in PWREMU_MGMT */
     /* Allow UART to run free, enable UART TX/RX */
     CT_UART_1.PWREMU_MGMT = 0x6001;
     /*** END INITIALIZATION ***/
     /* Priming the 'hostbuffer' with a message */
     hostBuffer.data[0] = 'H';
     hostBuffer.data[1] = 'e';
     hostBuffer.data[2] = 'l';
     hostBuffer.data[3] = 'l';
     hostBuffer.data[4] = 'o';
     hostBuffer.data[5] = '!';
     hostBuffer.data[6] = '\0';
     /*** SEND SOME DATA ***/
     /* Let's send/receive some dummy data */
     for (cnt = 0; cnt < MAX_CHARS; cnt++){
      /* Load character, ensure it is not string termination */
      if ((tx = hostBuffer.data[cnt]) == '\0')
       break;
      CT_UART_1.THR = tx;
      /* Because we are doing loopback, wait until LSR.DR == 1
       * indicating there is data in the RX FIFO */
      while ((CT_UART_1.LSR & 0x1) == 0x0);
      /* Read the value from RBR */
      buffer[cnt] = CT_UART_1.RBR;
      /* Wait for TX FIFO to be empty */
      while (!((CT_UART_1.FCR & 0x2) == 0x2));
     }
     /*** DONE SENDING DATA ***/
     /* Disable UART before halting */
     CT_UART_1.PWREMU_MGMT = 0x0;
     /* Halt PRU core */
     __halt();
    }
    and dowdload the .out file to the PRU_ICSS0_PRU0 ,it can not work.
    if I change the CT_UART_1 back to CT_UART, and  dowdload the .out file to the PRU_ICSS1_PRU0 ,it can work. 
    I think that I loss something it need to be initialized.
    Please tell me what's wrong?
  • Hi Garrett,
    I get it. the description CT_UART_1 is not correct. it always be compiled as C7(0x00028000).So, It must use the direct address as follow:
    uint32_t *pDdr =(uint32_t *)0x00068000UL;
    *(pDdr + 0x08) = 104; // CT_UART.DLL = 104; the 0x08 is the DLL 32bits offset address.
    and so on.