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

Вопросы по созданию своего загрузчика для LPC17xx

Всем доброго времени суток.

Адаптирую загрузчик с LPC2xxx на LPC176x. Копался в мануалах, столкнулся с тем, что у кортекса таблица векторов прерываний гораздо больше, чем у arm7. Как я понял, она может занимать максимум 1КБ против 64 байт у arm7. Для предыдущих проектов использовалась программа шифрования прошивки, которая знала расположение спецтаблицы, находящейся по определённому адресу сразу следом за таблицей векторов. Получается, теперь необходимо или ремапить таблицу векторов в кортексе для сохранения совместимости с софтом верхнего уровня, либо переписывать этот софт? Можно ли занимать адреса, скажем, 0x40...0x100 объявлением массива через __root const? И ещё, в каком документе от ARM описан участок памяти 0x0000 - 0x0400? В DDI0337H_cortex_m3_r2p0_trm.pdf нет. Просто code и всё. Кто может подсказать, что и где там обычно расположено? Компилятор - IAR.

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


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

Всем доброго времени суток.

Адаптирую загрузчик с LPC2xxx на LPC176x. Копался в мануалах, столкнулся с тем, что у кортекса таблица векторов прерываний гораздо больше, чем у arm7. Как я понял, она может занимать максимум 1КБ против 64 байт у arm7. Для предыдущих проектов использовалась программа шифрования прошивки, которая знала расположение спецтаблицы, находящейся по определённому адресу сразу следом за таблицей векторов. Получается, теперь необходимо или ремапить таблицу векторов в кортексе для сохранения совместимости с софтом верхнего уровня, либо переписывать этот софт? Можно ли занимать адреса, скажем, 0x40...0x100 объявлением массива через __root const? И ещё, в каком документе от ARM описан участок памяти 0x0000 - 0x0400? В DDI0337H_cortex_m3_r2p0_trm.pdf нет. Просто code и всё. Кто может подсказать, что и где там обычно расположено? Компилятор - IAR.

 

Да, придется спецтаблицу передвинуть за таблицу векторов. Но проблемы не вижу, т.к. со сменой ядра Вам обязательно пересобирать как загрузчик, так и основной софт. Вот и сдвиньте все дальше. Адреса 0х40 и выше конечно можно использовать как угодно (и объявлять тоже), но только есть ли гарантия, что не произойдет прерывания, адрес вектора которого попадет на ваши личные данные?

Описание на области памяти ищите в DS на контроллер. Cortex-M3 стандартизует лишь область векторов прерываний, да и то не строго, а остальное, как правило, отдано под пользовательский код.

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


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

Да, придется спецтаблицу передвинуть за таблицу векторов...

Да, к этому и пришёл. Спасибо. Думаю, в моём случае сдвинуть на 1КБ - не проблема.

 

Описание на области памяти ищите в DS на контроллер. Cortex-M3 стандартизует лишь область векторов прерываний, да и то не строго, а остальное, как правило, отдано под пользовательский код.

Если б NXP где-то явно это описала... В UM10360.pdf Rev. 2 — 19 August 2010 только на стр. 19 общая карта памяти :( Похоже, дизасмить придётся. А такой вопрос - где обычно после IARа находится стартовый вектор? Т.е., по какому адресу вызывать свою программу из загрузчика, если в *.icf файле я определяю:

define symbol __ICFEDIT_region_ROM_start__ = 0x00008000;

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


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

Да, к этому и пришёл. Спасибо. Думаю, в моём случае сдвинуть на 1КБ - не проблема.

 

 

Если б NXP где-то явно это описала... В UM10360.pdf Rev. 2 — 19 August 2010 только на стр. 19 общая карта памяти :( Похоже, дизасмить придётся. А такой вопрос - где обычно после IARа находится стартовый вектор? Т.е., по какому адресу вызывать свою программу из загрузчика, если в *.icf файле я определяю:

define symbol __ICFEDIT_region_ROM_start__ = 0x00008000;

 

Если внимательно прочесть, то ничего дизасмить не придется. После стандартных 16 прерываний ядра Cortex-M3 лежат ВСЕ векторы, которые имеются в данном камне. Считате, умножаете на 4 и т.д. После векторов память используется ИАРом по своему усмотрению. Но имхо и это знать вовсе не обязательно. Какая Вам разница куда именно ИАР положит какой код? Если обязательно сделать "дырку" между векторами и кодом для служебной информации, так сделайте ее с помощью конфига линкера. Точка входа в приложение у ИАРа располагается произвольно и знать ее вовсе не обязательно. Достаточно вычитать адрес начала кода из образа (опять же, см. описание первых 0х40 байтов в кортексе).

 

 

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


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

Попробовал сделать ремап векторов прерываний. Не заводится проц (или не выходит из NXP-шного загрузчика?). :( Что ещё не так мог сделать? Вроде всё просто должно быть.

 

В коде написал:

VTOR  = 0x400;

 

В *.icf файле:

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000400;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x0003FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x10000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x10007FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x400;
define symbol __ICFEDIT_size_heap__   = 0x800;
/**** End of ICF editor section. ###ICF###*/


define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy { readwrite };
//initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

place in ROM_region   { readonly };
place in RAM_region   { readwrite,
                       block CSTACK, block HEAP };

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


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

И ещё. Почему при указании в *.icf файле строки, например:

define symbol __ICFEDIT_region_ROM_start__ = 0x00001100;

всё-равно заполняет область 0x100...0xFFF кодом? В map-файле он явно написал:

"A1":  place at 0x00001000 { ro section .intvec };
"P1":  place in [from 0x00001100 to 0x0003ffff] { ro };
"P2":  place in [from 0x10000000 to 0x10007fff] { rw, block CSTACK, block HEAP };

  Section             Kind        Address    Size  Object
  -------             ----        -------    ----  ------
"A1":                                        0xc4
  .intvec             ro code  0x00001000    0xc4  startup_LPC17xx.o [1]
                             - 0x000010c4    0xc4

"P1":                                      0x675c
  .text               ro code  0x00001100  0x2050  blablabla.o [1]
...

Позиции в области 0x100...0xFFF нигде в map файле не встречаются. Если же в свойствах проекта указать заполнение нулями этой области, тогда да, там чисто, map-ы не отличаются, а код разумно вырастает на 4КБ. Правда, ни векторы, ни код всё-равно линкуются не туда. Где что не так?

 

P.S. С этим разобрался. Виноват IAR. hex-файл генерит правильно, а в бинарнике отрезает младшую часть неиспользуемых адресов *WALL* Только сильно легче не стало. С ремап-ом всё-равно не запускается код. Неужели никто не делал?

 

P.P.S. Похоже, догадываюсь, почему ремап не работает. Кто подскажет, чем заменить в icf-файле ранее использованную в xcl-файле директиву типа -KINTVEC=05000,1 ? Подобное позволяло иметь копию векторов прерываний по адресу 0x5000.

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


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

P.P.S. Похоже, догадываюсь, почему ремап не работает. Кто подскажет, чем заменить в icf-файле ранее использованную в xcl-файле директиву типа -KINTVEC=05000,1 ? Подобное позволяло иметь копию векторов прерываний по адресу 0x5000.

 

А можно поинтересоваться для чего нужны 2 копии таблицы векторов? Вы очень упорно копаете, но создается стойкое ощущение, что немного не туда :)

У Вас же будет бутлоадер? Наверное, он ляжет в один-два сектора в начале ПЗУ, так? А ведь он туда ляжет со своей таблицей, так? Тогда зачем Вам иметь еще и две таблицы у приложения? Его нужно просто сдвинуть на N-е кол-во секторов вперед и все. Только сдвинуть целиком, вместе с таблицей векторов. Например, так:

...
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00002000;
define symbol __ICFEDIT_region_ROM_end__   = 0x0003FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x10000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x10007FFF;
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = __ICFEDIT_region_ROM_start__;
/*-Sizes-*/
...

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


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

А можно поинтересоваться для чего нужны 2 копии таблицы векторов? Вы очень упорно копаете, но создается стойкое ощущение, что немного не туда :)

Можно, конечно. Причин было две:

1. Пока не был дан проект от второго программиста, который занимается основной программой, хотел в самом загрузчике обкатать перемещение таблицы векторов прерываний во флэше. Протупил (споткнулся) из-за неправильно генерируемого бинарника сначала, потом понял, что простыми методами из самого загрузчика не сделать такой тест. Надо хотя бы примитивную главную программку залить, или играться с ремапом в ОЗУ, т.к. начальная же область пустая :)

2. Поскольку проекты перетаскиваются с arm7, то ранее на Builder-е была создана спецпрограммка, которая в постбилде отрезала начальный пустой ненужный кусок от главной программы (включая вектора), получала инфу из спецтаблицы, расположенной следом за векторами (и меняла её тоже, всякую инфу добавляя), при этом имелась копия такой таблицы для главной программы по предопределённому адресу (с учётом смещения главной, ессно), из которой оная также получала необходимые сведения. Также постбилдной утилитой проводилось шифрование прошивки. Хотелось перенести такую технологию без изменений, введя копию таблицы через icf-файл, но, поняв в соседней ветке, что это нельзя сделать, пришлось делать через код в главной проге, объявляя две копии по предопределённым адресам. В принципе, несложно, но некрасиво :) Уже всё проверил.

 

Так что всем спасибо за советы.

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


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

От сабя скажу следующее:

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

В итоге от всей таблицы в ПЗУ осталось лишь

        DATA
__vector_table
        DCD     sfe(CSTACK)            ; Top of Stack
        DCD     __iar_program_start    ; Reset Handler
        DCD     NMI_Handler            ; NMI Handler
        DCD     HardFault_Handler         ; Hard Fault Handler
        DCD     MemManage_Handler         ; MPU Fault Handler
        DCD     BusFault_Handler          ; Bus Fault Handler
        DCD     UsageFault_Handler        ; Usage Fault Handler
__vector_table_0x1c
        DCD     0                         ; Valid user Code

После первоначального запуска инициализирутся драйвер NVIC, который создает таблицу в ОЗУ. Далее работаем уже исключительно с ней.

Очень удобно (и единственно возможно на данном камне) при динамической инициализации векторов прерываний.

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


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

В итоге от всей таблицы в ПЗУ осталось лишь...

Хм, тоже неплохое решение, которое вполне имеет право на существование. Возьму на заметку. Благодарю.

 

Да, ещё вопросик. Использую в сишном коде асмовскую вставку вида:

  asm("mov sp,#0x8400");
  asm("ldr sp,[sp,#0]");

 

Для сишных файлов константа 0x8400 определена. Есть ли какая-то возможность подставить эту константу для асма? Погуглил. Пишут, что требуется явно указывать :( Оно и понятно, но всё же...

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


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

Я для IAR такой код перехода в программу поставил

                VTOR = (unsigned)__section_begin(".intvect");
                asm ("ldm r1, {r0,r1}\n"
                     "mov r13, r0\n"
                     "mov r15, r1");
                while(1);

Здесь при оптимизации и записи в VTOR, нужная константа уже будет в r1 (можно по листингу проверить) осталось только стек и точку входа считать...

в конце while(1) стоит для оптимизатора.

 

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


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

Я для IAR такой код перехода в программу поставил...

Очень элегантно! Спасибо! По коду всё понял. Не поделитесь заодно полным описанием набора инструкций для Cortex-M3? Что-то я у ARM на сайте не нашёл pdf-ника нормального.

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


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

Не поделитесь заодно полным описанием набора инструкций для Cortex-M3? Что-то я у ARM на сайте не нашёл pdf-ника нормального.

Вам нужен arm architecture v7m reference manual, посмотрите новости местных закромов :)

 

 

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


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

Пишу спец загрузчик и как раз столкнулся с тем, что мне надо иметь две таблицы векторов прерываний.

Задача загрузчика записать приложение по адресам 0x0-0xFFFF, т.е после чего он уже будет не нужен. И на место него пользовательское приложение будет писать другие данные, но это не важно.

Механизм такого загрузчика предполагается сделать так.

1. Копируются вектора прерываний куда-нибудь (во флешь или озу)

2. Делается ремап.

3. Стартует загрузчик

 

Можно ли сделать копирование векторов прерываний в другую страницу на этапе линковки загрузчика, скажем по адресу 0x18000?

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


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

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

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

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

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

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

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

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

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

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