va_start неожиданное поведение - PullRequest
0 голосов
/ 11 апреля 2020

В настоящее время я работаю над микроконтроллером STM32, который связывается по последовательному каналу (UART Communication) с последовательным терминалом, установленным на моем компьютере (TeraTerm).

Я реализовал функцию на своем STM32, чье поведение такой же, как printf. Для этого я использовал va_start MACRO, va_list, vprint и va_end.

Вот различные функции:

-> printf, как (используя функцию 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 *:

Wrong pin char *

но на TeraTerm я получаю:

enter image description here

, поэтому 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

...