为什么无法复用模组的授权烧录 IO 口

Zigbee 子设备开发


clcl
Posts: 43

用的 ZSU 模组(EFR32MG21A020F1024IM32),由于引脚有些不够用,因此复用了 授权烧录脚 UART 口 (PA5 和 PA6)用作其他功能

Image

但是实际上,我发现当我设置了端口模式后,后面端口的模式会被自动覆盖掉,我写了一个测试代码:

  • 它会一直输出 "setup IO_ADC_MOTOR_CURRENT_IN_PIN",说明 PA5 的模式没有设置成功

Code: Select all

OPERATE_RET tuya_main_loop(VOID_T)
{
    uint32_t m = GPIO_PinModeGet(gpioPortA, 5);
    if (m != gpioModeDisabled) {
        TAL_PR_DEBUG("setup IO_ADC_MOTOR_CURRENT_IN_PIN\n");
        GPIO_PinModeSet(gpioPortA, 5, gpioModeDisabled, 0);
    }
    
uint32_t m2 = GPIO_PinModeGet(gpioPortA, 6); if (m2 != gpioModeInputPullFilter) { TAL_PR_DEBUG("setup IO_WIN_POS_DETECT_IN1_PIN\n"); GPIO_PinModeSet(gpioPortA, 6, gpioModeInputPullFilter, 1); } //... return OPRT_OK; }

请问这是怎么回事?

zeso
Posts: 132

Re: 为什么无法复用模组的授权烧录 IO 口

你好,请问是具体在什么位置重新配置PA5/6的端口模式?

我的栈溢不出。

clcl
Posts: 43

Re: 为什么无法复用模组的授权烧录 IO 口

在 tuya_init_last 里初始化的引脚

  • PA5 是配置成浮空模式,用作 ADC 输入

Code: Select all

GPIO_PinModeSet(gpioPortA, 5, gpioModeDisabled, 0);
zeso
Posts: 132

Re: 为什么无法复用模组的授权烧录 IO 口

你好,请使用tal_gpio.h的接口重新测试下。

我的栈溢不出。

clcl
Posts: 43

Re: 为什么无法复用模组的授权烧录 IO 口

设置了,没有效果

Code: Select all


TUYA_GPIO_BASE_CFG_T iocfg;
// UART_TXD0,烧录授权引脚,对应IC的PA05(Pin22)
iocfg.mode   = TUYA_GPIO_FLOATING;
iocfg.level  = TUYA_GPIO_LEVEL_LOW;
iocfg.direct = TUYA_GPIO_INPUT;
tal_gpio_init(TUYA_GPIO_NUM_22, &iocfg);
// UART_RXD0,烧录授权引脚,对应IC的PA06(Pin23)
iocfg.mode   = TUYA_GPIO_INPUT;
iocfg.level  = TUYA_GPIO_LEVEL_HIGH;
iocfg.direct = TUYA_GPIO_INPUT;
tal_gpio_init(TUYA_GPIO_NUM_23, &iocfg);

用 uint32_t m = GPIO_PinModeGet(gpioPortA, 5); 读出来是 0x00000004,对应 gpioModePushPull 模式

clcl
Posts: 43

Re: 为什么无法复用模组的授权烧录 IO 口

在设置完后,立即读端口模式是正确的值 0x0

要等几秒,放到延时 2s 执行的定时器里,然后读模式就是 0x00000004

clcl
Posts: 43

Re: 为什么无法复用模组的授权烧录 IO 口

我把我的业务逻辑,初始化代码,全都注释掉

然后在 IAR 的 Linker 选项里添加:--redirect GPIO_PinModeSet=_wrap_GPIO_PinModeSet

将 GPIO_PinModeSet 重定向到我自己实现的 _wrap_GPIO_PinModeSet 函数里

然后在里面添加了打印 TAL_PR_DEBUG("call GPIO_PinModeSet(%d, %d, %d, %d)\n", port, pin, mode, out);

这样就可以监视所有的 GPIO_PinModeSet 调用

Code: Select all

void _wrap_GPIO_PinModeSet(GPIO_Port_TypeDef port,
                           unsigned int pin,
                           GPIO_Mode_TypeDef mode,
                           unsigned int out)
{
    TAL_PR_DEBUG("call GPIO_PinModeSet(%d, %d, %d, %d)\n", port, pin, mode, out);

/* If disabling a pin, do not modify DOUT to reduce the chance of */
/* a glitch/spike (may not be sufficient precaution in all use cases). */
if (mode != gpioModeDisabled) {
    if (out) {
        GPIO_PinOutSet(port, pin);
    } else {
        GPIO_PinOutClear(port, pin);
    }
}

/* There are two registers controlling the pins for each port. The MODEL
 * register controls pins 0-7 and MODEH controls pins 8-15. */
if (pin < 8) {
    GPIO->P[port].MODEL = (GPIO->P[port].MODEL & ~(0xFu << (pin * 4))) | (mode << (pin * 4));
} else {
    GPIO->P[port].MODEH = (GPIO->P[port].MODEH & ~(0xFu << ((pin - 8) * 4))) | (mode << ((pin - 8) * 4));
}

if (mode == gpioModeDisabled) {
    if (out) {
        GPIO_PinOutSet(port, pin);
    } else {
        GPIO_PinOutClear(port, pin);
    }
}
}

重新编译后,程序跑起来之后,log 会一直打印:

Code: Select all

[D] : call GPIO_PinModeSet(0, 5, 0, 1)
[D] : call GPIO_PinModeSet(0, 5, 4, 1)
[D] : call GPIO_PinModeSet(0, 5, 0, 1)
[D] : call GPIO_PinModeSet(0, 5, 4, 1)
[D] : call GPIO_PinModeSet(0, 5, 0, 1)
[D] : call GPIO_PinModeSet(0, 5, 4, 1)
[D] : call GPIO_PinModeSet(0, 5, 0, 1)
[D] : call GPIO_PinModeSet(0, 5, 4, 1)
[D] : call GPIO_PinModeSet(0, 5, 0, 1)
[D] : call GPIO_PinModeSet(0, 5, 4, 1)
[D] : call GPIO_PinModeSet(0, 5, 0, 1)
[D] : call GPIO_PinModeSet(0, 5, 4, 1)
[D] : call GPIO_PinModeSet(0, 5, 0, 1)
[D] : call GPIO_PinModeSet(0, 5, 4, 1)
[D] : call GPIO_PinModeSet(0, 5, 0, 1)
[D] : call GPIO_PinModeSet(0, 5, 4, 1

说明一直有某个逻辑在循环设置 gpio PA5 的模式

我的程序里的所有 GPIO_PinModeSet 和 tal_gpio_init 我都注释了,还是会这样

zeso
Posts: 132

Re: 为什么无法复用模组的授权烧录 IO 口

请确认下是不是TAL_PR_DEBUG打印使用了串口导致的。

我的栈溢不出。

clcl
Posts: 43

Re: 为什么无法复用模组的授权烧录 IO 口

日志接口已经重写过了,使用 SWD 接口打印,不额外用任何 UART 口

使用 SEGGER_RTT logger 库进行打印,内部用的 SEGGER_RTT_vprintf

tal_log.h

Code: Select all


#include "miot-log.h"

#define TAL_PR_ERR(fmt, ...)                        MI_LOG_ERROR(fmt, ##__VA_ARGS__)
#define TAL_PR_WARN(fmt, ...)                       MI_LOG_WARNING(fmt, ##__VA_ARGS__)
#define TAL_PR_NOTICE(fmt, ...)                     MI_LOG_INFO(fmt, ##__VA_ARGS__)
#define TAL_PR_INFO(fmt, ...)                       MI_LOG_INFO(fmt, ##__VA_ARGS__)
#define TAL_PR_DEBUG(fmt, ...)                      MI_LOG_DEBUG(fmt, ##__VA_ARGS__)
#define TAL_PR_TRACE(fmt, ...)                      MI_LOG_DEBUG(fmt, ##__VA_ARGS__)

#define TAL_PR_HEXDUMP_ERR(title, buf, size)        MI_LOG_HEXDUMP(buf, size)
#define TAL_PR_HEXDUMP_WARN(title, buf, size)       MI_LOG_HEXDUMP(buf, size)
#define TAL_PR_HEXDUMP_NOTICE(title, buf, size)     MI_LOG_HEXDUMP(buf, size)
#define TAL_PR_HEXDUMP_INFO(title, buf, size)       MI_LOG_HEXDUMP(buf, size)
#define TAL_PR_HEXDUMP_DEBUG(title, buf, size)      MI_LOG_HEXDUMP(buf, size)
#define TAL_PR_HEXDUMP_TRACE(title, buf, size)      MI_LOG_HEXDUMP(buf, size)

zeso
Posts: 132

Re: 为什么无法复用模组的授权烧录 IO 口

你好,方便附一下代码我们测试验证。

我的栈溢不出。

Post Reply