cancel
Showing results for 
Search instead for 
Did you mean: 

Can STM32 GPIOx Register parse to each bit?

QNGUY.1
Associate II

Hello,

I am a new STM32 member. In many previous projects from PIC, we often #define GPIOx as a bit. So we can manipulate some operator directly and easily as example below.

Example:

#define LED_AL1 LATBbits.LATB6

#define LED_AL2 LATBbits.LATB7

LED_A1 ^= 1;

LED_A2 = ~LED_A2;

So I think STM32 MCU will also parse to each bit such as other MCUs.

If we want to parse a GPIOx to each bit, how can we do it ?

If you have an idea, please share us your comment.

Thanks in advance !

1 ACCEPTED SOLUTION

Accepted Solutions
QNGUY.1
Associate II

Thanks Nikita who had given me a new idea !

Finally, we also parsed GPIOx.ODR to bits successfully

#include "main.h"
#include "stm32l073xx.h"
#include "stm32l0xx_hal.h"
 
#define GPIOA_ODR            ((BITMODE_TypeDef *)  (GPIOA_BASE + 0x14U))
#define GPIOB_ODR            ((BITMODE_TypeDef *)  (GPIOB_BASE + 0x14U))
#define GPIOC_ODR            ((BITMODE_TypeDef *)  (GPIOC_BASE + 0x14U))
 
 
typedef struct
{
  __IO uint8_t Bit0		:	1 ;   /*!< GPIO bit 0,                     							Address offset: 0x00 */
  __IO uint8_t Bit1		:	1 ;   /*!< GPIO bit 1,                     							Address offset: 0x01 */
  __IO uint8_t Bit2		:	1 ;   /*!< GPIO bit 2,                     							Address offset: 0x02 */
  __IO uint8_t Bit3		:	1 ;   /*!< GPIO bit 3,                     							Address offset: 0x03 */
 
	__IO uint8_t Bit4		:	1 ;   /*!< GPIO bit 4,                     							Address offset: 0x04 */
  __IO uint8_t Bit5		:	1 ;   /*!< GPIO bit 5,                     							Address offset: 0x05 */
  __IO uint8_t Bit6		:	1 ;   /*!< GPIO bit 6,                     							Address offset: 0x06 */
  __IO uint8_t Bit7		:	1 ;   /*!< GPIO bit 7,                     							Address offset: 0x07 */
 
	__IO uint8_t Bit8		:	1 ;   /*!< GPIO bit 8,                     							Address offset: 0x08 */
  __IO uint8_t Bit9		:	1 ;   /*!< GPIO bit 9,                     							Address offset: 0x09 */
  __IO uint8_t Bit10	:	1 ;   /*!< GPIO bit 10,          	           						Address offset: 0x0A */
  __IO uint8_t Bit11	:	1 ;   /*!< GPIO bit 11,                    							Address offset: 0x0B */
 
	__IO uint8_t Bit12	:	1 ;   /*!< GPIO bit 12,                     						Address offset: 0x0C */
  __IO uint8_t Bit13	:	1 ;   /*!< GPIO bit 13,                     						Address offset: 0x0D */
  __IO uint8_t Bit14	:	1 ;   /*!< GPIO bit 14,                     						Address offset: 0x0E */
  __IO uint8_t Bit15	:	1 ;   /*!< GPIO bit 15,                     						Address offset: 0x0F */
 
  __IO uint8_t Bit16	:	1 ;   /*!< GPIO bit 16,                     						Address offset: 0x10 */
  __IO uint8_t Bit17	:	1 ;   /*!< GPIO bit 17,                     						Address offset: 0x11 */
  __IO uint8_t Bit18	:	1 ;   /*!< GPIO bit 18,                     						Address offset: 0x12 */
  __IO uint8_t Bit19	:	1 ;   /*!< GPIO bit 19,                     						Address offset: 0x13 */
 
	__IO uint8_t Bit20	:	1 ;   /*!< GPIO bit 20,                     						Address offset: 0x14 */
  __IO uint8_t Bit21	:	1 ;   /*!< GPIO bit 21,                     						Address offset: 0x15 */
  __IO uint8_t Bit22	:	1 ;   /*!< GPIO bit 22,                     						Address offset: 0x16 */
  __IO uint8_t Bit23	:	1 ;   /*!< GPIO bit 23,                     						Address offset: 0x17 */
 
	__IO uint8_t Bit24	:	1 ;   /*!< GPIO bit 24,                     						Address offset: 0x18 */
  __IO uint8_t Bit25	:	1 ;   /*!< GPIO bit 25,                     						Address offset: 0x19 */
  __IO uint8_t Bit26	:	1 ;   /*!< GPIO bit 26,          	           						Address offset: 0x1A */
  __IO uint8_t Bit27	:	1 ;   /*!< GPIO bit 27,                     						Address offset: 0x1B */
 
	__IO uint8_t Bit28	:	1 ;   /*!< GPIO bit 28,                     						Address offset: 0x1C */
  __IO uint8_t Bit29	:	1 ;   /*!< GPIO bit 29,                     						Address offset: 0x1D */
  __IO uint8_t Bit30	:	1 ;   /*!< GPIO bit 30,                     						Address offset: 0x1E */
  __IO uint8_t Bit31	:	1 ;   /*!< GPIO bit 31,                     						Address offset: 0x1F */
}BITMODE_TypeDef;
#include "main.h"
#include "stm32l073xx.h"
#include "stm32l0xx_hal.h"
#include "UserSystemDefine.h"
 
#define		ALED1			GPIOA_ODR->Bit9					// ALARM LED 1
#define		ALED2			GPIOA_ODR->Bit10				// ALARM LED 2
#define		PLED			GPIOB_ODR->Bit2					// POWER LED
 
if(htim->Instance==TIM2)
{
	//HAL_GPIO_TogglePin(GPIOA, ALED1_Pin);
	//GPIOA_ODR->Bit9 ^= 1;
	//GPIOA_ODR->Bit10 = ~GPIOA_ODR->Bit9;
	ALED1 ^= 1;
	ALED2 = ~ALED1;
	
}else if(htim->Instance==TIM3)
{
	//GPIOB_ODR->Bit2 ^= 1;
	PLED ^= 1;
}

Have a good time !

View solution in original post

3 REPLIES 3
Nikita91
Lead II

There is no such facility with the GCC compiler for ARM.

The STM32 GPIO architecture use a register (GPIOx->BSRR) to set and reset bits individually, so no read-modify-write to use. This is thread safe, while ^= is not.

A tip to toggle a pin (The optimization is based on this text in reference manuals: "Note: If both BSx and BRx are set, BSx has priority."): 

// Toggle multi pins on the port GPIOx
__STATIC_INLINE void bspTogglePins (GPIO_TypeDef * GPIOx, uint32_t pinMask)
{
	uint32_t odr = GPIOx->ODR ;
	
	GPIOx->BSRR = ((odr & pinMask) << 16u) | (~odr & pinMask) ;
}

QNGUY.1
Associate II

Thanks Nikita who had given me a new idea !

Finally, we also parsed GPIOx.ODR to bits successfully

#include "main.h"
#include "stm32l073xx.h"
#include "stm32l0xx_hal.h"
 
#define GPIOA_ODR            ((BITMODE_TypeDef *)  (GPIOA_BASE + 0x14U))
#define GPIOB_ODR            ((BITMODE_TypeDef *)  (GPIOB_BASE + 0x14U))
#define GPIOC_ODR            ((BITMODE_TypeDef *)  (GPIOC_BASE + 0x14U))
 
 
typedef struct
{
  __IO uint8_t Bit0		:	1 ;   /*!< GPIO bit 0,                     							Address offset: 0x00 */
  __IO uint8_t Bit1		:	1 ;   /*!< GPIO bit 1,                     							Address offset: 0x01 */
  __IO uint8_t Bit2		:	1 ;   /*!< GPIO bit 2,                     							Address offset: 0x02 */
  __IO uint8_t Bit3		:	1 ;   /*!< GPIO bit 3,                     							Address offset: 0x03 */
 
	__IO uint8_t Bit4		:	1 ;   /*!< GPIO bit 4,                     							Address offset: 0x04 */
  __IO uint8_t Bit5		:	1 ;   /*!< GPIO bit 5,                     							Address offset: 0x05 */
  __IO uint8_t Bit6		:	1 ;   /*!< GPIO bit 6,                     							Address offset: 0x06 */
  __IO uint8_t Bit7		:	1 ;   /*!< GPIO bit 7,                     							Address offset: 0x07 */
 
	__IO uint8_t Bit8		:	1 ;   /*!< GPIO bit 8,                     							Address offset: 0x08 */
  __IO uint8_t Bit9		:	1 ;   /*!< GPIO bit 9,                     							Address offset: 0x09 */
  __IO uint8_t Bit10	:	1 ;   /*!< GPIO bit 10,          	           						Address offset: 0x0A */
  __IO uint8_t Bit11	:	1 ;   /*!< GPIO bit 11,                    							Address offset: 0x0B */
 
	__IO uint8_t Bit12	:	1 ;   /*!< GPIO bit 12,                     						Address offset: 0x0C */
  __IO uint8_t Bit13	:	1 ;   /*!< GPIO bit 13,                     						Address offset: 0x0D */
  __IO uint8_t Bit14	:	1 ;   /*!< GPIO bit 14,                     						Address offset: 0x0E */
  __IO uint8_t Bit15	:	1 ;   /*!< GPIO bit 15,                     						Address offset: 0x0F */
 
  __IO uint8_t Bit16	:	1 ;   /*!< GPIO bit 16,                     						Address offset: 0x10 */
  __IO uint8_t Bit17	:	1 ;   /*!< GPIO bit 17,                     						Address offset: 0x11 */
  __IO uint8_t Bit18	:	1 ;   /*!< GPIO bit 18,                     						Address offset: 0x12 */
  __IO uint8_t Bit19	:	1 ;   /*!< GPIO bit 19,                     						Address offset: 0x13 */
 
	__IO uint8_t Bit20	:	1 ;   /*!< GPIO bit 20,                     						Address offset: 0x14 */
  __IO uint8_t Bit21	:	1 ;   /*!< GPIO bit 21,                     						Address offset: 0x15 */
  __IO uint8_t Bit22	:	1 ;   /*!< GPIO bit 22,                     						Address offset: 0x16 */
  __IO uint8_t Bit23	:	1 ;   /*!< GPIO bit 23,                     						Address offset: 0x17 */
 
	__IO uint8_t Bit24	:	1 ;   /*!< GPIO bit 24,                     						Address offset: 0x18 */
  __IO uint8_t Bit25	:	1 ;   /*!< GPIO bit 25,                     						Address offset: 0x19 */
  __IO uint8_t Bit26	:	1 ;   /*!< GPIO bit 26,          	           						Address offset: 0x1A */
  __IO uint8_t Bit27	:	1 ;   /*!< GPIO bit 27,                     						Address offset: 0x1B */
 
	__IO uint8_t Bit28	:	1 ;   /*!< GPIO bit 28,                     						Address offset: 0x1C */
  __IO uint8_t Bit29	:	1 ;   /*!< GPIO bit 29,                     						Address offset: 0x1D */
  __IO uint8_t Bit30	:	1 ;   /*!< GPIO bit 30,                     						Address offset: 0x1E */
  __IO uint8_t Bit31	:	1 ;   /*!< GPIO bit 31,                     						Address offset: 0x1F */
}BITMODE_TypeDef;
#include "main.h"
#include "stm32l073xx.h"
#include "stm32l0xx_hal.h"
#include "UserSystemDefine.h"
 
#define		ALED1			GPIOA_ODR->Bit9					// ALARM LED 1
#define		ALED2			GPIOA_ODR->Bit10				// ALARM LED 2
#define		PLED			GPIOB_ODR->Bit2					// POWER LED
 
if(htim->Instance==TIM2)
{
	//HAL_GPIO_TogglePin(GPIOA, ALED1_Pin);
	//GPIOA_ODR->Bit9 ^= 1;
	//GPIOA_ODR->Bit10 = ~GPIOA_ODR->Bit9;
	ALED1 ^= 1;
	ALED2 = ~ALED1;
	
}else if(htim->Instance==TIM3)
{
	//GPIOB_ODR->Bit2 ^= 1;
	PLED ^= 1;
}

Have a good time !

Nikita91
Lead II

I am curious to see the code generated for such operations. It is undoubtedly far from optimal.

Also it uses read-modify-write so not thred safe: Another thread must not use another IO from the same port at the same time ...