MaJerle / stm32-cube-cmake-vscode

STM32, VSCode and CMake detailed tutorial
MIT License
569 stars 57 forks source link

External Interrupt on GPIO PA0 Not Working in STM32 VS Code Extension #23

Closed zerovijay closed 4 months ago

zerovijay commented 4 months ago

External Interrupt on GPIO PA0 Not Working in STM32 VS Code Extension

Description

I have configured an external interrupt on GPIO PA0 to trigger on the falling edge via EXTI 0. The code works perfectly when using the STM32CubeIDE, but it fails to function as expected when using the STM32 VS Code extension.

I am using bare metal code, not relying on STM32 vendor libraries or CMSIS. Despite my deep dive into the registers and configurations, and numerous successful builds and uploads, the interrupt remains stubbornly non-functional in the VS Code extension environment.

Code Snippet

static inline uint8_t gpio_get_port_code(gpio_hw_t *gpiox)
{
    if (gpiox == GPIOA) {
        return 0;
    } else if (gpiox == GPIOB) {
        return 1;
    } else if (gpiox == GPIOC) {
        return 2;
    } else if (gpiox == GPIOD) {
        return 3;
    } else if (gpiox == GPIOE) {
        return 4;
    } else if (gpiox == GPIOH) {
        return 7;
    } else {
        return 0;
    }
}

void gpio_init(gpio_hw_t *gpiox, gpio_init_t *gpio_init)
{
    // Perform initial configuration based on mode

    if (gpio_init->mode <= GPIO_MODE_ANALOG) {
        gpio_set_mode(gpiox, gpio_init->pin, gpio_init->mode);
    } else {
        SYSCFG_REG_EN(); // Enable clock for SYSCFG

        if (gpio_init->mode == GPIO_MODE_EXTI_FALLING) {
            EXTI->FTSR &= ~(1 << gpio_init->pin);
            EXTI->FTSR |= (1 << gpio_init->pin);
        } else if (gpio_init->mode == GPIO_MODE_EXTI_RISING) {
            EXTI->RTSR &= ~(1 << gpio_init->pin);
            EXTI->RTSR |= (1 << gpio_init->pin);
        } else if (gpio_init->mode == GPIO_MODE_EXTI_CHANGE) {
            EXTI->FTSR |= (1 << gpio_init->pin);
            EXTI->RTSR |= (1 << gpio_init->pin);
        }

        const uint8_t exti_index = gpio_init->pin / 4;
        const uint8_t offset = gpio_init->pin % 4;
        const uint8_t port_code = gpio_get_port_code(gpiox);
        const uint8_t clear_mask = 0xFU;

        SYSCFGR->EXTICR[exti_index] &= ~(clear_mask << (offset * 4));
        SYSCFGR->EXTICR[exti_index] |= (port_code << (offset * 4));

        EXTI->IMR |= (1 << gpio_init->pin);
    }

    gpio_set_otype(gpiox, gpio_init->pin, gpio_init->otype);
    gpio_set_speed(gpiox, gpio_init->pin, gpio_init->speed);
    gpio_set_pupd(gpiox, gpio_init->pin, gpio_init->pupd);

    // Check for alternate function only if needed
    if (gpio_init->mode == GPIO_MODE_ALT_FUNC) {
        gpio_set_alt_func(gpiox, gpio_init->pin, gpio_init->alt_func);
    }
}

void gpio_irq_config(uint8_t irq_num, uint8_t enordi)
{
    volatile uint32_t *reg;
    uint8_t offset = irq_num % 32;

    switch (irq_num / 32) {
        case 0: reg = (enordi == ENABLE) ? &NVIC_ISER0 : &NVIC_ICER0; break;
        case 1: reg = (enordi == ENABLE) ? &NVIC_ISER1 : &NVIC_ICER1; break;
        case 2: reg = (enordi == ENABLE) ? &NVIC_ISER2 : &NVIC_ICER2; break;
        default: return; // Invalid irq_num, do nothing
    }

    *reg |= (1 << offset);
}

void gpio_irq_priority_config(uint8_t irq_num, uint8_t irq_priority)
{
    // Calculate the index of the NVIC priority register
    uint8_t nvic_ipr_index = irq_num / 4;

    // Calculate the offset within the NVIC priority register
    uint8_t offset_within_register = irq_num % 4;

    // Calculate the number of bits to shift the priority value
    uint8_t bits_to_shift = (offset_within_register * 8) + (8 - NUM_BIT_IMPLEMENTED);

    // Calculate the priority value with proper bit positioning
    uint32_t priority_value = irq_priority << bits_to_shift;

    // Update the NVIC priority register with the calculated priority value
    NVIC_IPR->pir[nvic_ipr_index] |= priority_value;
}

void gpio_irq_handle(enum gpio_pin pin)
{
    if (EXTI->PR & (1 << pin)) {
        EXTI->PR |= (1 << pin);
    }
}

Steps to Reproduce

  1. Configure GPIO PA0 for falling edge interrupt via EXTI 0 using the above initialization functions.
  2. Compile and upload the code using STM32CubeIDE (where it works).
  3. Compile and upload the same code using STM32 VS Code extension (where it doesn't work).

Expected Behavior

The interrupt should trigger on the falling edge of PA0 in both STM32CubeIDE and STM32 VS Code extension environments.

What I Have Tried

Additional Information

After many hours of staring at registers and flags, I think I've developed a slight case of brain damage. My coffee intake is through the roof. Any help to resolve this issue before I start talking to my microcontroller would be greatly appreciated!

Please assist me in resolving this issue.

Thank you!

MaJerle commented 4 months ago

Make sure your interrupt service routine is part of the build.

zerovijay commented 4 months ago

Fixed Interrupt Issue

Description

Fixed an issue where the USART6 interrupt was causing an infinite loop due to incorrect vector table alignment in the startup code.

Left one is incorrect one and right one is correct i got from stm32cubeide

Screenshot from 2024-06-14 20-42-37