AM64x MCU+ SDK  08.00.00
PRUICSS

Programmable Real-Time Unit and Industrial Communication Subsystem(PRUICSS) driver provides a well-defined API layer which allows applications to use the PRUICSS. PRUICSS is firmware programmable and can take on various personalities like Industrial Protocol Switch (for protocols like EtherCAT, Profinet, EtherNet/IP), Ethernet Switch, Ethernet MAC, Industrial Drives, etc.

Features Supported

  • PRU control features like enabling/disabling/resetting a Programmable Real-Time Units (PRU0 and PRU1), Auxiliary Programmable Real-Time Units (RTU_PRU0 and RTU_PRU1) or Transmit Programmable Real-Time Units (TX_PRU0 and TX_PRU1) core
  • Loading the firmware in PRU cores
  • Read/Write/Reset different memories inside PRUICSS
  • PRU and Host Event management. It does mapping of sys_evt/channel/hosts in the INTC module. APIs to register interrupt handler for events, generate an event, wait for occurrence of an event, and clear an event.
  • Basic configurations in registers like GPCFG, MII_RT_G_CFG, ICSSG_SA_MX
  • IEP clock selection, IEP counter enable/disable, IEP counter increment configuration
  • PRU Constant Table Configuration

SysConfig Features

Note
It is strongly recommend to use SysConfig where it is available instead of using direct SW API calls. This will help simplify the SW application and also catch common mistakes early in the development cycle.
  • Option to select the PRU-ICSS instance
  • Option to select the Core Clock Frequency
  • Based on above parameters, the SysConfig generated code does following:
    • Call PRUICSS_init in System_init, and PRUICSS_deinit in System_deinit
    • Enable the Core Clock and set the selected frequency
    • Create macros like CONFIG_PRU_ICSSG1 using the name passed in SysConfig. This is used as an input to PRUICSS_open API.

PRUICSS Interrupt Controller

The interrupt controller (INTC) module maps interrupts coming from different parts of the device (mapped to PRUICSS instance) to a reduced set of interrupt channels.

The interrupt controller has the following features:

  • Capturing up to 160 Events (inputs)
    • Upper 96 are external events
    • Lower 64 are internal events
  • Supports up to 20 output interrupt channels
  • Generation of 20 Host Interrupts
    • 2 Host Interrupts shared between the PRUs (PRU0 and PRU1) and TX_PRUs (TX_PRU0 and TX_PRU1).
    • 2 Host Interrupts for the RTU PRUs (RTU_PRU0 and RTU_PRU1).
    • 8 Host Interrupts exported from the PRU_ICSSG internal INTC for signaling the device level interrupt controllers (pulse and level provided).
    • 8 Host Interrupts (event 12 through 19) for the Task Managers.
  • Each event can be enabled and disabled.
  • Each host event can be enabled and disabled.
  • Hardware prioritization of events.

Following are some important points related to INTC configuration:

  • Any of the 160 internal interrupts can be mapped to any of the 20 channels.
  • Multiple interrupts can be mapped to a single channel.
  • An interrupt should not be mapped to more than one channel.
  • Any of the 20 channels can be mapped to any of the 20 host interrupts. It is recommended to map channel "x" to host interrupt "x", where x is from 0 to 19.
  • A channel should not be mapped to more than one host interrupt
  • For channels mapping to the same host interrupt, lower number channels have higher priority.
  • For interrupts on same channel, priority is determined by the hardware interrupt number. The lower the interrupt number, the higher the priority.
  • Host Interrupt 0 is connected to bit 30 in register 31 (R31) of PRU0 and PRU1 in parallel.
  • Host Interrupt 1 is connected to bit 31 in register 31 (R31) for PRU0 and PRU1 in parallel.
  • Host Interrupts 2 through 9 exported from PRUICSS and mapped to device level interrupt controllers.
  • Host Interrupt 10 is connected to bit 30 in register 31 (R31) to both RTU_PRU0 and RTU_PRU1 in parallel.
  • Host Interrupt 11 is connected to bit 31 in register 31 (R31) to both RTU_PRU0 and RTU_PRU1 in parallel.
  • Host Interrupts 12 through 19 are connected to each of the 4 Task Managers.

For industrial protocol examples running on R5F, Host Interrupts 2 through 9 exported from PRUICSS are used for signalling an interrupt to R5F. As this mapping is programmable and varies from example to example, we have a *_pruss_intc_mapping.h file for different protocol examples which is used for passing PRUICSS_IntcInitData structure while calling PRUICSS_intcInit API.

Following is an example of one mapping from ${SDK_INSTALL_PATH}/source/industrial_protocols/ethercat_slave/icss_fwhal/tiesc_pruss_intc_mapping.h used for EtherCAT Slave.

The following line maps PRU_ARM_EVENT2 to CHANNEL6.

{PRU_ARM_EVENT2,CHANNEL6, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_EDGE},\

CHANNEL6 is mapped to the fourth host interrupt mapped to device level interrupt controller(Host Interrupt 6 out of 20) through this line.

{CHANNEL6, PRU_EVTOUT4}

In AM64x, PRU_ICSSG0_PR1_HOST_INTR_PEND_0-PRU_ICSSG0_PR1_HOST_INTR_PEND_7 (8 host interrupts) are mapped to R5FSS0_CORE0_INTR_IN_120-R5FSS0_CORE0_INTR_IN_127. This values are for ICSSG0 events mapped to R5FSS0 CORE0. For details regarding interrupt numbers on other cores, please refer to "9.4 Interrupt Sources" section in Techincal Reference Manual(TRM) of AM64x, or corresponding section in TRM of other SoCs. These interrupt numbers can change from SoC to SoC, so please consult TRM before making any modifications to the interrupt map.

For the example mentioned above, interrupt number 124 (R5FSS0_CORE0_INTR_IN_124) should be used for intrNum parameter for PRUICSS_registerIrqHandler. PRUICSS_registerIrqHandler creates Hwi instance using HwiP_construct API with the intrNum passed,

This mapping alone determines which interrupt number on R5F will be associated with a particular interrupt from PRUICSS. For example, in the code shown above, where `PRU_ARM_EVENT2 maps to CHANNEL6, and CHANNEL6 maps to PRU_EVTOUT4 can be modified to following, and the interrupt number on R5F would still remain the same.

{PRU_ARM_EVENT2,CHANNEL7, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_EDGE},\
{CHANNEL7, PRU_EVTOUT4}

But the usefulness of channels is that channels allow us to map multiple PRU events to a single channel and in turn to a single host interrupt. For example, take a look at the following mapping used for link interrupt.

{MII_LINK0_EVENT, CHANNEL1, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\
{MII_LINK1_EVENT, CHANNEL1, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\
{CHANNEL1, PRU1}

This configuration maps both Port 0 and Port 1 link interrupts to a single channel and in turn to a single host interrupt for PRU1 (Host Interrupt 1 out of 20).

PRUICSS_intcInit API should be used to configure the INTC module.

Note
Please refer to section "6.4.7 PRU_ICSSG Local INTC" in Techincal Reference Manual(TRM) of AM64x for more details on INTC module

Example Usage

Include the below file to access the APIs

Instance Open Example

/*Use CONFIG_PRU_ICSSG1 macro as parameter to PRUICSS_open */
gPruicssHandle = PRUICSS_open(CONFIG_PRU_ICSSG1);
DebugP_assert(gPruicssHandle != NULL);

Sequence for loading a firmware on PRU and running the PRU core

/* Reset and disable PRU core */
PRUICSS_resetCore(gPruicssHandle, PRUICSS_PRU0);
/* Register an Interrupt Handler for an event */
pruEvtoutNum,
intrNum,
eventNum,
waitEnable,
irqHandler);
/* API to do Interrupt-Channel-host mapping */
PRUICSS_intcInit(gPruicssHandle, &pruicssIntcInitData);
/* Load the IRAM in PRU */
PRUICSS_writeMemory(gPruicssHandle,
0,
(uint32_t *) pruFirmware,
pruFirmwareLength);
/* Enable PRU */
PRUICSS_enableCore(gPruicssHandle, PRUICSS_PRU0);

API

APIs for PRUICSS

PRUICSS_resetCore
int32_t PRUICSS_resetCore(PRUICSS_Handle handle, uint8_t pruNum)
This function resets the PRU.
pruicss.h
PRUICSS_enableCore
int32_t PRUICSS_enableCore(PRUICSS_Handle handle, uint8_t pruNum)
This function enables the PRU.
PRUICSS_IRAM_PRU
#define PRUICSS_IRAM_PRU(n)
IRAM for PRU0/PRU1. n = 0 for PRU0,n = 1 for PRU1.
Definition: pruicss/v0/pruicss.h:104
PRUICSS_disableCore
int32_t PRUICSS_disableCore(PRUICSS_Handle handle, uint8_t pruNum)
This function disables the PRU.
PRUICSS_open
PRUICSS_Handle PRUICSS_open(uint32_t instance)
This function creates the handle for a PRUICSS instance.
DebugP_assert
#define DebugP_assert(expression)
Function to call for assert check.
Definition: DebugP.h:159
PRUICSS_intcInit
int32_t PRUICSS_intcInit(PRUICSS_Handle handle, const PRUICSS_IntcInitData *intcInitData)
This function does Interrupt-Channel-host mapping.
PRUICSS_writeMemory
uint32_t PRUICSS_writeMemory(PRUICSS_Handle handle, uint32_t pruicssMem, uint32_t wordoffset, const uint32_t *source_mem, uint32_t bytelength)
This function writes the given data to PRU memory.
PRUICSS_PRU0
#define PRUICSS_PRU0
Definition: pruicss/v0/pruicss.h:74
PRUICSS_registerIrqHandler
int32_t PRUICSS_registerIrqHandler(PRUICSS_Handle handle, uint32_t pruEvtoutNum, int32_t intrNum, int32_t eventNum, uint8_t waitEnable, PRUICSS_IrqHandler irqHandler)
This function registers an Interrupt Handler for an event.