Algol 0 Posted March 11, 2012 · Report post Доброго всем времени суток! Задача в целом тривиальна, но поскольку я впервые реализую ее с использование ОС, FreeRTOS в частности, то решил посоветоваться с более опытными людьми. Абстрактно задача заключается в опросе ацп с заданной частотой и отправкой полученных данных в коммуникационный порт. Следовательно можно выделить две задачи для ОС - задача №1 опроса ацп и задача №2 отправки готовых данных. Приоритет задачи 1 > приоритета задачи 2. Соответственно, чтобы запустить опрос ацп, нужно отсчитывать таймером заданные интервалы времени и в прерывании по переполнению таймера запускать задачу 1. Сейчас нахожусь на стадии чтения туториала по FreeRTOS..задачи моргания светодиодами и выдачи в консоль данных сделаны. Хотелось бы услышать 1) в целом верна ли моя концепция..или в рамках ОС можно сделать проще? Скажем отсчитывая периоды между опросами системным таймером ОС, но тогда снижается точность, если я правильно понял - интервал времени будет кратным системному тику. 2) данные между задачами нужно перебрасывать с помощью очереди в данном случае? 3) как лучше и/или проще пробудить задачу опроса ацп, блокированную событием таймера? Какое API для этого предоставляет FreeRTOS или же в прерывании от таймера просто искусственно повысить приоритет задачи опроса, чтобы по выходу из прерывания планировщик переключился на нее. Извините за некий сумбур...пока больше нахожусь на этапе сбора и осмысления информации. Все-таки работа с ОС требует некоторой перестройки мозгов, нежели standalone. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
aaarrr 1 Posted March 11, 2012 · Report post В этой концепции задача 1 просто лишняя: внутри прерывания таймера можно обслужить АЦП, а после накопления нужного количества данных известить об этом задачу 2. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Algol 0 Posted March 12, 2012 · Report post aaarrr Хм...логично. Хотя вот вчера добрался до главы работы с прерываниями в FreeRTOS tutorial book, так там на первой странице вроде как ответ на мой вопрос. Вроде как не рекомендуется делать большие обработчики прерываний, поэтому задачу блокируют бинарным семафором, а в прерывании просто разблокируют, тогда задача начнет свое выполнение сразу после выхода из прерывания. Мне кажется такой подход как то красивее...или я не прав? Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
AlexandrY 0 Posted March 12, 2012 · Report post Следовательно можно выделить две задачи для ОС - задача №1 опроса ацп и задача №2 отправки готовых данных. ... Опрос АЦП делать в отдельной задаче вообще не корректно. Не знаю на каком микроконтроллере вы работаете, но стоит организовать аппаратное преобразование с сохранением в память по DMA. А задача обмена просто читает из той памяти пользуясь тем, что DMA атомарно пишет слова. Использовать механизмы RTOS на таком низком уровне неэффективно. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Algol 0 Posted March 12, 2012 · Report post AlexandrY Прошу прощения, что возможно ввел в заблуждение стремлением абстрагировать задачу от архитектуры. Работаю с STM32. Насколько я понял из ваших слов, вы говорите о внутренней АЦП...в моей же задаче будет использоваться внешняя АЦП с SPI-интерфейсом, т.е. по прерыванию таймера должен работать аппаратный spi. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
viterra 0 Posted April 13, 2012 · Report post Стандартное решение. АЦП->SPI->DMA-> 2 'кольцевых' буфера. Один заполняется, второй в это время обрабатываете. Если скорость отсчётов не большая, то можно конечно и опросом, но как правило это не так. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
juvf 0 Posted April 13, 2012 (edited) · Report post поэтому задачу блокируют бинарным семафором, а в прерывании просто разблокируют, тогда задача начнет свое выполнение сразу после выхода из прерывания. Мне кажется такой подход как то красивее...или я не прав? такой подход лучше реализовать без прерываний. void task1(void*) { portTickType xLastWakeTime; xLastWakeTime = xTaskGetTickCount (); for(;;) { vTaskDelayUntil( &xLastWakeTime, 1000); //здесь читаем АЦП //здесь посылаем событие или сразу в компорт отправляем данные } } В таком случае чтение АЦП будет опрашиваться строго через каждые 1000 тиков. Точность будет мне кажется до 1 такта ЦПУ. с момента прерывания от системного таймера до момента переключения и входа в задачу task1() будет фиксированное кол-во тактов цпу (если конечно прерывание системного таймера не будет перекрыто более приоритетным прерыванием или запретом прерывания). Стандартное решение. АЦП->SPI->DMA-> 2 'кольцевых' буфера. Один заполняется, второй в это время обрабатываете. Если скорость отсчётов не большая, то можно конечно и опросом, но как правило это не так. Если частота выборок небольшая.... и чтение по спи быстрое, то vTaskDelayUntil вполне даже "красивее". Если конечно выборки частые, проц медленный, спи не быстрый...... то тут наверно применение АЦП->SPI->DMA будет оправдано. Иначе дма юзать - только если ради туториала. Edited April 13, 2012 by juvf Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...