реклама на сайте
подробности

 
 
> va_list thread-safe внутри critical region?, HardFault под FreeRTOS из-за va_arg
Cosmojam
сообщение Oct 15 2012, 18:47
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Всем привет!
Подскажите где я не прав.
Имеется примерно такой код для LPC1768 с FreeRTOS:
Код
uint_fast8_t syslog_write(SysLogRecordType type, const signed char * const threadname, const char *fmt, ...)
{
    /* whatever */
      char string[SYSLOG_MAXLINE] = {0};

    taskENTER_CRITICAL();

    va_list args;
    va_start(args, fmt);
    length = format_string(string, sizeof string, type, threadname, fmt, args);
    va_end(args);

    taskEXIT_CRITICAL();

        /* whatever */
}

Вызывается это из разных задач.

Функция format_string():
Код
static size_t format_string(char *buffer, size_t size, SysLogRecordType type, const char * const threadname, const char *fmt, va_list args)
{
/* whatever */
       vsprintf(buffer, fmt, args);

  /* whatever */
}

Проблема в том что когда syslog_write() вызывается в разных потоках, то в vsprintf() происходит HardFault (CFSR = 0x8200). Если заменить эту функцию на что угодно типа sprintf(buffer, "hi there") то всё работает стабильно. Т.е. связано это как-то с va_list. Я честно говоря плохо понимаю как эта фишка работае. При этом вызов её обёрнут в taskENTER_CRITICAL();
Если же syslog_write() вызывается только в одном потоке, то никаких проблем. Но стоит ему вызываться в разных вытесняющих друг друга - периодические фолты.


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Cosmojam
сообщение Oct 16 2012, 18:09
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Стека хватает - к гадалке не ходи. Пробовал безумные размеры выделять где "640кб всем хватит"
А насчёт кучи на NXP-шном форуме подсказали http://support.code-red-tech.com/CodeRedWiki/redlib_v2_notes макрос CR_PRINTF_CHAR чтобы printf() не выделяла память в куче под всю строку, а печатала по-символьно. Не помогло. Да и ведь там про printf()говорится, которые выделяет память прежде чем напечатать строку в символьное устройство, а у меня vsnprintf() который печатает строку в буфер и не более переданного размера буфера. Т.е. куча ему пофигу покуда буфер на стеке задачи. Но если разместить буфер в bss (сделав его static) то никаких изменений в поведении не наблюдается.
Если уж на то пошло посоветуйте достойный аналог vsnprint(). Вещественные числа не нужны, только целые со знаком и без и строки, и чтобы не пыталась выделять память без спроса

Сообщение отредактировал Cosmojam - Oct 16 2012, 18:18


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
Terminator
сообщение Oct 17 2012, 01:49
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 209
Регистрация: 7-12-04
Из: Томск
Пользователь №: 1 382



Цитата(Cosmojam @ Oct 17 2012, 01:09) *
Стека хватает - к гадалке не ходи. Пробовал безумные размеры выделять где "640кб всем хватит"

Прям странно очень. Скорее всего где-то ошибаешься.

У меня по всем проектам понатыканы DBG(...) через sprintf (не библиотечный конечно), отлично работает.
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Oct 17 2012, 09:18
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Цитата(Terminator @ Oct 17 2012, 04:49) *
Прям странно очень. Скорее всего где-то ошибаешься.

У меня по всем проектам понатыканы DBG(...) через sprintf (не библиотечный конечно), отлично работает.

Не, всё нормально со стеком. Ошибаюсь наверное в том что этот буфер выделяется на стеке вызывающей функцию задачи => стек всех задач должен быть больше на размер буфера. Поскольку работа с буфером ведётся внутри критической секции, то лучше сделать буфер в bss, заменить критическую секцию на мьютекс и возвращать мьютекс после записи буфера в очередь


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 08:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01416 секунд с 7
ELECTRONIX ©2004-2016