Перейти к содержанию
    

Распаковка zip на стороне ATmega

Здравствуйте,

 

Прошиваю два Spartan3 с помощью AVR Atmega2561, последовательно, один за другим. Использую WinAVR 2010****. Прошивки для обеих ПЛИС компоную с прошивкой для ATmega. НО прошивки для ПЛИС со временем стали довольно большими и не влезают в 256 Кб для ATmega. Битовое сжатие не помогает.

 

Придёться сжимать и распаковывать их потом с помощью самого ATmega при программировании ПЛИС. Существуюит ли алгоритмы распаковки zip для ATmega или какие-то другие решения этой проблемы? То, что я находил в сети работет с файлами, а в ATmega файлов по сути никаких и нет.

 

Буду благодарен за любую предоставленную помощь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ещё 10 лет назад статьи видел, про сжатие прошивок конфигураций для ПЛИС.

И необязательно zip, ввиду специфики заливаемого массива можно применять простейшие методы (например, кодировать повторяющиеся серии нулей или единиц).

Тогда это было связано с дороговизной флеши.

А теперь?

Что мешает поставить сбоку флешку и лить из неё?

 

Кстати, файл - это всего лишь массив данных.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, 10+ лет назад это интенивно обсуждалось в PVT.HARDW.MAX2PLUS.

Не знаю, как у xilinx, у альтеры прошивки в HEX выглядят как «много нулей, проскакивают ненули». Весьма неплохо жмутся простейшими алгоритамми типа модифицированного packbits (повторяться массово может только 0, поэтому его не нужно сохранять). Для распаковки: «если старший бит байта 0, то скопировать столько байт со входа на выход, иначе выдать на выход столько нулей, сколько записано в младших семи битах»

 

Или с битовой картой - берём со входа байт, идём по его битам. Если 0 — выдаём на выход нулевой байт, если 1 — копируем на выход байт со входа (© Ivan Mak).

 

Жмут они похуже ZIP-а, но распаковщик занимает настолько меньше места, что для меги256 может оказаться по сумме выгоднее zip.

 

Cyclone альтеровские уже в себе имеют распаковщик какого-то RLE и Quartus при соответствующей галке генерирует сжатый поток, у спартана3 такого нет?

Впрочем, кажется, какой-то из алгоритмов для первого циклона жал лучше, чем штатный квартусовский. Зато тот можно в конфиг eeprom записать и циклон сам поймёт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У нас в похожей ситуации используется сжатие RLE, которое тут уже упоминалось. Альтернативным решением м.б использование другого (более простого/дешевого) МК и SPI Flash.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за ответы.

 

Что мешает поставить сбоку флешку и лить из неё?

То, что аппаратура уже какая есть.

 

Cyclone альтеровские уже в себе имеют распаковщик какого-то RLE и Quartus при соответствующей галке генерирует сжатый поток, у спартана3 такого нет?

В Spartran 3 есть сжатие битового потока, есть сжатие z для многоблочных PROM Xilinx. У меня стоит больше задача распаковать это на стороне ATmega. Буду благодарен на ссылки с алгоритмами. На счёт первого бита в байте не совсем понял -- что если он на чамом деел уже такой есть (не искуственно созданный).

 

У нас в похожей ситуации используется сжатие RLE, которое тут уже упоминалось. Альтернативным решением м.б использование другого (более простого/дешевого) МК и SPI Flash.

Другие МК уже не поставить. RLE попробую посмотреть.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

О первом бите — ну так мы его так сгенерировали. Пример:

Вход на упаковку

FA AC 11 00 00 00 00 00 00 00 04 18 21 E7 00 00 00 00 00 00 00 00 00 00 22 00 44 55 00 00 00 00 00 00 00 01

 

Выход упаковщика

03 FA AC 11 87 04 04 18 21 E7 8A 04 22 00 44 55 87 01 01

Оиночный 00, выдленный курсивом, не было смысла пускать как ноль. До двух нулей смысла нет.

 

Распаковщик

03 FA AC 11 — копируем три байта со входа на выход

87 — пишем на выход семь нулей

04 04 18 21 E7 — копируем четыре байта со входа на выход

8A — пишем на выход десять нулей

04 22 00 44 55 — копируем четыре байта со входа на выход

87 — пишем на выход семь нулей

01 01 — копируем один байт со входа на выход

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Использую PackBits. На машине упаковка и распаковка работают нормально. При программировании AVR, тестовый у ПЛИС светодиод не мигает, т.е. ПЛИС программируется неправильно.

 

В чём может быть дело?

 

Процедура программирования ПЛИС несжатой прошивкой.

void FPGA_sendfile(uint_farptr_t buf, uint32_t buf_len)
{
  unsigned char i;
  uint32_t l;
  uint8_t c;

  for (l = 0; l < buf_len; l ++) // buf_len-1
   {
    c = pgm_read_byte_far(buf + l);
    for (i = 0;i < 8;i ++)
     {
        if ((c & 0x80)>0) SET_XSP_DIN;
        else CLEAR_XSP_DIN;
        CLEAR_XSP_CLK;
        c<<=1;
        SET_XSP_CLK;
     }
    }  
  SET_XSP_DIN;
}

 

Процедура программирования ПЛИС сжатой прошивкой.

void FPGA_sendpackedfile(uint_farptr_t buf, uint32_t buf_len)
{
  unsigned char i;
  uint32_t L;
//  uint8_t c;

  int32_t countChar;                      /* run/copy count */
  uint8_t c;                       /* current character */

  L =  - 1;
  while(L <= buf_len - 1) // - 2?
    {
      L += 1;
      countChar = (int32_t) pgm_read_byte_far(buf + L);

      if (countChar < 0)
    {
      /* we have a run write out  2 - countChar copies */
      countChar = (MIN_RUN - 1) - countChar;

      L += 1;

      while (countChar > 0)
        {
          c = pgm_read_byte_far(buf + L);
          for (i = 0;i < 8;i ++)
        {
          if ((c & 0x80)>0) SET_XSP_DIN;
          else CLEAR_XSP_DIN;
          CLEAR_XSP_CLK;
          c <<= 1;
          SET_XSP_CLK;
        }
          countChar--;
        }
    }
      else
    {
      /* we have a block of countChar + 1 symbols to copy */
      for (countChar++; countChar > 0; countChar--)
        {
          L += 1;
          c = pgm_read_byte_far(buf + L);

          for (i = 0; i < 8; i ++)
        {
          if ((c & 0x80)>0) SET_XSP_DIN;
          else CLEAR_XSP_DIN;
          CLEAR_XSP_CLK;
          c <<= 1;
          SET_XSP_CLK;
        }
        }
    }
    }
  SET_XSP_DIN;
}

 

Не пойму, где тут мог намудрить. Я прикрепил проект для тестирования упаковки/распаковки на инструментальной системе и проект для программирования целевой. Буду благодарен за советы и помощь.

 

packbits.zip

sp_control.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно делать и прямую распаковку. Там тоже ничего сложного нет, но вам понадобится довольно много озу, для формирования словаря. Иногда делают с предустановленным фиксированным словарём, тогда эффективность несколько ниже, но приведенные последовательности исключительно хорошо будет сжимать/разжимать. Прямой метод LZH даст эффективность ~ 80-90% от ZIP сжатия.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

  int32_t countChar;

Зачем 32 бита? У вас максимальный счетчик - 128

     countChar = (int32_t) pgm_read_byte_far(buf + L);
      if (countChar < 0)

Если pgm_read_byte_far возвращает беззнаковый char то работать не будет

    countChar = (MIN_RUN - 1) - countChar;

Это вообще не понял - там счетчик в чистом виде: countChar &= 0x7F;

     while (countChar > 0)
        {
          c = pgm_read_byte_far(buf + L);

А вот это ошибка - мы 0 должны выводить, а не содержимое следующего байта флеша:

     while (countChar > 0)
        {
          c = 0;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я делал сжатие несколько иначе - последовательность нулевых байтов заменялась одним нулевым байтом и следующим байтом, задающим количество нулевых байтов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

  int32_t countChar;

Зачем 32 бита? У вас максимальный счетчик - 128

На самом деле 129. Можно обойтись и 16-тью.

     countChar = (int32_t) pgm_read_byte_far(buf + L);
      if (countChar < 0)

Если pgm_read_byte_far возвращает беззнаковый char то работать не будет

Как тогда быть? Что использовать вместо pgm_read_byte_far?

    countChar = (MIN_RUN - 1) - countChar;

Это вообще не понял - там счетчик в чистом виде: countChar &= 0x7F;

 

     while (countChar > 0)
        {
          c = pgm_read_byte_far(buf + L);

А вот это ошибка - мы 0 должны выводить, а не содержимое следующего байта флеша:

 

     while (countChar > 0)
        {
          c = 0;

Я брал код отсюда (PackBits Variant): http://michael.dipperstein.com/rle/index.html

На инструментальной системе всё работает, поэтому на сам алгоритм я не особо грешу, а вот на реалтзацию для avr...

Надеюсь на вашу дальнейшую помощь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как тогда быть? Что использовать вместо pgm_read_byte_far?
Его и использовать. Приведение типа неправильное, должно быть countChar = (unsigned char) pgm_read_byte_far(buf + L);

Я брал код отсюда (PackBits Variant)
Пардон, я думал, что вы реализовали алгоритм от ReAl (он сюда подходит гораздо лучше)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приведение типа неправильное, должно быть countChar = (unsigned char) pgm_read_byte_far(buf + L);

pgm_read_byte и так по умолчанию uint8_t возвращает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пардон, я думал, что вы реализовали алгоритм от ReAl (он сюда подходит гораздо лучше)

Я на ACEX1K30..1K50 когда-то давно сверял, c битовой картой © Ivan Mak вроде бы чуть лучше работал.

А я просто по быстрячку Macintosh PackBits модифицировал под случай, когда массово повторяться может только 0, поэтому его нет смысла и писать в выходной поток.

 

Как тогда быть? Что использовать вместо pgm_read_byte_far?
У Вас в массиве во флеше записаны знаковые байты. Значит, нужно возврат pgm_read_byte_far приводить к знаковому байту.

   int8_t counter;
   counter = (int8_t)pgm_read_byte_far( ptr );

 

Я пользовался не знаковым числом, а флагом в старшем бите беззнакового 8-битного числа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я на ACEX1K30..1K50 когда-то давно сверял, c битовой картой © Ivan Mak вроде бы чуть лучше работал.

Не могли бы вы показать, во что превратится код из примера в сообщении №6, закодированный © Ivan Mak, а то из вашего описания я не понял, как он работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...