PRUSSv2 Interrupt Controller

From eLinux.org
Jump to: navigation, search

The PRUSS Interrupt Controller sits on the SCR 32-bit bus that interconnects elements of the PRUSS. It also has a direct outgoing connection to the ARM Interrupt Controller, EDMA and TSC_ADC Event triggers, allowing interrupts to these units to be dispatched by various components of the PRUSS. The controller also has a direct incoming connection, allowing it to receive events from various SoC external peripherals.

Important Note: It is vital to clear all system interrupts before the PRUSS is halted, else the PRUSS will not power down.

Features

A list of 64 possible interrupt events.
10 interrupt channels (Channel-0 to Channel-9), allowing for 10 separate active triggers, which may be triggered by one or more specified interrupts from the above list.
If more than one interrupt arrives at the same time, those assigned to a lower channel number will be given priority. If more than one interrupt arrives at the same time on the same channel, again, the interrupt with the lowest interrupt number from the above table is given priority.
10 host channels (Host-0 to Host-9), allowing for one or more interrupt channels to be directed to up to 10 different locations, either within or outside of the PRUSS.
The first two channels, Host-0 and Host-1, always directly point to Register R31 bit 30 and bit 31 respectively of the two PRU units, enabling PRUs to receive interrupts by checking these register bits.
Other locations a host channel may point to will typically be local peripherals, external components such as the EDMA for triggering a DMA transfer and the ARM Interrupt Controller for interrupting an operating system, allowing for software intervention.

Enabling the Interrupt Controller

Instruction Location Name Location Number
1. Globally enable interrupts by setting the Global Enable Register (GER) to 1 PRUSS_INTC + GER 0x0002_0000 + 10h
2. Set polarity of all incoming events through the System Interrupt Polarity Registers (SIPR0 and SIPR1) to Active High (set all bits to 1) PRUSS_INTC + SIPR0

PRUSS_INTC + SIPR1

0x0002_0000 + D00h

0x0002_0000 + D04h

3. Set the type of all incoming events through the System Interrupt Type Registers (SITR0 and SITR1) to 'pulse' (set all bits to 0) PRUSS_INTC + SITR0

PRUSS_INTC + SITR1

0x0002_0000 + D80h

0x0002_0000 + D84h

Although the Interrupt Controller supports settings for individual interrupt polarities and types, in the AM335X (BeagleBone) processor, these settings are ALWAYS Active High and Pulsed and as such can be configured as part of the global set-up as opposed to configuration for individual interrupts.

Configuring and enabling an Interrupt

Instruction Location Name Location Number
1. Map the chosen system event to an interrupt channel by inserting the channel number into the appropriate Channel Map Register (CMR0::15 - each register represents 4 system interrupts) PRUSS_INTC + CMR0 ...

PRUSS_INTC + CMR15

0x0002_0000 + 400h ...

0x0002_0000 + 43Ch

2. Map the configured interrupt channel to the chosen host channel by inserting the host channel number into the appropriate Host Map Register (HMR0::2 - each register represents 4 interrupt channels)

It is recommend to assign interrupt channel X to host channel X (Interrupt Channel 1 -> Host Channel 1 etc.)

PRUSS_INTC + HMR0 ...

PRUSS_INTC + HMR2

0x0002_0000 + 800h ...

0x0002_0000 + 808h

3. Clear the system interrupt's status by setting the appropriate bit in the System Interrupt Status Register to 1 (SECR0::1 - each register represents 32 interrupts) PRUSS_INTC + SECR0

PRUSS_INTC + SECR1

0x0002_0000 + 280h

0x0002_0000 + 284h

4. Enable the individual host channel by writing the host channel number to the Host Interrupt Enable Indexed Set Register (HIEISR)

Individual interrupts can be disabled by following the above step but by instead writing to the Host Interrupt Enable Indexed Clear Register (HIDISR)

PRUSS_INTC + HIEISR 0x0002_0000 + 34h
5. Enable the individual system interrupt (system event) by writing the interrupt number to the System Interrupt Enable Indexed Set Register (EISR)

Individual system interrupts can be disabled by following the above step but by instead writing to the System Interrupt Enable Indexed Clear Register (EICR)

PRUSS_INTC + EISR 0x0002_0000 + 28h

Servicing (clearing) an Interrupt

Instruction Location Name Location Number
1a. Clear the interrupt's status by setting the bit at the location of the interrupt number in the System Interrupt Status Enabled/Clear Register (SECR0::1 - for example, to clear Interrupt 12, write 1 to bit 12 in SECR0). PRUSS_INTC + SECR0

PRUSS_INTC + SECR1

0x0002_0000 + 280h

0x0002_0000 + 284h

1b. Alternatively, clear the interrupt's status by writing the interrupt number to the System Interrupt Status Enabled Indexed Clear Register (EICR). PRUSS_INTC + EICR 0x0002_0000 + 2Ch


Once an interrupt has been acted upon it should always be cleared to ensure the correct receipt of future interrupts.

Interrupt Nesting

Interrupt nesting allows various priorities of interrupts to be disabled when an interrupt event, with nesting configured, is received. Disabled interrupts are then re-enabled by the user writing to the ISR register.

There are three types of supported nesting:

Nesting of all host channels of the same or lower priority when an interrupt event is received
The nesting level can be set by placing the channel number in the Global Nesting Level Register (GNLR).
Nesting of an individual host channel, the individual host may not be interrupted by interrupt events on interrupt channels of the same or lower priority
The nesting level can be set individually by placing the channel number in the Host Interrupt Nesting Level Registers (HINLR0::1)
Software nesting, whereby the software disables all host channels on receipt of an interrupt, proceeded by enabling/disabling individual host channels and finally re-enabling all host channels, allowing only those manually enabled to continue processing interrupts. The changes are reversed once the interrupt request has been serviced by the software.
Requires the most CPU intervention and should be avoided if either of the first two nesting solutions are applicable.