Преодолевая пределы. Часть вторая. Ресурсы в IAR.

В первой части я продемонстрировал, как ресурсы могут быть созданы средствами ST Visual Develop. Но естественно держать проект в двух студиях несколько не удобно. В текущей публикации я расскажу, как все необходимые ресурсы могут быть созданы в среде разработки IAR.

Использование ресурсов в IAR

Кроме упомянутого способа задания адреса для ресурса через define, IAR поддерживает собственный способ задания адреса для переменных и констант через #pragma location. Так рассмотрим небольшой пример:

// Задание адреса с помощью макросов
#define intro ((const unsigned char*)0xA000)
#define string ((const char*)0xA1F8)
// Задание адреса с помощью директивы pragma
#pragma location=0xA200
__no_init const unsigned char intro2[504];
// Задание адреса в помощью оператора @
__no_init const char string2[8] @0xA3F8;

В результате для всех вариантов вызовов функций будет сгенерирован одинаковый код:

    LCD_writeString("IAR  Resources");
    008459    AE8560         LDW       X, #?<Constant "IAR  Resources">
    00845C    CD819B         CALL      LCD_writeString
    ...
    LCD_writeString( string );
    008468    AEA1F8         LDW       X, #0xA1F8
    00846B    CD819B         CALL      LCD_writeString
    ...
    LCD_writeString( string2 );
    008477    AEA3F8         LDW       X, #string2
    00847A    CD819B         CALL      LCD_writeString
    ...
    LCD_screen ( &intro[0] );
    008483    AEA000         LDW       X, #0xA000
    008486    CD80F8         CALL      LCD_screen
    ...
    LCD_screen ( &intro2[0] );
    00848F    AEA200         LDW       X, #intro2
    008492    CD80F8         CALL      LCD_screen

Какой из способов выбрать, решайте сами. Задание через #pragma и @ не переносимо на другие компиляторы, но "лучше следит" за типами данных. Правда есть сомнения, что с применением #pragma не даст о себе знать лимит по размеру кода. Проверить это пока не удалось.

Создание ASM проекта ресурсов в IAR

Создаем в рабочем пространстве разрабатываемого проекта новый ассемблерный проект и попробуем переделать его в проект ресурса.

Мне так и не удалось найти в ассемблере IAR простого способа задания адреса для участка кода, аналогичного .ORG в AVR. В целом способ задания адреса похож на способ, примененный в ассемблере STVD:

  1. объявляем регион памяти в определённой адресной области;
  2. объявляем помещение требуемых секций в выделенный регион памяти;
  3. указываем для кода/данных принадлежность к требуемой секции.

Только вот объявлять новые секции в ассемблерном коде, как это было в STVD, мы не можем. Для этих целей нужен отдельный файл, предназначенный для linker’а.

И так, создадим в папке проекта *.icf файл линкера:

/////////////////////////////////////////////////////////////////
//      Replace ILINK command file for Resource
/////////////////////////////////////////////////////////////////

define memory with size = 16M;

define region ResourceZone = [from 0xA200 to 0xA3FF];

/////////////////////////////////////////////////////////////////

place at start of ResourceZone  { ro section .recource2 };

/////////////////////////////////////////////////////////////////

Здесь мы объявили регион "ResourceZone" размером в 512 байт и начинающийся с адреса 0xA200. Далее мы указали что в данном регионе следует разместить секцию ".recource2".

Теперь нам надо указать линкеру использование нового файла конфигурации, взамен стандартного. Для этого убеждаемся что в окне Workspace у нас выбран проект ресурса, а не какой либо из файлов кода, после чего идем в меню Project -> Options и в открывшемся окне в списке категорий слева выбираем Linker. На закладке Config в группе Linker configuration file устанавливаем флажок Override default и в поле указываем путь к созданному *.icf файлу.
Настройка линкера в свойствах асемблерного проекта

С линкером разобрались, теперь надо разобраться с компилятором. В ассемблерном *.s файле заменяем код на следующее:

        MODULE  asmmain

        PUBLIC  __iar_program_start
        PUBLIC  main

        SECTION `.recource2`:CODE:NOROOT(0)

__iar_program_start:
main:

image:
	db $5e, $a2, $40, $80, $00, $00, $00, $00
	… ещё 61 строка данных …
	db $07, $0f, $1f, $3f, $7e, $7c, $78, $30
string:
	db "FD.IAR"
	end

Строка с SECTION сообщает, что дальнейший код/данные должны помещаться в секцию ".recource2". Метки __iar_program_start и main нужны дабы утихомирить компилятор с отладчиком пытающихся разобраться, откуда должно начаться выполнение. Теперь осталось только задать формирование *.s19 файла, что в принципе не обязательно. В опциях проекта в категории Output Converter на закладке Output:

  1. устанавливаем флажок Generate additional output;
  2. в выпадающем списке Output format выбираем Motorola;
  3. в группе Output file устанавливаем флажок Override default и в окне задаем имя выходного файла с расширением *.s19.
Настройка конвертора в свойствах асемблерного проекта

Теперь о приятном. Если в опциях проекта в категории Debugger задать в качестве отладчика ST-Link, то при запуске на отладку проекта студия зальет собранный ресурс в контроллер без каких либо проблем и возражений (естественно, если вы выбрали в настройках проекта правильный контроллер). Да к тому же начнется отладка прошивки и отладчик будет активно мигать светодиодом. Авто-остановки не будет, т.к. меткой входа указан адрес ресурса, а он никогда не выполняется, но есть возможность приостановить выполнение вручную.

Создание С проекта ресурсов в IAR

Создаем в рабочем пространстве разрабатываемого проекта новый Си проект и попробуем переделать его в проект ресурса. А после разбора ассемблерного проекта это не должно составить большой проблемы.

Аналогично создаем *.icf файл линкера:

/////////////////////////////////////////////////////////////////
//      Replace ILINK command file for Resource
/////////////////////////////////////////////////////////////////

define memory with size = 16M;

define region ResourceZone = [from 0xA400 to 0xA5FF];

/////////////////////////////////////////////////////////////////

place at start of ResourceZone  { ro section .recource3 };

/////////////////////////////////////////////////////////////////

Точно так же подменяем в опциях проекта файл конфигурации линкера и выходной файл:
Настройка линкера в свойствах проекта
Настройка конвертора в свойствах проекта

Содержимое *.c файла переписываем следующим образом:

typedef struct {
  unsigned char image[504];
  char string[8];
} Resource3;

#pragma location=".recource3"
const Resource3 recource3 = {
  {
    0x00,  … ещё 5 сотен значений … , 0x0f, 0x06, 0x00,
  },
  "C.Image"
};

Все ресурсы оформлены в виде структуры, для которой указано размещение в секции ".recource3" которая в соответствии с правилами линкера находится по адресу 0xA400 и составляет 512 байт. Оформление в виде одной структуры нам необходимо, что бы при компиляции не были выброшены "неиспользуемые" данные.

Теперь о "точке входа". Функцию main мы выбросили, т.к. она нам не нужна. Так же нам не нужен и генерируемый средой код настройки окружения, не нужна таблица векторов прерываний. Что бы всё это дело отключить идей в настройки проекта в категорию Linker на закладку Library:

  1. снимаем флажок Automatic runtime library selection;
  2. устанавливаем флажок Override default program entry;
  3. выбираем пункт Entry symbol и в окне вводим имя нашей структуры recource3.
Настройка точки входа для линкера в свойствах проекта

Благодаря этому, во-первых, сама структура не сможет быть удалена "как не используемая". Во-вторых, при компиляции проекта мы не получим ошибки "точка входа не найдена". В-третьих, в код не будет добавлено ничего лишнего. Как-то это получалось через Defined by application сделать, но уже не вспомню.

И снова о приятном. Указываем в качестве отладчика ST-Link и запускаем проект на отладку. Снова получаем автоматическую прошивку, только уже не без предупреждений:
Сообщение об ошибке при запуске
Сообщение об ошибке при запуске
В прочем ничего страшного тут нет. Просто отключаем лишний компонент среды и радуемся жизни.

Результат

В прочем результат не отличается от первой статьи. Все три способа работают одновременно, что не вызывает сомнения.
Вывод текста из всех ресурсов вывод изображения из ресурса STVD вывод изображения из ресурса асемблерного проекта IAR вывод изображения из ресурса C проекта IAR

Плюсы и минусы

Несомненным плюсом является возможность собрать все проекты (код и ресурсы) разрабатываемого устройства в одном рабочем пространстве (workspace):
Дерево проектов в IAR

Вторым плюсом является простота прошивки с применением отладчика. Нет риска, ошибиться при указании диапазоне адресов и случайно затереть что-то нужное. Среда самостоятельно прошивает только относящуюся к проекту область.

Третьим плюсом является возможность отладки при работе с проектом ресурса. Правда, только в режиме инструкций и без подстановки кода, но это лучше чем ничего. Вероятно, есть способ научить среду подтягивать отладочную информацию из других проектов.

Из минусов по-прежнему остаётся шанс что-нибудь забыть/потерять при прошивке.

Вместо заключения

Естественно, что данная модель удобнее для сопровождения. Так возможность разрабатывать и прошивать одной средой позволяет держать все необходимые компоненты вместе. Меньше риск что-либо забыть записать или не нарочно стереть. Но при этом мы не можем создавать ресурсы большего размера, чем позволяет среда разработки. В прочем "Война и мир" в каждом проекте нам не требуется, так что данный подход вполне хорош.

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

Файлы: odo_with_rc.zip, complite_iar.s19.zip

< Предидущая Следующая >
Hosted by uCoz