|
Как писать хороший код |
|
|
|
Dec 17 2014, 17:59
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Не могу выбрать подходящий способ написания кода для своих задач. Хочется обойтись без стороннего кода и без лишней сложности. Сейчас пытаюсь делать всю работу требующую немедленного реагирования в прерываниях, без дополнительных слоев абстракции. Но есть одна медленная задача, это интерфейс командной строки. Эта задача выполняется в главном цикле, в единственном контексте который может вызывать блокирующие функции т.к. вытесняющего планировщика и множества нитей нет. Пока единственная блокирующая функция это отправка символа в USART через несколько буферов. Блокировка выполняется в виде цикла ожидания в котором вызывается "планировщик". Последний может выполнять еще какие-то задачи или перевести МК в режим простоя. Еще какие-то задачи это переброс данных между USART и FIFO структурами с которыми удобно работать задаче интерфейса командной строки. То есть если выполнилась какая-то команда которая вызвала printf с очень длинным текстом который забил весь буфер, то putc вызванный внутри printf встанет на цикле ожидания и будет вызывать задачи которые могут вычистить выходной буфер. Для этого соответственно, те задачи работающие с FIFO не должны и не могут ни на чем блокироваться, что создает некоторые неприятности в их реализации. Дальше возникают вопросы эффективности такого метода, сейчас все задачи запускаются по каждому поводу. То есть по каждому выходу из режима простоя, который происходит на каждом прерывании. Можно обложить все задачи флагами которые выставлять в тех местах где образуется работа для соответствующей задачи. Или сделать динамическую очередь задач, чтобы не проверять кучу флагов. Несколько раз уже переписывать код по разному, обдумывал разные варианты. Но хорошего не приходит, всегда что-то не так. Например, очередь потребует нетривиальной реализации, чтобы можно было добавлять в нее задачи из прерываний. А запрета этих прерываний нужно избежать. Вопросы так же возникают по поводу того, что делать если понадобится вторая задача которая тоже захочет блокироваться. Как сделать хорошо и без вытесняющего переключения задач?
|
|
|
|
|
 |
Ответов
|
Dec 17 2014, 18:32
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Цитата(_pv @ Dec 17 2014, 21:09)  Protothreads? не то чтобы совсем хорошо, но зато без вытесняющего переключения Это только в пределах одной функции? А если у меня такой стек shTask->shEval->shExactMatch->someCMD->printf->putc->shSend ? И на месте someCMD может быть одна из многих команд.
|
|
|
|
|
Dec 18 2014, 09:55
|
Гуру
     
Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954

|
Цитата(amaora @ Dec 18 2014, 00:32)  Это только в пределах одной функции? А если у меня такой стек shTask->shEval->shExactMatch->someCMD->printf->putc->shSend ? И на месте someCMD может быть одна из многих команд. что в пределах одной функции? стэк чего? protothreads это, грубо говоря, тупо goto, очень красиво обёрнутные в макросы препроцессора С, которые позволяют писать код так, как будто это почти настоящие независимые потоки http://dunkels.com/adam/pt/expansion.htmlпри этом когда у одного "потока", например shSend, который данные в буфер uartа складывает вдруг закончится буфер и ему надо ждать, в этом месте макрос незаметно сделает возврат из функции обратно в главный цикл, там поделается еще что-то следующее, а когда управление по циклу опять дойдёт до функции shSend, то он вернётся в то место где проверялась занятость буфера и продолжит как будто никуда и не отходил. вместо того чтобы тупо сидеть и ждать когда освободится буфер.
|
|
|
|
|
Dec 18 2014, 13:05
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Цитата(_pv @ Dec 18 2014, 12:55)  что в пределах одной функции? стэк чего? protothreads это, грубо говоря, тупо goto, очень красиво обёрнутные в макросы препроцессора С, которые позволяют писать код так, как будто это почти настоящие независимые потоки http://dunkels.com/adam/pt/expansion.htmlпри этом когда у одного "потока", например shSend, который данные в буфер uartа складывает вдруг закончится буфер и ему надо ждать, в этом месте макрос незаметно сделает возврат из функции обратно в главный цикл, там поделается еще что-то следующее, а когда управление по циклу опять дойдёт до функции shSend, то он вернётся в то место где проверялась занятость буфера и продолжит как будто никуда и не отходил. вместо того чтобы тупо сидеть и ждать когда освободится буфер. Полный контекст не сохраняется, то есть хранить что-то в локальных переменных в одной из функций в той цепочке уже нельзя себе позволить. Да и как это будет работать если есть стек вызовов, а не одна функция как в примерах по ссылке, я не представляю. Мне видится, что лучше привести весь код задачи с блокировкой в автоматный вид, чем скрываться за макросами с неявными case/goto. Цитата Сделать кооперативную ось. Благо она делается на чистом С (без ассемблера) и занимает шиш да кумыш места в памяти. Имею привычку делать свою libc когда пишу код для МК, и у меня нет setjmp/longjmp. Никогда ими не пользовался и возможно неверно понимаю, что они должны делать. Почитаю еще, непонятно что будет если "прыгнуть" в то место из которого уже вышли и соответствующий фрейм стека уже освобожден и возможно затерт. Пока остановился на глобальном цикле и флагах задач которые выставляются в прерываниях или других задачах. Во время блокировки в shSend происходит вложенный вызов этого же цикла но уже с запретом повторного (рекурсивного) выполнения заблокированной задачи. Но так можно позволить делать только одной задаче, иначе возможны взаимоблокировки. И что-то сомневаюсь как сделать например текстовый вывод по запросу из прерывания, нужна еще одна задача которая сможет блокироваться на shSend.
Сообщение отредактировал amaora - Dec 18 2014, 13:06
|
|
|
|
|
Dec 19 2014, 01:00
|

pontificator
     
Группа: Свой
Сообщений: 3 055
Регистрация: 8-02-05
Из: страны Оз
Пользователь №: 2 483

|
Цитата(amaora @ Dec 18 2014, 23:35)  непонятно что будет если "прыгнуть" в то место из которого уже вышли и соответствующий фрейм стека уже освобожден и возможно затерт. Ну так именно для этого и используются библиотечные функции: setjmp сохраняет контекст и возвращает управление ядру, а longjmp восстанавливает контекст и прыгает в задачу, в то самое место, из которого задача возвращала управление ядру. А ядро в основном занято тем, что отсчитывает для каждой задачи задержки между моментом возврата в ядро и моментом, когда снова можно передавать управление задаче. При написании кода кажется, что каждая задача работает сама по себе, а команда DELAY(X) просто задает задержку X, на время которой задача останавливается.
|
|
|
|
Сообщений в этой теме
amaora Как писать хороший код Dec 17 2014, 17:59 menzoda Стандартное решение для простых задач:
- Расчеты р... Dec 18 2014, 08:01 =AK= Цитата(amaora @ Dec 18 2014, 04:29) Как с... Dec 18 2014, 11:54 HardEgor Цитата(amaora @ Dec 17 2014, 23:59) Как с... Dec 18 2014, 14:45 _Pasha я вообще без оберток пишу либо
Кодvoid *pc;
//
if... Dec 18 2014, 18:11 Make_Pic Цитата(_Pasha @ Dec 18 2014, 22:11) я воо... Sep 25 2015, 07:14  _Pasha Цитата(Make_Pic @ Sep 25 2015, 10:14) А м... Sep 26 2015, 07:01   Make_Pic Мне очень понравился ваш подход к написанию кода, ... Sep 16 2016, 06:30 jhm ЦитатаДальше возникают вопросы эффективности таког... Jan 9 2015, 09:26 Dog Pawlowa Цитата(amaora @ Dec 17 2014, 20:59) если ... Sep 25 2015, 07:27 _Pasha я в личку отвечу сейчас. Sep 16 2016, 18:04 DASM И года не прошло)) Sep 21 2016, 18:31 Njalenoc код, который согласован со стандартом Oct 18 2016, 16:36 Smoky Коллеги, допустимо ли использовать функции таким о... Dec 18 2016, 12:40 Сергей Борщ QUOTE (Smoky @ Dec 18 2016, 14:40) допуст... Dec 18 2016, 12:53  Smoky Цитата(Сергей Борщ @ Dec 18 2016, 18:53) ... Dec 18 2016, 13:03   zltigo Цитата(Smoky @ Dec 18 2016, 15:03) Исполь... Dec 18 2016, 13:29    Smoky Цитата(zltigo @ Dec 18 2016, 19:29) Этого... Dec 18 2016, 14:53     zltigo Цитата(Smoky @ Dec 18 2016, 16:53) Си нач... Dec 18 2016, 15:01      Smoky Цитата(zltigo @ Dec 18 2016, 21:01) Никуд... Dec 18 2016, 15:17   AlexandrY Цитата(Smoky @ Dec 18 2016, 15:03) До ком... Dec 18 2016, 18:16    zltigo Цитата(AlexandrY @ Dec 18 2016, 20:16) Ин... Dec 18 2016, 19:40 DASM Господи, обычный side effect.. железячники одни с... Dec 18 2016, 18:48 DASM Вы наконец то стали говорить вещи с которыми я сог... Dec 18 2016, 20:47 AlexandrY Цитата(DASM @ Dec 18 2016, 22:47) Вы нако... Dec 18 2016, 20:59
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|