2026-01-09 8:12 AM
I am working bare-metal on an STM32L433RCT6 (no HAL). I am seeing a precise data bus fault whenever I access a GPIO register.
Fault details from the debugger:
Fault type: Precise data bus fault
BFAR: 0x48000000
From RM0394, 0x48000000 is the GPIOA base address, so the fault occurs exactly on GPIO access.
The faulting instruction is a normal GPIO register read/write (e.g. ODR access). The GPIO struct layout and offsets are correct, and the compiler generates correct code.
I understand that on STM32, a precise bus fault on a valid peripheral address usually means the peripheral clock is disabled.
However, I explicitly enable the GPIO clock before accessing it:
*(volatile uint32_t*)0x4002104C |= (1 << 0); // RCC_AHB2ENR, GPIOAENAdditional context:
Custom register definitions for GPIO/RCC (not HAL)
Fault occurs before/at first GPIO access
Program resets and lands back in Reset_Handler
I will also attach the stm32l433xx.h, stm32l433xx_gpio_driver.h, stm32l433xx_gpio_driver.c code alongside the 001LedToggle.c file I am trying to execute.
stm32l433xx.h:
/*
* stm32l433xx.h
*
* Created on: Dec 29, 2025
* Author: Zaid
*/
#ifndef INC_STM32L433XX_H_
#define INC_STM32L433XX_H_
#include <stdint.h>
#define __vo volatile
#define FLASH_BASEADDR 0x08000000U
#define SRAM1_BASEADDR 0x20000000U
#define SRAM2_BASEADDR 0x10000000U
#define ROM_BASEADDR 0x1FFF0000U
#define SRAM1 SRAM1_BASEADDR
#define PERIPH_BASE 0x40000000U
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE 0x40010000U
#define AHB1PERIPH_BASE 0x40020000U
#define AHB2PERIPH_BASE 0x48000000U
/*Peripherals hanging on AHB2*/
#define GPIOA_BASEADDR (AHB2PERIPH_BASE + 0x0000)
#define GPIOB_BASEADDR (AHB2PERIPH_BASE + 0x0400)
#define GPIOC_BASEADDR (AHB2PERIPH_BASE + 0x0800)
#define GPIOD_BASEADDR (AHB2PERIPH_BASE + 0x0C00)
#define GPIOE_BASEADDR (AHB2PERIPH_BASE + 0x1000)
#define GPIOH_BASEADDR (AHB2PERIPH_BASE + 0x1C00)
#define RCC_BASEADDR (AHB1PERIPH_BASE + 0x1000)
/*Peripherals hanging on APB1*/
#define I2C1_BASEADDR (APB1PERIPH_BASE + 0x5400)
#define I2C2_BASEADDR (APB1PERIPH_BASE + 0x5800)
#define I2C3_BASEADDR (APB1PERIPH_BASE + 0x5C00)
#define SPI2_BASEADDR (APB1PERIPH_BASE + 0x3800)
#define SPI3_BASEADDR (APB1PERIPH_BASE + 0x3C00)
#define USART2_BASEADDR (APB1PERIPH_BASE + 0x4400)
#define USART3_BASEADDR (APB1PERIPH_BASE + 0x4800)
#define UART4_BASEADDR (APB1PERIPH_BASE + 0x4C00)
/*Peripherals hanging on APB2*/
#define USART1_BASEADDR (APB2PERIPH_BASE + 0x3800)
#define SPI1_BASEADDR (APB2PERIPH_BASE + 0x3000)
#define EXTI_BASEADDR (APB2PERIPH_BASE + 0x0400)
#define SYSCFG_BASEADDR (APB2PERIPH_BASE + 0x0000)
typedef struct
{
__vo uint32_t MODER; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t OTYPER; /*!<GPIO port output type register, Address offset: 0x04*/
__vo uint32_t OSPEEDR; /*!<GPIO port output speed register, Address offset: 0x08*/
__vo uint32_t PUPDR; /*!<GPIO port pull-up/pull-down register, Address offset: 0x0C*/
__vo uint32_t IDR; /*!<GPIO port input data register, Address offset: 0x10*/
__vo uint32_t ODR; /*!<GPIO port output data register, Address offset: 0x14*/
__vo uint32_t BSRR; /*!<GPIO port bit set/reset register, Address offset: 0x18*/
__vo uint32_t LCKR; /*!<GPIO port configuration lock register, Address offset: 0x1C*/
__vo uint32_t AFR[2]; /*!<AFR[0]: GPIO alternate function low register, AFR[1]: GPIO alternate function high register Address offset: 0x20-0x24*/
__vo uint32_t BRR; /*!<GPIO port bit reset register, Address offset: 0x28*/
}GPIO_RegDef_t;
typedef struct
{
__vo uint32_t CR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t ICSCR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t CFGR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t PLLCFGR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t PLLSAI1CFGR; /*!<GPIO port mode register, Address offset: 0x00*/
uint32_t RESERVED0;
__vo uint32_t CIER; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t CIFR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t CICR; /*!<GPIO port mode register, Address offset: 0x00*/
uint32_t RESERVED1;
__vo uint32_t AHB1RSTR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t AHB2RSTR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t AHB3RSTR; /*!<GPIO port mode register, Address offset: 0x00*/
uint32_t RESERVED2;
__vo uint32_t APB1RSTR1; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t APB1RSTR2; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t APB2RSTR; /*!<GPIO port mode register, Address offset: 0x00*/
uint32_t RESERVED3;
__vo uint32_t AHB1ENR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t AHB2ENR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t AHB3ENR; /*!<GPIO port mode register, Address offset: 0x00*/
uint32_t RESERVED4;
__vo uint32_t APB1ENR1; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t APB1ENR2; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t APB2ENR; /*!<GPIO port mode register, Address offset: 0x00*/
uint32_t RESERVED5;
__vo uint32_t AHB1SMENR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t AHB2SMENR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t AHB3SMENR; /*!<GPIO port mode register, Address offset: 0x00*/
uint32_t RESERVED6;
__vo uint32_t APB1SMENR1; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t APB1SMENR2; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t APB2SMENR; /*!<GPIO port mode register, Address offset: 0x00*/
uint32_t RESERVED7;
__vo uint32_t CCIPR; /*!<GPIO port mode register, Address offset: 0x00*/
uint32_t RESERVED8;
__vo uint32_t BDCR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t CSR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t CRRCR; /*!<GPIO port mode register, Address offset: 0x00*/
__vo uint32_t CCIPR2; /*!<GPIO port mode register, Address offset: 0x00*/
}RCC_RegDef_t;
#define GPIOA ((GPIO_RegDef_t*)GPIOA_BASEADDR)
#define GPIOB ((GPIO_RegDef_t*)GPIOB_BASEADDR)
#define GPIOC ((GPIO_RegDef_t*)GPIOC_BASEADDR)
#define GPIOD ((GPIO_RegDef_t*)GPIOD_BASEADDR)
#define GPIOE ((GPIO_RegDef_t*)GPIOE_BASEADDR)
#define GPIOH ((GPIO_RegDef_t*)GPIOH_BASEADDR)
#define RCC ((RCC_RegDef_t*)RCC_BASEADDR)
/*Enable Macros for GPIOx Peripherals*/
#define GPIOA_PCLK_EN() ( RCC->AHB2ENR |= (1 << 0))
//#define GPIOA_PCLK_EN() ( *(volatile uint32_t*)0x4002104C |= (1 << 0))
#define GPIOB_PCLK_EN() ( RCC->AHB2ENR |= (1 << 1))
#define GPIOC_PCLK_EN() ( RCC->AHB2ENR |= (1 << 2))
#define GPIOD_PCLK_EN() ( RCC->AHB2ENR |= (1 << 3))
#define GPIOE_PCLK_EN() ( RCC->AHB2ENR |= (1 << 4))
#define GPIOH_PCLK_EN() ( RCC->AHB2ENR |= (1 << 7))
/*Enable Macros for I2Cx Peripherals*/
#define I2C1_PCLK_EN() (RCC->APB1ENR1 |= (1<<21))
#define I2C2_PCLK_EN() (RCC->APB1ENR1 |= (1<<22))
#define I2C3_PCLK_EN() (RCC->APB1ENR1 |= (1<<23))
/*Enable Macros for SPIx Peripherals*/
#define SPI1_PCLK_EN() (RCC->APB2ENR |= (1<<12))
#define SPI2_PCLK_EN() (RCC->APB1ENR1 |= (1<<14))
#define SPI3_PCLK_EN() (RCC->APB1ENR1 |= (1<<15))
/*Enable Macros for USARTx Peripherals*/
#define USART1_PCLK_EN() (RCC->APB2ENR |= (1<<14))
#define USART2_PCLK_EN() (RCC->APB1ENR1 |= (1<<17))
#define USART3_PCLK_EN() (RCC->APB1ENR1 |= (1<<18))
/*Enable Macros for UARTx Peripherals*/
#define UART4_PCLK_EN() (RCC->APB1ENR1 |= (1<<19))
/*Enable Macros for SYSCFG Peripherals*/
#define SYSCFG_PCLK_EN() (RCC->APB2ENR |= (1<<0))
/*Disable Macros for GPIOx Peripherals*/
#define GPIOA_PCLK_DI() (RCC->AHB2ENR &= ~(1<<0))
#define GPIOB_PCLK_DI() (RCC->AHB2ENR &= ~(1<<1))
#define GPIOC_PCLK_DI() (RCC->AHB2ENR &= ~(1<<2))
#define GPIOD_PCLK_DI() (RCC->AHB2ENR &= ~(1<<3))
#define GPIOE_PCLK_DI() (RCC->AHB2ENR &= ~(1<<4))
#define GPIOH_PCLK_DI() (RCC->AHB2ENR &= ~(1<<5))
/*Disable Macros for I2Cx Peripherals*/
#define I2C1_PCLK_DI() (RCC->APB1ENR1 &= ~(1<<21))
#define I2C2_PCLK_DI() (RCC->APB1ENR1 &= ~(1<<22))
#define I2C3_PCLK_DI() (RCC->APB1ENR1 &= ~(1<<23))
/*Disable Macros for SPIx Peripherals*/
#define SPI1_PCLK_DI() (RCC->APB2ENR &= ~(1<<12))
#define SPI2_PCLK_DI() (RCC->APB1ENR1 &= ~(1<<14))
#define SPI3_PCLK_DI() (RCC->APB1ENR1 &= ~(1<<15))
/*Disable Macros for USARTx Peripherals*/
#define USART1_PCLK_DI() (RCC->APB2ENR &= ~(1<<14))
#define USART2_PCLK_DI() (RCC->APB1ENR1 &= ~(1<<17))
#define USART3_PCLK_DI() (RCC->APB1ENR1 &= ~(1<<18))
/*Disable Macros for UARTx Peripherals*/
#define UART4_PCLK_DI() (RCC->APB1ENR1 &= ~(1<<19))
/*Enable Macros for SYSCFG Peripherals*/
#define SYSCFG_PCLK_DI() (RCC->APB2ENR &= ~(1<<0))
/*Macros to reset GPIOx peripherals*/
#define GPIOA_REG_RESET() do{RCC->AHB2RSTR |= (1<<0); RCC->AHB2RSTR &= ~(1<<0);}while(0)
#define GPIOB_REG_RESET() do{RCC->AHB2RSTR |= (1<<1); RCC->AHB2RSTR &= ~(1<<1);}while(0)
#define GPIOC_REG_RESET() do{RCC->AHB2RSTR |= (1<<2); RCC->AHB2RSTR &= ~(1<<2);}while(0)
#define GPIOD_REG_RESET() do{RCC->AHB2RSTR |= (1<<3); RCC->AHB2RSTR &= ~(1<<3);}while(0)
#define GPIOE_REG_RESET() do{RCC->AHB2RSTR |= (1<<4); RCC->AHB2RSTR &= ~(1<<4);}while(0)
#define GPIOH_REG_RESET() do{RCC->AHB2RSTR |= (1<<7); RCC->AHB2RSTR &= ~(1<<7);}while(0)
/*Generic Macros*/
#define ENABLE 1
#define DISABLE 0
#define SET ENABLE
#define RESET DISABLE
#define GPIO_PIN_SET SET
#define GPIO_PIN_RESET RESET
#include "stm32l433xx_gpio_driver.h"
#endif /* INC_STM32L433XX_H_ */
stm32l433xx_gpio_driver.h :
/*
* stm32l433xx_gpio_driver.h
*
* Created on: Jan 1, 2026
* Author: Zaid
*/
#ifndef INC_STM32L433XX_GPIO_DRIVER_H_
#define INC_STM32L433XX_GPIO_DRIVER_H_
#include "stm32l433xx.h"
typedef struct
{
uint8_t GPIO_PinNumber; /*!<possible values from @GPIO_PIN_NUMBER>*/
uint8_t GPIO_PinMode; /*!<possible values from @GPIO_PIN_MODE>*/
uint8_t GPIO_PinSpeed; /*!<possible values from @GPIO_PIN_SPEED>*/
uint8_t GPIO_PinPuPdControl; /*!<possible values from @GPIO_PIN_CONFIG>*/
uint8_t GPIO_PinOPType; /*!<possible values from @GPIO_OUTPUT_TYPE>*/
uint8_t GPIO_PinAltFunMode;
}GPIO_PinConfig_t;
typedef struct
{
GPIO_RegDef_t *pGPIOx; /*!<This holds the base address of the GPIO port to which the pin belongs>*/
GPIO_PinConfig_t GPIO_PinConfig;/*!<This holds the config settings of the GPIO port to which the pin belongs>*/
}GPIO_Handle_t;
/*
* @GPIO_PIN_NUMBER
* GPIO pin number
*/
#define GPIO_PIN_NO_0 0
#define GPIO_PIN_NO_1 1
#define GPIO_PIN_NO_2 2
#define GPIO_PIN_NO_3 3
#define GPIO_PIN_NO_4 4
#define GPIO_PIN_NO_5 5
#define GPIO_PIN_NO_6 6
#define GPIO_PIN_NO_7 7
#define GPIO_PIN_NO_8 8
#define GPIO_PIN_NO_9 9
#define GPIO_PIN_NO_10 10
#define GPIO_PIN_NO_11 11
#define GPIO_PIN_NO_12 12
#define GPIO_PIN_NO_13 13
#define GPIO_PIN_NO_14 14
#define GPIO_PIN_NO_15 15
/*
* @GPIO_PIN_MODE
* GPIO pin possible modes
*/
#define GPIO_MODE_IN 0
#define GPIO_MODE_OUT 1
#define GPIO_MODE_ALTFN 2
#define GPIO_MODE_ANALOG 3
#define GPIO_MODE_IT_FT 4
#define GPIO_MODE_IT_RT 5
#define GPIO_MODE_IT_RFT 6
/*
* @GPIO_OUTPUT_TYPE
* GPIO pin possible output types
*/
#define GPIO_OP_TYPE_PP 0
#define GPIO_OP_TYPE_OD 1
/*
* @GPIO_PIN_SPEED
* GPIO pin possible output speed
*/
#define GPIO_SPEED_LOW 0
#define GPIO_SPEED_MEDIUM 1
#define GPIO_SPEED_FAST 2
#define GPIO_SPEED_HIGH 3
/*
* @GPIO_PIN_CONFIG
* GPIO pin pull up AND pull down configuration macros
*/
#define GPIO_NO_PUPD 0
#define GPIO_PIN_PU 1
#define GPIO_PIN_PD 2
/*Peripheral Clock Control*/
void GPIO_PeriClockControl(GPIO_RegDef_t *pGPIOx, uint8_t EnorDi);
/*Init and De-Init*/
void GPIO_Init(GPIO_Handle_t *pGPIOHandle);
void GPIO_DeInit(GPIO_RegDef_t *pGPIOx);
/*Data read and write*/
uint8_t GPIO_ReadFromInputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber);
uint16_t GPIO_ReadFromInputPort(GPIO_RegDef_t *pGPIOx);
void GPIO_WriteToOutputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber, uint8_t Value);
void GPIO_WriteToOutputPort(GPIO_RegDef_t *pGPIOx, uint8_t Value);
void GPIO_ToggleOutputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber);
/*IRQ Configuration and ISR Handling*/
void GPIO_IRQConfig(uint8_t IRQNumber, uint8_t IRQPriority, uint8_t EnorDi);
void GPIO_IRQHandling(uint8_t PinNumber);
#endif /* INC_STM32L433XX_GPIO_DRIVER_H_ */
stm32l433xx_gpio_driver.c:
/*
* stm32l433xx_gpio_driver.c
*
* Created on: Jan 1, 2026
* Author: Zaid
*/
#include "stm32l433xx_gpio_driver.h"
/*
* *************************************************************
* @FN - GPIO_PeriClockControl
*
* @brief - Enables or disables peripheral clock for given GPIO port
*
* @PAram[in] - base address of gpio peripheral
* @PAram[in] - ENABLE or DISABLE macros
* @PAram[in] -
*
* @return - none
*
* @note - none
*
*/
/*Peripheral Clock Control*/
void GPIO_PeriClockControl(GPIO_RegDef_t *pGPIOx, uint8_t EnorDi)
{
if(EnorDi == ENABLE)
{
if(pGPIOx == GPIOA)
{
//GPIOA_PCLK_EN();
*(volatile uint32_t*)0x4002104C |= (1 << 0);
}else if(pGPIOx == GPIOB)
{
GPIOB_PCLK_EN();
}else if(pGPIOx == GPIOC)
{
GPIOC_PCLK_EN();
}else if(pGPIOx == GPIOD)
{
GPIOD_PCLK_EN();
}else if(pGPIOx == GPIOE)
{
GPIOE_PCLK_EN();
}else if(pGPIOx == GPIOH)
{
GPIOH_PCLK_EN();
}
}
else
{
if(pGPIOx == GPIOA)
{
GPIOA_PCLK_DI();
}else if(pGPIOx == GPIOB)
{
GPIOB_PCLK_DI();
}else if(pGPIOx == GPIOC)
{
GPIOC_PCLK_DI();
}else if(pGPIOx == GPIOD)
{
GPIOD_PCLK_DI();
}else if(pGPIOx == GPIOE)
{
GPIOE_PCLK_DI();
}else if(pGPIOx == GPIOH)
{
GPIOH_PCLK_DI();
}
}
}
/*Init and De-Init*/
/*
* *************************************************************
* @FN - GPIO_Init
*
* @brief - Initializes GPIO port
*
* @PAram[in] - gpio config
* @PAram[in] -
* @PAram[in] -
*
* @return - none
*
* @note - none
*
*/
void GPIO_Init(GPIO_Handle_t *pGPIOHandle)
{
uint32_t temp = 0; //temp. register
//1. Configure the mode of GPIO pin
if(pGPIOHandle->GPIO_PinConfig.GPIO_PinMode <= GPIO_MODE_ANALOG)
{
//non interrupt mode
temp = (pGPIOHandle->GPIO_PinConfig.GPIO_PinMode << (2 * pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber));
pGPIOHandle->pGPIOx->MODER &= ~(0x3 << ( pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber));//clearing
pGPIOHandle->pGPIOx->MODER |= temp;//setting
//temp = 0;
}else
{
// later (interrupt)
}
//2. Configure speed
temp = 0;
temp = (pGPIOHandle->GPIO_PinConfig.GPIO_PinSpeed << (2 * pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber));
pGPIOHandle->pGPIOx->OSPEEDR &= ~(0x3 << pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber);//clearing
pGPIOHandle->pGPIOx->OSPEEDR |= temp;//setting
temp = 0;
//3. Configure pupd settings
temp = (pGPIOHandle->GPIO_PinConfig.GPIO_PinPuPdControl << (2 * pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber));
pGPIOHandle->pGPIOx->PUPDR &= ~(0x3 << pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber);//clearing
pGPIOHandle->pGPIOx->PUPDR |= temp;//setting
temp = 0;
//4. Configure output type
temp = (pGPIOHandle->GPIO_PinConfig.GPIO_PinOPType << (2 * pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber));
pGPIOHandle->pGPIOx->OTYPER &= ~(0x3 << pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber);//clearing
pGPIOHandle->pGPIOx->OTYPER |= temp;//setting
temp = 0;
//5. Configure Alternate Functionality
if(pGPIOHandle->GPIO_PinConfig.GPIO_PinMode == GPIO_MODE_ALTFN)
{
//Configure the Alt Function registers
uint8_t temp1, temp2;
temp1 = pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber / 8;
temp2 = pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber % 8;
pGPIOHandle->pGPIOx->AFR[temp1] &= ~(0xF << pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber);//clearing
pGPIOHandle->pGPIOx->AFR[temp1] |= pGPIOHandle->GPIO_PinConfig.GPIO_PinAltFunMode << (4 * temp2);
}
}
/*
* *************************************************************
* @FN - GPIO_DeInit
*
* @brief - Deinitializes GPIO port
*
* @PAram[in] - gpio base address
* @PAram[in] -
* @PAram[in] -
*
* @return - none
*
* @note - none
*
*/
void GPIO_DeInit(GPIO_RegDef_t *pGPIOx)
{
if(pGPIOx == GPIOA)
{
GPIOA_REG_RESET();
}else if(pGPIOx == GPIOB)
{
GPIOB_REG_RESET();
}else if(pGPIOx == GPIOC)
{
GPIOC_REG_RESET();
}else if(pGPIOx == GPIOD)
{
GPIOD_REG_RESET();
}else if(pGPIOx == GPIOE)
{
GPIOE_REG_RESET();
}else if(pGPIOx == GPIOH)
{
GPIOH_REG_RESET();
}
}
/*Data read and write*/
/*
* *************************************************************
* @FN - GPIO_ReadFromInputPin
*
* @brief - Reads from gpio pin
*
* @PAram[in] - gpio base address
* @PAram[in] - gpio pin number
* @PAram[in] -
*
* @return - 0 or 1
*
* @note - none
*
*/
uint8_t GPIO_ReadFromInputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber)
{
uint8_t value;
value = (uint8_t)((pGPIOx->IDR >> PinNumber) & 0x00000001);
return value;
}
/*
* *************************************************************
* @FN - GPIO_ReadFromInputPort
*
* @brief - Reads from gpio port
*
* @PAram[in] - gpio base address
* @PAram[in] -
* @PAram[in] -
*
* @return - value read at port
*
* @note - none
*
*/
uint16_t GPIO_ReadFromInputPort(GPIO_RegDef_t *pGPIOx)
{
uint16_t value;
value = (uint16_t)pGPIOx->IDR;
return value;
}
/*
* *************************************************************
* @FN - GPIO_WriteToOutputPin
*
* @brief - Writes to gpio pin
*
* @PAram[in] - gpio base address
* @PAram[in] - gpio pin number
* @PAram[in] - value to be written
*
* @return - none
*
* @note - none
*
*/
void GPIO_WriteToOutputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber, uint8_t Value)
{
if(Value == GPIO_PIN_SET )
{
//write 1 to output data register at the bit field corresponding to the pin number
pGPIOx->ODR |= (1 << PinNumber);
}else
{
pGPIOx->ODR &= ~(1 << PinNumber);
}
}
/*
* *************************************************************
* @FN - GPIO_WriteToOutputPort
*
* @brief - Writes to gpio port
*
* @PAram[in] - gpio base address
* @PAram[in] - value to be written
* @PAram[in] -
*
* @return - none
*
* @note - none
*
*/
void GPIO_WriteToOutputPort(GPIO_RegDef_t *pGPIOx, uint8_t Value)
{
pGPIOx->ODR = Value;
}
/*
* *************************************************************
* @FN - GPIO_ToggleOutputPin
*
* @brief - Toggles gpio port
*
* @PAram[in] - gpio base address
* @PAram[in] - gpio pin number
* @PAram[in] -
*
* @return - none
*
* @note - none
*
*/
void GPIO_ToggleOutputPin(GPIO_RegDef_t *pGPIOx, uint8_t PinNumber)
{
pGPIOx->ODR ^= (1 << PinNumber);
}
/*IRQ Configuration and ISR Handling*/
/*
* *************************************************************
* @FN - GPIO_IRQConfig
*
* @brief - Configures Interrupt
*
* @PAram[in] - address of gpio interrupt
* @PAram[in] - type of priority
* @PAram[in] - ENABLE or DISABLE macros
*
* @return - none
*
* @note - none
*
*/
void GPIO_IRQConfig(uint8_t IRQNumber, uint8_t IRQPriority, uint8_t EnorDi)
{
}
/*
* *************************************************************
* @FN - GPIO_IRQHandling
*
* @brief - Configures Interrupt for a pin
*
* @PAram[in] - gpio pin number
* @PAram[in] -
* @PAram[in] -
*
* @return - none
*
* @note - none
*
*/
void GPIO_IRQHandling(uint8_t PinNumber)
{
}
001LedToggle.c:
/*
* 001led_toggle.c
*
* Created on: Jan 7, 2026
* Author: Zaid
*/
#include "stm32l433xx.h"
void delay(void)
{
for(int i=0 ; i < 500000; i++);
}
int main(void)
{
GPIO_PeriClockControl(GPIOA,ENABLE);
GPIO_Handle_t GpioLed;
GpioLed.pGPIOx = GPIOA;
GpioLed.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NO_5;
GpioLed.GPIO_PinConfig.GPIO_PinMode = GPIO_MODE_OUT;
GpioLed.GPIO_PinConfig.GPIO_PinSpeed = GPIO_SPEED_FAST;
GpioLed.GPIO_PinConfig.GPIO_PinOPType = GPIO_OP_TYPE_PP;
GpioLed.GPIO_PinConfig.GPIO_PinPuPdControl = GPIO_NO_PUPD;
GPIO_Init(&GpioLed);
while(1)
{
GPIO_ToggleOutputPin(GPIOA, GPIO_PIN_NO_5);
delay();
}
return 0;
}
2026-01-09 8:37 AM
What happens if you use the peripheral and bit definitions from stm32l4xx.h instead of your custom ones?
2026-01-09 9:20 AM
I've compiled your sources and tried on an STM32F431 (the differences are irrelevant for this test) and it works as expected, no fault occured.
What hardware is this, a "known good" board like Nucleo or your own? How exactly is PA5 connected?
JW
2026-01-09 11:18 AM - edited 2026-01-09 11:19 AM
This doesn't really add up.
Accessing a peripheral without the clock enabled will not cause a hard fault.
> Fault occurs before/at first GPIO access
Does it happen before access? Or at? Which line access?
> Program resets and lands back in Reset_Handler
A hard fault won't cause a program reset, unless a watchdog is enabled.
I suspect an insufficient power issue that gets triggered by stimulating a GPIO.
2026-01-09 12:54 PM
Well, It gets stuck in an infinite loop and the fault analyzer call for a hard fault, with the whole precise data bus fault, I also checked the address 0x4000 201C through the memory browser, and that too was not updated. Something I doubt is that, I could smell the heat, if that makes sense when I initially ran the code on my nucleo board. I had made an error then, in the RCC struct, of not taking care of the reserved memory, other than that, I dont have any issues that I could point towards the hardware. I also went through the schematic, found an LD4 LED, connected via a BJT to PB13, though couldnt find it on my board for some reason. Went around looking for any other on board LED that ran via a GPIO port, came to find, that LD2 was associated with PA5, hence the choice of it.
The hardware btw is STM32L433RCT6P-NUCLEO 64 board.
2026-01-09 1:01 PM
Well, I think I have gotten the first line a bit wrong, when I stepped into GPIO_Init is when the hardfault strikes,(more like the stack analyzer opens up and the fault analyzer calls a hard fault here) particularly at the statement (present in the file stm32l433xx_gpio_driver.c):
pGPIOHandle->pGPIOx->MODER &= ~(0x3 << ( pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber));//clearingand if I comment it out, it proceeds to the statement below it.
If you step over this line, you are then sent to the Reset_Handler, under which Infinite Loop is written. I am sorry if I am not clear, I am new to this.
2026-01-09 1:02 PM
couldnt figure out where the header file is at, srry :(
2026-01-09 3:36 PM - edited 2026-01-09 3:41 PM
pGPIOHandle->pGPIOx->MODER &= ~(0x3 << ( pGPIOHandle->GPIO_PinConfig.GPIO_PinNumber));//clearing
This doesn't clear the correct bits for pins > 0. You are missing a factor of 2.
This bug puts pins PA2 and PA3 into output and AF mode when you try to set the state of PA5.
Consider also changing the register value only once rather than putting the pin in intermediate states. Use the HAL library as reference for what to do.
Consider using BSRR rather than ODR to change states, like HAL.
Using standard CMSIS headers rather than redefining things will make your code better and more readable.
> STM32L433RCT6P-NUCLEO 64 board
> came to find, that LD2 was associated with PA5, hence the choice of it.
There is no LED on PA5. Might want to recheck your references. LD2 is a 5V USB.
STM32 Nucleo-64-P boards (MB1319) - User manual
2026-01-09 9:54 PM
Even after changing by a factor of 2, the same error persisted.
I am currently learning bare metal programming and hence the choice to avoid HAL.
Also, my NUCLEO board's whole layout seems to be different from the one given in the user manual. There seems to be no LD4 in the first place on my board, only up to LD3. Using the PB13 yields no results.