Skip to content

Commit 632a07d

Browse files
Florian Vaussardgalak
Florian Vaussard
authored andcommitted
gpio: stm32: Use atomic set/reset in stm32_gpio_set()
The current implementation of stm32_gpio_set() uses the GPIO output data register to change the state of individual GPIOs. The generated assembler needs at least 3 instructions: load / modify / store. This opens a small race window, for example if a thread and an interrupt both try to change the state of the same GPIO bank. Use the GPIO bit set/reset register to perform the atomic change without locking. This also has the benefit of a more optimised implementation, which can be useful for GPIO-intensive work. Compare the new version: 08000c98 <stm32_gpio_set>: 8000c98: f001 010f and.w r1, r1, zephyrproject-rtos#15 8000c9c: 2301 movs r3, zephyrproject-rtos#1 8000c9e: b902 cbnz r2, 8000ca2 <stm32_gpio_set+0xa> 8000ca0: 3110 adds r1, zephyrproject-rtos#16 8000ca2: 408b lsls r3, r1 8000ca4: 6183 str r3, [r0, zephyrproject-rtos#24] 8000ca6: 2000 movs r0, #0 8000ca8: 4770 bx lr and the old one: 08000c98 <stm32_gpio_set>: 8000c98: 2301 movs r3, zephyrproject-rtos#1 8000c9a: f001 010f and.w r1, r1, zephyrproject-rtos#15 8000c9e: fa03 f101 lsl.w r1, r3, r1 8000ca2: 6943 ldr r3, [r0, zephyrproject-rtos#20] 8000ca4: b10a cbz r2, 8000caa <stm32_gpio_set+0x12> 8000ca6: 4319 orrs r1, r3 8000ca8: e001 b.n 8000cae <stm32_gpio_set+0x16> 8000caa: ea23 0101 bic.w r1, r3, r1 8000cae: 6141 str r1, [r0, zephyrproject-rtos#20] 8000cb0: 2000 movs r0, #0 8000cb2: 4770 bx lr Change-Id: Ie5800d1c345016028d1b9a099f5d74cac35f592a Signed-off-by: Florian Vaussard <[email protected]>
1 parent 8fcb780 commit 632a07d

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

arch/arm/soc/st_stm32/stm32f4/soc_gpio.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,12 @@ int stm32_gpio_set(uint32_t *base, int pin, int value)
210210
{
211211
struct stm32f4x_gpio *gpio = (struct stm32f4x_gpio *)base;
212212

213-
int pval = 1 << (pin & 0xf);
214-
215213
if (value) {
216-
gpio->odr |= pval;
214+
/* atomic set */
215+
gpio->bsr = (1 << (pin & 0x0f));
217216
} else {
218-
gpio->odr &= ~pval;
217+
/* atomic reset */
218+
gpio->bsr = (1 << ((pin & 0x0f) + 0x10));
219219
}
220220

221221
return 0;

0 commit comments

Comments
 (0)