Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: State machine
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
sat
Где можно почитать по теме/посмотреть примеры на С, асме
bialix
Сайты:
http://is.ifmo.ru
http://softcraft.ru - раздел Автоматы

еще см. на сайте iar.com программу VisualState
-Tумблер-
Цитата(sat @ Feb 2 2005, 15:29)
...посмотреть примеры на С, асме
*


Прямо здесь smile.gif и сейчас excl.gif :

void main (void)
{


while (1)
{

automat_1 ();
automat_2 ();
...
automat_N ();


}




}


void automat_i (void)
{
static char state=0;

switch (state)
{
case 0:
// чтото полезное может быть делаем
if (некоторое условие) state=... ;
// если условие выполнено, перейдем в другое состояние
return;

case 1:
// используем подчиненный автомат:
if (slave_automat_1 ()) state = .. ;
return;

...
case K:
return;

default: state=0; return; // авария !!


}


}

Важно понимать на уровне инстинктов:
- Все обьекты материального Мира - автоматы состояний
- придется полностю перестроить мозги
- возможно это удасться не сразу, зато окупится потом.

- что переход из состояния в состояние это как правило
наиболее сложная часть и может быть представлена
множеством состояний а лучше отдельным подчиненным автоматом.
Или их совокупностью.

- "автомат в состоянии" - это как правило ожидание условия
перехода в другие состояния. Но не всегда.

smile.gif
ALys
1. IAR VisualSTATE - в пакете примеры (под разные контроллеры), есть симулятор самого автомата, т.е. в среде можно отладить логику работы автомата

2. TS Controls - программа для разработки автоматов состояний с генерацией кода на C и С++
ig_z
Цитата(ALys @ Feb 3 2005, 18:52)
2. TS Controls - программа для разработки автоматов состояний с генерацией кода на C и С++
*


Что то не ставится на ХР. Или это аддон к чему - то?
Может есть какой нибудь официальный сайт или мож какое нибудь описание?
sat
Что то не ставится на ХР. Или это аддон к чему - то?
Может есть какой нибудь официальный сайт или мож какое нибудь описание?
*

[/quote]

Вроде нормально встал
http://www.tscontrols.com/support.html - вот такое адрес
maegg
Может коротенько объясните, зачем это нужно и в каких случаях стоит применять?
vet
Цитата(maegg @ Feb 7 2005, 16:17)
Может коротенько объясните, зачем это нужно и в каких случаях стоит применять?
*

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

[/quote]

Прекрастно ставится и на XP и w2k и NT.
Сам файл программы называется VState.exe

Сайта поддержки нет. (Прога - что называется проверенная временем)
В комплекте справка и примеры - все довольно прозрачно.

Выходной код С и С++;
basileus
SWITCH MACRO
local MYP
CLR ZH
ADZ (MYP>>1)
IJMP /*Уйдем на обработчик*/
MYP
MyPrep VAR $
REPT \1
RJMP \2
ENDR
ENDM


CASE MACRO
val VAR $
ORG MyPrep+2*(\1)
RJMP ?Prg\1
ORG val
Public ?Prg\1
?Prg\1
ENDM


SWITCHC $80,?badEvnt
/*где $80 - индекс переключателЯ*/


?badEvnt /*прекратить разбор -обработка ошибки*/
RET


CASE $48 /*48 -команда */
CASE $4A /*4A -команда */
RJMP ?exit1

CASE $42 /*42 -команда */
CASE $44 /*44 -команда */
CASE $46 /*46 -команда */
RET
Tran
Уважаемые, подскажите, пожалуйста, среды разработки для конечных автоматов. Я попробовал работать и на VisualState и на TS Control, обе генерят медленный код. Может, есть какие-нибудь другие проги?
BVU
Можно почитать теорию графов, там заложен базовый смысл всего этого.
Sergu
Вот хорошие объяснения с примерами есть:


State-Oriented Programming
http://www.embedded.com/2000/0008/0008feat1.htm

Embedded State Machine Implementation
http://www.embedded.com/2000/0012/0012feat1.htm
TMX
Код
/***************************************************
* definitions Section
***************************************************/
typedef void(*PVOID)(void);
typedef PVOID(*STATE)(void);

/***************************************************
* Export Variables Section
***************************************************/
STATE State_ptr = state_1;

/***************************************************
*   Function Prototype Section
***************************************************/
STATE State_1();
STATE State_2();
STATE State_3();

/**************************************************
* Function name    : void main (void)
* Created by  : tmx
* Date created  : 12.09.2005 14:27
* Description  : main
**************************************************/
void main (void)
{
    while (1)
    {
 State_ptr = (STATE) State_ptr();
    }
}

/**************************************************
* Function name    : STATE State_1()
* Created by  : tmx
* Date created  : 12.09.2005 14:23
* Description  : STATE function
* Notes      : called by ptr from main cycle in bgnd
**************************************************/
STATE State_1()
{
    if (event_1)
    {
 return (STATE) State_2;
    }
    else
 return (STATE) State_1;
}

/**************************************************
* Function name    : STATE State_2()
* Created by  : tmx
* Date created  : 12.09.2005 14:24
* Description  : STATE function
* Notes      : called by ptr from main cycle in bgnd
**************************************************/
STATE State_1()
{
    if (event_1)
    {
 return (STATE) State_3;
    }
    else
 return (STATE) State_2;
}

/**************************************************
* Function name    : STATE State_3()
* Created by  : tmx
* Date created  : 12.09.2005 14:24
* Description  : STATE function
* Notes      : called by ptr from main cycle in bgnd
**************************************************/
STATE State_3()
{
    if (event_3)
    {
 return (STATE) State_1;
    }
    else
 return (STATE) State_3;
}
Tran
Этот код Вы наверняка писали руками. А есть ли проги, в которых можно нарисовать граф переходов, отладить, а потом сгенерить код по этому графу? Есть VisualState и на TS Control, но код они генерят - просто атас, особенно VisualState. В качестве примера я как-то сваял такой граф. Power - всегда нажатая кнопка, LEDon и LEDoff - состояния, в которых диод горит или потушен соответственно. Гонял на MSP430 на частоте 8,192 МГц. В случае VisualState диод моргал с частотой около 3 кГц, т.е. переход по состояниям выполнялся с частотой 6 кГц, или один переход выполнялся через 8192/6 = 1365 тиков тактовой частоты. Многовато для такого простого графа. В случае TS Control диод моргал с частотой 20 кГц, если отключить очередь событий, то 40 Кгц, т.е. один переход через 100 тиков. Лучше, конечно, но в TS Control нет симулятора.
Так вот может кто знает прогу , в которой есть симулятор и которая генерит более-менее приемлемый код? А теорию я знаю.
lolikandr
Если интересует интересный инструмент, то посмотри сей инструмент: http://www.softcraft.ru/download/auto/switch/v2s.zip
Вот его описание:
Конвертор Visio2SWITCH предназначен для автоматической генерации С/С++ кода по автоматным графам, нарисованных в Visio в соответствии с требованиями SWITCH-технологии.

Теорию по которой оно работает можешь посмотреть на http://www.softcraft.ru/auto.shtml, а более точнее http://www.softcraft.ru/design/switch/sw01.shtml.
TMX
Цитата(Tran @ Sep 12 2005, 14:14)
Этот код Вы наверняка писали руками. А есть ли проги, в которых можно нарисовать граф переходов, отладить, а потом сгенерить код по этому графу? Есть  VisualState и на TS Control, но код они генерят - просто атас, особенно VisualState. В качестве примера я как-то сваял такой граф. Power - всегда нажатая кнопка, LEDon и LEDoff - состояния, в которых диод горит или потушен соответственно. Гонял на MSP430 на частоте 8,192 МГц.  В случае VisualState диод моргал с частотой около 3 кГц, т.е. переход по состояниям выполнялся с частотой 6 кГц, или один переход выполнялся через 8192/6 = 1365 тиков тактовой частоты. Многовато для такого простого графа. В случае TS Control диод моргал с частотой 20 кГц, если отключить очередь событий, то 40 Кгц, т.е. один переход через 100 тиков. Лучше, конечно, но в TS Control нет симулятора.
*

провел эксперимент:
PIC18F6620 / 11.059 МГц:
47.67 КГц с откл. прерываниями

по поводу автоматической программы: по совету bialix тоже смотрел VisualState
разложил по затратам времени на этапах:
1. Написание драйверов в/в, служ.прг, и т.п. (вручную) - 30 %
2. рисование диаграммы состояний и согласование с заказчиком - 40% (как минимум - 2 - 3 вида на каждый автомат)
3. реализация кода вручную - 5%
4. отладка и тестирование на макете - 25%

автоматическая генерация кода не оказывает существенного влияния, как мне кажется.
Владимир_2010
Применение теории конечных автоматов к программированию микроконтроллеров очень заинтересовало. Привидите пожалуйста простой (конкретный пример для двух-трех состояний (код в codevision или winavr) для микроконтроллера семейства avr?! Я пока не могу разобраться с кодом и идеей изложенной в теме форума.
С теорией немного знаком – в институте на курсах по автоматизации учили рисовать графы состояния, а потом переходить к релейно-контакторной схеме. Хотелось посмотреть как это реализовать на С "вручную" применительно к микроконтроллерам avr.
Спасибо за внимание.
TMX
Цитата(Владимир_2010 @ Mar 4 2009, 16:54) *
Применение теории конечных автоматов к программированию микроконтроллеров очень заинтересовало. Привидите пожалуйста простой (конкретный пример для двух-трех состояний (код в codevision или winavr) для микроконтроллера семейства avr?! Я пока не могу разобраться с кодом и идеей изложенной в теме форума.
С теорией немного знаком – в институте на курсах по автоматизации учили рисовать графы состояния, а потом переходить к релейно-контакторной схеме. Хотелось посмотреть как это реализовать на С "вручную" применительно к микроконтроллерам avr.
Спасибо за внимание.


Ок.

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

Сначала общие слова:


Задача:

светофор имеет выходы: три лампы (кр, жел, зел), входы: кнопка. Есть встроенный таймер (внутренний вход).

Как работает в штатном режиме лень объяснять, при нажатии на кнопку старается зажечь зеленый.

Практическая реализация:

сначала надо это промоделировать (изобразить), это можно сделать по-разному, кому как нравится.

1. можно в каждом состоянии опрашивать только требуемые события - самый простой способ.

2. можно все события представит в виде битового поля, предварительно опрашивать их, заполнять поле, а потом в каждом состоянии опрашивать при переходе в новое состояние выполнять действия. Подход Шалыто, хорош тем, что диаграмма состояний изображается в виде булевых выражений, можно применить аппарат дискр.математики для минимизации состояний.

3. можно каждое состояние представить в виде "состояние вообще", у которого есть действия, предпринимаемые при входе в состояние и действия, предпринимаемые при переходах в другие состояния. Это подход HSM. Удобен для реализации в ООП.

эти три подхода можно рассматривать с различных точек зрения.

например, с точки зрения потоков управления: в первом случае функции автомата все делают сами, во втором битовое поле сначала заполняется в каком-то диспетчере, в третьем - обычно все управление происходит в диспетчере, а классы состояний автомата просто описательные. И т.п.

На этапе рисования состояний следует решить, как будет осуществляться ввод-вывод. Классический подход: считать входы, прокрутить автомат, выставить выходы (как в ПЛК).

Еще надо выбрать политику моделирования: рисуем много состояний, или вводим дополнительные переменные (или иерархии для HSM).

Пример: можно сделать одно состояние "горит желтый" и в нем опрашивать флаг нажатия кнопки, а можно два: "желтый, кнопка была нажата", "желтый, кнопка не была нажата". В первом случае требуется ОЗУ, во втором ПЗУ, отлаживать легче второй.

Про реализацию напишу позже
Diz
Рекомендую ознакомиться с реализацией иерархических конечных автоматов
от Миро Самека - http://www.state-machine.com. С тех пор, как проникся этой концепцией, ничего другого и не хочется. Диспетчер использую самописный,
работает пошустрее и GPL не нарушает.


В простейшем виде, без иерархии, это выглядит как набор функций-обработчиков,
по одной на каждое состояние. В каждой функции switch/case с перечислением
всех интересующих в этом состоянии событий и связанных с ними действий,
прямо в теле функции. Отдельно хранится указатель на текущее состояние (текущую функцию-обработчик). При смене состояния этот указатель изменяется.

Как только в системе происходит событие, номер события кладется в очередь
сообщений (например, из прерывания). В main-е диспетчер выгребает событие
из очереди, вызывает обработчик по указателю текущего состояния и передает
ему событие как аргумент.

Если интересно, могу рассказать и про вариант с иерархией. Всякие графические
генераторы конечных автоматов (нетривиальных) малополезны, а код после них
невозможно модифицировать. Имхо, конечно же. Другое дело - визуализация
уже написанного на низком уровне конечного автомата.
_Pasha
Цитата(Diz @ Mar 4 2009, 20:33) *
Рекомендую ознакомиться с реализацией иерархических конечных автоматов
от Миро Самека


Книжку сравнительно недавно искал. Она Здесь лежит


Такшта, без паникиsmile.gif 
УПС. Там человек выложил на рапиду. Время вышло, ясное дело. Короче, коллегиально: если кому надо, выложу либо сюда либо в закрома. Пишите.
Alex B._
Цитата(_Pasha @ Mar 4 2009, 21:20) *
УПС. Там человек выложил на рапиду. Время вышло, ясное дело.

еще не вышло, спасибо!
Владимир_2010
Diz спасибо за ссылку на книги. В сети также есть «Samek Miro, Practical UML Statecharts in C/C++. 2008».
Diz писал:
Цитата
Другое дело – визуализация уже написанного на низком уровне конечного автомата

Нельзя ли в этом месте поподробней?! Задачи по дискретным системам автоматики я решал в основном по методе/идее изложено в книге «Юдицкий С.А. Проектирование дискретных систем автоматики. 1980». На русском искал, но больше ничего не встречал по этой теме. Встречались книги просто про конечные автоматы, без приложений к автоматике. Но там одна математика.
Вот как я решал задачки по автоматике: по методе вначале рисовал конечный автомат (графы с переходами) в пакете Stateflow от Matlab, затем проверял логику работы автомата моделируя различные состояния, далее записывал граф в виде уравнений/формул (вручную на бумажке), оптимизировал (вручную на бумажке) если требовалось конечный автомат с применением методов дискретной математики. Потом формулы рисовал в виде релейно-контакторной схемы (или функционально-логической схемы – триггеры, или, и, не), писал программу на Step7 (софт для программирования логических контроллеров Siemens) или на CX-Programmer (софт плк Omron) и прогонял логику работы с использованием симулятора для этих контроллеров.
Применяя эту методу к нескольким различным задачам, убедил себя (возможно зря) что самое главное для любой задачи по автоматике на плк это нарисовать правильно конечный автомат (графы с переходами) и проверить его работу средствами моделирования – все остальное дело техники, рутинный труд, все можно делать по одному шаблону/правилам, выключив мозг, нужно только время. Хотел даже весь этот процесс автоматизировать и написать автоматический генератор из графов всех этих формул и схем. Но потом подумал, что не надо горячиться: наверняка все это давным-давно уже сделано кем-то. Теперь вот вижу что на языке Си IAR реализует этот подход в VisualState, Telelogiс, великий ученый Шалыто А. А. и его друзья.
Вопросы:
1) Какие инструменты для моделирования/визуализации абстрактного конечного автомата есть кроме VisualState, Stateflow? Кто чем пользуется, опишите пожалуйста и поделитесь впечатлениями.
2) Какие инструменты для визуализация/моделирования/отладки уже написанного на языке С алгоритма есть?! Если применительно к мк AVR: в Proteus если загнать hex файл – не видно кода на Си и видны только входы/выходы с мк, при отладке в AVRStudio – код на Си виден, но не наглядно – нет временных диаграмм. И еще: может есть другие инструменты, без приложениям к мк?!
3) Есть ли что-нибудь из книг наподобие Miro Samek на русском для Cи?!

TMX писал
Цитата
Про реализацию напишу позже

Ждем, интересны детали – уверен, что каждый по-разному генерирует код из графов.

Diz писал
Цитата
Если интересно, могу рассказать и про вариант с иерархией

Интересно все и с иерархией и без. Если это возможно – то с простыми примерами, постановка задачи, с графом на 3-4 состояния, с кодом и с комментариями, желательно на Си для микроконтроллеров. Все в форум не войдет – может быть в rar(е) куда-нибудь выложите.
Спасибо.
TMX
Цитата(Владимир_2010 @ Mar 5 2009, 10:54) *
Применяя эту методу к нескольким различным задачам, убедил себя (возможно зря) что самое главное для любой задачи по автоматике на плк это нарисовать правильно конечный автомат (графы с переходами) и проверить его работу средствами моделирования – все остальное дело техники, рутинный труд, все можно делать по одному шаблону/правилам, выключив мозг, нужно только время. Хотел даже весь этот процесс автоматизировать и написать автоматический генератор из графов всех этих формул и схем. Но потом подумал, что не надо горячиться: наверняка все это давным-давно уже сделано кем-то. Теперь вот вижу что на языке Си IAR реализует этот подход в VisualState, Telelogiс, великий ученый Шалыто А. А. и его друзья.

Присоединяюсь.
У нас вообще рисуют , отлаживают и реализуют автоматы разные люди. В разных средах.
Примерные этапы разработки:
1. Разделение уровня драйверов и автоматов.
2. Спецификация на драйверы.
3. Разработка драйверов для микроконтроллера.
3. Разработка драйверов для LabWindows/CVI
3. Рисование автоматов.
4. Реализация автоматов на С.
5. Отладка на PC в среде CVI.
6. Перенос на мк (сборка).

автоматы очень удобны для написания протоколов обмена, в этом случае отладка на PC не всегда возможна.

используем ДРАКОН, рисуем в EDGE Diagrammer
_Pasha
А что-нибудь есть в ту же тему, но с текстовым вводом, визуализацией и экспортом в Си? Так сказать, рисовалка наоборот...
ЗЫ текстовый ввод не на LD
TMX
Цитата(Владимир_2010 @ Mar 5 2009, 10:54) *
Интересно все и с иерархией и без. Если это возможно – то с простыми примерами, постановка задачи, с графом на 3-4 состояния, с кодом и с комментариями, желательно на Си для микроконтроллеров. Все в форум не войдет – может быть в rar(е) куда-нибудь выложите.
Спасибо.


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

К сожалению, на русском языке можно почитать Шалыто и Парондажанова. На английском есть пяток книг, но там самые азы - только Самек предлагает интересную реализацию.

Если нужно протокол сваять, то можно взять реализацию COCO/R для С и написать в L1 грамматике правила обработки, там генерится автомат, работает очень быстро. Правила обработки распознанных пакетов тоже удобно описывать автоматом, но на другом уровне.

Продолжаю про автоматы - светофор как я думаю, вы и сами создать сможете, достаточно будет одного состояния.
Простейшая реализация:
состояния автомата нумеруются.
пишется функция, в которой выбирается текущее состояние, в этом состоянии опрашиваются условия перехода в другое состояние.
функция периодически вызывается.
Код
enum (RED, GREEN, YELLOW);

static char automaton_state = RED;

void super_auto(void)
{
  switch (automaton_state)
  {
    case RED:
      if (timer_flag)
      {
        output_control(RED_LAMP, OFF);
        output_control(GREEN_LAMP, ON);
        start_timer (GREEN_DELAY);
        automaton_state = GREEN;
      }
      break;
    case YELLOW:
...
...
  }
}


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

есть несколько модернизированных реализаций такого типа.
_Pasha
Цитата(TMX @ Mar 5 2009, 18:17) *
недостатки: если состояний много, то они могут перебираться долго. На самом деле здесь помог бы переход по изменяемой метке, типа GOTO STATE, но в С такого нет.
есть несколько модернизированных реализаций такого типа.

Позволю себе немного поправить Вас:

С недавних пор реализация оператора switch() отдана на откуп оптимизатору, т.е если структура приводится к таблице переходов - никакого перебора не будет. За таким подходом - будущее. В принципе, компиляторы смогут даже патчить входные значения, например


Код
switch(state)

{

case 1:

case 2:

case 14:

case 15:

}


Что мешает  в "рваных" вариантах и вычислять адрес в таблице перехода по какому-нибудь вспомогательному алгоритму?


По поводу вычисляемого goto - в гнусях такая фича ведь есть и давно. Если она войдет в "скрижали"...
Diz
Что касается визуализации, то я имел в виду следующее. Автомат описывается на С.
Перед компляцией запускается утилита, которая парсит C-файл, находит все, относящееся к автомату - состояния, события, переходы, иерархию - после чего рисует красивый statechart. Который можно окинуть взглядом и убедиться, что все в порядке.
Вот, для примера Pelican (светофор) от Самека:
Нажмите для просмотра прикрепленного файла
TMX
Цитата(_Pasha @ Mar 5 2009, 18:38) *
Позволю себе немного поправить Вас:

С недавних пор реализация оператора switch() отдана на откуп оптимизатору, т.е если структура приводится к таблице переходов - никакого перебора не будет. За таким подходом - будущее. В принципе, компиляторы смогут даже патчить входные значения, например


Встречал такое в аппнотах для PIC.
Но это не бесплатно: таблица переходов тоже место занимает, кроме того, если вычисляемое значение, то компилятор может пустыми операциями забивать место.
Реально проблема встает в дешевых контроллерах, где мало памяти, стека, скорости и т.п. или при реализации автомата в обработчике прерываний.

Чтобы не полагаться на компилятор используются модернизированные методы:

выше упоминалась ссылка http://www.embedded.com/2000/0012/0012feat1.htm
там Martin Gomez вручную забивает таблицу переходов: http://i.cmpnet.com/embedded/gifs/2000/001...t1_listing1.gif
Недостатки: во-первых, надо записывать в трех местах и легко ошибиться.
Во-вторых, вообще не понятно, зачем такая громоздкая реализация: состояние храниться в виде номера, функции и указателя на функцию. по номеру выбирается ссылка на функцию состояний и вызывается сама функция. Реализация требует и память и стек.
Гораздо проще хранить состояние в виде ссылки на функцию. Память не используется, стек используется. Ошибиться при переходе сложнее.

Цитата(Diz @ Mar 5 2009, 19:55) *
Что касается визуализации, то я имел в виду следующее. Автомат описывается на С.
Перед компляцией запускается утилита, которая парсит C-файл, находит все, относящееся к автомату - состояния, события, переходы, иерархию - после чего рисует красивый statechart. Который можно окинуть взглядом и убедиться, что все в порядке.
Вот, для примера Pelican (светофор) от Самека:
Нажмите для просмотра прикрепленного файла

не слышал о таком, есть программа, которая flowchart генерирует.
Писать программу без картинки - если получается, тогда зачем картинка?
Diz
Цитата(TMX @ Mar 5 2009, 20:09) *
не слышал о таком, есть программа, которая flowchart генерирует.
Писать программу без картинки - если получается, тогда зачем картинка?


На самом деле картинка это побочный эффект. У меня упомянутая утилита (скрипт на питоне) собирает информацию об автомате и создает h-файл с несколькими дополнительными таблицами. Нужными для ускорения переходов между состояними в полностью иерархическом автомате - то, как сделано у Самека, с реалтаймовым поиском наименьшего общего предка в графе, жутко медленно.
Ну а заодно можно и проверить нарушения правил кодирования statechart-а, и картинку сделать.
Картинка - в первую очередь для самодокументации.
_Pasha
Цитата(TMX @ Mar 5 2009, 20:09) *
там Martin Gomez вручную забивает таблицу переходов


no comment smile.gif


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


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


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

2.Например, для повышения уровня языка реализации до проблемно-ориентированного  http://www.citforum.ru/internet/xml/graphml/
TMX
Цитата(_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.Обычно проблему снаала описывают, а потом реализуют.

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

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

Вот мои небольшие наблюдения на смежную тему кооперативной многозадачностиhttp://electronix.ru/forum/index.php?showtopic=59333
TMX
Цитата(Diz @ Mar 6 2009, 16:20) *
Наверное, jumptable может быть полезен для сохранения текущего состояния в eeprom и восстановления после сбоя. Пишем лишь индекс, а не потенциально
опасный указатель.

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

реализовать кооперативную многозадачность с помощью конечных автоматов - собственно, этим я хотел закончить про реализации.
TMX
Недостатки прямого присваивания значения переменной состояния, типа
Код
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:
        ...
  }
}


кроме некоторого контроля за присваиванием, такой подход не дает никаких премуществ.
Просто на практике не всегда бывает возможно обеспечить полноту тестов.
Dog Pawlowa
Цитата(TMX @ Mar 6 2009, 18:35) *
сомнительно. все равно потом по указателю функция вызывается,

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

Кароч, я использую индексы и массивы функций. Иногда двумерный массив functions[state][event] в каком-нить менюшном сервисе.
-=TRO=-
Внутри программируемой логики собирают микропроцесоры и пишут для них программы.
На микроконтроллерах пишут программы эмулирующие логику(конечные автоматы).
Походу использовать компоненты по назначению сегодня не модно.
Или просто грани стираются, и будущее за гибридными технологиями.
Скоро наверно будем делать проэкты для одного кристалла из пары сотен операционников, нескольких микроконтроллеров, и массива программируемой логики.
TMX
Цитата(Dog Pawlowa @ Mar 10 2009, 19:14) *
Индекс проще проверит на валидность. Всего лишь на максимум.
Индекс удобно использовать при генерации события по смене состояния.
Индекс удобно использовать для возврата в старое состояние.

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


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

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

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

насколько я знаю, в 70-х годах было мнение, что наиболее перспективная парадигма в программировании - автоматный подход.
"Лучше забивать молотком шурупы, чем закручивать отверткой гвозди"
Dog Pawlowa
Цитата(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;
}
}
_Pasha
Весь смех в том, что сишная или иная ЯВУ-программа при помощи переменной state эмулирует счетчик команд целевой машины. Вот эта некузявость порядком раздражает. sad.gif 
Rst7
Цитата
при помощи переменной state эмулирует счетчик команд целевой машины.


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

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

Вот и меня не жмет. А switch или таблица - это вопрос качества монитора и разрешения biggrin.gif
Если все case не помещаются на два-три экрана, то лучше бить на таблицу. Если помещаются, то лучше помолиться за IAR, который при оптимизации ту же таблицу сам нарисует.
Diz
Цитата(TMX @ Mar 6 2009, 17:35) *
сомнительно. все равно потом по указателю функция вызывается,
для таких случаев обычно пишут лог переходов в том или ином виде, ну и список разрешенных переходов (собственно, он у Гомеса есть).


Пример взят из реальной задачи - нужно было при каждой смене состояния сохранять
его во внешней eeprom, чтобы восстановить при пропадании питания. Лог переходов писать смысла нет, так как не важно, каким путем мы попали в данное состояние - важен сам факт попадания.
Индекс - один байт, пишется атомарно. При загрузке легко его проверить на попадание
в диапазон разрешенных состояний. Если будет восстановлено неверное состояние,
неприятно, но не так разрушительно как вызов функции по неверному указателю.
Еще одна особенность - прошивка могла быть обновлена, и обработчики
могли бы лежать на других адресах.
TMX
Цитата(Diz @ Mar 11 2009, 11:24) *
Пример взят из реальной задачи - нужно было при каждой смене состояния сохранять
его во внешней eeprom, чтобы восстановить при пропадании питания. Лог переходов писать смысла нет, так как не важно, каким путем мы попали в данное состояние - важен сам факт попадания.
Индекс - один байт, пишется атомарно. При загрузке легко его проверить на попадание
в диапазон разрешенных состояний. Если будет восстановлено неверное состояние,
неприятно, но не так разрушительно как вызов функции по неверному указателю.
Еще одна особенность - прошивка могла быть обновлена, и обработчики
могли бы лежать на других адресах.


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

Цитата(Dog Pawlowa @ Mar 10 2009, 20:36) *
Да все тупо...

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

с событиями не совсем ясно:
насколько я понял, функции опроса событий возвращают 0, если события нет и номер события, если событие есть. Как происходит нумерация событий?
Получается, что события имеют приоритет, в порядке которого они опрашиваются. Из этого следует, что в любом состоянии приоритет событий одинаков. Более того, каждое состояние должно реагировать на все события.
А если, допустим, первое событие - кнопка нажата, а второе - таймер сработал. Тогда при нажатой кнопке даже в состоянии "ждать таймер" система не будет не него реагировать.
Dog Pawlowa
Цитата(TMX @ Mar 11 2009, 12:06) *
то есть, если надо убрать одну функцию из центра списка, придется перенумеровывать все последующие?

Вовсе нет. Если это состояние не используется, есть два пути:
1) не делать ничего, разместив указатель на пустую функцию

#define stSelfTest 1 >> #define st1 1
#define f1 fSelfTest >> #define f1 fEmpty

2) или, если два байта в таблице вдруг понадобились, перенести сюда функцию, последнюю в списке.

Цитата(TMX @ Mar 11 2009, 12:06) *
с событиями не совсем ясно:
насколько я понял, функции опроса событий возвращают 0, если события нет и номер события, если событие есть. Как происходит нумерация событий?
Получается, что события имеют приоритет, в порядке которого они опрашиваются. Из этого следует, что в любом состоянии приоритет событий одинаков. Более того, каждое состояние должно реагировать на все события.
А если, допустим, первое событие - кнопка нажата, а второе - таймер сработал. Тогда при нажатой кнопке даже в состоянии "ждать таймер" система не будет не него реагировать.

Разумеется, тут есть ограничения, которые закладываются на уровне проектирования системы. Они всегда есть, реализовывать, например, подавление дребезга с помощью такого автомата бессмысленно. Точнее, можно, но в отдельном автомате, и события для отдельного автомата должны быть другие. Я обычно предусматриваю отдельно до написания автомата все входящие события с запасом по ресурсам, все, требующее быстрой реакции, выносится в background (прерывания и общий цикл).

Состояние не должно реагировать на все события, тут Вы не правы.
_Pasha
Цитата(Diz @ Mar 11 2009, 11:24) *
Индекс - один байт, пишется атомарно.


Здесь и далее - плюспицот за каждое слово smile.gif К тому же, состояний, критичных к пропаданию питания, не должно быть много.


Цитата(TMX @ Mar 11 2009, 12:06) *
я не уверен в содержимом eeprom, если запись ведется в момент пропадания питания.

В приличных девайсах надо закладывать раннюю диагностику пропадания питания. sad.gif
TMX
Цитата(Dog Pawlowa @ Mar 11 2009, 13:12) *
Состояние не должно реагировать на все события, тут Вы не правы.

Возможно, я не совсем понял про функции опроса событий. Если они работают как написано ниже, то я был не прав:
Все события обрабатываются однократно - функция опроса возвращает номер каждого события один раз.
По окончании обработки переменная сбрасывается в ноль.
При следующем опросе функция возвращает ноль - т.к. событие уже было отослано.

Фактически, это модель с монитором однократных событий. Сложно сказать, какие преимущества и недостатки у моделей.
А вот насчет вашей реализации - похоже на реализацию Gomez, но event driven, и те же недостатки.

Простой switch по состояниями имеет меньше источников ошибок, поскольку там нет нумерации и перечисление событий только в одном месте.

Цитата(_Pasha @ Mar 11 2009, 14:40) *
Здесь и далее - плюспицот за каждое слово smile.gif К тому же, состояний, критичных к пропаданию питания, не должно быть много.

В приличных девайсах надо закладывать раннюю диагностику пропадания питания. sad.gif


А "много" это сколько? "Плюспицот" - это много? Тестировали атомарность записи в eeprom? А если да, то как?

Я имею дело со всякими девайсами и разными процессорами. В различных средах разработки, кстати. Поэтому молиться на IAR как-то не тянет.
Например, были готовые серийные девайсы с внешней EEPROM на программном SPI. Именно с проблемой восстановления.
Я - за рациональные решения. Объясните, пожалуйста, зачем нужна ранняя диагностика питания и как она сказывается на приличности? Если результата можно добиться программными средствами - это красиво и целесообразно.
Уточняю - это не для всех случаев. Я не против диагностики, я даже за резевный ионистор в НЕОБХОДИМЫХ случаях. А вопросы о приличности оставляю на рассмотрение депутатов.
_Pasha
Цитата(TMX @ Mar 11 2009, 17:22) *
Тестировали атомарность записи в eeprom? А если да, то как?


Я заходил с другого края: при получении инфы о падении питания все операции запрещаются и пишется блок состояния контроллера с тем расчетом, что пока питание будет падать - времени для записи обязано хватить. Вариант с 24хх тоже рулит благодаря тому, что пишется сразу страница. Несложный комплекс мер, в том числе блочная CRC/LRC, кеширование данных из eeprom итд, навсегда убирают из обихода понятие "атомарность". Имхо, если речь заходит об  атомарности записи в eeprom - значит возможность обеспечить нормальную работу контроллера  отсутствует либо недоступна какая-то часть софта.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.