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

 
 
5 страниц V  < 1 2 3 4 5 >  
Reply to this topicStart new topic
> State machine, Приведите примеры реализации
_Pasha
сообщение Mar 5 2009, 17:50
Сообщение #31


;
******

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



Цитата(TMX @ Mar 5 2009, 20:09) *
там Martin Gomez вручную забивает таблицу переходов


no comment smile.gif


Цитата
 в виде номера, функции и указателя на функцию. по номеру выбирается ссылка на функцию состояний и вызывается сама функция. Реализация требует и память и стек.


Писать программу без картинки - если получается, тогда зачем картинка?


1. А что? Дорого? Зато может способствовать уменьшению количества функций

2.Например, для повышения уровня языка реализации до проблемно-ориентированного  http://www.citforum.ru/internet/xml/graphml/
Go to the top of the page
 
+Quote Post
TMX
сообщение Mar 6 2009, 07:35
Сообщение #32


Частый гость
**

Группа: Свой
Сообщений: 100
Регистрация: 19-01-05
Из: Москва
Пользователь №: 2 064



Цитата(_Pasha @ Mar 5 2009, 20:50) *
no comment smile.gif


Возможно, я не совсем понятно выразился - Gomez забивает не всю таблицу переходов автомата, а только одномерный массив jump table, указателей на функции состояний. Там в самом начале листинга можно ее увидеть.
В любом случае это не дает преимуществ по сравнению с прямым присвоением:
Код
void(*state_pointer)(void) = RED_state;
void main (void)
{
  while(1)
  {
    state_pointer();
  }
}

void RED_state (void)
{
      if (timer_flag)
      {
        output_control(RED_LAMP, OFF);
        output_control(GREEN_LAMP, ON);
        start_timer (GREEN_DELAY);
        state_pointer = GREEN_state;
        return;
      }
              if (button_flag)
......................
}


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

По поводу объема: в 8-битных процессорах если указатель занимает 2 байта, то каждое присвоение требует 2 команды ассемблера. Соответственно для автомата на 50 состояний и 150 переходов потребуется 300 команд в ПЗУ (600Б для AVR), для switch с переменной состояния типа char потребуется 300Б ПЗУ на переходы, для Gomez-технологии потребуется 300Б на переходы и 100Б на jump_table, итого 400Б. Для 16-ти и 32-х битных объем switch и присвоения указателей практически одинаков, а для Gomeza все равно дополнительно требуется место для jump table.
Цитата
1. А что? Дорого? Зато может способствовать уменьшению количества функций
2.Например, для повышения уровня языка реализации до проблемно-ориентированного http://www.citforum.ru/internet/xml/graphml/


1. За счет чего? C использованием switch вообще одна функция.
2.Обычно проблему снаала описывают, а потом реализуют.

если еще есть интерес, могу продолжить про реализации...
Go to the top of the page
 
+Quote Post
Diz
сообщение Mar 6 2009, 13:20
Сообщение #33


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 1-08-06
Пользователь №: 19 250



Наверное, jumptable может быть полезен для сохранения текущего состояния в eeprom и восстановления после сбоя. Пишем лишь индекс, а не потенциально
опасный указатель.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 6 2009, 13:42
Сообщение #34


;
******

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



Цитата(TMX @ Mar 6 2009, 10:35) *
если еще есть интерес, могу продолжить про реализации...

Интерес есть!

Вот мои небольшие наблюдения на смежную тему кооперативной многозадачностиhttp://electronix.ru/forum/index.php?showtopic=59333
Go to the top of the page
 
+Quote Post
TMX
сообщение Mar 6 2009, 14:35
Сообщение #35


Частый гость
**

Группа: Свой
Сообщений: 100
Регистрация: 19-01-05
Из: Москва
Пользователь №: 2 064



Цитата(Diz @ Mar 6 2009, 16:20) *
Наверное, jumptable может быть полезен для сохранения текущего состояния в eeprom и восстановления после сбоя. Пишем лишь индекс, а не потенциально
опасный указатель.

сомнительно. все равно потом по указателю функция вызывается,
для таких случаев обычно пишут лог переходов в том или ином виде, ну и список разрешенных переходов (собственно, он у Гомеса есть).

реализовать кооперативную многозадачность с помощью конечных автоматов - собственно, этим я хотел закончить про реализации.
Go to the top of the page
 
+Quote Post
TMX
сообщение Mar 10 2009, 13:42
Сообщение #36


Частый гость
**

Группа: Свой
Сообщений: 100
Регистрация: 19-01-05
Из: Москва
Пользователь №: 2 064



Недостатки прямого присваивания значения переменной состояния, типа
Код
state = NEW_state
в том, что при большом количестве ветвлений можно случайно пропустить присваивание.
Одним из методов контроля на этапе компиляции является следующий:
функция состояния возвращает значение следующего состояния
Код
void main (void)
{
static char state = STATE_X;
  while(1)
  {
    state = state_function(state);
  }
}

char state_function (char state)
{
  switch(state)
  {
      case STATE_X:
        if (event)
        {
          return STATE_Y;
        }
        else
          return STATE_X;
      case STATE_Y:
        ...
      case STATE_Z:
        ...
  }
}


кроме некоторого контроля за присваиванием, такой подход не дает никаких премуществ.
Просто на практике не всегда бывает возможно обеспечить полноту тестов.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Mar 10 2009, 16:14
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(TMX @ Mar 6 2009, 18:35) *
сомнительно. все равно потом по указателю функция вызывается,

Индекс проще проверит на валидность. Всего лишь на максимум.
Индекс удобно использовать при генерации события по смене состояния.
Индекс удобно использовать для возврата в старое состояние.

Кароч, я использую индексы и массивы функций. Иногда двумерный массив functions[state][event] в каком-нить менюшном сервисе.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
-=TRO=-
сообщение Mar 10 2009, 16:47
Сообщение #38


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 24-10-07
Из: zp.ua
Пользователь №: 31 690



Внутри программируемой логики собирают микропроцесоры и пишут для них программы.
На микроконтроллерах пишут программы эмулирующие логику(конечные автоматы).
Походу использовать компоненты по назначению сегодня не модно.
Или просто грани стираются, и будущее за гибридными технологиями.
Скоро наверно будем делать проэкты для одного кристалла из пары сотен операционников, нескольких микроконтроллеров, и массива программируемой логики.
Go to the top of the page
 
+Quote Post
TMX
сообщение Mar 10 2009, 16:57
Сообщение #39


Частый гость
**

Группа: Свой
Сообщений: 100
Регистрация: 19-01-05
Из: Москва
Пользователь №: 2 064



Цитата(Dog Pawlowa @ Mar 10 2009, 19:14) *
Индекс проще проверит на валидность. Всего лишь на максимум.
Индекс удобно использовать при генерации события по смене состояния.
Индекс удобно использовать для возврата в старое состояние.

Кароч, я использую индексы и массивы функций. Иногда двумерный массив functions[state][event] в каком-нить менюшном сервисе.


с первым согласен. Только какой смысл в такой проверке? Проверка в рантайме - от какого бага она спасает? Если на этапе отладки - использование только поименованных констант не позволит вызвать неописанное состояние. С другой стороны, где гарантия, что индексы идут подряд.
со вторым и третьим - не могу ничего сказать. Не могли бы вы написать пример реализации поподробнее? Для одномерного и двумерного массива? Особенно, для functions[state][event], что является индексом массива?

я считаю, что удобство понятие не только субъективное.
Удобно - когда логическая ошибка проявляется как можно раньше. Например, на этапе компиляции (стоимость обнаружения)
Удобно - когда при введении нового состояния его надо прописывать как можно в меньшем количестве списков (связность). И компилятор следит за правильностью (стоимость).
Неудобно - когда в нескольких списках описание состояния должно быть с одинаковым номером (связность).

Цитата(-=TRO=- @ Mar 10 2009, 19:47) *
Внутри программируемой логики собирают микропроцесоры и пишут для них программы.
На микроконтроллерах пишут программы эмулирующие логику(конечные автоматы).
Походу использовать компоненты по назначению сегодня не модно.

насколько я знаю, в 70-х годах было мнение, что наиболее перспективная парадигма в программировании - автоматный подход.
"Лучше забивать молотком шурупы, чем закручивать отверткой гвозди"
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Mar 10 2009, 17:36
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(TMX @ Mar 10 2009, 20:57) *
с первым согласен. Только какой смысл в такой проверке?

В некоторых случаях смысл есть. Например, после ресета можно вернуться в нужную точку. Делал прибор, который, зараза, был чувствителен к ESD. Вот и пришлось решать проблему программно.


Цитата(TMX @ Mar 10 2009, 20:57) *
Не могли бы вы написать пример реализации поподробнее? Для одномерного и двумерного массива?

Да все тупо...
CODE
// Определения состояний и функций

#define stRestart 0
#define f0 fRestart

#define stSelfTest 1
#define f1 fSelfTest

#define stWaiting 2
#define f2 fWaiting

// массив функций
const VECTORS function[stQty] =
{ f0, f1, f2, f3,..}

//основной цикл процесса

event=GetTimerEvent();
if (!event) event=GetOtherEvent(); // тут собыий много может быть
...
if (!event) if (state-old_state) event=evNew;
function[state]();
event=0;

// пример функции

void fRestart(void)
{ switch (event)
{ case evNew:
....
GetDateAndTime();
SetLcdPos(1,2); printf("%s",rtc_date);
Old();
break;

case ev500ms:
switch (restart_counter)
{ ...
сase 4: if (!LowPowerStart) state= stSelfTest;
else {SetLcdPos(1,2); printf(msgStartLowVoltage[lang]); }
} break;
if (restart_counter<4) restart_counter++;
break;

case evUpDn:
state=stStartUserMenu;
break;
}
}
Причина редактирования: Уменьшение видимого размера цитаты исходника.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 10 2009, 18:17
Сообщение #41


;
******

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



Весь смех в том, что сишная или иная ЯВУ-программа при помощи переменной state эмулирует счетчик команд целевой машины. Вот эта некузявость порядком раздражает. sad.gif 
Go to the top of the page
 
+Quote Post
Rst7
сообщение Mar 10 2009, 19:15
Сообщение #42


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
при помощи переменной state эмулирует счетчик команд целевой машины.


Я давно предлагал любителям обратить внимание на вычисляемый goto в гнусе.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 10 2009, 19:51
Сообщение #43


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Rst7 @ Mar 10 2009, 21:15) *
Я давно предлагал любителям обратить внимание на вычисляемый goto в гнусе.
Тада, и я это предложение даже проиллюстрировал уже
http://electronix.ru/forum/index.php?showt...mp;#entry520130
и парой постов дальше с массивом и индексом.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Mar 11 2009, 07:18
Сообщение #44


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(ReAl @ Mar 10 2009, 22:51) *
Тада, и я это предложение даже проиллюстрировал уже...

LOL : чуть дальше "Но реально не применяю :-), как-то не жмёт пока обычный switch()... "

Вот и меня не жмет. А switch или таблица - это вопрос качества монитора и разрешения biggrin.gif
Если все case не помещаются на два-три экрана, то лучше бить на таблицу. Если помещаются, то лучше помолиться за IAR, который при оптимизации ту же таблицу сам нарисует.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Diz
сообщение Mar 11 2009, 08:24
Сообщение #45


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 1-08-06
Пользователь №: 19 250



Цитата(TMX @ Mar 6 2009, 17:35) *
сомнительно. все равно потом по указателю функция вызывается,
для таких случаев обычно пишут лог переходов в том или ином виде, ну и список разрешенных переходов (собственно, он у Гомеса есть).


Пример взят из реальной задачи - нужно было при каждой смене состояния сохранять
его во внешней eeprom, чтобы восстановить при пропадании питания. Лог переходов писать смысла нет, так как не важно, каким путем мы попали в данное состояние - важен сам факт попадания.
Индекс - один байт, пишется атомарно. При загрузке легко его проверить на попадание
в диапазон разрешенных состояний. Если будет восстановлено неверное состояние,
неприятно, но не так разрушительно как вызов функции по неверному указателю.
Еще одна особенность - прошивка могла быть обновлена, и обработчики
могли бы лежать на других адресах.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 09:13
Рейтинг@Mail.ru


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