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

Просмотр и проверка файлов прошивки Intel HEX, S-record и BIN

Вставьте текст файла прошивки или откройте .hex, .s19 или .bin — инструмент разберёт каждую запись, сверит длину и контрольную сумму, покажет карту памяти с промежутками и перекрытиями, hex-дамп образа, размер прошивки и CRC-32. Здесь же файл можно перевести из HEX в S-record или BIN и обратно и исправить испорченные контрольные суммы. Всё считается в браузере: файл никуда не отправляется.

Исходные данные

или пример:

Вставьте текст, откройте файл .hex, .s19 или .bin или перетащите его сюда. Файл не покидает браузер.

HEX

стёртая флеш-память — FF

Результат

Размер прошивки
24 байта
данные с 0x0000 по 0x0017, 1 диапазон
Формат
Intel HEX, 16-битные адреса3 записи, с данными 2
Проверка записей
ошибок нет
CRC-32 образа
0xEF3FD8CA24 байта от 0x0000, промежутки — FF: как у файла .bin
Сумма байтов
0x69 · 0x0E698 и 16 бит, по тому же образу

Записи: 3

  • :начало записи
  • ■длина
  • ■адрес
  • ■тип
  • ■данные
  • ■контрольная сумма
СтрокаЗаписьТипАдрес или значениеСумма: в файле / верная
1:10000000259A1D9A29E236E940E84A95F1F73A959200 данные0x0000, 16 байт92 / 92
2:08001000D9F72A95C1F7F5CFDD00 данные0x0010, 8 байтDD / DD
3:00000001FF01 конец файлаконец файлаFF / FF

Карта памяти

ЧтоНачалоКонецРазмер
данные0x00000x001724 байта
Всего данных24 байта

Hex-дамп образа

HEX
000025 9A 1D 9A 29 E2 36 E9 40 E8 4A 95 F1 F7 3A 95|%...).6.@.J...:.|
0010D9 F7 2A 95 C1 F7 F5 CF |..*..... |

Слева адрес, затем 16 байтов и их символы ASCII; точка — непечатный байт. Бледные байты — заполнение промежутков, целые строки промежутка свёрнуты.

Преобразовать и скачать

Формат
Данных в записи
:10000000259A1D9A29E236E940E84A95F1F73A9592
:08001000D9F72A95C1F7F5CFDD
:00000001FF

Записи как у GNU objcopy: строки CRLF, запись не пересекает границу 64 КБ, база ниже 1 МБ задаётся записью 02, выше — записью 04, стартовый адрес сохраняется.

Расчёт выполнен по формулам и данным из источников, приведённых на этой странице, и не заменяет проверку: параметры компонентов у разных производителей и даже партий различаются. Перед применением сверяйте результат с документацией на конкретные детали.

Файлы прошивки чаще всего приходят в одном из двух текстовых форматов. Intel HEX придумала Intel для программаторов ПЗУ. Его выдаёт утилита objcopy из GNU Binutils — avr-objcopy в Arduino IDE, arm-none-eabi-objcopy в STM32CubeIDE, — а также Keil и IAR; читают его avrdude, STM32CubeProgrammer и почти любой программатор. Motorola S-record (файлы .s19, .s28, .s37, .srec, .mot) — формат Motorola, привычный для микроконтроллеров NXP и Renesas. Оба описывают одно и то же: какие байты по каким адресам записать. Третий вариант — двоичный образ .bin без адресов и проверок.

Как пользоваться

  1. Вставьте текст файла в поле, откройте файл кнопкой или перетащите его на панель. Кнопки примеров подставят прошивку AVR, начало образа STM32, тот же код в S-record и файл с ошибками.
  2. Под панелью появятся ошибки и замечания, таблица записей с раскрашенными полями, карта памяти и hex-дамп.
  3. Для файла .bin задайте адрес, с которого он пишется в память: у STM32 это 08000000.
  4. Чтобы сравнить прошивку с объёмом памяти, выберите плату или микроконтроллер.
  5. В блоке «Преобразовать и скачать» выберите формат и скачайте файл. Если в файле неверные контрольные суммы, в блоке ошибок появится кнопка их исправления.

Как устроена запись Intel HEX

Каждая строка — одна запись. Она начинается с двоеточия, дальше идут байты, записанные парами шестнадцатеричных цифр, старшая цифра первой:

ПолеСимволовЧто содержит
Начало1двоеточие «:»
Длина2число байтов в поле данных, от 00 до FF
Адрес416-битное смещение первого байта данных, старший байт первым
Тип2что это за запись, от 00 до 05
Данные2 на байтданные или параметры записи
Контрольная сумма2дополнение суммы предыдущих байтов до нуля

Типов записей шесть:

ТипНазваниеДанныеЧто делает
00данныебайты прошивкикладёт байты с адреса базы + смещение
01конец файланетзавершает файл, всегда :00000001FF
02расширенный адрес сегмента2 байтабаза = значение × 16, адреса до 0x10FFEF — чуть больше 1 МБ
03стартовый адрес CS:IP4 байтаточка входа для 8086
04расширенный линейный адрес2 байтастаршие 16 бит адреса, до 4 ГБ
05стартовый линейный адрес4 байтаточка входа, 32 бита

Поле адреса в записях 01–05 не используется и заполняется нулями. Записи 03 и 05 программатору не нужны — он пишет только данные, — но objcopy переносит в них точку входа из ELF-файла: в HEX загрузчика Arduino есть запись 03 с адресом 0000:7E00, а в прошивке STM32 запись 05 указывает на обработчик сброса.

Контрольная сумма: пример вручную

Возьмём вторую строку примера AVR: :08001000D9F72A95C1F7F5CFDD.

ПолеБайтыСумма нарастающим итогом
Длина0808
Адрес00 1018
Тип0018
ДанныеD9 F7 2A 95 C1 F7 F5 CF623

Младший байт суммы — 23. Контрольная сумма — его дополнение до 100: 100 − 23 = DD, как и записано в конце строки. Проверяют наоборот: сумма всех байтов записи вместе с контрольной должна оканчиваться на 00 — 623 + DD = 700. Восемь байтов данных начинаются с адреса 0010, значит, запись занимает 0010–0017.

Контрольная сумма ловит одиночную испорченную цифру, но не перестановку байтов и не потерю целой строки. Запись конца файла выдаёт только обрыв в конце, а пропавшую строку в середине покажет лишь CRC образа, если есть эталонное значение — например, опубликованное вместе с прошивкой.

Адрес: 16 бит, сегменты и линейная база

Поле адреса в записи данных — всего 16 бит. Файл без записей 02 и 04 описывает первые 64 КБ: этого хватает ATmega328P с его 32 КБ флеш-памяти. Для больших адресов перед записями данных ставят запись базы:

A=база+смещение+i,база={USBA⋅16после записи 02ULBA⋅65536после записи 04A = \text{база} + \text{смещение} + i, \qquad \text{база} = \begin{cases} \text{USBA} \cdot 16 & \text{после записи 02} \\ \text{ULBA} \cdot 65536 & \text{после записи 04} \end{cases}

Здесь i — номер байта в записи. База действует, пока её не сменит следующая запись 02 или 04. Примеры:

Запись базыСмещениеАдрес байтаГде встречается
:020000021200EA24620x00014462пример Keil
:020000023000CCE0000x0003E000загрузчик Arduino Mega 2560
:02000004FFFFFC24620xFFFF2462пример Keil
:020000040800F200000x08000000начало флеш-памяти STM32

Записи различаются переносом. После записи 02 смещение заворачивается внутри 64-килобайтного сегмента: байт за FFFF ложится в начало того же сегмента. После записи 04 адрес просто продолжается и заворачивается только за FFFFFFFF. GNU objcopy таких записей не создаёт — он обрывает запись на границе 64 КБ и ставит новую базу: ниже 1 МБ — записью 02, выше — записью 04. Если в одном файле встречаются и 02, и 04, objcopy при чтении складывает обе базы; так же считает пример в документе Intel о формате HEX-32. Инструмент делает так же и предупреждает: другие программы могут взять только последнюю базу.

Формат Motorola S-record

S-запись начинается с буквы S и цифры типа, за ними пары шестнадцатеричных цифр:

ПолеСимволовЧто содержит
Тип2S0…S9
Длина2число байтов после этого поля: адрес, данные и контрольная сумма
Адрес4, 6 или 816, 24 или 32 бита, по типу записи
Данные2 на байтданные или текст заголовка
Контрольная сумма2дополнение до единицы младшего байта суммы длины, адреса и данных
ТипАдресНазначение
S016 бит, обычно 0000заголовок: имя модуля или любой текст, например «HDR»
S1, S2, S316, 24, 32 битаданные
S5, S616, 24 битачисло записей S1–S3 перед ней, необязательная; S6 — позднее расширение
S7, S8, S932, 24, 16 битконец блока S3, S2, S1 и стартовый адрес

Главное отличие от Intel HEX — адрес полной длины прямо в каждой записи данных и другое правило контрольной суммы: не дополнение до нуля, а инверсия младшего байта суммы. Для S9030000FC сумма 03 + 00 + 00 = 03, а FF − 03 = FC. Отличие в длине: поле длины в S-записи считает и адрес с контрольной суммой, а в Intel HEX — только данные. Завершающая запись S7 по описанию Motorola закрывает блок S3, S8 — блок S2, S9 — блок S1, но S7 и S8 нужны, только когда стартовому адресу не хватает двух байтов; иначе любой блок закрывают записью S9. Поэтому S9 после S3 законна, а S7 после S1 инструмент лишь отмечает как необычную. Запись S4 не определена.

Карта памяти, дамп и двоичный образ

Записи не обязаны идти по порядку и подряд. Инструмент собирает их в непрерывные диапазоны. Между диапазонами остаются промежутки: в hex-дампе и в файле .bin они заполняются байтом FF — так выглядит стёртая флеш-память. Байт заполнения можно сменить, например на 00 для образа ПЗУ.

Если две записи пишут в один адрес, в образ попадает более поздняя — так поступит программатор, записывая строки по очереди. Перекрытие с разными байтами — ошибка: обычно это два HEX-файла, склеенные вручную, или прошивка, наложенная на загрузчик по неверному адресу. Перекрытие с одинаковыми байтами безвредно, но тоже отмечается.

CRC-32 и суммы байтов считаются по тому же образу, что лёг бы в файл .bin: от первого адреса с данными до последнего, с заполнением промежутков. Это CRC-32 в варианте ZIP (CRC-32/ISO-HDLC) — та же, что у архиватора zip и функции zlib.crc32 в Python; команда POSIX cksum по умолчанию считает другой CRC. Другой алгоритм или диапазон — например, блок CRC микроконтроллера — подберите в калькуляторе CRC.

При переводе в Intel HEX инструмент пишет файл так же, как GNU objcopy: по 16 байт в записи (можно 32), строки CRLF, база ниже 1 МБ — записью 02, выше — записью 04, стартовый адрес сохраняется. Загрузчики Arduino optiboot и stk500v2 из ArduinoCore-avr после разбора и обратной записи совпадают с исходными файлами байт в байт. S-записи получают тип по наибольшему адресу данных и стартовому адресу: S1 до FFFF, S2 до FFFFFF, S3 выше. Заголовок S0 исходного S-record переносится байт в байт; при переводе из HEX или BIN в него пишется имя файла, если оно латиницей, иначе «HDR».

Размер прошивки и объём флеш-памяти

Размер прошивки — число байтов с данными, без промежутков и без повторов при перекрытии. Arduino IDE после компиляции сообщает ту же величину: сумму секций .text и .data, которые попадают в HEX; EEPROM уходит в отдельный файл .eep.

Сравнивать её надо не со всем объёмом флеш-памяти, а с доступным: загрузчик занимает её конец. По boards.txt ядра Arduino AVR скетчу на Arduino Uno доступно 32 256 байт из 32 768 (512 байт у optiboot), на Nano — 30 720 (под загрузчик отведено 2 КБ), на Mega 2560 — 253 952 из 262 144. Выберите плату в списке — инструмент покажет процент, как Arduino IDE, и предупредит, если данные залезают в область загрузчика или за пределы памяти. Объёмы памяти микроконтроллеров в том же списке взяты из данных атласа: описаний устройств Microchip для ATmega328P, ATmega8, ATtiny85 и ATtiny13A и базы STM32CubeMX для STM32F103C8, STM32F401CC и STM32F411CE. Файл «with_bootloader» из Arduino IDE и сам загрузчик лежат там законно. Подробнее о загрузчиках — в глоссарии, о прошивке без них — на странице avrdude.

Для STM32 важен ещё и адрес: флеш-память начинается с 0x08000000. Если в файле нет записи 04 и данные начинаются с нуля, программатор либо откажется писать, либо запишет их в другое место. Как устроены флеш-память, загрузчик и защита STM32 — на странице о флеш-памяти STM32.

Типичные ошибки

  • Неверная контрольная сумма. Строку правили вручную или файл испортился при передаче. Инструмент покажет записанную и верную сумму и, если длина записи совпадает с числом байтов, исправит её. Если не совпадает и длина — байты потеряны, и новая сумма лишь скроет это.
  • Нет записи конца файла. Файл оборвался при копировании или склеивании. Часть программаторов отказывается от такого файла, часть молча пишет неполную прошивку.
  • Записи после конца файла. Обычно это два файла, склеенные без удаления строки :00000001FF в конце первого. Программаторы обычно читают только первый.
  • Перекрывающиеся записи. Две части прошивки претендуют на один адрес. Чаще всего это прошивка, собранная для другого начального адреса, или повторно вставленный кусок.
  • 16-битный адрес вместо 32-битного. Прошивка STM32 без записи 04 окажется по адресу 0x00000000 вместо 0x08000000. Запись 04 в файле для AVR сама по себе не ошибка: если не исключить секции .eeprom, .fuse и .signature ключами -R, avr-objcopy кладёт их в HEX по адресам 0x810000 и выше, а прошивка ATmega2560 выходит за 64 КБ, и некоторые программы адресуют её записью 04 вместо 02. Насторожить должен диапазон, которого у выбранного микроконтроллера нет: его покажут карта памяти и сравнение с объёмом флеш-памяти.
  • Строчные буквы и пустые строки. Спецификация пишет цифры заглавными, но большинство программ понимает и строчные; пустые строки пропускаются. Инструмент отмечает это как замечание, не как ошибку.

Конфиденциальность

Файл читается и разбирается в браузере, на сервер ничего не передаётся, а в адресе страницы сохраняются только настройки — байт заполнения, адрес .bin, выбранная плата, формат вывода и число байтов в записи.

Частые вопросы

Как узнать размер прошивки по HEX-файлу?

Не по размеру файла. В Intel HEX каждый байт записан двумя символами, а у строки есть ещё двоеточие, длина, адрес, тип, контрольная сумма и перевод строки: строка с 16 байтами данных занимает 45 символов, и файл в 2,8 раза больше прошивки. Размер прошивки — сумма длин записей данных без перекрытий. Инструмент показывает её первой строкой результата; для скетча Arduino это то же число, что пишет Arduino IDE после компиляции, — сумма секций .text и .data.

Чем HEX отличается от BIN?

BIN — точная копия памяти без адресов: первый байт файла ложится по адресу, который указывают программатору, промежутки заполнены. HEX хранит адрес каждой записи и контрольные суммы, поэтому в одном файле могут быть несвязанные области — например, прошивка и загрузчик, — а повреждение строки заметно. Для STM32 BIN обычно пишут с адреса 0x08000000, для AVR — с нуля.

Как посчитать контрольную сумму строки Intel HEX?

Сложите все байты строки после двоеточия, кроме последнего: длину, два байта адреса, тип и данные. Возьмите младший байт суммы и вычтите его из 100 (в шестнадцатеричной записи). Для :0400000508000009 сумма 04 + 05 + 08 + 09 = 1A, а 100 − 1A = E6. Проверка обратная: сумма всех байтов вместе с контрольной должна оканчиваться на 00.

Что означает строка :020000040800F2?

Это запись типа 04 — расширенный линейный адрес. Её два байта данных 08 00 становятся старшими 16 битами адреса всех следующих записей данных: запись с адресом 0000 ляжет по 0x08000000, где у STM32 начинается флеш-память. Без такой записи файл адресует только первые 64 КБ.

Программатор пишет, что в HEX-файле ошибка контрольной суммы. Что делать?

Вставьте файл в инструмент — он покажет номер строки, сумму в файле и верную. Обычно строку испортили при ручной правке, копировании через буфер или пересылке. Если данные правили намеренно, кнопка «Исправить контрольные суммы» пересчитает их. Если вместе с суммой не сходится и поле длины — у записи потерялся или прибавился байт, — пересчитывать сумму нельзя: надо заново собрать или скачать прошивку.

Почему CRC-32 файла не совпадает с тем, что показывает программатор?

CRC зависит от того, какие байты в неё вошли. Здесь CRC-32 считается по образу от первого до последнего адреса с заполнением промежутков — как у файла .bin. Программатор может считать по всей флеш-памяти, с другим байтом заполнения или другим алгоритмом: блок CRC в STM32 по умолчанию даёт CRC-32/MPEG-2, а не «обычный» CRC-32 из ZIP. Совпадающий диапазон и алгоритм подберите в калькуляторе CRC.

Источники

  1. Intel. Hexadecimal Object File Format Specification, Revision A, 6 января 1988 — архивная копия официального файла Intel: поля записи, типы 00–05, правило контрольной суммы, адрес для записей 02 и 04 с переносом по модулю 64 КБ и 4 ГБ — эталоны тестов
  2. Intel. Data-File Conversion to INTEL HEX-32 Format (сервис Zapcode), 2000 — архивная копия документа с intel.com: пример сложения баз записей 04 и 02, адрес 0x010930F0; контрольные суммы в его примере напечатаны неверно — тест это проверяет
  3. Keil (Arm). Knowledgebase 1584: GENERAL: INTEL HEX FILE FORMAT — архивная копия: разобранная запись данных, адреса FFFF2462 и 00014462, запись 05, пример файла — эталоны тестов
  4. Motorola. M68000 Family Programmer's Reference Manual, 1992 (NXP M68000PRM), приложение C «S-Record Output Format» — поля S-записи, типы S0–S9, контрольная сумма как дополнение до единицы, пример модуля на с. C-3 — эталон тестов
  5. P. Miller. SRecord 1.65: srec_motorola(5) — записи-счётчики S5 и S6, пример файла с S5
  6. GNU Binutils 2.45: bfd/ihex.c и bfd/srec.c — как objcopy пишет Intel HEX: по 16 байт, CRLF, запись не пересекает границу 64 КБ, база ниже 1 МБ — записью 02, выше — 04; при чтении базы 02 и 04 складываются. S-записи: по 16 байт, тип S1/S2/S3 по адресам данных, в S0 — имя файла до 40 символов
  7. Arduino. ArduinoCore-avr, коммит 11b9130: загрузчики optiboot и stk500v2, boards.txt, platform.txt — HEX-файлы загрузчиков от avr-objcopy — эталоны тестов (обратная запись байт в байт); upload.maximum_size: Uno 32 256, Nano 30 720, Mega 2560 253 952 байт; размер скетча = .text + .data
  8. Microchip. ATmega Series Device Support (ATmega_DFP) 3.6.299 и ATtiny Series Device Support (ATtiny_DFP) 3.4.278, файлы описания устройств atdf — объём флеш-памяти ATmega328P, ATmega2560, ATmega8, ATtiny85 и ATtiny13A в списке для сравнения — из данных атласа GAW, собранных из этих паков
  9. STMicroelectronics. STM32_open_pin_data (база STM32CubeMX 6.18.0), коммит 7d1f151 — объём флеш-памяти STM32F103C8 (64 КБ), STM32F401CC (256 КБ) и STM32F411CE (512 КБ) — из данных атласа GAW
  10. STMicroelectronics. PM0075 Rev 2. STM32F10xxx Flash memory microcontrollers, programming manual — таблица 3: основная флеш-память STM32F1 начинается с адреса 0x0800 0000

Где пригодится

Встроить калькулятор на свой сайт

Скопируйте код и вставьте его в HTML страницы, статьи или вики. Виджет бесплатный, без рекламы, счётчиков и cookie. Условие одно — ссылка на GAW под рамкой остаётся на месте. Подробнее о виджетах

<iframe src="https://gaw.ru/embed/hex-dump/" title="Просмотр и проверка файлов прошивки Intel HEX, S-record и BIN" width="100%" height="640" style="border:1px solid #e3e5e9;border-radius:8px" loading="lazy" allow="clipboard-write"></iframe>
<p style="margin:6px 0 0;font-size:14px">Калькулятор: <a href="https://gaw.ru/tools/hex-dump/">Просмотр и проверка файлов прошивки Intel HEX, S-record и BIN</a> — GAW.ru</p>
Автоподстройка высоты рамки

Если сайт разрешает скрипты, добавьте этот код один раз в любом месте страницы: рамка будет менять высоту вместе с результатом расчёта.

<script>window.addEventListener("message",function(e){if(e.origin!=="https://gaw.ru"||!e.data||e.data.type!=="gaw:embed-height")return;var f=document.querySelectorAll('iframe[src^="https://gaw.ru/embed/"]');for(var i=0;i<f.length;i++)if(f[i].contentWindow===e.source)f[i].style.height=e.data.height+"px"})</script>

Обновлено .

Нашли ошибку в расчёте?