Можно ли использовать неабсолютный диапазон адресов в SRecord и вставить некоторые данные в последние байты двоичного файла?

Я делаю проект для микроконтроллера ARM Cortex-M4 с использованием STM32CubeIDE (IDE на основе Eclipse с компилятором gcc) и хочу встроить CRC всей прошивки в конец двоичного файла. Я уже модифицировал скрипт компоновщика, чтобы создать некоторые переменные, помещенные в конец скомпилированного двоичного файла. Вот мои модификации скрипта компоновщика:

... linker script ...
  /* My section (it is the last section in linker script) */
  .end_of_code :
  {
    . = ALIGN(4);
    KEEP (*(.end_of_code.fwSize)) /* Force memory allocation even if variable is unused */
    KEPP (*(.end_of_code.fwCrc)) /* Force memory allocation even if variable is unused */

    _end_of_code = .; /* Get current address */
    _size_of_code = ABSOLUTE (_end_of_code - ORIGIN(FLASH)); /* Subtruct current address from start of image */
  } >FLASH

А вот объявление вышеуказанных переменных в C:

// Some C file

extern uint32_t _size_of_code; // Linker variable

const __attribute__((section(".end_of_code.fwSize"))) uint32_t fwSize = (uint32_t) &_size_of_code;
const __attribute__((section(".end_of_code.fwCrc"))) uint32_t fwCrc = 0xFFFFFFFF;

Последняя переменная, созданная с помощью скрипта компоновщика, должна хранить CRC32 всей прошивки. Я хочу использовать скрипт SRecord для вычисления значения CRC и иметь возможность ссылаться на это значение, как на обычную переменную в коде C.

Моя цель - создать скрипт SRecord, который будет открывать файл с помощью -binaryформат, замените последние 4 байта CRC32, вычисленным SRecord, и сделайте вывод с замененным значением CRC. Но я не понимаю, как поместить неабсолютный диапазон адресов в -crop или же -excludeфильтры. Я хочу сделать что-то вроде этого:

# SRecord script
fw.bin -binary
-CRC32 -maximum-addr fw.bin -binary -4
-o fw_with_CRC.bin -binary

У меня вопрос: возможно ли и как использовать относительные адреса с SRecord? Или возможно и как перезаписать какие-то данные в конце бинарного файла с помощью SRecord?

Об альтернативных решениях: я знаю, что могу удалить переменную fwCrc из компоновщика и создать что-то вроде этого:

#define FW_CRC_ADDR    ( ((uint32_t) &fwSize) + 0x04 )
#define GET_FW_CRC()   ( *(uint32_t *) FW_CRC_ADDR )

но такое решение мне не подходит. Я хочу иметь переменную, в которой хранится значение CRC. Решения, которые вводят некоторые данные / переменные вместо неиспользуемых элементов вектора прерывания, тоже не подходят.

Возможно, я могу принять решение, в котором переменная fwCrc не выделяет память и добавляет CRC в конец двоичного файла с помощью SRecord, но я не знаю, как заставить компоновщик не выделять память для переменной, используемой в коде C.

1 ответ

Я нашел решение, которое может быть кому-то полезно, но оно не дает прямого ответа на мой вопрос об относительной адресации в SRecord. Это решение описывает, как добавить CRC к образу прошивки и получить доступ к значению CRC в C, как к переменной noramal.

Решение было протестировано с компилятором GCC и скриптом компоновщика, созданным STM32CubeIDE.

  1. Тип раздела компоновщика, в котором хранится значение CRC, следует изменить на (NOLOAD). Это заставляет компоновщик НЕ выделять память для переменных, назначенных этому разделу в двоичном образе. Больше информации о (NOLOAD)можно найти здесь.
... linker script ...

  /* Last section in linker script */
  .end_of_code :
  {
    . = ALIGN(4);
    KEEP (*(.end_of_code.fwSize)) /* Last variable in flash memory */

    _end_of_code = .; /* Get current address */
    _size_of_code = ABSOLUTE (_end_of_code - ORIGIN(FLASH)); /* Subtruct current address from start of image */
  } >FLASH

  /* New section for CRC */
  .crc (NOLOAD) :
  {
    . = ALIGN(4);
    
    *(.crc.fwCrc))
    
    . = ALIGN(4);
  } >FLASH

... /DISCARD/ ...

} /* SECTIONS */
  1. Добавьте CRC в прошивку к максимальному адресу, например, во время выполнения команды post build:
srec_cat infile.bin -binary -STM32 -maximum-addr infile.bin -binary -o outfile.bin -binary
  1. Объявить переменную C справа __attribute__:
const __attribute__((section(".crc.fwCrc"))) uint32_t fwCrc;

В результате описанных выше манипуляций будет создан образ прошивки с добавленным к нему CRC. К значению CRC можно получить доступ, как к обычной переменной C, используя fwCrc переменная. const был использован квалификатор, поскольку значение этой переменной хранится во FLASH-памяти и не может быть изменено напрямую с помощью операторов присваивания, таких как =.

Другие вопросы по тегам