Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Язык программирования (и ОС) ФОРТ (FORTH) Форт из трех инструкций для встраиваемых систем


Информационный Канал Subscribe.Ru

последняя версия новой книги по Форту: http://akps.ssau.ru

PS: кто работает с Фортом на реальном embedded железе ? Можно ли реализивать
подобную
технику разработки для гарвардской архитектуры (MCS51, AVR, PIC, ..) ?

Форт из трех инструкций для встраиваемых систем 

С примерами для Motorola MC68HC11 

 Frank Sergeant, 1991 
809 W. San Antonio St. 
San Marcos, Texas 78666 

--------------------------------------------------------------------------------
Subsections 
Обзор 
Literary Justifications 
Хотите ли вы Форт в целевой системе ? 
Разработаем простейший Форт 
Философия ? 
Можем ли мы это сделать ? 
Распределенная разработка 
Let's ваш Форт и мой Форт Do Lunch 
Пример сессии 
3FVM монитор для 68HC11 
Загрузка 
Использование трех примитивов 
Литература 

--------------------------------------------------------------------------------

(c) Dmitry Ponyatov <forth@km.ru>, public domain 

Обзор 

Сколько инструкций нужно, чтобы сделать Форт для вашей целевой системы ? Растет
ли память на 
деревьях ? Оплачивается ли стоимость системы разработки из вашего собственного
кармана ? Форт 
из трех инструкций делает Форт применимым для целевых систем с очень ограниченной
памятью. Он 
может быть быстро запущен на любом необычном или новом железе. Вы не должны отбрасывать
Форт 
из-за ограничений по памяти или времени. Он занимает всего 66 байт на Motorola
MC68HC11. 
Представлен полный исходный код. 

--------------------------------------------------------------------------------
Literary Justifications 

I come to Forthifize the 68HC11 not to praise it. 

Had we but memory enough and time, 
   this wastefulness, Programmer, were no crime. 
The embedded system box is a private place and fine, 
   but none should there, I think, megabyte ROMs enshrine. 

--------------------------------------------------------------------------------

Хотите ли вы Форт в целевой системе ? 

Да. Это статья в FORML58, и кажется обоснованным предполагать, что вы хотите
использовать Форт
на целевой системе, если это возможно, при условии что вы можете достать его.
Без Форта, 
возможно даже без какого-либо мониторного ПЗУ, вы можете оказаться в следующей
ситуации: вы 
должны написать некоторый код, прошить его в EPROM, выяснить почему он не работает,

модифицировать ваш код, снова прошить EPROM ... и делать это снова и снова до
тех пор, пока 
что-то не начнет работать. В конце концов светодиод начинает мигать, и ваши непрограммирующие

друзья удивляются, зачем вы столько маньячите, чтобы сделать такую элементарную
штуку ! Вы say 
there's got to be простой путь, и начинаете думать, можете ли вы позволить себе
приобрести 
дорогую систему разработки. 

Но как вы можете поместить Форт в вашу целевую систему ? Если вы станете писать
свой Форт, вы 
окажетесь в той же ситуации циклической перепрошивки EPROM и выяснения причин,
почему ваш Форт 
не работает. Если вы купите его, он может не работать с вашей аппаратной конфигурацией,
он 
может быть слишком дорог или ресурсоемок, в комплекте поставки может не оказаться
полного 
исходного кода. Кроме того, у вас может не оказаться времени, чтобы сделать все
это до того, 
как придется работать над реальным проектом. Конечный продукт может потребовать
увеличения 
размеров печатной платы или дополнительного ПЗУ или ОЗУ, которые необходимы для
этого Форта. 

--------------------------------------------------------------------------------

Footnotes
 ... FORML58 
какое-то буржуйское периодическое издание, посвященное Форту 
--------------------------------------------------------------------------------

Разработаем простейший Форт 

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

функций, тогда целевой системе нужно будет только обеспечивать работу примитивов.


Абсолютно минимальная целевая система должна делать, как мне кажется, только
выборку байта, 
запись байта и вызов процедуры. Все остальное может быть сделано в высокоуровневом
Форте на 
хост-системе59. Предполагается, что хост и целевая система соединены последовательным
каналом 
(UART), и посылка и прием байт по этому каналу будет включена как часть часть
выполнения трех 
примитивных функций. Используя эти три примитивные фукнции, можно читать и изменять
память, 
загружать и выполнять новые процедуры. Назовем это 3FVM -- виртуальная форт-машина
из трех 
инструкций60. "Everything else being the same," 3FVM должна быть достаточно простой
для 
написания и отладки ее кода. Вот ее описание в псевдокоде: 

1. Инициализировать процессор. 
2. Инициализировать UART. 
3. Бесконечный цикл: 
Получить байт через UART. 
If byte = 01 [fetch] ( чтение байта ) 
Получить адрес через UART. 
Прочитать байт по адресу. 
Отправить байт через UART. 
Else If byte = 02 [store] ( запись байта ) 
Получить адрес через UART. 
Получить байт через UART. 
Записать байт по адресу. 
Else If byte = 03 [call] ( вложенный вызов ) 
Получить адрес через UART. 
Сделать вложенный вызов по адресу. 
End If. 

Шаги 1 и 2 выполняют установку процессора и UART в начальное состояние, включая
инициализацию 
стеков и установку различных режимов. Эти шаги чрезвычайно просты на HC11. Когда
этот процессор
просыпается в его загрузочный режим, внутреннее ПЗУ устанавливает стек, включает
UART, и 
ожидает загрузку программы через UART. На HC11 шаг 1 состоит из установки адресуемости

внутренних регистров и портов. Это делается загрузкой в регистр X базового адреса
пространства 
регистров. Выходная линия последовательного порта HC11 просыпается в режиме "монтажное
ИЛИ". 
Для шага 2 нам нужно только выключить "монтажное ИЛИ" для этой линии. Это убирает
необходимость
установки подтягивающего регистра на этот вывод процессора. 

В основной части интерпретатора 3 функции получения байта или получения адреса
через UART 
требуются в нескольких местах, поэтому они должны быть оформлены как процедуры.
Действительно,
получение адреса будет использовать процедуру получения байта. Байт посылается
на хост только 
в одном месте, так что эту пересылку можно реализовать inline без вызовы процедуры.


--------------------------------------------------------------------------------

Footnotes
 ... хост-системе59 
рабочем ПК 
 ... инструкций60 
в оригинале 3-instruction Forth, эквивалентный перевод подобрать не удалось 

--------------------------------------------------------------------------------

Философия ? 

Да, мы можем исключить последнии инструкцию и при этом все еще способны читать
и писать все 
ОЗУ и регистры целевой системы. К сожалению мы не сможем тестировать код на целевой
системе. 
Только с двумя инструкциями (чтение и запись) мы можем exercise the devil out
железа, но на 
самом деле нам необходима третья инструкция (вызов) для расширения Форта. Так
что использовать
FVM только с двумя инструкциями (2FVM) я не хочу. 

Можем ли мы назвать это Фортом даже с этими тремя инструкциями ? У него нет стека
данных, 
заголовков слов, даже innner или outer интерпретатора (я колеблюсь в выборе между
ними). Он 
зависит от хоста61. Она расширяема и даже главный цикл может быть расширен дополнительными

командами кроме fetch, store и call. Так что, это Форт или нет ? Я склоняюсь
ответить "да". Он 
имеет такие атрибуты Форта как простота, экономичность и (я надеюсь) элегантность.


What, though, about linking together calls to earlier routines in order to build
later 
routines ? Наиболее obvious подход -- построить набор процедур простого языка
ассеблера на 
хосте и загрузить их в целевую систему по одному и протестировать их. Затем загрузить
более 
высокоуровневые ассемблерные процедуры, которые вызывают низкоуровневые. Это
наиболее 
эффективный по памяти подход. Если у вас в целевой системе есть достаточно ОЗУ,
вы можете 
использовать 3FVM для построения и тестирования полноценного Форта, и затем использовать
его.
С другой строны, начиная с 3FVM вы получаете работающую интерактивную форт-подобную
среду 
разработки. 

--------------------------------------------------------------------------------

Footnotes
 ... хоста61 
но, с другой стороны, какая целевая форт-система, соединенная с ПК по последовательному
каналу, не зависит от хоста хотя бы для to at least some extent ? 

--------------------------------------------------------------------------------

Можем ли мы это сделать ? 

"Но подождите," говорите вы, "у 68HC11 есть только 192 байта встроенного ОЗУ
(или 256 или 512, 
в зависимости от версии) -- однозначно это недостаточно для Форта или любого
другого 
монитора !" Да, это недостаточно для обычноого монитора или традиционного Форта.
Тем не менее, 
этот процессор имеет досточно памяти для работы 3FVM, и это все что нам нужно.
Эта 3FVM для 
HC11 занимает всего 66 байт в целевой системе. Она была создана с использованием
Pygmy Forth, 
работающем на ПК. Следующий далее листинг исходного кода -- листинг этих 66 байт
машинного 
языка HC11, так что вы можете использовать этот код с любым Фортом, работающем
на любом хосте. 
Даже древнего медленного ПК вполне достаточно; не требуется никакой быстрой или
дорогой 
системы разработки. 

Как только эта крошечная программа запущена, вы можете использовать ее для чего
угодно. Эта 
техника работает с любыми микропроцессорами, но особенно просто работать с семейством
Motorola 
68HC11. Прежде всего я уже привел полный листинг программы. Если вы не пользуетесь
HC11, то вы 
должны написать эквивалентную программу для другого процессора. Вторая причина
-- встроенный в 
HC11 режим загрузки через UART. Это позволяет избежать прошивки ПЗУ при разработке
программ. 
Вы можете загружать 3FVM по последовательному порту. 

68HC11 дает вам также другой бонус. В режиме загрузки внутреннее ПЗУ инициализирует
чип и 
включает встроенный последовательный порт. С другим процессором вам придется
написать ваш 
собственный код для выполнения этого этапа. Если процессор не имеет встроенного
UARTа, вам 
необходимо поставить внешний чип последовательног или параллельного порта, или
реализовать его 
программно используя выводы процессора. 

--------------------------------------------------------------------------------
Распределенная разработка 

Наши три инструкции: 

XC@ выборка байта 
XC! запись байта 
XCALL вызов процедуры 

Это токенизированный62 Форт. Хост посылает опкод (код операции, один байт кода)
на 68HC11. 
Опкод 01 обозначает XC@, опкод 02 -- XC!, опкод 03 -- XCALL, любые другие опкоды
игнорируются. 
Когда хост хочет прочитать байт он сначала посылает 01 для выбора инcтрукции
XC@, а затем 
посылает адрес, по которому 68HC11 нужно выполнить чтение. По получению опкода
01 68HC11 
выполняет инструкцию XC@, которая сама получает адрес, читает байт и посылает
его на хост. 
Инструкция XC! работает аналогично. Хост посылает опкод 02, адрес и значение
байта. Для 
инструкции XCALL хост посылает опкод 03 и адрес процедуры. Используя инструкцию
XC! вы можете 
загрузить код коротких процедур для тестирования, или большие программы, при
условии что 
целевая система имеет достаточно ОЗУ, или вы можете программировать встроенное
(ЭС)ПЗУ, если 
оно есть в вашем процессоре. После того, как процедура загружена, хост может
послать команду 
XCALL, и 68HC11 запустит эту процедуру на выполнение. Если процедура оканчивается
корректным 
возвратом (RTS), управление снова автоматически передается на 3FVM монитор. 

Так как все регистры статуса, управления и ввода/вывода 68HC11 отображаются на
память, вы 
можете использовать XC@ и XC! для их чтения и установки, как и обычную память.
На других 
процессорах вам потребуется больше чем 3 инструкции, если вам требуется работать
с регистрами 
или портами ввода/вывода, которые не отображены на память. В этом случае вам
потребуется 5 или 
6FVM. 

--------------------------------------------------------------------------------

Footnotes
 ... токенизированный62 
tokenized 
--------------------------------------------------------------------------------

Let's ваш Форт и мой Форт Do Lunch 

"Подождите еще," говорите вы, "я не собираюсь сидеть и вводить value address
XC! снова и снова 
для загрузки программы !" Нет, конечно нет. Вы запускаете Форт на хосте и заставляете

хост-Форт делать эту работу для вас. Вы вводите высокоуровневые команды и хост
разбирает их на
наши три простые команды, которые понимает 3FVM на целевой системе. Это распределенная

встраиваемая система разработки. Часть работы выполняется на хосте, и часть на
целевой 
системе. Это позволяет вам использовать всю мощь Форта и всю мощь интерпретатора
без 
необходимости больших ресурсов на целевой системе. 

Под мощью интерпретатора я подразумеваю что вы можете читать и устанавливать
регистры и память 
интерактивно с клавиатуры хоста или из скриптов на Форте. Это позволяет вам упражняться
с 
железом напрямую. Это намного быстрее и удобнее, чем писать целые программы,
прошивать из в 
ПЗУ и разбираться почему они не работают. Использование 3FVM дает вам мощь системы
разработки 
бесплатно, если вы используете 68HC11, и задешево, если вы используете другой
процессор. 

--------------------------------------------------------------------------------

Пример сессии 

Если вы можете ввести 003F XC@ . и понимаете что вы только что отобразили занчение
байта 
памяти 68HC11 по адресу $003F, значит вы знаете достаточно. 

Вот пример сессии. 

Предположим что я подключил 68HC11 так что порт A (вывод 1) управляет светодиодом
(LED). Я не 
могу вспомнить, 0 или 1 включает LED, и я не уверен что система вообще работает.
Я смотрю в 
даташит на процессор и нахожу что порт A отображается на на адрес памяти 0000.
Так как для 
управления LEDом используется только один бит порта A, но к этому порту больше
ничего не 
подключено, я могу просто устанавливать весь байт в $FF или $00 и смотреть что
происходит. 

HEX
0 0 XC!      ( LED включается )
FF 0 XC!     ( LED выключается )

Теперь я хочу посмотреть что-то более интересное, так что я пишу маленькую форт-программу,

мигающую светодиодом. Те, кто не знаком с Фортом, могут считать этот код определением

клавиатурных макросов: 

DECIMAL
: LED-ON ( -)  0 0 XC! ;
: LED-OFF  ( -) $FF 0 XC!  ;
: DELAY ( -)   500 MS    ;
: FLASHES ( # -)   FOR  LED-ON DELAY LED-OFF DELAY NEXT ;
25 FLASHES   ( глюкалово длится около 25 секунд )

или 

10000 FLASHES ( около 3 часов тоски )

MS обозначает задержку в миллисекундах, так что 500 MS вызывает задержку в пол-секунды.
Если в 
вашей форт-системе нет этого слова (команды), вы можете определить его: 

: MS  0 DO 2000 0 DO LOOP LOOP ;

Введя 10000 MS вы увидите сколько времени занимает выполнение этого пустого цикла.
Если цикл 
выполняется не за 10 секунд, повторяйте ввод этого определения, увеличивая или
уменьшая 2000 
до тех пор, пока не получите нужную скорость выполнения на вашей машине. 

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

--------------------------------------------------------------------------------

3FVM монитор для 68HC11 

Следующий код, запущенный под Pygmy Forth на ПК, создает образ памяти с программой
нашего 
3FVM-монитора для 86HC11. Предполагается что ассемблер HC11 уже загружен в Pygmy.


( имена регистров UART /SCI, Serial Communication Interface/ HC11 )
    $2E CONSTANT SCSR ( адрес регистра SCI Status )
    $2F CONSTANT SCDR ( адрес регистра SCI Data )

( метки для двух процедур )
    VARIABLE 'GET-BYTE
    VARIABLE 'GET-ADDR

( сколько байт занимает 3FVM ? )
    VARIABLE MONITOR-LENGTH

( определение двух макросов на ассемблере HC11 )
    : GET-BYTE, ( - )  'GET-BYTE @ BSR,  ;
    : GET-ADDR, ( - )  'GET-ADDR @ BSR,  ;

( создаем 3FVM )
  CODE MONITOR         ( НЕ ВЫПОЛНЯЙТЕ это слово на ПК )
       CLRA, CLRB, XGDX,  ( теперь X указывает на базовый адрес регистров )
       CLRA, $28 ,X STA,  ( отключаем на порте D "монтажное ИЛИ" )

      ( определяет 2 процедуры )
       NEVER, IF,  ( обертка вокруг 2 процедур )

       ( get-byte )  HERE 'GET-BYTE !
       HERE   SCSR  ,X   $20 BRCLR, ( ожидание входящего байта )
                      SCDR  ,X LDA, ( чтение последовательного порта )
                               RTS, ( байт в регистре A )

       ( get-addr )  HERE 'GET-ADDR !
                          GET-BYTE,
                               TAB, ( первый байт в регистр B )
                          GET-BYTE, ( второй байт в регистр A )
                              XGDY, ( перенос в регистр Y )
                               RTS, ( адрес в регистр Y )

     THEN,

    ( начало бесконечного основного цикла интерпретатора )
     BEGIN,
       GET-BYTE,   ( получить опкод )
       1 #, CMPA, 0=, IF,

         ( запрошена инструкция XC@ )
                          GET-ADDR,
                          0 ,Y LDA,
        HERE  SCSR  ,X   $80 BRCLR, ( ожидание передачи )
                                    ( регистр данных пуст )
                     SCDR  ,X  STA, ( послать байт на ПК )

       ELSE,
       2 #, CMPA, 0=, IF,

         ( запрошена инструкция XC! )
                          GET-ADDR,
                          GET-BYTE,
                          0 ,Y STA,

       ELSE,
       3 #, CMPA, 0=, IF,

         ( запрошена инструкция XCALL )
                          GET-ADDR,
                          0 ,Y JSR,

       THEN,  THEN,  THEN,
     NEVER, UNTIL,  ( переход на начало цикла )
  END-CODE

( вычисляем сколько занимает 3FVM )
  HERE  ' MONITOR -  MONITOR-LENGTH !

Для загрузки этого кода вы должны иметь ассемблер HC11, работающий на ПК в Pygmy
Forth. Вы 
можете скачать этот ассемблер с Forth roundtable на GEnie -- ищите в секции файлов
для 68HC11. 
Тем не менее, конечная цель приведенного кода -- создание образа памяти из 66
байт. Вот дамп 
этого кода: 

0000   4F 5F 8F 4F A7 28 20 0F  1F 2E 20 FC A6 2F 39 8D
0010   F7 16 8D F4 18 8F 39 8D  EF 81 01 26 0D 8D F0 18
0020   A6 00 1F 2E 80 FC A7 2F  20 16 81 02 26 09 8D DF
0030   8D D6 18 A7 00 20 09 81  03 26 05 8D D2 18 AD 00
0040   20 D5

Вы можете создать этот образ любыми другими средствми, но мы в любом случае будем
использовать 
Форт при разработке, поэтому этот образ можно напрямую определить с помощью слова
C, в вашем 
хост-Форте без использования ассемблера для HC11. Тем не менее, уверены ли вы
что вам не нужен 
ассемблер для дальнейшей рабьоты с HC11 ? 

HEX
CREATE MONITOR
  4F C, 5F C, 8F C, 4F C, A7 C,  ...  20 C, D5 C,

создаст тот же образ памяти для HC11. Или вы можете накидать все байты на стек
данных, 
перевернуть их порядок используя стек возвратов, и выполнить C, в цикле: 

DECIMAL
VARIABLE MONITOR-LENGTH    66 MONITOR-LENGTH !
: COMMA-THEM-IN ( ... - )
  66 FOR POP SWAP PUSH PUSH NEXT  (   ) ( rs: ... )
            ( теперь байты находятся на стеке возвратов )
  66 FOR POP POP C, PUSH NEXT  (   ) ( rs:   )
                  ( теперь байты находятся в памяти )  ;

HEX
4F 5F 8F 4F A7 28 20 0F  1F 2E 20 FC A6 2F 39 8D
F7 16 8D F4 18 8F 39 8D  EF 81 01 26 0D 8D F0 18
A6 00 1F 2E 80 FC A7 2F  20 16 81 02 26 09 8D DF
8D D6 18 A7 00 20 09 81  03 26 05 8D D2 18 AD 00
20 D5  
( помещаем все 66 байт на стек данных )

CREATE MONITOR
    COMMA-THEM-IN

--------------------------------------------------------------------------------

Загрузка 

Следующий шаг -- загрузка полученного образа в HC11. Следующие слова определены
на хосте, 
чтобы обеспечить загрузку 3FVM в HC11. 

 .OUT  ( a # - ) скопировать строку на HC11.
?EMIT ( c - )   вывести печатаемый символ или его код (для служебных символов).
 .OUTE ( a # - ) скопировать строку на HC11 и вывести это от HC11.
?HEX  ( - )     вывести hex значение of any waiting serial characters.
DL    ( - )     загрузить 3FVM в HC11.

: .OUT ( a # - )  FOR DUP C@ SER-OUT 1+ NEXT DROP ;

: ?EMIT ( c - ) DUP $20 $7F BETWEEN IF EMIT ELSE . THEN ;

: .OUTE ( a # - )
  FOR DUP C@ SER-OUT  SER-IN ?EMIT  1+ NEXT DROP ;

: ?HEX ( - ) BASE @ HEX
     BEGIN SER-IN? WHILE SER-IN 3 U.R REPEAT BASE ! ;

: DL ( - )  
  $FF SER-OUT  ( активировать HC11 )
  ['] MONITOR ( a )  MONITOR-LENGTH @  ( a # )
  .OUT 1000 FOR NEXT ?HEX     ;

--------------------------------------------------------------------------------

Использование трех примитивов 

Как только 3FVM была загружена в HC11, эти примитивы могут быть использованы
на хосте. Вот 
несколько примеров. 

FLIP  ( hhll - llhh)    преобразовать порядок байт Intel 
                        в порядок Motorola и обратно.
ADDR-OUT ( a -)         послать 16-битный адрес на HC11 в виде двух байт.
XC@   ( a - c)          получить байт из памяти HC11 по адресу a.
XC!   ( c a -)          записать байт в HC11 по адресу a.
XCALL ( a -)            выполнить в HC11 вызов процедуры по адресу a.
XDUMP ( a - a+16)       вывести 16 байт начиная с адреса а.
XDU   ( a # - a')       повторить XDUMP нужное число раз.

: FLIP ( hhll - llhh) DUP $100 * SWAP $100 U/ OR ;

: ADDR-OUT ( a -)  DUP SER-OUT   FLIP SER-OUT   ;

: XC@ ( a - c) 1 SER-OUT   ADDR-OUT  SER-IN  ;

: XC! ( c a -) 2 SER-OUT   ADDR-OUT  SER-OUT  ;

: XCALL ( a -) 3 SER-OUT  ADDR-OUT  ;

: XDUMP ( a - a' )
  HEX CR DUP 4 U.R 2 SPACES ( a )
  DUP ( a a ) 2 FOR
                 8 FOR DUP XC@ 3 U.R 1+ NEXT
                 SPACE
               NEXT DROP  2 SPACES
  ( a ) 2 FOR
            8 FOR DUP XC@ DUP $20 $7F WITHIN NOT
                  IF DROP $2E THEN EMIT 1+
              NEXT SPACE
         NEXT ;

: XDU ( a # - a' ) FOR ?SCROLL XDUMP NEXT  DROP  ;

--------------------------------------------------------------------------------

Литература 

Harold M. Martin, "Developing a Tethered Forth Model," 
SIGForth Newsletter, Vol. 2, No. 3. 

Brad Rodriguez, "A Z8 Talker and Host," 
The Computer Journal, issue 51, July/August, 1991. 

--------------------------------------------------------------------------------

(c) Dmitry Ponyatov <forth@km.ru>, public domain 

Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.prog.forth
Архив рассылки
Отписаться Вебом Почтой
Вспомнить пароль

В избранное