LP-AM243: PRU UART error on LP AM243x

Part Number: LP-AM243
Other Parts Discussed in Thread: TMDS243EVM, TMDS64DC01EVM

Tool/software:

Hello

I'm working with the PRU on the AM243 and have been trying to run the PRU hardware UART example for a few days. I have reviewed almost all the past issues related to PRU UART on the ti forum but have not reached a conclusion. I used the .cmd and pru_uart.h files from the AM64. I did the pinmux settings via CCS, but I couldn't get a result. I'm new to PRU at TI and would be very grateful for your help. The files I'm using and the necessary photos are attached.

First I load the code into the r core. Then I run the m core, disconnect it and load the pru code into the iccsg0 pru 0 core.

 pru_hardware.uart.c:


#include <stdint.h>
#include <pru_uart.h>

#define FIFO_SIZE 16
#define MAX_CHARS 8

struct {
uint8_t msg; // Not used today
uint8_t data[FIFO_SIZE];
} hostBuffer;

uint8_t buffer[MAX_CHARS];

void main(void)
{
uint8_t tx;
uint8_t cnt;


CT_UART.DIVLSB_bit.DLL = 104; // CT_UART.DIVLSB = 104;
CT_UART.DIVMSB_bit.DLH = 0;//CT_UART.DIVMSB = 0;
CT_UART.MODE = 0x0;


CT_UART.INT_EN = 0x7;


/* TODO: Add 8-byte RX FIFO trigger */
//CT_UART.FCR = (0x8) | (0x4) | (0x2) | (0x1); /* AM335x: FCR, set to 0xF */
CT_UART.FCR = (0x80) | (0x4) | (0x2) | (0x01); // 8-byte RX FIFO trigger


CT_UART.LCTR = 3;
// CT_UART.LCTR = 3; /* AM335x: LCR */


CT_UART.MCTR = 0x10;

CT_UART.PWR = 0x6001;


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';


for (cnt = 0; cnt < MAX_CHARS; cnt++) {

if ((tx = hostBuffer.data[cnt]) == '\0')
break;

CT_UART.THR = tx;

//while ((CT_UART.LSR1_bit.DR == 0x0));
while ((CT_UART.LSR1 & 0x1) == 0x0);

buffer[cnt] = CT_UART.RBR;
// buffer[cnt] = CT_UART.RBR_TBR_bit.RBR_DATA; /* AM335x: RBR */

/* Wait for TX FIFO to be empty */
while (!((CT_UART.FCR & 0x2) == 0x2));
//while (!((CT_UART.IIR_bit.INTID) == 0x1));
// while (!((CT_UART.INT_FIFO_bit.IIR_INTID) == 0x1)); /* AM335x: FCR */
/* original code: while (!((CT_UART.FCR & 0x2) == 0x2)); */
/* TODO: Since this is a read, IIR should be used, not FCR.
I assume they meant to put
while (!((CT_UART.IIR & 0x2) == 0x2));
*/
}

CT_UART.PWR = 0x0;

__halt();
}


pru_uart.h:



#ifndef _PRU_UART_H_
#define _PRU_UART_H_

/* PRU UART register set */
typedef struct {

/*
* PRU_UART_RBR_TBR register bit field
* RBR and TBR / THR register pair
*
* This is a unique register pair in that RBR and THR
* share the same address. RBR is read-only while THR is
* write-only.
*
* Additionally, RBR and THR share an address with DLL. To
* read/write RBR/THR write 0 to the DLAB bit in the LCR
* register. To modify DLL write a 1.
*
* DLL also has a dedicated
* address which does not require toggling the DLAB bit.
*/
union {
/* PRU_UART_RBR register bit field */
union {
volatile uint32_t RBR;

volatile struct {
unsigned DATA : 8; // 7:0
unsigned rsvd8 : 24; // 31:8
} RBR_bit;
};

/* PRU_UART_THR register bit field */
union {
volatile uint32_t THR;

volatile struct {
unsigned DATA : 8; // 7:0
unsigned rsvd8 : 24; // 31:8
} THR_bit;
};
}; // 0x0

/* PRU_UART_INT_EN register bit field */
union {
volatile uint32_t INT_EN;

volatile struct {
uint32_t ERBI : 1; // 0
uint32_t ETBEI : 1; // 1
uint32_t ELSI : 1; // 2
uint32_t EDSSI : 1; // 3
uint32_t rsvd4 : 28; // 31:4
} INT_EN_bit;
}; // 0x4

/*
* IIR and FCR register pair
* This is a unique register pair in that IIR and FCR
* share the same address. IIR is read-only while FCR is
* write-only.
*/
union {
/* PRU_UART_IIR register bit field */
union {
volatile uint32_t IIR;

volatile struct {
unsigned IPEND : 1; // 0
unsigned INTID : 3; // 3:1
unsigned rsvd4 : 2; // 5:4
unsigned FIFOEN : 2; // 7:6
unsigned rsvd8 : 24; // 31:8
} IIR_bit;
};

/* PRU_UART_FCR register bit field */
union {
volatile uint32_t FCR;

volatile struct {
unsigned FIFOEN : 1; // 0
unsigned RXCLR : 1; // 1
unsigned TXCLR : 1; // 2
unsigned DMAMODE1 : 1; // 3
unsigned rsvd4 : 2; // 5:4
unsigned RXFIFTL : 2; // 7:6
unsigned rsvd8 : 24; // 31:8
} FCR_bit;
};
}; // 0x8

/* PRU_UART_LCTR register bit field */
union {
volatile uint32_t LCTR;

volatile struct {
uint32_t WLS0 : 1; // 0
uint32_t WLS1 : 1; // 1
uint32_t STB : 1; // 2
uint32_t PEN : 1; // 3
uint32_t EPS : 1; // 4
uint32_t SP : 1; // 5
uint32_t BC : 1; // 6
uint32_t DLAB : 1; // 7
uint32_t rsvd8 : 24; // 31:8
} LCTR_bit;
}; // 0xc

/* PRU_UART_MCTR register bit field */
union {
volatile uint32_t MCTR;

volatile struct {
uint32_t DTR : 1; // 0
uint32_t RTS : 1; // 1
uint32_t OUT1 : 1; // 2
uint32_t OUT2 : 1; // 3
uint32_t LOOP : 1; // 4
uint32_t AFE : 1; // 5
uint32_t rsvd6 : 26; // 31:6
} MCTR_bit;
}; // 0x10

/* PRU_UART_LSR1 register bit field */
union {
volatile uint32_t LSR1;

volatile struct {
uint32_t DR : 1; // 0
uint32_t OE : 1; // 1
uint32_t PE : 1; // 2
uint32_t FE : 1; // 3
uint32_t BI : 1; // 4
uint32_t THRE : 1; // 5
uint32_t TEMT : 1; // 6
uint32_t RXFIFOE : 1; // 7
uint32_t rsvd8 : 24; // 31:8
} LSR1_bit;
}; // 0x14

/* PRU_UART_MSR register bit field */
union {
volatile uint32_t MSR;

volatile struct {
uint32_t DCTS : 1; // 0
uint32_t DDSR : 1; // 1
uint32_t TERI : 1; // 2
uint32_t DCD : 1; // 3
uint32_t CTS : 1; // 4
uint32_t DSR : 1; // 5
uint32_t RI : 1; // 6
uint32_t CD : 1; // 7
uint32_t rsvd8 : 24; // 31:8
} MSR_bit;
}; // 0x18

/* PRU_UART_SCRATCH register bit field */
union {
volatile uint32_t SCRATCH;

volatile struct {
uint32_t DATA : 8; // 7:0
uint32_t rsvd8 : 24; // 31:8
} SCRATCH_bit;
}; // 0x1c

/* PRU_UART_DIVLSB register bit field */
union {
volatile uint32_t DIVLSB;

volatile struct {
uint32_t DLL : 8; // 7:0
uint32_t rsvd8 : 24; // 31:8
} DIVLSB_bit;
}; // 0x20

/* PRU_UART_DIVMSB register bit field */
union {
volatile uint32_t DIVMSB;

volatile struct {
uint32_t DLH : 8; // 7:0
uint32_t rsvd8 : 24; // 31:8
} DIVMSB_bit;
}; // 0x24

/* PRU_UART_PID register bit field */
union {
volatile uint32_t PID;

volatile struct {
uint32_t PID : 32; // 31:0
} PID_bit;
}; // 0x28

uint8_t rsvd2c[4]; // 0x2c - 0x2f

/* PRU_UART_PWR register bit field */
union {
volatile uint32_t PWR;

volatile struct {
uint32_t FREE : 1; // 0
uint32_t RES : 1; // 1
uint32_t rsvd2 : 11; // 12:2
uint32_t URRST : 1; // 13
uint32_t UTRST : 1; // 14
uint32_t URST : 1; // 15
uint32_t rsvd16 : 16; // 31:16
} PWR_bit;
}; // 0x30

/* PRU_UART_MODE register bit field */
union {
volatile uint32_t MODE;

volatile struct {
uint32_t OSM_SEL : 1; // 0
uint32_t rsvd1 : 31; // 31:1
} MODE_bit;
}; // 0x34

} uart;

volatile __far uart CT_UART __attribute__((cregister("PRU_UART", far), peripheral));

#endif /* _PRU_UART_H_ */



.cmd :

/*
* AM64x_PRU0.cmd
*
* Example Linker command file for linking programs built with the C compiler
* on AM64x PRU0 cores
*
* Copyright (C) 2021-2022 Texas Instruments Incorporated - https://www.ti.com/
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

-cr /* Link using C conventions */

/* Specify the System Memory Map */
MEMORY
{
PAGE 0:
/* 12 KB PRU Instruction RAM */
PRU_IMEM : org = 0x00000000 len = 0x00003000

PAGE 1:
/* Data RAMs */
/* 8 KB PRU Data RAM 0; use only the first 4 KB for PRU0 and reserve
* the second 4 KB for RTU0 and Tx_PRU0 */
PRU0_DMEM_0 : org = 0x00000000 len = 0x00001000 CREGISTER=24
/* 8 KB PRU Data RAM 1; reserved completely for Slice1 cores - PRU1,
* RTU1 and Tx_PRU1; do not use for any Slice0 cores */
PRU0_DMEM_1 : org = 0x00002000 len = 0x00001000 CREGISTER=25
/* NOTE: Custom split of the second 4 KB of ICSS Data RAMs 0 and 1
* split equally between the corresponding RTU and Tx_PRU cores in
* each slice */
RTU0_DMEM_0 : org = 0x00001000 len = 0x00000800
TX_PRU0_DMEM_0 : org = 0x00001800 len = 0x00000800
RTU0_DMEM_1 : org = 0x00003000 len = 0x00000800
TX_PRU0_DMEM_1 : org = 0x00003800 len = 0x00000800

PAGE 2:
/* C28 needs to be programmed to point to SHAREDMEM, default is 0 */
/* 64 KB PRU Shared RAM */
PRU_SHAREDMEM : org = 0x00010000 len = 0x00010000 CREGISTER=28

/* Internal Peripherals */
/* NOTE: Use full INTC length instead of 0x200 to match the pruIntc
* structure definition in pru_intc.h, ignoring the second Constant
* Register #6 that starts at 0x200 offset within INTC */
PRU_INTC : org = 0x00020000 len = 0x00001504 CREGISTER=0
PRU_IEP1 : org = 0x0002F000 len = 0x00000100 CREGISTER=1
PRU_IEP1_0x100 : org = 0x0002F100 len = 0x0000021C CREGISTER=2
PRU_ECAP : org = 0x00030000 len = 0x00000060 CREGISTER=3
PRU_CFG : org = 0x00026000 len = 0x00000100 CREGISTER=4
PRU_CFG_0x100 : org = 0x00026100 len = 0x00000098 CREGISTER=5
/* XXX: PRU_INTC_0x200 is part of INTC space, and is therefore commented
* out as it conflicts with PRU_INTC size above. To use PRU_INTC_0x200,
* split up the pruIntc structure and CT_INTC variable in
* include/PROCESSOR/pru_intc.h */
/*PRU_INTC_0x200: org = 0x00020200 len = 0x00001304 CREGISTER=6*/
PRU_UART : org = 0x00028000 len = 0x00000038 CREGISTER=7
PRU_IEP0_0x100 : org = 0x0002E100 len = 0x0000021C CREGISTER=8
MII_G_RT : org = 0x00033000 len = 0x00000F44 CREGISTER=9
TM_CFG_PRU0 : org = 0x0002A000 len = 0x0000004C CREGISTER=10
PRU0_CTRL : org = 0x00022000 len = 0x00000030 CREGISTER=11
PA_STATS_QRAM : org = 0x00027000 len = 0x00001000 CREGISTER=12
PA_STATS_CRAM : org = 0x0002C000 len = 0x00001000 CREGISTER=13
MII_MDIO : org = 0x00032400 len = 0x00000088 CREGISTER=21
PRU_RTU_RAT0 : org = 0x00008000 len = 0x00000854 CREGISTER=22
PRU_IEP0 : org = 0x0002E000 len = 0x00000100 CREGISTER=26
MII_RT : org = 0x00032000 len = 0x00000070 CREGISTER=27

/* External Regions */
/* Random length 0x100 assigned to the below regions */
RSVD14 : org = 0x00024800 len = 0x00000100 CREGISTER=14
RSVD15 : org = 0x60000000 len = 0x00000100 CREGISTER=15
RSVD16 : org = 0x70000000 len = 0x00000100 CREGISTER=16
RSVD17 : org = 0x80000000 len = 0x00000100 CREGISTER=17
RSVD18 : org = 0x90000000 len = 0x00000100 CREGISTER=18
RSVD19 : org = 0xA0000000 len = 0x00000100 CREGISTER=19
RSVD20 : org = 0xB0000000 len = 0x00000100 CREGISTER=20
RSVD23 : org = 0xC0000000 len = 0x00000100 CREGISTER=23
/* Random length 0x10000 (max len value) assigned to programmable C29-31*/
RSVD29 : org = 0xD0000000 len = 0x00010000 CREGISTER=29
RSVD30 : org = 0xE0000000 len = 0x00010000 CREGISTER=30
RSVD31 : org = 0xF0000000 len = 0x00010000 CREGISTER=31
}

/* Specify the sections allocation into memory */
SECTIONS {
/* Forces _c_int00 to the start of PRU IRAM. Not necessary when loading
an ELF file, but useful when loading a binary */
.text:_c_int00* > 0x0, PAGE 0

.text > PRU_IMEM, PAGE 0
.stack > PRU0_DMEM_0, PAGE 1
.bss > PRU0_DMEM_0, PAGE 1
.cio > PRU0_DMEM_0, PAGE 1
.data > PRU0_DMEM_0, PAGE 1
.switch > PRU0_DMEM_0, PAGE 1
.sysmem > PRU0_DMEM_0, PAGE 1
.cinit > PRU0_DMEM_0, PAGE 1
.rodata > PRU0_DMEM_0, PAGE 1
.rofardata > PRU0_DMEM_0, PAGE 1
.farbss > PRU0_DMEM_0, PAGE 1
.fardata > PRU0_DMEM_0, PAGE 1
}