cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L433 Precise BusFault on GPIO access (BFAR = 0x48000000) despite enabling GPIO clock

lris
Associate

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, GPIOAEN

Additional context:

  • Custom register definitions for GPIO/RCC (not HAL)

  • Fault occurs before/at first GPIO access

  • Program resets and lands back in Reset_Handler

  • BFAR(via Fault Analyzer) consistently reports 0x48000000

    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;
}

 

11 REPLIES 11

Oh well, I am doing a course on bare metal development, and the instructor had me do this, to grasp the inner workings of an MCU and learning to understanding register mapping and in general to utilise a reference manual, so that one could do so on any MCU, which is arm based.

Also, out of curiosity, how can you pin point to the fact that its the header file causing problem and not the driver file?

I will try to compile the code now using already made header file like you mention, I  am starting to doubt the legitimacy of my nucleo board (is it possible for nucleo boards to be about easy to duplicate as is the case with arduino UNO boards?).

waclawek.jan
Super User

Also, my NUCLEO board's whole layout seems to be different from the one given in the user manual.

Post photo.

I'm not familiar with the -P suffixed mcus i.e. those which have external SMPS. Isn't there some substantial difference from the non-P-suffixed parts which has to be observed before going for the blinky? In other words, to which core-power do they default, is it a no-SW-setup-required mode, and is that mode supported by the board in question?

JW

 

PS. +1 to using the CMSIS-mandated device header; although @gbm: at some point probably everybody who doesn't use an 3-rd party "library" such as Cube/HAL (or Cube/LL or anything else) tends to write some framework to use the relatively clumsily accessible GPIO features, and I wouldn't call that *hardware abstraction* (althought here we can debate on the fact that most mcu HALs out there are not hardware abstraction either)

PS2. On my 'L431 board I used for testing, LED is at PA0, that's why I haven't spotted the issue with the MODER value shift...