SysTick Interrupt Configuration and NVIC Priority Settings

The core issue revolves around the SysTick interrupt not triggering on an ARM Cortex-M0 processor integrated into the PGA970 system. The SysTick timer is a fundamental peripheral in ARM Cortex-M processors, often used for generating periodic interrupts for task scheduling or timekeeping. However, in this case, despite proper configuration of the SysTick registers and enabling interrupts globally, the SysTick handler is not being invoked. This suggests a misconfiguration in the interrupt priority settings, NVIC (Nested Vectored Interrupt Controller) setup, or potential hardware limitations.

The SysTick timer is configured with a reload value of 0x4F and enabled with the control register (SYST_CSR) set to 0x00000007. This configuration ensures that the timer counts down from 0x4F to 0, sets the count flag, and generates an interrupt. However, the interrupt is not being serviced, as evidenced by the SYST_Handler not being called. The NVIC registers, particularly NVIC_INT_CTRL (renamed to ISCR by TI), show that the SysTick exception is recognized (VECACTIVE is set to 15), but the VECPENDING and ISRPENDING fields remain empty, indicating that the interrupt is not being acknowledged or prioritized correctly.

The root cause appears to be related to the NVIC priority settings for the SysTick interrupt. The ARM Cortex-M0 architecture allows for up to 32 external interrupts, but the SysTick timer is considered a system interrupt and is not part of the external interrupt vector. Instead, its priority is managed through the System Handler Priority Registers (SHPR), specifically SHPR3. The PGA970 implementation, however, does not follow the CMSIS (Cortex Microcontroller Software Interface Standard) conventions, making it difficult to configure the SysTick priority correctly. Additionally, the absence of the core_cm0.h file, which provides standard definitions for ARM Cortex-M0 peripherals, further complicates the configuration process.

Misconfigured System Handler Priority Registers and Missing CMSIS Definitions

The primary cause of the SysTick interrupt not triggering is the misconfiguration of the System Handler Priority Registers (SHPR). On the ARM Cortex-M0, the SysTick interrupt is classified as a system interrupt, and its priority is set in the SHPR3 register. However, the PGA970 implementation does not provide a straightforward way to access or configure this register. Instead, the priority for system interrupts is managed through vendor-specific registers, which are not well-documented.

The NVIC_PRI0 and NVIC_PRI1 registers are used to set the priority for external interrupts, but they do not affect the SysTick interrupt. The SysTick interrupt requires its priority to be set in the SHPR3 register, which is not directly accessible in the provided code. This misalignment between the ARM Cortex-M0 architecture and the PGA970 implementation is a significant barrier to proper interrupt handling.

Furthermore, the absence of the core_cm0.h file, which is part of the CMSIS, exacerbates the issue. The CMSIS provides standardized definitions for ARM Cortex-M processors, including the SHPR registers and the NVIC_SetPriority function, which simplifies the configuration of interrupt priorities. Without these definitions, developers must manually define the register addresses and bit fields, increasing the likelihood of errors.

Another potential cause is the optional nature of the SysTick timer on the ARM Cortex-M0. While the SysTick timer is a standard feature in most Cortex-M processors, it is not mandatory, and some implementations may omit it. The PGA970 firmware release notes indicate that the SysTick feature was removed in version 1.6, suggesting that it may not be fully supported or functional in earlier versions. This raises the possibility that the SysTick timer is either not implemented or not properly integrated into the PGA970 system.

Correcting NVIC Configuration and Verifying SysTick Implementation

To resolve the SysTick interrupt issue, the following steps should be taken:

  1. Manually Define System Handler Priority Registers: Since the PGA970 implementation does not provide access to the SHPR3 register through standard CMSIS definitions, it must be manually defined. The SHPR3 register is located at offset 0x020 within the System Control Block (SCB) and is used to set the priority for system interrupts, including SysTick. The following code snippet demonstrates how to define and configure the SHPR3 register:

    #define SCB_BASE 0xE000E000
    #define SCB_SHPR3 (*((volatile unsigned long *)(SCB_BASE + 0x020)))
    
    void Interrupt_Config(void) {
        // Set SysTick priority to the highest level (0x00)
        SCB_SHPR3 = 0x00000000;
    }
    

    This code sets the SysTick interrupt priority to the highest level, ensuring that it is serviced immediately when triggered.

  2. Verify SysTick Timer Implementation: Before proceeding with further debugging, it is essential to confirm that the SysTick timer is implemented and functional on the PGA970. This can be done by checking the device datasheet or consulting the firmware release notes. If the SysTick timer is not implemented, an alternative timer peripheral must be used for periodic interrupt generation.

  3. Check Interrupt Vector Table Alignment: The interrupt vector table must be correctly aligned and populated with the appropriate handler addresses. The SYST_Handler should be mapped to the SysTick exception number (15) in the vector table. The following code snippet demonstrates the correct vector table configuration:

    #pragma DATA_SECTION(g_pfnVectors, ".intvecs")
    void (* const g_pfnVectors[])(void) = {
        (void (*)(void))((unsigned long)&__STACK_TOP),
        ResetISR,                // Reset handler
        NmiSR,                   // NMI handler
        FaultISR,                // Hard fault handler
        IntDefaultHandler,       // MPU fault handler
        IntDefaultHandler,       // Bus fault handler
        IntDefaultHandler,       // Usage fault handler
        0,                       // Reserved
        0,                       // Reserved
        0,                       // Reserved
        0,                       // Reserved
        IntDefaultHandler,       // SVCall handler
        IntDefaultHandler,       // Debug monitor handler
        0,                       // Reserved
        IntDefaultHandler,       // PendSV handler
        SYST_Handler,            // SysTick handler
        // Additional interrupt handlers...
    };
    

    Ensure that the SYST_Handler is correctly placed at index 15 in the vector table.

  4. Enable Global Interrupts: Global interrupts must be enabled using the __set_PRIMASK(0) function. This ensures that the processor can service interrupts when they occur. Additionally, the SysTick timer must be enabled and configured with the desired reload value:

    void main(void) {
        Interrupt_Config();
        __set_PRIMASK(0);           // Enable global interrupts
        SYST_Config(0x0000004F, 0x00000007);  // Configure SysTick timer
        while (1) {}                // Wait for interrupts
    }
    
  5. Debugging and Verification: Use a debugger to verify that the SysTick interrupt is being triggered and that the SYST_Handler is being called. Monitor the SYST_CSR, SYST_RVR, and SYST_CVR registers to ensure that the timer is functioning as expected. Additionally, check the NVIC_INT_CTRL register to confirm that the SysTick exception is being acknowledged and prioritized correctly.

By following these steps, the SysTick interrupt issue on the PGA970 with the ARM Cortex-M0 processor can be resolved. Proper configuration of the NVIC priority settings, verification of the SysTick timer implementation, and alignment of the interrupt vector table are critical to ensuring that the SysTick interrupt is serviced correctly.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *