2012-08-31 03:09 AM
The file stm32f4xx.h defines the BSRR as two 16 bit ''halves''.
typedef struct
{
__IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
__IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
__IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
__IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
__IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
__IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
__IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */
__IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */
__IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
__IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x24-0x28 */
} GPIO_TypeDef;
The Ref. Manual says the BSRR bits, ''can be accessed in word, half-word or byte mode.''.
Can I just declare,
__IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */
to write 32 bits in one write? Anyone done this?
2012-08-31 04:39 AM
Probably, you'd need to watch for dependencies within the library, or use a nameless union if the compiler permits.
Not used it on the F4, but on F0, see no reason the hardware side would work as you expect.2012-08-31 04:56 AM
Hi Clive,
''dependencies within the library'' seems to be the problem. If I add the line,__IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */
to the library structure, it breaks the normal GPIOX->BSRRL and GPIOX->BSRRH operations. Although as you guessed, the 32 bit write to the BSRR does seem to work OK.
I could just define the various port BSRR addresses as const pointers to uint32_t I suppose?
2012-08-31 06:12 AM
*((uint32_t *)&GPIOD->BSRRL) = 0x10002000;
2012-09-03 02:43 AM
Thanks for the hint. If anyone wants to do this, the style below works.
*((uint32_t *)&GPIOG->BSRRL) = ((uint32_t)GPIO_Pin_8); //set bit
*((uint32_t *)&GPIOG->BSRRL) = ((uint32_t)GPIO_Pin_8) << 16; //reset bit
However it seems to be optimised away at (Keil ARM) level 3 optimisation. I thought adding ''volatile'' would do the job but it seems not. It seems to be necessary to add a synchronisation instruction. Either DSB (Data Synchronisation Barrier) or DMB seems to work and also keeps execution in order. Does anyone know which is correct?
This following code (including ''volatile'' and a barrier) seems to work OK at level 3 optimisation. (DSB works too.)
while(1)
{
*((volatile uint32_t *)&GPIOG->BSRRL) = ((uint32_t)GPIO_Pin_8); //set bit
__DMB();
*((volatile uint32_t *)&GPIOG->BSRRL) = ((uint32_t)GPIO_Pin_8) << 16; //reset bit
__DMB();
}