Программатор Orange
Описание языка HPL


rev 2.0 (25.05.2001)

    Язык HPL (Hardware Programming Language) разработан специально для описания низкоуровневых протоколов обмена с различными устройствами.

Рассмотрим реализацию языка HPL в трансляторе программатора Orange.
Примеры обозначены символом (*), Изменения - символом '!'.

Символ ';' является признаком комментария - конец строки начиная с этого символа не обрабатывется.

  • Числа. Числа могут задаваться в двоичном, десятичном и шестнадцатеричном формате:
    (*) 1234 - десятичная константа
    (*) 010101B - двоичная
    (*) 0x1234 или 01234H - шестнадцатеричная.
  • Адрес. Ключевое слово ADR содержит текущее значение адресного регистра (32 разряда), по которому выполняется чтение/запись данных. Для адресного регистра могут использоваться операции установки (только в пользовательских секциях) и инкремента (в секциях блочного чтения и записи)
  • Данные. Для доступа к данным в буфере по текущему адресу используется ключевое слово DATA. Данные доступны пословно (8 или 16 бит в зависимости от установленного типа памяти) или поразрядно.
  • Регистры. Для выполнения математических и логических операций, описания констант и хранения данных можно использовать 16 тридцатидвухразрядных регистров R0...R9,RA...RF. Регистры R0...R9 универсальные, регистры RA...RF специального назначения. Через них передаются пераметры:
    RA - передача параметров
    RB - размер блока чтения/записи
    RC - зарезервирован
    RD - номер области для микросхем, имеющих несколько областей памяти, например, для микроконтроллеров.
    RE - глобальный код операции (1-READ,2-VERIFY,3-WRITE,4-USER)
    RF - полный размер памяти.

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

    Описание протокола состоит из нескольких секций, обязательными из них являются три: начальная, [READ] - чтение слова и [WRITE] - записи слова.

Кроме этого, дополнительно можно использовать необязательные секции:

[SETUP] - начальная установка, вызывается однократно при загрузке модуля
[INIT] - инициализация, вызывается однократно перед всеми операциями.
[WRITEINIT] - инициализации записи, вызывается один раз перед началом записи EEPROM.
[WRITEEND] - завершение записи, вызывается один раз после записи всех слов EEPROM.
[READBLOCK] - Чтение блока
[WRITEBLOCK] - Запись блока
[END] - завершение операции, вызывается один раз для любой операции.

    При необходимости могут быть описаны дополнительные пользовательские секции, которые вызываются однократно при выборе в меню. Их названия также записываются в скобках [].

! Можно использовать локальные секции (функции). Для описания функций перед именем добавляется символ '_' :

(*) [_START]

Функции должны быть описаны в модуле до их использования. Вызов функции осуществляется по имени:

(*) _START.

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

Секции чтения и записи вызываются при выполнении операций Read и Write для каждого слова.

В режиме чтения порядок вызова секций следующий:

[INIT]
FOR (ADR=0,ADR {
    [READ]
}
[END]

Порядок вызова секций в режиме записи:

[INIT]
[WRITEINIT]
FOR (ADR=0,ADR {
     [WRITE]
     IF (Проверка записи)
         [READ]
}
[WRITEEND]
[END]

Порядок вызова для пользовательских комманд: [INIT]
[USERSECTION]
[END]

В начальной секции описываются:

  • Входные и выходные сигналы для подключения к EEPROM (pins):
    (*) PINO=SCL,0 - Выход, SCL - имя сигнала, 0 - номер бита для драйвера
    (*) PINI=SDA,1 - Вход, SDA - имя сигнала, 1 - номер бита для драйвера

    Входные и выходные сигналы могут иметь одинаковые имена. Имена должны быть не длиннее восьми символов. Имена не могут совпадать с зарезервирован- ными ключевыми словами: "PINO","PINI","CDELAY","SOCKET","CONST","REG","LOOP","ADR","DATA" Символ # перед именем является признаком инверсии сигнала:

    (*) PINO=#DTA,0

    Дополнительно можно указать реальный вывод микросхемы, к которому подключен сигнал:

    (*) PINO=SDA,1,5

    Это необходимо для создания графического изображения микросхем, подключаемых через адаптеры.

  • Задержка после каждой операции установки пина (в микросекундах):

    (*) CDELAY=10

    Позволяет регулировать скорость обмена. Реальные задержки могут получаются насколько больше заданных.

  • Номер панельки для установки EEPROM (по схеме Orange-1)

    (*) SOCKET=1

    Если параметр SOCKET не указан, он считается равным 0. Можно создавать свои новые Socket, но для того, чтобы условное графическое изображение микросхемы отображалось в окне Chip Info, таблица выводов должна быть внесена в драйвер или описана в модуле.
  • ! Дополнительная информация о модуле, которая отображается в нижнем окне. Не более одной строки

    (*) INFO="Новый модуль"

  • ! Общее число выводов в корпусе EEPROM (по умолчанию - 8) (*) ALLPINS=14

  • ! Объявления регистров, доступных для просмотра и редактирования через меню (Buffer->Registers). Имена регистров не должны совпадать. Если регистры используются локально внутри секций, объявлять их не нужно.

    (*) R0=Protect - где "Protect" - имя регистра

    После имени регистра через запятую может быть указан режим отображения значения регистра: H - hex, D - Dec, B - Bin

    (*) R1=CODE,H

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

Краткое описание инструкций приведено ниже:

  • Установка пина константой, битом данных, адреса или регистра:
    (*) SDA=1
    (*) SDA=DATA[2]
    (*) SCL=ADR[3]
    (*) PIN=R2[3]

  • ! Проверка текущего состояния бита (линий ввода) или бита регистра R0-R7
    (*) DAT?1
    (*) R2[4]?0
    или всего регистра:
    (*) R4?0x1234

         Если после операции сравнения в скобках {} описан блок инструкций, то он выполняется при равенстве бита(регистра) и константы, иначе выполняется инструкция следующая за скобками. Если такой блок не описан, при несовпадении проверяемого значения выполнение операции прерывается с выводом сообщения "Error: Chip not respond!" и номером строки HPL файла, на котором произошла остановка.

    (*) R2[4]?0 {P1=0}, P2=1
    Если 4 бит регистра R2 равен 0, то выполняется инструкция P1=0, а потом P2=1, если бит равен 1 - то сразу P2=1

         Если перед сравниваемым числом стоит символ !, то условие меняется на противоположное. (Блок выполняется при несовпадении значений).

    (*) R2?!1234H {P1=0}
    Если R2 не равен 1234H, то выполняется инструкция P1=0, если R2 = 1234H, выполняется следующая инструкция.

  • Установка константы. Значения констант должны лежать в пределах 0...65535.
    (*) CONST=159

  • ! Операции с регистрами.

    1. Операции присвоения (копирования):
      Регистр-регистр (*) R2=R5
      Регистр-данные (*) R2=DATA
      Данные-регистр (*) DATA=R3
      Разрядность данных в зависимости от установленного типа микросхемы составляет 8 либо 16 бит.

    2. Арифметические и логические операции
      (В операциях может участвовать константа или другой регистр):
      установка "=" (*) R0=356H
      сложение "+" (*) R0=+123 ; R0=R0+123
      вычитание "-" (*) R0=-R1 ; R0=R0-R1
      умножение "*" (*) R0=*R1 ; R0=R0*R1
      деление "/" (*) R0=/5 ; R0=R0/5
      взятие остатка "%" (*) R0=%10 ; R0=R0%10
      циклический сдвиг "<<",">>" (*) R0=>>1 ; сдвиг R0 вправо на 1 разряд
      Логическое И - AND "&" (*) R0=&R2 ; R0=R0 and R2
      Логическое ИЛИ - OR "|" (*) R0=|R2 ; R0=R0 or R2
      Исключающее ИЛИ - XOR "^" (*) R0=^R2 ; R0=R0 xor R2

      В операциях деления и взятия остатка запрещено использовать константу 0 либо регистр, содержащий 0!

      3) Битовые операции с регистрами (*) R0[R1]=1 - бит регистра R0, равный R1 установить в 1
  • ! Циклы. Переменная циклов может быть 3 видов: адрес, данные чтения/записи и константа. Кроме того может быть описан универсальный цикл, без указания переменной, в этом случае доступ осуществляется через счетчик (индекс) цикла I. Универсальные циклы могут быть вложенными, во внутреннем цикле непосредственно доступен только счетчик внутреннего цикла. Для универсальных циклов границы могут быть также заданы через регистры. Для совместимости с будущими версиями рекомендуется использовать только универсальные циклы!

    Константа должна быть задана до начала цикла с помощью инструкции CONST Границы цикла должны лежать в пределах:
    0...32767 - для универсальных циклов
    0...32767 - для циклов CONST
    0...1023 - для циклов DATA
    0...31 - для циклов ADR
    При выполнении кода для универсальных циклов не контролируется выход индексов за пределы реального размера DATA, ADR и CONST.

    Скобки "{","}" ограничивают тело цикла.

    (*) LOOP=(15,0) {DI=R0[I],...}
    линия вывода DI поочередно принимает значения бит 15..0 значения регистра R0. (*) LOOP=(7,0) {DI=ADR[I],...} (*) LOOP=ADR(7,0) {DI=I,...} - старый вариант линия вывода DI поочередно принимает значения бит 7..0 текущего значения адресного слова.

    (*) LOOP=0,15) {DATA[I]=DO,..} (*) LOOP=DATA(0,15) {I=DO,..} - старый вариант поочередное считывание бит 0..15 слова данных с линии ввода DO.

    (*) R1=10H
    LOOP=(5,0) {D=R1[I],..}
    (*) CONST=10H
    LOOP=CONST(5,0) {D=I,..} - старый вариант линия вывода D поочередно принимает значения бит 5..0 константы (10H)

    (*) LOOP=(R1,R2) {R3[I]=DATA[I]}
    Копирование битов от R1 до R2 адресного слова в соответствующие биты регистра R3


    (*) LOOP=(0,7){ P1=0,LOOP=(6,1){P1=0,P1=1} }
    Вложенные циклы.

  • Задержка (в микросекундах). Значение задержки может быть в пределах 1мкс...65с.
    (*) P=200

  • Вывод сообщения. Вывод на экран окна с сообщением, строка должна быть заключена в кавычки. Внутри строки можно использовать стандартные модификаторы аналогичные используемым в языке C для printf(). (Для всех числовых аргументов необходим параметр l (long int)).

    X - шестнадцатеричное значение
    u - десятичное значение

    Транслятор не проверяет правильность передаваемых аргументов!

    (*) PRINT=("Hello, World")
    (*) PRINT=("Code=%04lX",R1) - Вывод значения регистра R1 в шестнадцатеричном виде - минимум 4 цифры.

    Можно также использовать дополнительные модификаторы, определяющие тип окна:
    E - Error - сообщение об ошибке
    (*) PRINT=E("Hello, Mr. Bug!")

    S - Status - запись в статусное окно
    (*) PRINT=S("Progress %03lu",R0)

    A - Ask - запрос подтверждения пользователя
    Значение возвращается в регистре RA (Ok=1,Cancel=0)
    PRINT=A("Are you ready ?")

  • Завершение текущей секции: EXIT

  • Запрет/Разрешение прерываний: IDISABLE/IENABLE Используются для выполнения критичных по времени операций.

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