linjinming2000 发表于 2025-8-5 14:38

关于gpio_bits_toggle函数的错误

* @brieftoggle the selected data port bits.
* @paramgpio_x: to select the gpio peripheral.
*         this parameter can be one of the following values:
*         GPIOA, GPIOB, GPIOC, GPIOD, GPIOE.
* @parampins: gpio pin number
*         parameter can be any combination of gpio_pin_x, gpio_pin_x as following values:
*         - GPIO_PINS_0
*         - GPIO_PINS_1
*         - GPIO_PINS_2
*         - GPIO_PINS_3
*         - GPIO_PINS_4
*         - GPIO_PINS_5
*         - GPIO_PINS_6
*         - GPIO_PINS_7
*         - GPIO_PINS_8
*         - GPIO_PINS_9
*         - GPIO_PINS_10
*         - GPIO_PINS_11
*         - GPIO_PINS_12
*         - GPIO_PINS_13
*         - GPIO_PINS_14
*         - GPIO_PINS_15
*         - GPIO_PINS_ALL
* @retval none
*/
void gpio_bits_toggle(gpio_type *gpio_x, uint16_t pins)
{
gpio_x->odt ^= pins;
}

上面是新增的引脚翻转函数,但是该函数不是原子操作的,再反转过程中由于中断中修改了该ODT寄存器的值后会导致中断中修改的值错误,正确的做法是下面的代码:

void gpio_bits_toggle(gpio_type *gpio_x, uint16_t pins)
{
uint32_t odt = gpio_x->odt;
gpio_x->scr =((odt&pins) << 16) | (~odt&pins);
}

mark一江水 发表于 2025-8-5 18:36

感谢提醒,我们后续会再做优化。

丙丁先生 发表于 2025-8-6 04:43

流水灯吗

xch 发表于 2025-8-6 11:27

本帖最后由 xch 于 2025-8-6 11:28 编辑

void gpio_bits_toggle(gpio_type *gpio_x, uint16_t pins)
{
__disable_irq();
gpio_x->odt ^= pins;
__enable_irq();
}

怕中断就关闭中断。不行吗?一共加两字节长度,两条指令
页: [1]
查看完整版本: 关于gpio_bits_toggle函数的错误