// STM32C031 LED toggle using TIM3 interrupt in Wokwi (PlatformIO/STM32CubeIDE compatible)
// Target: STM32C031F6
#include <stdint.h>
// Peripheral base addresses
#define RCC_BASE 0x40021000
#define GPIOA_BASE 0x50000000
#define TIM3_BASE 0x40000400
#define NVIC_ISER ((volatile uint32_t *)0xE000E100)
// Register offsets/macros
#define RCC_IOPENR (*(volatile uint32_t *)(RCC_BASE + 0x34))
#define RCC_APBENR1 (*(volatile uint32_t *)(RCC_BASE + 0x1C))
#define GPIOA_MODER (*(volatile uint32_t *)(GPIOA_BASE + 0x00))
#define GPIOA_ODR (*(volatile uint32_t *)(GPIOA_BASE + 0x14))
#define TIM3_CR1 (*(volatile uint32_t *)(TIM3_BASE + 0x00))
#define TIM3_DIER (*(volatile uint32_t *)(TIM3_BASE + 0x0C))
#define TIM3_SR (*(volatile uint32_t *)(TIM3_BASE + 0x10))
#define TIM3_PSC (*(volatile uint32_t *)(TIM3_BASE + 0x28))
#define TIM3_ARR (*(volatile uint32_t *)(TIM3_BASE + 0x2C))
#define TIM3_CNT (*(volatile uint32_t *)(TIM3_BASE + 0x24))
#define LED_PIN 5
#define GPIO_PIN5 (1 << LED_PIN)
// Forward declaration for ISR
void TIM3_IRQHandler(void);
int main(void)
{
// 1. Enable clocks for GPIOA and TIM3
RCC_IOPENR |= (1 << 0); // Enable GPIOA
RCC_APBENR1 |= (1 << 1); // Enable TIM3
// 2. Set PA5 as output
GPIOA_MODER &= ~(3 << (LED_PIN * 2));
GPIOA_MODER |= (1 << (LED_PIN * 2));
// 3. Configure TIM3
TIM3_CR1 = 0x0000; // Disable timer
TIM3_PSC = 47999; // Prescaler for 1ms tick (48MHz / (PSC+1))
TIM3_ARR = 499; // 500ms interval
TIM3_CNT = 0;
TIM3_DIER |= (1 << 0); // Enable update interrupt
TIM3_CR1 |= (1 << 0); // Enable counter
// 4. Enable TIM3 interrupt in NVIC (TIM3_IRQn = 29)
NVIC_ISER[0] = (1 << 29);
// 5. Enable global interrupts
__asm__("cpsie i");
while (1) {
// Main loop does nothing
}
}
// Interrupt handler
void TIM3_IRQHandler(void)
{
if (TIM3_SR & (1 << 0)) {
TIM3_SR &= ~(1 << 0); // Clear update interrupt flag
GPIOA_ODR ^= GPIO_PIN5; // Toggle PA5
}
}