реклама на сайте
подробности

 
 
> Как писать хороший код
amaora
сообщение Dec 17 2014, 17:59
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778



Не могу выбрать подходящий способ написания кода для своих задач. Хочется обойтись без стороннего кода и без лишней сложности.

Сейчас пытаюсь делать всю работу требующую немедленного реагирования в прерываниях, без дополнительных слоев абстракции. Но есть одна медленная задача, это интерфейс командной строки. Эта задача выполняется в главном цикле, в единственном контексте который может вызывать блокирующие функции т.к. вытесняющего планировщика и множества нитей нет. Пока единственная блокирующая функция это отправка символа в USART через несколько буферов. Блокировка выполняется в виде цикла ожидания в котором вызывается "планировщик". Последний может выполнять еще какие-то задачи или перевести МК в режим простоя. Еще какие-то задачи это переброс данных между USART и FIFO структурами с которыми удобно работать задаче интерфейса командной строки. То есть если выполнилась какая-то команда которая вызвала printf с очень длинным текстом который забил весь буфер, то putc вызванный внутри printf встанет на цикле ожидания и будет вызывать задачи которые могут вычистить выходной буфер. Для этого соответственно, те задачи работающие с FIFO не должны и не могут ни на чем блокироваться, что создает некоторые неприятности в их реализации.

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

Как сделать хорошо и без вытесняющего переключения задач? smile3046.gif
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
_Pasha
сообщение Dec 18 2014, 18:11
Сообщение #2


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



я вообще без оберток пишу либо
Код
void *pc;
//
if pc != NULL goto *pc;

либо смешанные стейт машины, где переменная у switch(pc)
принимает не только безымянные значения с помощью __LINE__ и такой-то матери
но и предопределенные, и стейт машину можно без гемора переключить в другое состояние.
При этом, выполнение прерываний на стейт машинах это тоже часть задумки.
Красиво, безобразно и единообразно sm.gif
В процессе эксплуатации прототред-лайк сопрограмм юзер-программист sm.gif сталкивается с соблазном запилить
абсолютно все прототредами либо сильно извращаться на длинных вычислениях.
так я Вам скажу, делать этого абсолютно не нужно, если у Вас есть какая-то приоритетная часть - ее можно из прерывания по таймеру вызвать.
все решаемо, в общем. И у такой программно-аппаратной РТОС хорошие характеристики.

Кроме того, волшебные коллбеки повышают универсальность написанного.

Сообщение отредактировал _Pasha - Dec 18 2014, 18:13
Go to the top of the page
 
+Quote Post
Make_Pic
сообщение Sep 25 2015, 07:14
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 779
Регистрация: 9-10-04
Из: Россия, Пермь
Пользователь №: 828



Цитата(_Pasha @ Dec 18 2014, 22:11) *
я вообще без оберток пишу либо
Код
void *pc;
//
if pc != NULL goto *pc;

либо смешанные стейт машины, где переменная у switch(pc)
...
Кроме того, волшебные коллбеки повышают универсальность написанного.

А можно пример вашей машины с применением callback функций?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Sep 26 2015, 07:01
Сообщение #4


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Make_Pic @ Sep 25 2015, 10:14) *
А можно пример вашей машины с применением callback функций?

Да там собственно и показывать нечего.
Предположим у нас есть грубо говоря - драйвер, он чего-то делает по SPI, но это "что-то" состоит из команды, статуса и блока данных
У нас есть одна и та же функция, protothread - like для того, чтобы:
1. Выбрать CS ведомого, пнуть spi, послав команду - выполняется из основного потока
2. Забрать статус - выполняется уже из прерывания. Тут же настраивается DMA на блок данных
3. Коллбэк из прерывания TCIF DMA - вызывает абсолютно ту же функцию, которая выставляет флаги готовности и выключает CS ведомого.

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

В итоге получается, что текст пестрит "командами" типа yield, sleep, wake - но читается как линейный код.

CODE

void *thread(void *pc)
{
if(pc != NULL) goto *pc;
if(pending == NULL) return NULL;
// transaction start
slave_CS(0);
// put the 1 st byte (command)
slave_put(pending->command);
if(!pending->block)
{//non-blocking mode
spi_enable_rx_buffer_not_empty_interrupt(spi.port);
if(pending->size)
{//setup dma for data block
provide_dma();
return &&Get_Status;
}
else
{// transaction end
return &&Zero_Data;
}
}
else
{// blocking
my_wait(SPI_SR_RXNE);
}
Get_Status:
pending->status = slave_get();
if(pending->block)
{// block mode
char *ptr = pending->data;
while(pending->size)
{
pending->size -= 1;
slave_put(pending->read? 0xFF: *ptr++);
my_wait(SPI_SR_RXNE);
if(pending->read)
{
*ptr++ = slave_get();
}
}
goto Trans_END;
}
/*state mashine for non-block*/
spi_disable_rx_buffer_not_empty_interrupt(spi.port);
/*enable dma*/
if(pending->read) spi_enable_rx_dma(spi.port);
spi_enable_tx_dma(spi.port);
return &&Trans_END_Irq;
Trans_END_Irq:
if(pending->read) spi_disable_rx_dma(spi.port);
spi_disable_tx_dma(spi.port);
Trans_END:
slave_CS(1);//close
if(pending->chain_CB != NULL) pending->chain_CB();
pending = NULL; // trans. end
status_unread=1; // got status
return NULL;

Zero_Data:
pending->status = slave_get();
spi_disable_rx_buffer_not_empty_interrupt(spi.port);
goto Trans_END;
}

вот. а вызовы - разбросаны по всему тексту.
кроме того, там же есть и неблокирующий вариант - в зависимости от выставленного флага pending->block
единственно, усложнение - тогда, когда в жесткую стейт-машину возможны вклинивания "сторонних сил" sm.gif
там нужно предусмотреть чтобы вызов шел с конкретным указателем.
Go to the top of the page
 
+Quote Post
Make_Pic
сообщение Sep 16 2016, 06:30
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 779
Регистрация: 9-10-04
Из: Россия, Пермь
Пользователь №: 828



Мне очень понравился ваш подход к написанию кода, но из вырванного куска кода из контекста, с моим уровнем знаний сложно разобраться - Решил вернуться к вашему примеру - pls можно более подробнее описание вашей псевдооперационки с объявления и описанием переменных, функций, прототипов.

Если не трудно, хотя бы на коротком примере?

Сообщение отредактировал Herz - Sep 22 2016, 09:06
Причина редактирования: Избыточное цитирование
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- amaora   Как писать хороший код   Dec 17 2014, 17:59
- - _pv   Protothreads? не то чтобы совсем хорошо, но зато б...   Dec 17 2014, 18:09
|- - amaora   Цитата(_pv @ Dec 17 2014, 21:09) Protothr...   Dec 17 2014, 18:32
|- - _pv   Цитата(amaora @ Dec 18 2014, 00:32) Это т...   Dec 18 2014, 09:55
|- - amaora   Цитата(_pv @ Dec 18 2014, 12:55) что в пр...   Dec 18 2014, 13:05
|- - =AK=   Цитата(amaora @ Dec 18 2014, 23:35) непон...   Dec 19 2014, 01:00
- - 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
- - 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


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 29th July 2025 - 09:11
Рейтинг@Mail.ru


Страница сгенерированна за 0.01411 секунд с 7
ELECTRONIX ©2004-2016