7. PRU-ICSS Firmware

7.5. PRU-ICSS ESPI

7.5.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.5.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.5.3. Firmware Build Instruction

7.5.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.5.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.5.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.