2020-09-09 11:28 PM
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 !
Solved! Go to Solution.
2020-09-13 11:34 PM
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 !
2020-09-10 03:47 AM
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) ;
}
2020-09-13 11:34 PM
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 !
2020-09-14 07:58 AM
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 ...