Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: двоичные семафоры для FreeRTOS
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > FreeRTOS
ddiimmaa
В FreeRTOS работа двоичного семафора реализована в виде макросов, которые вызвают функции очереди при создании семафора, на самом деле вместо семафора создаётся очередь в 1 элемент размером в 0 байт.

Другими словамии Двоичный мемафор -- очередь 1 элементx0 байт

В итоге получаеться что почти все элементы структуры Очереди не используются: из двух списков (списки читателей и писателей) используеться только один. Переменные "Счётчик элементов" и "Размер элемента" всегда заведомо равны 1 и 0, так зачем их хранить в памяти????

Не знаю как создатель ОС -- Ричард Барри, но по моему тратить такое ценный ресурс как ОЗУ на двоичный семафор расточительно.

В связи с этим я написал свой вариант Двоичных семафоров
Он выложен на http://freertos.narod.ru. В нём в качестве двоичного семафора используеться толко Один список то есть
typedef xList Semph,
что позволяет экономить на памяти, и выигрывает в скорости. Особенно это может быть применено в системах где не нужны очереди сообщений, где нужны только семафоры.

Если кого заинтересовало прошу скачивать и пользоваться. Если это чудо зароботает у кого ещё можно и написать что-нибудь тут!
zltigo
Цитата(ddiimmaa @ Dec 12 2008, 19:47) *
Не знаю как создатель ОС -- Ричард Барри, но по моему тратить такое ценный ресурс как ОЗУ на двоичный семафор расточительно.

На самом деле семафор эта такая сущность, задачи которой можно рещить, особенно в микроконтроллерном мире, другими способами. По этой причине реализация его ввиде макроса на очереди позволяет его в первом приближении иметь, напимер при быстром портировании чего либо готового, причем во вполне рабочем и отлаженном варианте.
Цитата
В связи с этим я написал свой вариант Двоичных семафоров
Он выложен на http://freertos.narod.ru. В нём в качестве двоичного семафора используеться толко Один список то есть
typedef xList Semph,
что позволяет экономить на памяти, и выигрывает в скорости. Особенно это может быть применено в системах где не нужны очереди сообщений, где нужны только семафоры.

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

Посмотрю обязательно!
P.S.
Оказывается раньше уже смотрел smile.gif Оталось проникнутся и попробовать живьем, при случае!

Цитата(ddiimmaa @ Dec 12 2008, 19:47) *
Не знаю как создатель ОС -- Ричард Барри, но по моему тратить такое ценный ресурс как ОЗУ на двоичный семафор расточительно.

Пообщаться пробовали smile.gif sad.gif ? Мужик сильно упертый sad.gif, на мой взгляд.
ddiimmaa
Цитата
На самом деле семафор эта такая сущность, задачи которой можно рещить, особенно в микроконтроллерном мире, другими способами.

Семафор -- основа основ, а другими способами, это как? -- бесконечный цикл ожидания или система управляемая событиями? -- тогда это как-то не по ОС-овски выходит.
Цитата
Систем, где нужны очереди/сообщения переделал за свою жизнь немало, а вот на голых семафорах как-то не приходилось еще задач встречать.

Ну не знай, по моему первое и самое простое, основа основ -- семафор. Семафор используется для защиты от совместного доступа к одной и той же части устройства или одним и тем же переменным. Зачем мне тут очередь каких-то сообщений? Мне главное чтобы одновременно эту часть устройства не использовали несколько потоков.

Даже там, где передаётся информация, можно обойтись семафором, если пара производитель/потребитель( читатель/писатель) в определённый момент времени существует
всего лишь одна. То есть никогда нет такого, что два читателя или два писателя.
Вот у меня так на атмеге написана работа с АЦП, SPI, TWI, просто и со вкусом: очень даже неплохо работает семафор + указатель на буфер + счётчик и всё тут: приложение заказывает небходимое число байт а прерывание заполняет ему буфер, пока то висит на семафоре. Множно сказать, что я и написал очередь сообщений, ан нет! то как написано на полноценную очередь сообщений не катит, так как и писатель и читатель всего лишь один, и вообще писатель не задача а прерывание.
Цитата
Пообщаться пробовали :) :( ? Мужик сильно упертый :( , на мой взгляд.

Пробовал! Особого энтузиазизьма у него это не вызвало! И у меня немного чешуться руки "утереть ему нос" за это.
На мой взгляд тоже упёртый и гнёт свою линию жёстко. У него есть своё вИденье того, как надо развивать своё ПО. Ну чтож влаг ему в руки. Мне кажеться, дело всё в том, что у него двойное лицензирование. И то, что он развивает FreeRTOS под GPL -- это просто хороший рекламный трюк.
zltigo
Цитата(ddiimmaa @ Dec 13 2008, 21:03) *
Ну не знай, по моему первое и самое простое, основа основ -- семафор. Семафор используется для защиты от совместного доступа к одной и той же части устройства или одним и тем же переменным.

Ну давайте по порядку, если это какая-то "мелкая" недолго занимемая часть устройства, то для разруливания доступа к ней совершенно незачем дергать ядро системы ввиде семафоров. Тут много более эффективнее критические секциии во всем своем разнообразии, начиная с банальных запретов прерываний. Если это действительно сложное и долго обслуживаемое "устройство", то очень часто его обслуживает свой, действительно сложный процесс - тут уже может быть буферизация, приоритеты, замораживание процессов...
Цитата
Даже там, где передаётся информация, можно обойтись семафором, если пара производитель/потребитель( читатель/писатель) в определённый момент времени существует

Ну зачем-же обходится-то smile.gif надо все делать наиболее бескомпромисно smile.gif
Цитата
Вот у меня так на атмеге написана работа с АЦП, SPI, TWI, просто и со вкусом: очень даже неплохо работает семафор + указатель на буфер + счётчик и всё тут: приложение заказывает небходимое число байт а прерывание заполняет ему буфер, пока то висит на семафоре. Множно сказать, что я и написал очередь сообщений, ан нет! то как написано на полноценную очередь сообщений не катит, так как и писатель и читатель всего лишь один, и вообще писатель не задача а прерывание.

Ну-ну... Семафор-то зачем? Задача вообще спит "вечным" сном. Обработчик прерывания получив порцию чего-то и положив в буфер поднимет задачу. Так у меня издревле, например, консолька работает - набежала командная стока - поднимаем задачу с ней разбирающуюся.
Код
static __noreturn void Console( void *param )
{
.......
    cbuf_parser( &cmd, &cbuf.buf[0] );        // Call Command Line parser
    vTaskSuspend( NULL );
    }
}

__irq __arm  void uart_isr( void )
{

......
    case '\r':
        xTaskResumeFromISR( handle_Console );
        break;
.....
}
ddiimmaa
Цитата(zltigo @ Dec 13 2008, 22:28) *
Ну-ну... Семафор-то зачем? Задача вообще спит "вечным" сном. Обработчик прерывания получив порцию чего-то и положив в буфер поднимет задачу. Так у меня издревле, например, консолька работает - набежала командная стока - поднимаем задачу с ней разбирающуюся.
Код
static __noreturn void Console( void *param )
{
.......
    cbuf_parser( &cmd, &cbuf.buf[0] );        // Call Command Line parser
    vTaskSuspend( NULL );
    }
}

__irq __arm  void uart_isr( void )
{

......
    case '\r':
        xTaskResumeFromISR( handle_Console );
        break;
.....
}


Ну дак это вы заранее знаете какая у вас там задача консоль ждёт, а я вот не знаю заренне какая задача у меня будет ждать очередные 10 имерений с АЦП. Что мне прикажете делать?
Тут я вижу два варианта
1. в особую глобальную переменую задача ложить свой handle , а потом прерывание делает xTaskResumeFromISR( эта глобальная переменная); что по сути и являеться вариантом списка ждуших задач на одном семафоре.
2. Использовать очередь сообщений, но пардонте, в очереди сообщений есть две штуки которые жрут память 1. песполезно болтаеться список процессов ждуших к отправке занимает 9 байт(не бог весть что но у меня вообще эти 10 измерений АЦП занимаю 20 байт) 2. очередь имеет буфер который на фиг мне не нужен (тоже жрёт память)
3. Вариант делать спец процесс который будет принимать заявки и что-то там кому-нибудь раздавать -- вообще не катит так как займёт ещё больше ОЗУ




Цитата(zltigo @ Dec 13 2008, 22:28) *
Ну давайте по порядку, если это какая-то "мелкая" недолго занимемая часть устройства....

Вот в том то и дело, что мелкая но долго занимаемая -- у меня например АЦП долго работает!
Цитата
Ну зачем-же обходится-то :) надо все делать наиболее бескомпромисно :)

Вот я и стараюсь безкомпромисно, только относительно размера бесполезно затрачиваемой ОЗУ, да и по скорости простой семафор явно быстрее очереди сообщений работать будет!
zltigo
Цитата(ddiimmaa @ Dec 14 2008, 15:37) *
1. в особую глобальную переменую задача ложить свой handle , а потом прерывание делает xTaskResumeFromISR( эта глобальная переменная); что по сути и являеться вариантом списка ждуших задач на одном семафоре.

Типа да, и без дополнительных сущностей.
Цитата
2. Использовать очередь сообщений, но пардонте...

Это смотря как ее использовать, например можно сладывать в нее указатели на внешний буфер. Можно ее блокировать и складывать в обработчике прерывания результаты прямо ее буфер....
Цитата
3. Вариант делать спец процесс который будет принимать заявки и что-то там кому-нибудь раздавать -- вообще не катит так как займёт ещё больше ОЗУ

При этом наличие _нескольких_ процессов ждущих результатов ADC Вас не смущает. А может вместо них должен быть один тот самый процесс?
Цитата
Вот в том то и дело, что мелкая но долго занимаемая -- у меня например АЦП долго работает!
...простой семафор явно быстрее очереди сообщений работать будет!

Простой-то он простой, но ядро системы тоже нагружает. При этом самое неприятное с моей точки зрения то, то относительно своей ОЧЕНЬ ПРОСТОЙ функции он ресурсов потребляет многовато sad.gif
Предпочитаю по мелочам не "дергаться". В общем до сих пор (совершенно не отказывая себе в чем-то) ни во FreeRTOS, ни в одной из своих систем используемых с 90x годов семафоры в сколь-нибудь явном виде не реализовавал.
ddiimmaa
Цитата(zltigo @ Dec 14 2008, 17:01) *
При этом наличие _нескольких_ процессов ждущих результатов ADC Вас не смущает. А может вместо них должен быть один тот самый процесс?

Тут нет не смущает, существующего уровня реалтайма мне хватает. Всё равно АЦП медленный и заранне мне всё равно не надо чтобы он что-то считывал. И вообще вероятность того, что будут висеть две и более задачи на семафоре очень мала, хотя и есть. Вот из-за этого мне и надо защитить минимальными средствами АЦП от одновременного доступа. Можно было бы использовать критические секции но уж он больно медленно считает по сравнению с работой самого семафора.
Цитата
Простой-то он простой, но ядро системы тоже нагружает. При этом самое неприятное с моей точки зрения то, то относительно своей ОЧЕНЬ ПРОСТОЙ функции он ресурсов потребляет многовато sad.gif
Предпочитаю по мелочам не "дергаться". В общем до сих пор (совершенно не отказывая себе в чем-то) ни во FreeRTOS, ни в одной из своих систем используемых с 90x годов семафоры в сколь-нибудь явном виде не реализовавал.

Чтож рад за вас yeah.gif что вы не юзаете семафоры, видимо я тут начитался всяких Таненбаумов и прочее wacko.gif , где написано, что это самое простое что должно зашищять от гонок.
zltigo
Цитата(ddiimmaa @ Dec 14 2008, 17:45) *
...написано, что это самое простое что должно зашищять от гонок.

Так ведь правда написана! Постое в применениии и очень понятное средство. Но как-то уж обычно в моих задачах "лобовым" представляется.
Terminator
Интересная тема smile.gif
Цитата(zltigo @ Dec 14 2008, 19:01) *
Цитата(ddiimmaa)
1. в особую глобальную переменую задача ложить свой handle , а потом прерывание делает xTaskResumeFromISR( эта глобальная переменная); что по сути и являеться вариантом списка ждуших задач на одном семафоре.
Типа да, и без дополнительных сущностей.


А как быть в такой ситуации?
Драйвер SPI с использованием PDC (sam7). Сейчас для информирования задачи об окончании работы PDC, используется семафор, признанный zltigo слишком тяжеловесным для этого smile.gif
Если переделать на глобальную переменную с handle, то получается вроде красиво
Код
void SPIWrite(void *buf, uint32_t size, xTaskHandle currHandle)
{
  ...
  spiHandle = currHandle;
  startpdc;
  vTaskSuspend(NULL);
}

А если предположить что в момент startpdc запустится задача/задачи с более высоким приоритетом и займут cpu на большое время в течении которого PDC всё сделает и в прерывании выполнит xTaskResumeFromISR(spiHandle), то по логике получим остановленную без причины задачу.

Конечно пример неочень хороший, но ведь такое возможно же? smile.gif
Terminator
Пример выше и с семафором работать не будет, т.е. гипотетическая ситуация также приведёт к остановленной задаче.
Как же тогда правильно разрулить подобную ситуацию?
Terminator
Простите протупил blush.gif с семафором будет работать в любом случае.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.