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

двоичные семафоры для FreeRTOS

В FreeRTOS работа двоичного семафора реализована в виде макросов, которые вызвают функции очереди при создании семафора, на самом деле вместо семафора создаётся очередь в 1 элемент размером в 0 байт.

 

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

 

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

 

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

 

В связи с этим я написал свой вариант Двоичных семафоров

Он выложен на http://freertos.narod.ru. В нём в качестве двоичного семафора используеться толко Один список то есть

typedef xList Semph,

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

 

Если кого заинтересовало прошу скачивать и пользоваться. Если это чудо зароботает у кого ещё можно и написать что-нибудь тут!

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


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

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

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

В связи с этим я написал свой вариант Двоичных семафоров

Он выложен на http://freertos.narod.ru. В нём в качестве двоичного семафора используеться толко Один список то есть

typedef xList Semph,

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

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

Если кого заинтересовало прошу скачивать и пользоваться.

Посмотрю обязательно!

P.S.

Оказывается раньше уже смотрел :) Оталось проникнутся и попробовать живьем, при случае!

 

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

Пообщаться пробовали :) :( ? Мужик сильно упертый :(, на мой взгляд.

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


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

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

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

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

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

 

Даже там, где передаётся информация, можно обойтись семафором, если пара производитель/потребитель( читатель/писатель) в определённый момент времени существует

всего лишь одна. То есть никогда нет такого, что два читателя или два писателя.

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

Пообщаться пробовали :) :( ? Мужик сильно упертый :( , на мой взгляд.

Пробовал! Особого энтузиазизьма у него это не вызвало! И у меня немного чешуться руки "утереть ему нос" за это.

На мой взгляд тоже упёртый и гнёт свою линию жёстко. У него есть своё вИденье того, как надо развивать своё ПО. Ну чтож влаг ему в руки. Мне кажеться, дело всё в том, что у него двойное лицензирование. И то, что он развивает FreeRTOS под GPL -- это просто хороший рекламный трюк.

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


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

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

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

Даже там, где передаётся информация, можно обойтись семафором, если пара производитель/потребитель( читатель/писатель) в определённый момент времени существует

Ну зачем-же обходится-то :) надо все делать наиболее бескомпромисно :)

Вот у меня так на атмеге написана работа с АЦП, 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;
.....
}

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


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

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

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. Вариант делать спец процесс который будет принимать заявки и что-то там кому-нибудь раздавать -- вообще не катит так как займёт ещё больше ОЗУ

 

 

Ну давайте по порядку, если это какая-то "мелкая" недолго занимемая часть устройства....

Вот в том то и дело, что мелкая но долго занимаемая -- у меня например АЦП долго работает!

Ну зачем-же обходится-то :) надо все делать наиболее бескомпромисно :)

Вот я и стараюсь безкомпромисно, только относительно размера бесполезно затрачиваемой ОЗУ, да и по скорости простой семафор явно быстрее очереди сообщений работать будет!

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


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

1. в особую глобальную переменую задача ложить свой handle , а потом прерывание делает xTaskResumeFromISR( эта глобальная переменная); что по сути и являеться вариантом списка ждуших задач на одном семафоре.

Типа да, и без дополнительных сущностей.

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

Это смотря как ее использовать, например можно сладывать в нее указатели на внешний буфер. Можно ее блокировать и складывать в обработчике прерывания результаты прямо ее буфер....

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

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

Вот в том то и дело, что мелкая но долго занимаемая -- у меня например АЦП долго работает!

...простой семафор явно быстрее очереди сообщений работать будет!

Простой-то он простой, но ядро системы тоже нагружает. При этом самое неприятное с моей точки зрения то, то относительно своей ОЧЕНЬ ПРОСТОЙ функции он ресурсов потребляет многовато :(

Предпочитаю по мелочам не "дергаться". В общем до сих пор (совершенно не отказывая себе в чем-то) ни во FreeRTOS, ни в одной из своих систем используемых с 90x годов семафоры в сколь-нибудь явном виде не реализовавал.

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


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

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

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

Простой-то он простой, но ядро системы тоже нагружает. При этом самое неприятное с моей точки зрения то, то относительно своей ОЧЕНЬ ПРОСТОЙ функции он ресурсов потребляет многовато :(

Предпочитаю по мелочам не "дергаться". В общем до сих пор (совершенно не отказывая себе в чем-то) ни во FreeRTOS, ни в одной из своих систем используемых с 90x годов семафоры в сколь-нибудь явном виде не реализовавал.

Чтож рад за вас :yeah: что вы не юзаете семафоры, видимо я тут начитался всяких Таненбаумов и прочее :wacko: , где написано, что это самое простое что должно зашищять от гонок.

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

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


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

...написано, что это самое простое что должно зашищять от гонок.

Так ведь правда написана! Постое в применениии и очень понятное средство. Но как-то уж обычно в моих задачах "лобовым" представляется.

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


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

Интересная тема :)

1. в особую глобальную переменую задача ложить свой handle , а потом прерывание делает xTaskResumeFromISR( эта глобальная переменная); что по сути и являеться вариантом списка ждуших задач на одном семафоре.
Типа да, и без дополнительных сущностей.

 

А как быть в такой ситуации?

Драйвер SPI с использованием PDC (sam7). Сейчас для информирования задачи об окончании работы PDC, используется семафор, признанный zltigo слишком тяжеловесным для этого :)

Если переделать на глобальную переменную с handle, то получается вроде красиво

void SPIWrite(void *buf, uint32_t size, xTaskHandle currHandle)
{
  ...
  spiHandle = currHandle;
  startpdc;
  vTaskSuspend(NULL);
}

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

 

Конечно пример неочень хороший, но ведь такое возможно же? :)

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


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

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

Как же тогда правильно разрулить подобную ситуацию?

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


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

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

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

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

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

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

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

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

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

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