AM261x MCU+ SDK: PRUICSS

| AM261x MCU+ SDK 26.00.00 |

PRUICSS

Programmable Real-Time Unit and Industrial Communication Subsystem(PRU-ICSS) driver provides a well-defined API layer which allows applications to use the PRU-ICSS. PRU-ICSS is firmware programmable and can take on various personalities like Industrial Communication 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)
- Loading the firmware in PRU cores
- Read/Write/Reset different memories inside PRU-ICSS
- 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_ICSS0` 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 PRU-ICSS instance) to a reduced set of interrupt channels.

The interrupt controller has the following features:

- Capturing up to 64 Events (inputs)
- Supports up to 10 output interrupt channels
- Generation of 10 Host Interrupts
- Each event can be enabled and disabled.
- Each host event can be enabled and disabled.

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

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 Technical 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.

# Example Usage

Include the below file to access the APIs

#include <drivers/pruicss.h>

Instance Open Example

/*Use CONFIG_PRU_ICSS0 macro as parameter to PRUICSS_open */
gPruicssHandle = PRUICSS_open(CONFIG_PRU_ICSS0);
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);
PRUICSS_disableCore(gPruicssHandle, PRUICSS_PRU0);
/* Register an Interrupt Handler for an event */
PRUICSS_registerIrqHandler(gPruicssHandle,
pruEvtoutNum,
intrNum,
eventNum,
waitEnable,
irqHandler);
/* API to do Interrupt-Channel-host mapping */
PRUICSS_intcInit(gPruicssHandle, &pruicssIntcInitData);
/* Load the IRAM in PRU */
PRUICSS_writeMemory(gPruicssHandle,
PRUICSS_IRAM_PRU(0),
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/m_v0/pruicss.h:97
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:187
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/m_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.