реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Стартовый загрузчик, с нуля
ДЕЙЛ
сообщение Sep 5 2014, 07:49
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(ДЕЙЛ @ Sep 3 2014, 14:34) *
Есть ещё вопрос по безусловному переходу.

если написать такой код:
Код
int i;
void main (void)
{
for (i = 0; i<20; i++)
      {
       asm (" nop ");
      }
asm (" B 0x???? ");
}

то по какому адресу нужно сделать безусловный переход, чтобы программа стала заново выполняться и возможно ли это? МК LPC1778, среда IAR.

С этим разобрался, для программного сброса перезапуска программы и соответственно для передачи управления по какому-либо адресу младший бит этого адреса должен быть всегда установлен, если используется Cortex-M3. Т.е. для программного перезапуска нужно написать:
Код
asm (" B 1 ");

Для меня этот эксперимент принципиален для уяснения принципа передачи управления по конкретному адресу флеш, т.к. бутлоадер таким способом запускает программу, как я представляю.
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Sep 5 2014, 10:08
Сообщение #17


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(menzoda @ Sep 4 2014, 09:33) *
2. Если используется стандартный шаблон проекта, то в обработчике прерывания сброса обычно идет вызов процедуры SysInit, которая выполняет инициализацию некоторого оборудования (PLL например).

А если у меня в проекте никакие библиотеки не подключены? Просто имеется такой код:
Код
void main (void)
{
  while(1)
  {
  }
}

и ещё вопрос
Если я участок памяти программы, начиная с нулевого адреса, полностью скопирую в ОЗУ по адресу ADRES, затем после процедуры копирования сделаю перескок ассемблерной инструкцией asm (" B ADRES ");, то это будет равносильно выполнению программы заново? Работать будет?

Пока в матчасть вникаю, до железа руки не доходят.

Вот ещё непонятность.
в описании ядра CM3 есть такие слова: "Таблица векторов прерываний может быть перемещена по другому адресу в области кода или в области ОЗУ" и далее имеется описание регистра смещения таблицы векторов VTOR. Как выглядит участок программы, который перемещает эту таблицу векторов? Нужно просто в регистр смещения записать новый адрес? Какие-то дополнительные действия нужны? Хотелось бы посмотреть пример исходника.

Сообщение отредактировал ДЕЙЛ - Sep 5 2014, 10:43
Go to the top of the page
 
+Quote Post
menzoda
сообщение Sep 5 2014, 10:45
Сообщение #18


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Цитата(ДЕЙЛ @ Sep 5 2014, 14:08) *
А если у меня в проекте никакие библиотеки не подключены? Просто имеется такой код:
Код
void main (void)
{
  while(1)
  {
  }
}

SysInit находится до этого кода. Есть ли он или нет надо смотреть в стартап-файле, но даже если его нет, все остальное остается в силе и не зависит от того используешь ты библиотеки или нет.

Цитата(ДЕЙЛ @ Sep 5 2014, 14:08) *
Если я участок памяти программы, начиная с нулевого адреса, полностью скопирую в ОЗУ по адресу ADRES, затем после процедуры копирования сделаю перескок ассемблерной инструкцией asm (" B ADRES ");, то это будет равносильно выполнению программы заново? Работать будет?

В общем случае нет. На этапе компоновки вместо вызовов функций и обращений к переменным подставляются абсолютные адреса, то есть необходимо заранее знать где будет исполняться программа. Если ты переместишь программу в другое место, то все сломается. Однако, компоновщик может поддерживать генерацию кода, инвариантного к расположению в памяти (position independent). По крайней мере в тулчейне от ARM я видео такую опцию, но подробно не интересовался.

Кроме того, как я уже говорил - кто будет сбрасывать состояние оборудование перед началом выполнения программы? Все это реализуемо, но требует понимания проблемы и дополнительных телодвижение. Поэтому, подытожив, еще раз отвечу на твой вопрос:
Цитата
будет равносильно выполнению программы заново? Работать будет?

В общем случае нет.

Цитата
Пока в матчасть вникаю, до железа руки не доходят.

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

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

Цитата
Вот ещё непонятность.
в описании ядра CM3 есть такие слова: "Таблица векторов прерываний может быть перемещена по другому адресу в области кода или в области ОЗУ" и далее имеется описание регистра смещения таблицы векторов VTOR. Как выглядит участок программы, который перемещает эту таблицу векторов? Нужно просто в регистр смещения записать новый адрес? Какие-то дополнительные действия нужны? Хотелось бы посмотреть пример исходника.

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

Сообщение отредактировал menzoda - Sep 5 2014, 11:05
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Sep 5 2014, 11:09
Сообщение #19


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(menzoda @ Sep 5 2014, 14:45) *
Может лучше исходить из конечной цели?

конечная цель такая: имеется LPC1778, имеется скомпилированный файл proga.bin.
Нужно сделать так, чтобы я мог по какому-нибудь интерфейсу с ПК этот файл побайтно отправить своей программой, а в контроллере эти байты встретит чуть ранее загруженный самопальный бутлоадер, который всё принятое разложит в памяти и запустит на выполнение. С написанием программы для ПК проблем не вижу, больше вопросов по принимающей стороне, т.е. с организацией записи прошивки в МК самопальным загрузчиком. Далее предполагаю передавать прошивку по радиоканалу и тем самым иметь возможность удалённо перепрошивать девайс.
Go to the top of the page
 
+Quote Post
menzoda
сообщение Sep 5 2014, 13:25
Сообщение #20


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



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

- Думаем сколько секторов памяти (начиная с первого) выделить под загрузчик.
- Настраиваем проект1 загрузчика так, чтобы его таблица векторов прерываний располагалась по нулевому адресу2, а остальной код не выходил за рамки отведенной памяти.
- Настраиваем проект основного ПО так, чтобы его образ не выходил за рамки отведенной области, а таблица векторов прерываний находилась в начале области.
- Загрузчик может работать с файлами формата Intel HEX. Файл состоит из простых текстовых строк с данными и адресом, куда эти данные записать. Это стандарт де-факто для прошивки различных устройств. Генерируется всеми средствами разработки. Можно использовать и другие форматы.
- Для простоты передача управления от загрузчика к основному ПО будет происходить через безусловный переход. При необходимости этот механизм можно заменить чем-нибудь другим.
- Цель безусловного перехода - обработчик прерывания сброса основного ПО. Адрес обработчика находится в известном векторе прерывания. Таблица векторов прерываний находится в начале области, отведенной под основное ПО.
- Для перехода к основному ПО необходимо (именно в такой последовательности):
1. запретить все прерывания
2. привести состояние использованной периферии к начальному
3. задать в регистре смещения новое положение таблицы векторов прерываний основного ПО
4. совершить переход
- Загрузчик может получать файл прошивки по любому интерфейсу. При получении файла он разбирает его формат и записывает содержимое в соответствующую область памяти. Если используется формат Intel HEX, то мы имеем явное указание куда записывать данные3. Если используется простой бинарный образ, то записываем его последовательно в начало области, отведенной под основное ПО.
- Перед переходом к основному ПО загрузчик должен убедиться, что оно существует. Для этого при записи ПО подсчитываем его контрольную сумму, результат записываем в заранее определенное место. Перед переходом пробегаемся по области основного ПО и сверяем контрольную сумму. Если все хорошо - переходим, если не сошлось - остаемся в загрузчике4.
- Чтобы перейти из основного ПО в загрузчик - программно сбрасываем контроллер.

Вроде все верно. Если что - другие поправят.

1 Настраивать придется скрипт компоновщика (линкера).
2 Имеется ввиду адрес, к которому обращается ядро после сброса. Он обычно (но необязательно) численно равен нулю.
3 При этом все-равно нужно проверять, что мы попадаем в область основного ПО, чтобы при получении неправильного файла случайно не перетереть загрузчик.
4 Можно придумать какой-нибудь другой алгоритм определения наличия ПО.

Сообщение отредактировал menzoda - Sep 5 2014, 13:27
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Sep 8 2014, 06:39
Сообщение #21


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Вот исходники загрузчика для LPC178X. Практически один в один по описанию из первого поста:

https://github.com/blackyblack/LPC-DfuSe-Bootloader
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Sep 8 2014, 12:46
Сообщение #22


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Цитата(AlexandrY @ Sep 2 2014, 16:37) *
LPC так легко взламывают.


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

Не корысти ради, а из любопытства, когда нам клиенты наши собственные прошивки принесут. Исправленные и дополненные.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Sep 30 2014, 10:35
Сообщение #23


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Пока в исходник загрузчика глубоко не влазил. Хочу попробовать что-либо записать во флеш из программы.

т.е. если написать вот так:
Код
adres = (unsigned int*)0x20000200; //область оперативной памяти
*adres = 0x12345678;

то всё нормально - в ячейку с указанным адресом записывается число, а если написать вот так
Код
adres = (unsigned int*)0x1000; //область флеш-памяти
*adres = 0x12345678;

то ничего не записывается. Тут нужно предварительно какие-то настройки делать. В мануале что-то написано, но нет примеров.
Хотелось бы увидеть самый простой пример включения возможности записи в ячейку флеш. МК LPC1778
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 30 2014, 11:36
Сообщение #24


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ДЕЙЛ @ Sep 30 2014, 13:35) *
В мануале что-то написано, но нет примеров.
Хотелось бы увидеть самый простой пример включения возможности записи в ячейку флеш. МК LPC1778
У них нет возможности записи в ячейку. Вы можете записать только блок. Пример там писать не стали - вся запись сводится к загрузке 4 регистров и вызвове одной функции IAP. Читайте раздел Flash Memory до просветления.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Sep 30 2014, 12:50
Сообщение #25


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(Сергей Борщ @ Sep 30 2014, 15:36) *
У них нет возможности записи в ячейку. Вы можете записать только блок. Пример там писать не стали - вся запись сводится к загрузке 4 регистров и вызвове одной функции IAP. Читайте раздел Flash Memory до просветления.

Но ведь хочется спросить и тут разжёваный ответ получить rolleyes.gif Спасибо за направляющий ответ, буду копать.

Как в общих чертах происходит запись блока? Какие шаги нужно проделать?

Сообщение отредактировал ДЕЙЛ - Sep 30 2014, 13:08
Go to the top of the page
 
+Quote Post
Lagman
сообщение Sep 30 2014, 14:00
Сообщение #26


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(ДЕЙЛ @ Sep 30 2014, 16:50) *
Но ведь хочется спросить и тут разжёваный ответ получить rolleyes.gif Спасибо за направляющий ответ, буду копать.

Как в общих чертах происходит запись блока? Какие шаги нужно проделать?

Прочитать сраницу из flash, изменить байтик, (возможно очистить flash), записать станицу во flash. Все подробности в application note (а такой есть 99%) на ваш процессор.
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Oct 6 2014, 21:21
Сообщение #27


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Покопался в настройках линкера, нашёл настройки линкера:
Config->Edit->Linker configuration file editor->Vector Table-> .intvec start = 0x7000
Config->Edit->Linker configuration file editor->Memory Regions-> ROM = 0x7000 - 0x7FFFF
После компилирования и запуска в пошаговом режиме видно, что программа раположена по адресу, начиная с 0x7000, на этом этапе всё работает нормально - данные бегут из UART0.
Получается, что программа уже нормально записана в память и работоспособна.
Далее пробую написать маленькую программу, расположенную в обычном месте, т.е. в начальном секторе флеш.
Пишу такой текст:
Код
main()
{
asm ("B 0x7000");
}

Перебрал несколько возможных адресов, но всегда зависает в Hard Fault.


Цитата(menzoda @ Sep 5 2014, 17:25) *
- Для простоты передача управления от загрузчика к основному ПО будет происходить через безусловный переход.
......
- Цель безусловного перехода - обработчик прерывания сброса основного ПО. Адрес обработчика находится в известном векторе прерывания. Таблица векторов прерываний находится в начале области, отведенной под основное ПО.

В каком известном векторе прерывания находится адрес обработчика? Как узнать этот адрес?


Цитата(menzoda @ Sep 5 2014, 17:25) *
- Для перехода к основному ПО необходимо (именно в такой последовательности):
1. запретить все прерывания
2. привести состояние использованной периферии к начальному
3. задать в регистре смещения новое положение таблицы векторов прерываний основного ПО
4. совершить переход

Написал маленькую тестовую программу без подключения библиотек и лишних файлов
Код
unsigned int *VTOR
int main()
{
VTOR = (unsigned int*)0xE000ED08; //адрес регистра смещения таблицы
*VTOR = 0x7000;  //смещение адреса таблицы веторов прерываний
asm ("B 0x7000"); //адрес перехода
}

Т.е.
1. Прерывания не разрешал, близко к ним не подходил в этом коде.
2. Переферию не трогал
3. С этим вопрос - как узнать адрес?
4. По какому адресу переходить? Как его узнать?

UP1: в прикреплённом архиве проект основного ПО и второй проект тестовой программы, которая должна запускть основное ПО

Сообщение отредактировал ДЕЙЛ - Oct 6 2014, 21:23
Эскизы прикрепленных изображений
Прикрепленное изображение
Прикрепленное изображение
Прикрепленное изображение
 

Прикрепленные файлы
Прикрепленный файл  ______________________________________________.rar ( 1.14 мегабайт ) Кол-во скачиваний: 52
 
Go to the top of the page
 
+Quote Post
menzoda
сообщение Oct 8 2014, 05:17
Сообщение #28


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Цитата
В каком известном векторе прерывания находится адрес обработчика? Как узнать этот адрес?

Первый вектор таблицы содержит адрес вершины стека, второй - адрес обработчика прерываний сброса, подробнее смотри в документации ARM на своё ядро (искать по словам vector table).

Цитата
Написал маленькую тестовую программу без подключения библиотек и лишних файлов

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

Исходя из твоего третьего скриншота, тебе надо прочитать содержимое по адресу 0x7004, судя по скриншоту оно было равно 0x8105, и перейти в этот самый 0x8105.

Сообщение отредактировал menzoda - Oct 8 2014, 05:22
Go to the top of the page
 
+Quote Post
toweroff
сообщение Oct 8 2014, 14:52
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



bb-offtopic.gif
ДЕЙЛ, я, конечно, ничего против не имею, но такая боевая расцветка темы оформления каждый день по несколько часов сидения у монитора глаза не заворачивает на затылок? sm.gif
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Oct 8 2014, 18:57
Сообщение #30


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(menzoda @ Oct 8 2014, 09:17) *
Во-первых, ты переходишь по адресу в первом векторе таблицы, а это адрес вершины стека, так что надо переходить по второму. Во-вторых, ты переходишь в этот вектор, а надо прочитать значение из этого вектора и перейти уже по нему.

Исходя из твоего третьего скриншота, тебе надо прочитать содержимое по адресу 0x7004, судя по скриншоту оно было равно 0x8105, и перейти в этот самый 0x8105.

Написал две строки
Код
*VTOR = 0x380000; //смещение таблицы относительно начала области кода (0x0000) 0x7000 передвинуты на 7 бит влево, т.к. смещение записывается в битах 28:7
asm ("B 0x8105");

Нивкакую не работает. Что ещё упустил и как правильно написать для перехода к программе, начинающейся с адреса 0x7000?
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th July 2025 - 05:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.01509 секунд с 7
ELECTRONIX ©2004-2016