首页 > 解决方案 > va_start 意外行为

问题描述

我目前正在开发一个 STM32 MCU,它通过串行链路(UART 通信)与安装在我的计算机上的串行终端(TeraTerm)进行通信。

我在我的 STM32 上实现了一个函数,其行为与 printf 相同。为此,我使用了 va_start MACRO、va_list、vprint 和 va_end。

以下是不同的功能:

--> printf like(使用UART函数发送数据)

/**
 *  \fn APP_errors_t SER_send_multiple(char* ui8_data_p, ...)
 *  \brief  function to send multiple data (like the printf function) via the serial link
 *  \param  ui8_data_p, string that will be sent via serial link
 *  \param  ... next data
 *  \return Any of the following values:
 *          SER_OK_E : if init is a success
 *          other : value if failure
*/
APP_errors_t SER_send_multiple(char* ui8_data_p, ...)
{
    APP_errors_t ret;
    va_list argp;
    va_start(argp, ui8_data_p);
    ret = vprint(ui8_data_p, argp);
    if(ret!= SER_OK_E)
    {
        SER_send("Error in SER_send_multiple function\r", strlen("Error in SER_send_multiple function\r"));
    }
    va_end(argp);
    return ret;
}

--> 函数 vprint 用于合并所有拆分的

/**
  * \brief APP_errors_t vprint(const char *fmt, va_list argp)
  * \param fmt This is the C string that contains the text to be written to the str
  *  \return Any of the following values:
  *         SER_OK_E : if init is a success
  *         other : value if failure
*/
// todo, cas ou le message à envoyer est trop grand ?
static APP_errors_t vprint(const char *fmt, va_list argp)
{
    char string[SER_TX_MAX_SIZE];
    if(0 < vsprintf(string,fmt,argp)) // build string
    {
        return SER_send(string, strlen(string));
    }
    // dead code
    return SER_OK_E;
}

--> 上面函数调用的函数

/**
 *  \fn APP_errors_t SER_send(char* ui8_data_p, uint16_t ui16_size)
 *  \brief  function to send data via the serial link
 *  \param  ui8_data_p, string that will be sent via serial link
 *  \param  ui16_size, number of chars that we want to send
 *  \return Any of the following values:
 *          E_OK : if init is a success
 *          other : value if failure
*/
APP_errors_t SER_send(char* ui8_data_p, uint16_t ui16_size)
{
    if(HAL_UART_Transmit(&huart2, (uint8_t*)ui8_data_p, ui16_size, SER_SEND_TIMEOUT) != HAL_OK)
    {
        return SER_TRANSMIT_ERROR_E;
    }
    return SER_OK_E;
}

所以有什么问题 ?

在另一个函数中,我正在调用 SER_send_multiple(char* ui8_data_p, ...) 函数:

SER_send_multiple("Pin does not exist  %s \r", args[OFF_PIN]);

args 是一个 char * 数组:

错误的 pin char *

但在 TeraTerm 我收到:

在此处输入图像描述

所以MCU只是发送第一个字符。

这是所有代码(第一行只是一个测试):

SER_send_multiple("Pin does not exist :  %s \r", args[OFF_PIN]);
SPCMD_arguments_T const * pins = &all_pins_a[inc];
while(ui8_found != 1 && pins->name_cmd != NULL) {
    if(strcmp(args[OFF_PIN], pins->name_cmd ) == 0) {
        GPIO_InitStruct.Pin = pins->value_define;
        ui8_found = 1;
    }
    pins = &all_pins_a[++inc];
}
//uint8_t length = strlen(args[OFF_PIN]);
if(!ui8_found)
{
    SER_send_multiple("Pin does not exist :  %s \r", args[OFF_PIN]);
    return 1;
}

最后,如果我取消注释 uint8_t length = strlen(args[OFF_PIN]); TeraTerm 正在接收:

succes_wrong_pin

那么那里到底发生了什么?这是一个废话,取消注释这条线不应该改变我的应用程序的行为吗?

有什么线索吗?

问候

AJT

标签: cstdmicrocontroller

解决方案


推荐阅读