[FAQ] How do I implement Interrupt Nesting on a C2000 (C28x) device?

Part Number: C2000WARE

Tool/software:

On a C2000 device with a C28x core, the Peripheral Interrupt Expansion (PIE/ePIE) Module inherently allow for nesting of interrupts. By default, the CPU will service each interrupt to completion without breaking out of an ISR even if a higher priority interrupt gets flagged during its execution. Once the CPU finishes executing an ISR, it will then service the highest priority interrupt (according to the location in the PIE table) that is both flagged and enabled. In the PIE table, interrupts with the lowest-numbered channel in the lowest-numbered group have the highest priority.

There two scenarios where nesting would be necessary in an application.

  • Simple Nesting - Highest priority interrupts need to be branched to even if the CPU is already servicing another interrupt
  • Changing Priority - The application needs to change the priority order of two (or more) interrupts from what is set in the PIE table

How is interrupt nesting implemented in software for each of the scenarios and interrupt use cases?

    • Simple Nesting

      • Scenario: Application needs to have highest priority interrupts branched to even if the CPU is already servicing another interrupt
        • Case 1: All INTs used are in unique PIE groups

          • In highest PIE priority ISR
            • [ISR application code]
            • Clear ACK of current PIE group [if ACK exists]
            • No additional code needed
          • In lowest PIE priority ISR
            • EINT
            • [ISR application code]
            • DINT
            • Clear ACK of current PIE group [if ACK exists]
          • In medium PIE priority ISRs (not highest or lowest priority)
            • Enable only all IERs of higher priority [used] groups
            • EINT
            • [ISR application code]
            • DINT
            • Clear ACK of current PIE group [if ACK exists]
        • Case 2: Two (or more) INTs used share a PIE group AND lowest used group has only one INT used

          • In highest PIE priority ISR
            • [ISR application code]
            • Clear ACK of current PIE group [if ACK exists]
            • No additional code needed
          • In lowest PIE priority ISR
            • EINT
            • [ISR application code]
            • DINT
            • Clear ACK of current PIE group [if ACK exists]
          • In medium PIE priority ISRs (not highest or lowest priority)
            • Other INTs in group are used
              • Current INT is highest priority inside its group
                • Enable only all IERs of higher priority [used] groups
                • EINT
                • [ISR application code]
                • DINT
                • Clear ACK of current PIE group [if ACK exists]
              • Current INT is not highest priority inside its group
                • Save PIEIER register of current PIE group
                • Enable only IERs for all higher priority groups + IER for current group
                  • Use masks from sw_prioritization_isr_levels.h
                • Enable PIEIER only of all higher PIE priority interrupts in same group
                  • Use masks from sw_prioritization_isr_levels.h
                • Clear ACK of current PIE group [if ACK exists]
                • Wait 1 cycle (NOP)
                • EINT
                • [ISR application code]
                • DINT
                • Restore PIEIER for the current PIE group
            • No other INTs in group are used
              • Enable only all IERs of higher priority [used] groups
              • EINT
              • [ISR application code]
              • DINT
              • Clear ACK of current PIE group [if ACK exists]
        • Case 3: Two (or more) interrupts used share same PIE group AND lowest used group has more than one INT used

          • In highest PIE priority ISR
            • [ISR application code]
            • Clear ACK of current PIE group [if ACK exists]
            • No additional code needed
          • In lowest PIE priority ISR
            • Enable IER of current group
            • Clear ACK of current PIE group [if ACK exists]
            • Wait 1 cycle (NOP)
            • EINT
            • [ISR application code]
            • DINT
            • Clear ACK of current PIE group [if ACK exists]
          • In medium PIE priority ISRs (not highest or lowest priority)
            • Other INTs in group are used
              • Current INT is highest priority inside its group
                • Enable only all IERs of higher priority [used] groups
                • EINT
                • [ISR application code]
                • DINT
                • Clear ACK of current PIE group [if ACK exists]
              • Current INT is not highest priority inside its group
                • Save PIEIER register of current PIE group
                • Enable only IERs for all higher priority groups + IER for current group
                  • Use masks from sw_prioritization_isr_levels.h
                • Enable PIEIER only of all higher PIE priority interrupts in same group
                  • Use masks from sw_prioritization_isr_levels.h
                • Clear ACK of current PIE group [if ACK exists]
                • Wait 1 cycle (NOP)
                • EINT
                • [ISR application code]
                • DINT
                • Restore PIEIER for the current PIE group
            • No other INTs in group are used
              • Enable only all IERs of higher priority [used] groups
              • EINT
              • [ISR application code]
              • DINT
              • Clear ACK of current PIE group [if ACK exists]
    • Changing Priority

      • Scenario: Application needs to change the priority order of two (or more) interrupts from what is set in the PIE table.
      • The priority order of which ISR begins execution first cannot be changed from what is in the PIE table. However, this implementation will change the priority order of which ISR ends execution first. Also note that all interrupts enabled in a prioritized group will nest even if only some are meant to be prioritized. The priority order can be changed for a group overall & within a group but not for two individual interrupts in different groups. 
        • Case 1: All INTs used are in unique PIE groups

          • In highest user-defined priority ISR
            • [ISR application code]
            • Clear ACK of current PIE group [if ACK exists]
            • No additional code needed
          • In lowest user-defined priority ISR
            • EINT
            • [ISR application code]
            • DINT
            • Clear ACK of current PIE group [if ACK exists]
          • In medium user-defined priority ISRs (not highest or lowest priority)
            • Enable only all IERs of higher user-defined priority [used] groups
            • EINT
            • [ISR application code]
            • DINT
            • Clear ACK of current PIE group [if ACK exists]
        • Case 2: Two (or more) INTs used share a PIE group AND lowest used group has only one INT used

          • In highest user-defined priority ISR
            • [ISR application code]
            • Clear ACK of current PIE group [if ACK exists]
            • No additional code needed
          • In lowest user-defined priority ISR
            • EINT
            • [ISR application code]
            • DINT
            • Clear ACK of current PIE group [if ACK exists]
          • In medium user-defined priority ISRs (not highest or lowest priority)
            • Other INTs in group are used
              • Current INT is highest user-defined priority inside its group
                • Enable only all IERs of higher user-defined priority [used] groups
                • EINT
                • [ISR application code]
                • DINT
                • Clear ACK of current PIE group [if ACK exists]
              • Current INT is not highest user-defined priority inside its group
                • Save PIEIER register of current PIE group
                • Enable only IERs for all higher user-defined priority groups + IER for current group
                  • Use masks from sw_prioritization_isr_levels.h
                • Enable PIEIER only of all higher user-defined priority interrupts in same group
                  • Use masks from sw_prioritization_isr_levels.h
                • Clear ACK of current PIE group [if ACK exists]
                • Wait 1 cycle (NOP)
                • EINT
                • [ISR application code]
                • DINT
                • Restore PIEIER for the current PIE group
            • No other INTs in group are used
              • Enable only all IERs of higher user-defined priority [used] groups
              • EINT
              • [ISR application code]
              • DINT
              • Clear ACK of current PIE group [if ACK exists]
        • Case 3: Two (or more) interrupts used share same PIE group AND lowest used group has more than one INT used

          • In highest user-defined priority ISR
            • [ISR application code]
            • Clear ACK of current PIE group [if ACK exists]
            • No additional code needed
          • In lowest user-defined priority ISR
            • Enable IER of current group
            • Clear ACK of current PIE group [if ACK exists]
            • Wait 1 cycle (NOP)
            • EINT
            • [ISR application code]
            • DINT
            • Clear ACK of current PIE group [if ACK exists]
          • In medium user-defined priority ISRs (not highest or lowest priority)
            • Other INTs in group are used
              • Current INT is highest user-defined priority inside its group
                • Enable only all IERs of higher user-defined priority [used] groups
                • EINT
                • [ISR application code]
                • DINT
                • Clear ACK of current PIE group [if ACK exists]
              • Current INT is not highest user-defined priority inside its group
                • Save PIEIER register of current PIE group
                • Enable only IERs for all higher user-defined priority groups + IER for current group
                  • Use masks from sw_prioritization_isr_levels.h
                • Enable PIEIER only of all higher user-defined PIE priority interrupts in same group
                  • Use masks from sw_prioritization_isr_levels.h
                • Clear ACK of current PIE group [if ACK exists]
                • Wait 1 cycle (NOP)
                • EINT
                • [ISR application code]
                • DINT
                • Restore PIEIER for the current PIE group
            • No other INTs in group are used
              • Enable only all IERs of higher user-defined priority [used] groups
              • EINT
              • [ISR application code]
              • DINT
              • Clear ACK of current PIE group [if ACK exists]

    The masks from the sw_prioritization_isr_levels.h file located in following path: C2000Ware_VERSION#/driverlib/[DEVICE_GPN]/examples/[CORE_IF_MULTICORE]/interrupt/sw_prioritized_isr_levels.h can be used if needed for the specific use case.

    Additional Resources

    C28x Interrupt Nesting

    TMS320x280x, 2801x, 2804x DSP System Control and Interrupts Reference Guide