|
|
  |
libopencm3, Неплохая либа для кортексов... |
|
|
|
Apr 13 2015, 10:00
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Вы знаете, но честно говоря меня напрягают оценки результатов труда одного программиста, другим. Прога это такая субъективная вещь ... Я правда тоже тут с одним образчиком творчества работаю .... Тоже разговариваю одними междометиями и нецензурными словами, но всё же ... Можно понять и тех кто делал тот же stdlib или куб. Когда я последний проект начинал был только stdlib - посмотрел, что он для меня обладает избыточной функциональностью. И отказался от него. Особенно меня напрягла работа с портами. Для инициализации порта требуется ввести три енума потом три массива и работать через процедуры. Короче на первый взгляд значительный и неоправданный оверхед. Особенно в сравнении с тем как я привык писать. Но когда потом смотрел некоторые части понимаешь смысл написанного. Так как у меня написано - не стандартизуешь. Мы разные цели ставим перед собой. Они изначально закладывают избыточность и пишут библиотеки, чтобы максимально перекрыть все возможные применения. А я строю реальное приложение, устраняю избыточность, нацелен на локальное использование. В общем объёме приложения - объём драйверов у меня составляет единицы процентов. Учитывая что я их пишу в 2 - 3 уровня, то получается драйвера камнезависимые вообще копейки. Поэтому я могу себе позволить их написать. Хоть каждый раз. А стандартными воспользоваться как примером в каких то случаях. Это общие моменты, а конкретно ... Я вижу что куб был рассчитан на применение в составе ОСи. Причём обкатывался с разными. Приведу пример. Я использовал драйвер Ethernet из куба. Поскольку у меня не было заведено прерывания на обрыв линии, как это реализовано в кубе, то мне пришлось это сделать опросом в другой задаче... Я посмотрел их код и вижу например heth->State ... Это для чего написано? Для разруливания работы с устройством из под разных задач. И некоторые другие вещи. И как результат подключение не вызвало никаких проблем. У меня всё заработало устойчиво. Наверняка там тоже есть что оптимизировать. Так этим никто не запрещает заниматься. Даже механизм блокировки вы можете привести в соответствие с применяемой осью.
|
|
|
|
|
Apr 14 2015, 14:21
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Тут всё просто. Если ждать долго, то надо на окончение ожидания настраивать прерывание, и ждать флага. Если недолго, то ждать, опрашивая в цикле. В частности, FRAM работает быстро, поэтому есть вероятность, что от попыток переноса ожидания в прерывания будут только дополнительные тормоза. Естественно, ожидание в цикле опроса желательно производить в менее приоритетной задаче, чтобы более важные задачи могли этот цикл прервать.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 14 2015, 14:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 386
Регистрация: 5-04-05
Из: моська, RF
Пользователь №: 3 863

|
Цитата(AHTOXA @ Apr 14 2015, 17:21)  Если ждать долго, то надо на окончение ожидания настраивать прерывание, и ждать флага. Кто вам создаст это прерывание? А "флаг" как ждать? Чем его ожидание отличается от ожидания бита? Цитата(AHTOXA @ Apr 14 2015, 17:21)  Если недолго, то ждать, опрашивая в цикле. Это ничего в принципе не меняет. Просто вечный while переходит из HALа в вашу программу. Можно сделать while (нет бита) шедьюлинг();правда тогда период опроса будет много миллисекунд, что может быть долго.
|
|
|
|
|
Apr 14 2015, 14:51
|
Гуру
     
Группа: Участник
Сообщений: 2 219
Регистрация: 16-08-12
Из: Киров
Пользователь №: 73 143

|
Цитата(Golikov A. @ Apr 14 2015, 14:16)  А вот теперь я задумался, а как с учетом заточености под RTOS правильно делать передачу данных, допустим по SPI в режиме мастера, допустим с какой-нибудь FRAM? Ведь там есть послать данные, подождать бита готовности памяти и принять их. Как бита ждать? Вообще-то для этого под оси и пишутся драйвера, они висят на прерываниях железа, более высокого уровня, чем переключатель контента у оси, и работают через стандартные потоки, как драйвер ком-порта под виндой, например... Ну или ждите в вечном цикле, если это устройство монопольно используется.
Сообщение отредактировал mantech - Apr 14 2015, 14:52
|
|
|
|
|
Apr 14 2015, 17:01
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Dr.Alex @ Apr 14 2015, 19:35)  Кто вам создаст это прерывание? А "флаг" как ждать? Чем его ожидание отличается от ожидания бита? Прерывание мне никто не создаст, придётся самому :-) Под флагом я имел в виду какой-нибудь объект синхронизации операционной системы (event, mutex). Соответственно, ожидание такого флага -- усыпляет ожидающий процесс. Цитата(Dr.Alex @ Apr 14 2015, 19:35)  Это ничего в принципе не меняет. Просто вечный while переходит из HALа в вашу программу. Можно сделать while (нет бита) шедьюлинг(); Ну зачем же вечный? Можно с тайм-аутом. Мысль моя была о том, что если период ожидания бита ожидается короткий (например, гарантирован в даташите на FRAM), то такое ожидание ничем не отличается от просто небольшого цикла по ходу выполнения. Поэтому принимать специальные меры для перевода процесса в сон на время этого ожидания вряд ли целесообразно. Например, я не усыпляю процессор на время передачи пары байт по SPI. А вот на время передачи блока из 512 байт в SD-карту - уже усыпляю, ибо уже успею за это время сделать что-нибудь ещё полезное. ЗЫ. В вытесняющей оси "while (нет бита) шедьюлинг();" ничего не даст, потому что вернёт управление тому же самому процессу. Лучше тогда while (нет бита) sleep(1);
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 14 2015, 17:04
|
Профессионал
    
Группа: Свой
Сообщений: 1 386
Регистрация: 5-04-05
Из: моська, RF
Пользователь №: 3 863

|
Цитата(AHTOXA @ Apr 14 2015, 20:01)  Ну зачем же вечный? Можно с тайм-аутом. С тайм-аутом или без не важно, всё равно это "вечный цикл" с точки зрения операционки. Цитата(AHTOXA @ Apr 14 2015, 20:01)  ЗЫ. В вытесняющей оси "while (нет бита) шедьюлинг();" ничего не даст, потому что вернёт управление тому же самому процессу. Лучше тогда while (нет бита) sleep(1); Осёвый "sleep" это и есть функция, вызывающая шедьюлинг..
|
|
|
|
|
Apr 14 2015, 17:59
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Dr.Alex @ Apr 14 2015, 22:04)  С тайм-аутом или без не важно, всё равно это "вечный цикл" с точки зрения операционки. Нет. С тайм-аутом цикл не вечный. Это просто несколько шагов выполнения алгоритма. То, что они оформлены в цикл - ничего не меняет. Так можно договориться до того, что и вычисление математических функций тоже придётся признать "вечным циклом", неприменимым в программировании с ОС. А что, какой-нибудь atan2() - вон как долго вычисляется! Значительно дольше, чем я буду ожидать флага опустошения передатчика SPI перед отправкой туда символа. Цитата(Dr.Alex @ Apr 14 2015, 22:04)  Осёвый "sleep" это и есть функция, вызывающая шедьюлинг.. Нет. Осёвый "sleep" не просто вызывает шедулинг, он ещё перед этим переводит текущий процесс в состояние ожидания.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 14 2015, 18:16
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата Вообще-то для этого под оси и пишутся драйвера, они висят на прерываниях железа, более высокого уровня, чем переключатель контента у оси, и работают через стандартные потоки, как драйвер ком-порта под виндой, например... Ну или ждите в вечном цикле, если это устройство монопольно используется. это плохой ответ, не о чем... Цитата А вот на время передачи блока из 512 байт в SD-карту - уже усыпляю, Имеется ввиду, запускаем ДМА, а задачу в sleep, то есть ОС будет к ней возвращаться с каким то своим достаточно большим интервалом, так? Подытожим, у нас есть варианты: 1. усыпление процесса и возврат к нему с долгими интервалами для проверки дождались или нет (ожидание чего-то очень долгого) 2. это прерывание на окончание ожидания и в нем какой-то симафор, что позволяет ожидающую задачу усыпить до появления симафора. (если надо подождать среднюю длительность) 3. это долбим проверку интервала прямо в задаче циклом. В некоторых ОС будут переключать задачи по временным интервалам, если ожидание затянется, а в некоторых все задачи будут ждать эту. (ожидаем чего-то очень короткого) правильные варианты? Мне как-то внутренне кажется устраивать заопарк прерываний в ОС не верно. Ну то есть отправку UART сделать буфер, и прерывание символ ушел - пихать следующий символ, и так поступить со всеми интерфейсами. Боюсь что так система станет слабо предсказуемой и постоянно что-то ковыряющейся в прерываниях... Ведь их то между собой поделить будет нельзя, посылки по UART забьют передачи по другим интерфейсам, например... Не понятно как это решить в универсальной библиотеке
|
|
|
|
|
Apr 14 2015, 18:40
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(Golikov A. @ Apr 14 2015, 21:16)  Мне как-то внутренне кажется устраивать заопарк прерываний в ОС не верно. Именно, о чем я вам и говорил. В драйверах доступа к всяческой памяти никаких вытеснений и семафоров RTOS. Кто так делает убивает RTOS и получает просто примитивную многозадачность. Нельзя надеятся, что RTOS облегчит написание низкоуровневых драйверов. Наоборот она их усложняет. Работа с быстрой периферией по прежнему пишется в стиле автоматов состояний. Задержки делаются аппаратными таймерами. Переключение состояний автоматов производится в процедурах обслуживания прерываний по цепочке от разных источников включая DMA. Сами прерывания это прерывания уровня ядра. Прерывание RTOS вызывается только когда уже готов блок данных для обработки. И вот там-то взводится объект синхронизации о готовности данных.
|
|
|
|
|
Apr 15 2015, 03:04
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(AlexandrY @ Apr 15 2015, 00:40)  Работа с быстрой периферией по прежнему пишется в стиле автоматов состояний. Задержки делаются аппаратными таймерами. Переключение состояний автоматов производится в процедурах обслуживания прерываний по цепочке от разных источников включая DMA. Иногда (при необходимости быстрой работы со сложной периферией) получаются очень сложные автоматы состояний со множеством состояний (десятками) и сложными переходами между ними. Код становится трудночитаем, ведь программирование в стиле автоматов состояний гораздо хуже читается чем линейный код. В таких случаях я иногда применяю подход "а-ля ISR-псевдозадача": создаю отдельный контекст (стек), при завершении очередной транзакции с периферией (получении прерывания от неё, от DMA или от таймера), внутри ISR переключаюсь на этот контекст, выполняю участок кода до след. запроса к периферии (после которого следует обратное переключение контекста на исходный стек ISR с выходом из ISR). И по завершении этого запроса - опять вход в ISR-псевдозадачу. Получается простой хорошо читаемый линейный код вместо леса автомата состояний. Надо только не забывать про уровни приоритетов ISR, участвующих в этом (на NVIC). Можно просто сделать все одного уровня. Цитата(AlexandrY @ Apr 15 2015, 00:40)  Прерывание RTOS вызывается только когда уже готов блок данных для обработки. И вот там-то взводится объект синхронизации о готовности данных. О готовности данных, или освобождении какого-то ресурса (занятого буфера или флага в API доступа к драйверу, работающему на уровне прерываний) и т.п..
|
|
|
|
|
Apr 15 2015, 03:59
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Golikov A. @ Apr 14 2015, 23:16)  Имеется ввиду, запускаем ДМА, а задачу в sleep, то есть ОС будет к ней возвращаться с каким то своим достаточно большим интервалом, так? Не в sleep, а в wait(). В ожидание объекта синхронизации (event, mutex, ...). А объект синхронизации взводится в прерывании по окончании передачи. В этом случае ОС не будет возвращаться к ожидающей задаче с каким-бы то ни было интервалом - задача будет спать чётко до момента окончания передачи. И затем практически сразу проснётся.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 15 2015, 04:46
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(jcxz @ Apr 15 2015, 06:04)  Иногда (при необходимости быстрой работы со сложной периферией) получаются очень сложные автоматы состояний со множеством состояний (десятками) и сложными переходами между ними. Код становится трудночитаем, ведь программирование в стиле автоматов состояний гораздо хуже читается чем линейный код. В таких случаях я иногда применяю подход "а-ля ISR-псевдозадача": создаю отдельный контекст (стек), при завершении очередной транзакции с периферией (получении прерывания от неё, от DMA или от таймера), внутри ISR переключаюсь на этот контекст, выполняю участок кода до след. запроса к периферии (после которого следует обратное переключение контекста на исходный стек ISR с выходом из ISR). И по завершении этого запроса - опять вход в ISR-псевдозадачу. Получается простой хорошо читаемый линейный код вместо леса автомата состояний. Надо только не забывать про уровни приоритетов ISR, участвующих в этом (на NVIC). Можно просто сделать все одного уровня.
О готовности данных, или освобождении какого-то ресурса (занятого буфера или флага в API доступа к драйверу, работающему на уровне прерываний) и т.п.. В принципе не возражаю, только вот это - "хорошо читаемый" напрягает. Субъективизм же. Во первых в скоростной периферии важнее хорошая отлаживаемость Во вторых хорошо читаемый только короткий код. Расположите все ISR связанные с одним автоматом в одном месте и получите короткий код, понятно откоментируйте и отформатируйте и получите отличную читаемость.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|