Перейти к содержанию
    

Использование семафоров до старта планировщика

При использовании семафоров наткнулся на HardFault и задумался, а можно ли их использовать до старта планирощика?

 

Или перед использовением (xSemaphoreTake(Recursive) / xSemaphoreGive(Recursive)) нужно проверять xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED ?

 

Подробности такие. До старта планировщика задач (vTaskStartScheduler()) создается семафор _semaphore = xSemaphoreCreateRecursiveMutex() и потом используется в виде пары:

 

xSemaphoreTakeRecursive(_semaphore, (portTickType)portMAX_DELAY)

...

xSemaphoreGiveRecursive(_semaphore)

 

Конечно смысла в семафорах до старта задач нет, до старта задач поток один. Но это унифицированный код, он используется и из задач, и до старта планировщика.

 

Все работало нормально, но вчера вылез HardFault, трассировка привела к этому участку в queue.c:

 

if( xTaskResumeAll() == pdFALSE )

{

portYIELD_WITHIN_API();

}

 

При вызове portYIELD_WITHIN_API() вылетает в HardFault.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Конечно смысла в семафорах до старта задач нет, до старта задач поток один. Но это унифицированный код, он используется и из задач, и до старта планировщика.

Все работало нормально, но вчера вылез HardFault, трассировка привела к этому участку в queue.c:

 

if( xTaskResumeAll() == pdFALSE )

{

portYIELD_WITHIN_API();

}

 

При вызове portYIELD_WITHIN_API() вылетает в HardFault.

А это Ваш код? В смысле Вы так придумали или это код совместной работы в команде? А зачем так извращаться вообще? Мне, можно сказать новичку, итак ясно, что при вызове portYIELD_WITHIN_API() работа перейдет к планировщику. А как оно у Вас до сих пор работало интересно? :) Конечно в мире разные бывают любители и пр. Но вот зачем иногда не совсем понятно.

 

Изменено пользователем AleksBak

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, очереди/семафоры/sleep() с остановленным шедулером не работают.

Я поначалу кинулся расставлять проверки "планировщик работает" прямо в код операционки (мне кажется, это правильнее, чем тыкать во все возможные места xTaskGetSchedulerState() ), но потом просто перенёс большую часть кода в задачи (до того у меня вся инициализация железа была в main() - осталось только самое необходимое).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, это код из queue.c, привел его для понимания что вызывает HardFault

Да это понятно. Я неправильно выразился - имел ввиду, что код/проект/структуру программы Вы сами придумали или кто-то "заставляет"(совместная команда, код какой задачи закрытый и пр.) именно так поступить (использовать семафоры до старта). Уже тут esaulenka и написал к чему пришел и как получше тут будет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

(до того у меня вся инициализация железа была в main() - осталось только самое необходимое).

В main() действительно самая минимальная инициализация и подъем, например, консоли. После чего или запускается задача инициализации и потом прибивается за ненадобностью, или ставится hook на IdleTask и потом убирается.

int main(void)
{
int id = iap_getid();
    init_clock( configQUARC_HZ, configCPU_CLOCK_HZ );
    gpio_init();
    init_system_heap( id );
    xIdleTaskCreate( IDLE_TASK_STACK_SIZE );
    // Start Console and Console Task.
    init_console( CONSOLE_BAUD_RATE, CONSOLE_PRIORITY, CONSOLE_TASK_STACK_SIZE );
    hellomessage();
    vSetIdleHook( init_system );
    vTaskStartScheduler( INTERNAL_TIMER );            
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да это понятно. Я неправильно выразился - имел ввиду, что код/проект/структуру программы Вы сами придумали или кто-то "заставляет"(совместная команда, код какой задачи закрытый и пр.) именно так поступить (использовать семафоры до старта). Уже тут esaulenka и написал к чему пришел и как получше тут будет.

Сам придумал. Код унифицированный, он не знает что работает из задачи или не из задачи. При работе из задачи ресурс должен быть защищен от одновременного использорвания из нескольких потоков, потому в коде семафоры.

 

Я поначалу кинулся расставлять проверки "планировщик работает" прямо в код операционки (мне кажется, это правильнее, чем тыкать во все возможные места xTaskGetSchedulerState() ), но потом просто перенёс большую часть кода в задачи (до того у меня вся инициализация железа была в main() - осталось только самое необходимое).

У меня в main только одноразовые инициализации, требующие много стековой памяти. Чтобы не выделять много стека под каждую задачу. А так тоже все остальное в задачах. Также реализовано отслеживание зависания задач.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

потому в коде семафоры.

Некоторое количество лет назал, где-то в районе появления FreeRTOS 2.0 я начал с ней копаться. До этого имел за плечами работу с операционными сисиемами, как с чужими, так и со своими. Удивило тогда меня, что всякие семафоры и иже с ними сделаны через макросы очередей. Призадумался я да и понял, что семафоры и иже с ними в общем-то есть ЛИШНЯЯ сущность. И с тех пор не пользую. За ненадобностью.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Некоторое количество лет назал, где-то в районе появления FreeRTOS 2.0 я начал с ней копаться. До этого имел за плечами работу с операционными сисиемами, как с чужими, так и со своими. Удивило тогда меня, что всякие семафоры и иже с ними сделаны через макросы очередей. Призадумался я да и понял, что семафоры и иже с ними в общем-то есть ЛИШНЯЯ сущность. И с тех пор не пользую. За ненадобностью.

А как вы решаете проблему с одновременной работой участка кода из нескольких задач? Конечно в случае если участок кода критичен чтобы к нему не обращались из нескольких задая одновременно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как вы решаете проблему с одновременной работой участка кода из нескольких задач? Конечно в случае если участок кода критичен чтобы к нему не обращались из нескольких задая одновременно.

Как оказалось :), система может строится так, что такая задача может быть решена и без лобовых семафоров. Например, чем этот "участок кода" не есть отдельная задача получающая сообщения и их обрабатывающая? Естественно, при этом нужно много тщательнее продумывать структуру, ибо задачи действительно должны быть задачами выполняющими разумны едействия, а не кучей "кусков кода". Семафоры это в общем-то заплатки. Ими удобно и привычно можно латать, а можно и не латать :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как оказалось :), система может строится так, что такая задача может быть решена и без лобовых семафоров. Например, чем этот "участок кода" не есть отдельная задача получающая сообщения и их обрабатывающая?

Это слишком расточительно, на тот же лог выделять отдельную задачу.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это слишком расточительно, на тот же лог выделять отдельную задачу.

Лог дело важное и одновременно он не должен перекашивать систему тормозя задачи, причем с перекосами приоритетов. Так что именно разработке логирования надо уделять особое внимание и не скупится. Если действительно сыпется идет обильная информция с самых разных уровней, причем не всегда, а когда, наример, отладку включили, то надо ОЧЕНЬ крепко думать, как организовать доступ к логу.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если действительно сыпется идет обильная информция с самых разных уровней, причем не всегда, а когда, наример, отладку включили, то надо ОЧЕНЬ крепко думать, как организовать доступ к логу.

Не обильная, иначе не переварить человеку. При использовании задачи для того же лога возникает новая проблема - какой длины выделить очередь для сообщений, чтобы лог всегда гарантировано мог принять новое сообщение. В итоге снова приходим к семафорам :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не обильная, иначе не переварить человеку, для которого этот лог и ведется.

Ну лог, на то и лог, что бы читать его и длинными зимними вечерами :).

И лучше хорошо подумать как не тратить целую задачу на это.

Затраты одного MCB и стека, который по любому хоть в отдельной, хоть нет, логированим съедаться будет.

Плюс при использовании задачи для того же лога возникает новая проблема - какой длины выделить очередь для сообщений, чтобы лог всегда гарантировано мог принять новое сообщение.

Средний темп выдачи лога по любому должен быть оценен. Хоть с задачей, хоть без задачи, хоть с семафорами, хоть без ничего, хоть как. Не будет буферизации будет "никак". Где будет буфер в очереди или нет, дело десятое. Если задачам придется непрерывно драться и ждать МЕДЛЕННОГО логирования, то это перекосит всю систему.

Если вдруг, при какой то нештатной ситуации темп выдачи лога резко возрос, то тем блее следует аккуратно разбираться с тем, кто может ждать, кто не может, а чья инфрмация вообще сейчас неважна - выкинуть в пропость.

В итоге снова приходим к семафорам :)

Дались Вам эти семафоры. Это совершенно виртуальная штука, функционал котрых может быть организован разнообразными способами. Естественно НЕ с целью сделать те-же яйца в профиль, а получить дополнительный функционал. Ведь та же реализация семафоров на очередях на самом деле просто усекала функционал очереди, котрый, если подумать, можно использовать БОЛЕЕ полно и эффективно.

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ведь та же реализация семафоров на очередях на самом деле просто усекала функционал очереди, котрый, если подумать, можно использовать БОЛЕЕ полно и эффективно.

Согласен, у FreeRtos только очереди, на базе нее реализовали все примитивы. А вот в новых версиях появилась xTaskNotify() / xTaskNotifyWait(), это тоже на очередях, или там свой механизм? Это эффективнее очередей для ожидания задачей сигнала к старту?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...