7. PRU-ICSS Firmware

7.6. PRU-ICSS ESPI

7.6.1. Introduction

PRU-ICSS eSPI serves as an example for firmware-based eSPI peripheral support. The Processor SDK package includes full source code for eSPI FW.

7.6.2. Firmware Organization

FW Item Directory
Source code <PDK>/packages/ti/drv/spi/firmware/icss_espi/src/
Design Guide <PDK>/packages/ti/drv/spi/docs/

7.6.3. Firmware Build Instruction

7.6.3.1. Build instruction from Processor SDK Release package

Pre-requisites to Building

Refer to the Processor SDK RTOS Building page for information on setting up the build environment.

Compiling Driver/Firmware

  1. make spi

Running CCS Application

CCS applications will be build and run just like any other project with one exception. Before loading the binary, from the menu-bar run Scripts > PRU_ICSS > PRU_ICSS_Init.

7.6.4. Supported EVMs

Supported EVMs and pin configurations for these EVMs are listed below. See the design document in <PDK>/packages/ti/drv/spi/docs/ for more information.

EVM Name PRU-ICSS Instances PRU-ICSS Revision
bbbAM335x 1 REV1
idkAM437x 2 REV1

bbbAM335x

Core PRU Functional Pin GPIO Pins EVM Port EVM Pin
ICSS1 PRU1
OUT[0]
OUT[1]
OUT[2]
OUT[3]
Alert
EN
IN[0]
IN[1]
IN[2]
IN[3]
SCL
CS
pr1_pru0_pru_r30_4 J3 41
pr1_pru0_pru_r30_5 J3 42
pr1_pru0_pru_r30_6 J3 39
pr1_pru0_pru_r30_7 J3 40
pr1_pru0_pru_r30_9 J3 29
pr1_pru0_pru_r30_10 J3 28
pr1_pru0_pru_r30_0 J3 45
pr1_pru0_pru_r30_1 J3 46
pr1_pru0_pru_r30_2 J3 43
pr1_pru0_pru_r30_3 J3 44
pr1_pru0_pru_r30_8 J3 27
pr1_pru0_pru_r30_11 J3 30
A8 n/a Reset GPIO_3_19 J9 26

idkAM437x

Core PRU Functional Pin GPIO Pins EVM Port EVM Pin
ICSS1 PRU0
OUT[0]
Alert
EN
IN[0]
SCL
CS
pr1_pru0_pru_r30_6 P16 49
pr1_pru0_pru_r30_11 P16 48
pr1_pru0_pru_r30_8 P16 6
pr1_pru0_pru_r30_16 P16 42
pr1_pru0_pru_r30_10 P16 46
pr1_pru0_pru_r30_9 P16 8
A9 n/a Reset GPIO_5_9 P16 32

7.6.5. eSPI Applications

We have included a simple example test application which handles PUT_IORD_SHORT, PUT_IOWR_SHORT, PUT_MEMRD32_SHORT, and PUT_MEMWR32_SHORT packets with expected address/data values. This can be used as a starting point to build your own applications, along with the following: - eSPI uses the MCSPI API

  • Open as MCSPI instance 2
  • HW interrupts must be enabled
    • i.e. HwiP_enableInterrupt(espi_cfg.intNum)
  • MCSPI_transfer() is blocking and takes a SPI_Transaction parameter which is used as follows:
    • RX Transfer: - transaction.rxBuf = <some pre-allocated buffer> - transaction.txBuf = Null - transaction.count = max packet size
    • TX Transfer: - transaction.rxBuf = Null - transaction.txBuf = <some pre-allocated buffer> - transaction.count = <size of packet>
  • The application must parse the full eSPI packet, and must respond with the full proper eSPI packet (the RSP code and CRC will be taken care of by the firmware)

example-application

/* Refer to eSPI FW Example for details */

Board_init(boardCfg);

...

/* Initialize the ESPI fw configuration */
ESPI_socInitFwCfg();

/* Get the default ESPI init configurations */
ESPI_socGetFwCfg(ESPI_INSTANCE, &espi_cfg);

/* Modify the default eSPI configurations if necessary */

/* Set the default ESPI init configurations */
  ESPI_socSetFwCfg(ESPI_INSTANCE, &espi_cfg);

/* Set GPIO pin configurations */
GPIO_setConfig(ESPI_GPIO_PIN_RESET, GPIO_DEVICE_CONFIG(espi_cfg.resetPin.port,
                                                espi_cfg.resetPin.pinNum) |
             GPIO_CFG_IN_INT_RISING | GPIO_CFG_INPUT);

/* Initialize GPIO */
GPIO_init();

/* Initialize the MCSPI paramters */
MCSPI_Params_init(&mcspiParams);

/* Init SPI driver */
MCSPI_init();

/* Enable interrupts (necessary for  */
HwiP_enableInterrupt(espi_cfg.intNum);

/* Grab ESPI handle from SoC config list */
fwHandle = (MCSPI_Handle)MCSPI_open(ESPI_INSTANCE, 0, &mcspiParams);

...

/* Read ESPI Packet */
transaction.txBuf = NULL; /* indicates we want RX */
transaction.rxBuf = (uint8_t*) rxBuf;
transaction.count = ESPI_PACKET_MAX_SIZE;
retVal = MCSPI_transfer(fwHandle, &transaction);  /* blocking */

...

/* Prepare TX response */
transaction.txBuf = (uint8_t*) txBuf;
transaction.rxBuf = NULL; /* indicates we want TX */
transaction.count = ESPI_PACKET_MAX_SIZE;

...

/* Put response in TX queue */
retVal = MCSPI_transfer(fwHandle, &transaction);

...

Examples List

Refer to the Release Notes for details concerning eSPI support across different EVMs.

Name Description Expected Results
ESPI_FwExample Driver Firmware example application for ESPI FW instances A short write to 0xDEAD or 0x0D0E0A0D will not print or return anything. A short read from 0xDEAD or 0x0D0E0A0D will return the command opcode + the byte-number of the response. A read from any other address will return the opcode minus the byte-number of the response.

Firmware Design Guide

Document Location
eSPI FIRMWARE Design Guide <PDK>/packages/ti/drv/spi/docs/ESPI_FW_DESIGN_GUIDE.doc

NOTE: For normal use of eSPI FW, there is no need to refer to the design guide. This document can be cosulted in case of interest in details of internal firmware operation, or a desire to modify the firmware.


7.7. PRU-ICSS UART

7.7.1. Introduction

PRU-ICSS UART serves as an example for PRU firmware-based UART peripheral support. The UART firmware (UART FW) allows additional UART instances for SOCs beyond those supported by SOC hardware. The Processor SDK package includes full source code for UART FW.

7.7.2. FIRMWARE FEATURES

The following UART specifications are supported by the PRU UART firmware:

  • Up to 3 UARTs are supported per PRU with the following configuration options
    • Baud rate: common baud rates up to 115200
    • Bits per transfer: 5-9 bit characters
    • Number of stop bits: 1, 1.5, 2
    • Parity: even, odd, none
    • Flow control: HW, none (SW flow control currently unsupported)
    • Full-duplex communication
  • Each UART can simultaneously support different configurations
    • UART0 can have a different baud rate, number of stop bits, etc. when compared to UART1 or UART2 in the same PRU
  • The firmware is self-contained in a single PRU
    • The firmware does not use shared resources within an ICSS including IEP Timer and Scratchpad
    • In case 3 or less UART instances are required, only one PRU core is required for the UART firmware

The table below shows a comparison of the features supported by the UART firmware with those available on hardware IP.

UART Supported Feature Hardware IP Software IP (Firmware)
Number of hardware instances SoC dependent 3 (per PRU)
Baud rates SoC dependent (up to 12 Mbps) All common baud rates between 300-115200
Bits per character 5-8 bits 5-9 bits
Number of stop bits 1, 1.5, 2 1, 1.5, 2
Parity types Even, Odd, Mark, Space, none Even, Odd, none
Flow control types HW, SW, none HW, none

7.7.3. Firmware Organization

FW Item Directory
Source code <PDK>/packages/ti/drv/uart/firmware/icss_i2c/src
Design Guide <PDK>/packages/ti/drv/uart/docs

7.7.4. Firmware Build Instructions

7.7.4.1. Build instructions from Processor SDK Release package

Pre-requisites to Building

Refer to the Processor SDK RTOS Building page for information on setting up the build environment.

Compiling UART Firmware

  • cd <PDK>/packages/ti/drv/uart
  • make firm

Compiling UART LLD

  • cd <PDK>/packages/ti/drv/uart
  • make lib

Compiling UART Driver & Firmware

  • cd <PDK>/packages/
  • make uart

Firmware binaries at the end of the firmware build will be located at:

  • <PDK>/packages/ti/drv/uart/firmware/<FIRMWARE_TYPE>/bin/<SOC>/<HOST_CORE>/<REVISION>
  • <FIRMWARE_TYPE> indicates the firmware type i.e. icss_uart
  • <SOC> indicates the SOC type, e.g. am335x
  • <HOST_CORE> indicates the Host core type on which the built binary can be loaded, e.g. a8host
  • <REVISION> indicates the revision of the firmware binary based on core (there are 2 revision of PRU-ICSS core), e.g. REV1.

7.7.5. Supported EVMs

Supported EVMs and pin configurations for these EVMs are listed below. See the design document in <PDK>/packages/ti/drv/uart/docs/ for more information.

EVM Name PRU-ICSS Instances PRU-ICSS Revision
bbbAM335x 6 REV1

bbbAM335x

ICSS PRU Instance Functional Pin PRU GPIO Pins EVM Port EVM Pin
ICSS1 PRU0 UART0 TX pr1_pru0_pru_r30_0 P9 31
RX pr1_pru0_pru_r31_1 P9 29
CTS - - -
RTS - - -
ICSS1 PRU0 UART1 TX pr1_pru0_pru_r30_2 P9 30
RX pr1_pru0_pru_r31_3 P9 28
CTS - - -
RTS - - -
ICSS1 PRU0 UART2 TX pr1_pru0_pru_r30_5 P9 27
RX pr1_pru0_pru_r31_7 P9 25
CTS - - -
RTS - - -
ICSS1 PRU1 UART0 TX pr1_pru0_pru_r30_0 P8 45
RX pr1_pru0_pru_r31_1 P8 46
CTS pr1_pru1_pru_r31_2 P8 43
RTS pr1_pru1_pru_r30_3 P8 44
ICSS1 PRU1 UART1 TX pr1_pru0_pru_r30_4 P8 41
RX pr1_pru0_pru_r31_5 P8 42
CTS pr1_pru1_pru_r31_6 P8 39
RTS pr1_pru1_pru_r30_7 P8 40
ICSS1 PRU1 UART2 TX pr1_pru0_pru_r30_8 P8 27
RX pr1_pru0_pru_r31_9 P8 29
CTS pr1_pru1_pru_r31_10 P8 28
RTS pr1_pru1_pru_r30_11 P8 30

7.7.6. UART Firmware Example & Test

Example are test applications are available in the package for reference purpose and starting point.

The example application uses the UART stdio API to repeatedly read characters transmitted from a PC UART. The acquired characters are then written (echoed) back to the PC UART.

The test applications are more complex than the example application, and perform many more types of UART transfers than the example application. The test applications performs transfers using UART software IP (implemented in PRU firmware) and hardware IPs with different combinations of UART settings. Both the UART and UART stdio APIs are exercised (note the UART software and hardware IPs use the same UART-LLD API). The test applications are further described in the Firmware Design Guide.


Sample code for UART write & read:

/* Refer to UART FW example & tests for details */
...

/* Initialize the UART FW configuration */
UART_socInitFwCfg();

Board_init(boardCfg);
...

UART_init();

/* Get the default UART init configuration */
UART_socGetFwCfg(uartInst, &uart_cfg);
/* Modify the default UART configurations if necessary */
/* Set the default UART init configurations */
UART_socSetFwCfg(uartInst, &uart_cfg);
...

UART_Params_init(&uartParams);
uartParams.readCallback = UART_callback;
uartParams.readMode = UART_MODE_CALLBACK;
uartParams.writeCallback = UART_callback;
uartParams.writeMode = UART_MODE_CALLBACK;
uartParams.parityType = UART_PAR_NONE;
handle = UART_open(uartInst, &uartParams);
...

/* Initiate UART write */
UART_transactionInit(&wrCbTransaction);
wrCbTransaction.buf = (void *)wrBuff;
wrCbTransaction.count = sizeof(wrBuffer)/2;
if (UART_write2(handle, &wrCbTransaction) == UART_ERROR) {
    /* UART write failed */
}
...

/* Initiate UART read */
UART_transactionInit(&rdCbTransaction);
rdCbTransaction.buf = (void *)rdBuff;
rdCbTransaction.count = sizeof(rdBuffer)/2;
if (UART_read2(handle, &callbackTransaction) == UART_ERROR) {
    /* UART read failed */
}

List of Examples & Tests

Refer to the Release Notes for details concerning UART support across different EVMs.

Name Description Expected Results
UART_FwExample Example application for PRU UART FW driver

Status messages will be displayed on console based based on pass/fail criteria:

Pass criteria:

All Passed

UART_FwTest Simple test application for PRU UART FW driver

Status messages will be displayed on console based on pass/fail criteria:

Pass criteria:

All tests have passed.

UART_FwTestExtLb More complex test test application for PRU UART FW driver, superset of UART_FwTest

Status messages will be displayed on console based on pass/fail criteria:

Pass criteria:

All tests have passed.


Firmware Design Guide

Document Location
UART Firmware Design Guide <PDK>/packages/ti/drv/uart/docs/UART_FW_DESIGN_GUIDE.pdf

NOTE: Design document includes details for internal firmware implementation and can be used in case of modification required for firmware.