// STM32F4xx Register Definitions (Basic subset needed for GPIO)
typedef struct {
volatile uint32_t MODER; // GPIO port mode register
volatile uint32_t OTYPER; // GPIO port output type register
volatile uint32_t OSPEEDR; // GPIO port output speed register
volatile uint32_t PUPDR; // GPIO port pull-up/pull-down register
volatile uint32_t IDR; // GPIO port input data register
volatile uint32_t ODR; // GPIO port output data register
volatile uint32_t BSRR; // GPIO port bit set/reset register
volatile uint32_t LCKR; // GPIO port configuration lock register
volatile uint32_t AFR[2]; // GPIO alternate function registers
} GPIO_TypeDef;
// RCC register definition
typedef struct {
volatile uint32_t CR; // RCC clock control register
volatile uint32_t PLLCFGR; // RCC PLL configuration register
volatile uint32_t CFGR; // RCC clock configuration register
volatile uint32_t CIR; // RCC clock interrupt register
volatile uint32_t AHB1RSTR; // RCC AHB1 peripheral reset register
volatile uint32_t AHB2RSTR; // RCC AHB2 peripheral reset register
volatile uint32_t AHB3RSTR; // RCC AHB3 peripheral reset register
volatile uint32_t RESERVED0;
volatile uint32_t APB1RSTR; // RCC APB1 peripheral reset register
volatile uint32_t APB2RSTR; // RCC APB2 peripheral reset register
volatile uint32_t RESERVED1[2];
volatile uint32_t AHB1ENR; // RCC AHB1 peripheral clock enable register
volatile uint32_t AHB2ENR; // RCC AHB2 peripheral clock enable register
volatile uint32_t AHB3ENR; // RCC AHB3 peripheral clock enable register
volatile uint32_t RESERVED2;
volatile uint32_t APB1ENR; // RCC APB1 peripheral clock enable register
volatile uint32_t APB2ENR; // RCC APB2 peripheral clock enable register
} RCC_TypeDef;
// Memory map for STM32F4xx
#define PERIPH_BASE 0x40000000UL
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL)
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL)
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x10000000UL)
#define RCC_BASE (AHB1PERIPH_BASE + 0x3800UL)
#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000UL)
#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800UL)
#define RCC ((RCC_TypeDef *)RCC_BASE)
#define GPIOA ((GPIO_TypeDef *)GPIOA_BASE)
#define GPIOC ((GPIO_TypeDef *)GPIOC_BASE)
// Main program
int main(void)
{
// Enable GPIO clocks (GPIOA and GPIOC)
RCC->AHB1ENR |= (1 << 0) | (1 << 2); // GPIOAEN and GPIOCEN
// Configure PA0 as input with pull-up
GPIOA->MODER &= ~(3 << (2 * 0)); // Clear mode bits (input)
GPIOA->PUPDR = (GPIOA->PUPDR & ~(3 << (2 * 0))) | (1 << (2 * 0)); // Pull-up
// Configure PC13 as output (push-pull, low speed)
GPIOC->MODER = (GPIOC->MODER & ~(3 << (2 * 13))) | (1 << (2 * 13)); // Output
GPIOC->OTYPER &= ~(1 << 13); // Push-pull
GPIOC->OSPEEDR &= ~(3 << (2 * 13)); // Low speed
GPIOC->PUPDR &= ~(3 << (2 * 13)); // No pull
uint8_t lastState = 1; // Initial state (button not pressed)
while(1)
{
uint8_t currentState = (GPIOA->IDR >> 0) & 1;
if(currentState == 0 && lastState == 1) // Button pressed (active low)
{
// Toggle LED on PC13
GPIOC->ODR ^= (1 << 13);
// Simple debounce delay
for(volatile int i = 0; i < 100000; i++);
}
lastState = currentState;
}
return 0;
}
// Minimal startup code for ARM Cortex-M
void Reset_Handler(void)
{
// Initialize .data section (if needed)
// Zero .bss section (if needed)
main();
while(1); // Infinite loop if main returns
}