Виртуальная машина для ардуино?

Тема в разделе "Флудилка", создана пользователем valeraba, 27 авг 2018.

  1. DIYMan

    DIYMan Guest

    По соотношению - такая же зависимость, как под Uno, т.е. накладные расходы в процентах - одинаковы. Всё, мозги размяли, можно выдыхать :)

    Ессно, задача написания полноценного (более-менее) интерпретатора байт-кода - дело непростое. Но, опять же - имею своё мнение о том, что - задачи надо решать по мере поступления, и не пытаться впихнуть невпихуемое сразу и везде. Да, архитектуру парсера и представления байт-кода - продумывать надо, безусловно, но: также стоит отталкиваться и от задачи; вполне вероятно, что для какой-то конкретной задачи - можно родить интерпретатор, который устроит, и не будет при этом обобщённым по самое не балуй. В приведённом примере - достаточно расширить поддерживаемые команды на ещё один блок, например, вывод в Serial - и будет щастье в виде вывода в Serial. Сейчас изображу...
     
    Последнее редактирование модератором: 28 сен 2018
  2. parovoZZ

    parovoZZ Гуру

    вам заняться нечем?
     
  3. DIYMan

    DIYMan Guest

    Вот, собственно - новая команда: напечатать в Serial переданный текст:
    Код (C++):
    //--------------------------------------------------------------------------------------------------------------------------------
    typedef enum
    {
      incrementForBlock,
      endForBlock,
      pinWriteBlock,
      serialPrintBlock,
     
    } BlockType;
    //--------------------------------------------------------------------------------------------------------------------------------
    uint8_t block[] = {
        incrementForBlock, // это цикл for c инкрементом
        0x03, 0xE8, // 1000 проходов
        1, // шаг инкремента

        // тут тело цикла
       
          pinWriteBlock, // пишем в пин
          13, // номер пина
          HIGH, // уровень

          serialPrintBlock, // выводим в Serial
          'H', 'e', 'l', 'l', 'o', '\n', '\0',

          pinWriteBlock, // пишем в пин
          13, // номер пина
          LOW, // уровень
         
        // конец тела цикла

        endForBlock // цикл for закончился
    };
    //--------------------------------------------------------------------------------------------------------------------------------
    uint16_t executePinWriteBlock(uint8_t* bytecode)
    {
      bytecode++; // пропустили идентификатор блока (pinWriteBlock)
     
      //Serial.println(*bytecode);
      //Serial.println(*(bytecode+1));
     
      digitalWrite(*bytecode, *(bytecode+1));

      return 3; // возвращаем длину блока
    }
    //--------------------------------------------------------------------------------------------------------------------------------
    uint16_t executeSerialPrintBlock(uint8_t* bytecode)
    {
      bytecode++; // пропустили идентификатор блока (serialPrintBlock)
      uint16_t len = 2;

      while(*bytecode != '\0')
      {
        Serial.print((char)*bytecode++);
        len++;
      }

      return len;
    }
    //--------------------------------------------------------------------------------------------------------------------------------
    void executeIncrementForBlock(uint8_t* bytecode)
    {
      bytecode++; // пропустили идентификатор блока (incrementForBlock)
     
      uint16_t passes = (*bytecode++ << 8) | (*bytecode++);
      uint8_t increment = *bytecode++;
     
      Serial.print(F("Passes: ")); Serial.println(passes);
      Serial.print(F("Increment: ")); Serial.println(increment);

      uint32_t start = millis();

      uint8_t* startCode = bytecode;
      bool canExitWhile = false;
     
      for(uint16_t i=0;i<passes;i+=increment)
      {
        canExitWhile = false;
       
        while(!canExitWhile) // шаримся по блокам тела цикла
        {
          switch(*startCode)
          {
            case pinWriteBlock:
              startCode += executePinWriteBlock(startCode);
            break;

            case serialPrintBlock:
              startCode += executeSerialPrintBlock(startCode);        
            break;
     
           case endForBlock:
            //Serial.println("BEGIN");
            startCode = bytecode;
            canExitWhile = true;
           break;
     
           default:
            //Serial.println("!!!!!");
           break;
          } // switch
         
        } // while

      } // for

      uint32_t end = millis();
      uint32_t elapsed = end - start;

      Serial.print(F("Count passes: "));
      Serial.println(passes);
      Serial.print(F("Elapsed time, ms: "));
      Serial.println(elapsed);
      float hz = (1.0/elapsed)*1000*passes;
      Serial.print(F("Frequency: "));
      Serial.println(hz);
     
    }
    //--------------------------------------------------------------------------------------------------------------------------------
    void setup()
    {
      Serial.begin(57600);
     
      pinMode(13,OUTPUT);

      uint16_t passes = 1000;
      uint32_t start = millis();
     
      for(uint16_t i=0;i<passes;i++)
      {
        digitalWrite(13,HIGH);
        digitalWrite(13,LOW);
      }

      uint32_t end = millis();
      uint32_t elapsed = end - start;

      Serial.print(F("Count passes: "));
      Serial.println(passes);
      Serial.print(F("Elapsed time, ms: "));
      Serial.println(elapsed);
      float hz = (1.0/elapsed)*1000*passes; // сколько раз за секунду выполнится тело цикла
      Serial.print(F("Frequency: "));
      Serial.println(hz);

      Serial.println();
      Serial.println("BYTE CODE TEST: ");
      Serial.println();

      executeIncrementForBlock(block);

    }
    //--------------------------------------------------------------------------------------------------------------------------------
    void loop()
    {
      // put your main code here, to run repeatedly:

    }
    //--------------------------------------------------------------------------------------------------------------------------------
     
    Так что - узкоспециализированный/не узкоспециализированный, но - под свои задачи всегда можно написать достаточно эффективный инструмент, в принципе.
     
  4. DIYMan

    DIYMan Guest

    Да, плюшками балуемся.
     
  5. Mitrandir

    Mitrandir Гуру

    Помню на третьем курсе писал курсовую, автоматический пререводчик с одного языка программирования на другой. Хоть с русского на с++. Требования для конвертации: наличие интерпретатора исходного языка на целевом. Конечно о оптимальности и быстродействии полученного кода речи не шло. Увы за давностью лет разработки утеряны.
     
    Igor68 и DIYMan нравится это.
  6. А это вообще возможно? Контрпример: на си есть функция, обрабатывающая массив произвольной длины и нужно перевести ее на паскаль.
     
  7. valeraba

    valeraba Нерд

    Виртуальная машина моего ПЛК не умеет работать с периферией микраша напрямую. Скрипт работает только с параметрами общей системы, состоящей из множества устройств и подключённых к общей информационной шине.
    [​IMG]
    Поэтому поиск в словаре устройства нужного параметра по его уникальному имени не так быстр.
    Каждый раз, после прогона скрипта, все параметры изменившие своё значения, автоматически уходят на сервер и записываются в базу данных.

    Скрипт может использовать как параметры собственного устройства, так и других устройств, подключенных к общей системе. ПЛК может отслеживать любые параметры системы и воздействовать на собственные параметры.

    Если бы я напрямую дрыгал ножкой микраша, то это было бы много быстрее. Но передо мной стояла другая задача, а именно, нужно было наладить взаимодействие различных устройств друг с другом через пользовательские скрипты.
     
    Igor68 нравится это.
  8. DIYMan

    DIYMan Guest

    Как ищете? Применяете ли хэширование? По строкам сравнивать - не очень, ессно.
     
  9. valeraba

    valeraba Нерд

    Нет, хэширование не применяю, поэтому эта операция жутко дорогая. Да пока и не нужно было особого быстродействия, поэтому оптимизацию не делал. Когда я на реле подавал килогерцы, оно только еле слышно пищит, к сожалению, реле в sonoff не твердотельные.
     
  10. Mitrandir

    Mitrandir Гуру

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

    Увы подробностей мало помню. Прошло более 10 лет
     
    Последнее редактирование: 28 сен 2018
  11. DIYMan

    DIYMan Guest

    Не дороже, чем каждый раз строки сравнивать ;) Подготовили map, потом быренько раз - и тыркнулись туда, куда надо. Впрочем, дело хозяйское ;)
     
  12. valeraba

    valeraba Нерд

    А моя виртуалка не боится рекурсий. Вот скрипт вычисления факториала:
    [​IMG]
    А вот ассемблерный код этого скрипта для моей виртуалки.
    Код (Text):
    shift -1
    ldi 10
    call factorial, 1
    print
    exit
    :factorial
    ld_arg 0
    ldi 1
    gt
    je 8
    ld_arg 0
    ld_arg 0
    ldi 1
    sub
    call factorial, 1
    mul
    ret
    ldi 1
    ret
     
    Сам байткод составил 49 байт. Могло бы быть и меньше при использовании целочисленной арифметики, но моя виртулка использует везде именно дробную арифметику.

    Безусловно так, у меня например указатели функций всех инструкций лежат в одной таблице, дабы не делать полную проходку в поисках нужной функции через switch(). Ведь у меня их сейчас аж 37 ассемблерных инструкций.
     
    DIYMan нравится это.
  13. Mitrandir

    Mitrandir Гуру

    DIYMan нравится это.
  14. DIYMan

    DIYMan Guest

    Вот, оттуда, о чём я и говорил неоднократно ;):
     
    Mitrandir нравится это.
  15. parovoZZ

    parovoZZ Гуру

    А как вашими байт-кодами настроить таймер? Или настроить периферию в стм32 не прибегая к таким старомодным вещам, как cubemx?
     
  16. Mitrandir

    Mitrandir Гуру

    Ввести соответствуещие байткоды в язык.
     
  17. parovoZZ

    parovoZZ Гуру

    а напрямую нельзя? Зачем лишняя сущность?
     
  18. Mitrandir

    Mitrandir Гуру

    Хотябы чтобы кросплатформенность сделать
     
  19. DIYMan

    DIYMan Guest

    Щас паровоз затянется глубоко, и, шумно выдохнув и прищурив правый глаз, с видом побитого жизнью гуру ехидно спросит:
    :D:D:D
     
    parovoZZ и Mitrandir нравится это.
  20. parovoZZ

    parovoZZ Гуру

    да вообще не угадал))
    Мне кажется, вы все идете не туда. Для чего в MCU тянуть технологии, которые предназначены для MPU?
    Между AVR и ARM? Я правильно понял?