ДЕЙЛ 31 5 сентября, 2014 Опубликовано 5 сентября, 2014 · Жалоба Есть ещё вопрос по безусловному переходу. если написать такой код: int i; void main (void) { for (i = 0; i<20; i++) { asm (" nop "); } asm (" B 0x???? "); } то по какому адресу нужно сделать безусловный переход, чтобы программа стала заново выполняться и возможно ли это? МК LPC1778, среда IAR. С этим разобрался, для программного сброса перезапуска программы и соответственно для передачи управления по какому-либо адресу младший бит этого адреса должен быть всегда установлен, если используется Cortex-M3. Т.е. для программного перезапуска нужно написать: asm (" B 1 "); Для меня этот эксперимент принципиален для уяснения принципа передачи управления по конкретному адресу флеш, т.к. бутлоадер таким способом запускает программу, как я представляю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 5 сентября, 2014 Опубликовано 5 сентября, 2014 (изменено) · Жалоба 2. Если используется стандартный шаблон проекта, то в обработчике прерывания сброса обычно идет вызов процедуры SysInit, которая выполняет инициализацию некоторого оборудования (PLL например). А если у меня в проекте никакие библиотеки не подключены? Просто имеется такой код: void main (void) { while(1) { } } и ещё вопрос Если я участок памяти программы, начиная с нулевого адреса, полностью скопирую в ОЗУ по адресу ADRES, затем после процедуры копирования сделаю перескок ассемблерной инструкцией asm (" B ADRES ");, то это будет равносильно выполнению программы заново? Работать будет? Пока в матчасть вникаю, до железа руки не доходят. Вот ещё непонятность. в описании ядра CM3 есть такие слова: "Таблица векторов прерываний может быть перемещена по другому адресу в области кода или в области ОЗУ" и далее имеется описание регистра смещения таблицы векторов VTOR. Как выглядит участок программы, который перемещает эту таблицу векторов? Нужно просто в регистр смещения записать новый адрес? Какие-то дополнительные действия нужны? Хотелось бы посмотреть пример исходника. Изменено 5 сентября, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
menzoda 0 5 сентября, 2014 Опубликовано 5 сентября, 2014 (изменено) · Жалоба А если у меня в проекте никакие библиотеки не подключены? Просто имеется такой код: void main (void) { while(1) { } } SysInit находится до этого кода. Есть ли он или нет надо смотреть в стартап-файле, но даже если его нет, все остальное остается в силе и не зависит от того используешь ты библиотеки или нет. Если я участок памяти программы, начиная с нулевого адреса, полностью скопирую в ОЗУ по адресу ADRES, затем после процедуры копирования сделаю перескок ассемблерной инструкцией asm (" B ADRES ");, то это будет равносильно выполнению программы заново? Работать будет? В общем случае нет. На этапе компоновки вместо вызовов функций и обращений к переменным подставляются абсолютные адреса, то есть необходимо заранее знать где будет исполняться программа. Если ты переместишь программу в другое место, то все сломается. Однако, компоновщик может поддерживать генерацию кода, инвариантного к расположению в памяти (position independent). По крайней мере в тулчейне от ARM я видео такую опцию, но подробно не интересовался. Кроме того, как я уже говорил - кто будет сбрасывать состояние оборудование перед началом выполнения программы? Все это реализуемо, но требует понимания проблемы и дополнительных телодвижение. Поэтому, подытожив, еще раз отвечу на твой вопрос: будет равносильно выполнению программы заново? Работать будет? В общем случае нет. Пока в матчасть вникаю, до железа руки не доходят. Мне кажется ты немного не с той стороны начал. Сейчас тебе на каждый вопрос надают кучу ответов, что можно, что нельзя, нужно то, нужно это, только запутают. Вон, хотя бы посмотреть на мои ответы - вроде как нельзя, но в принципе можно. Сейчас как зароешся во всем этом... Может лучше исходить из конечной цели? Например, сделать загрузчик для такого-то МК, который должен то-то и то-то, а не "что будет, если я вызову инструкцию перехода". Так сказать от общего к частному, сначала по советам сделаешь работающий загрузчик, а потом будешь разбираться почему именно так. Вот ещё непонятность. в описании ядра CM3 есть такие слова: "Таблица векторов прерываний может быть перемещена по другому адресу в области кода или в области ОЗУ" и далее имеется описание регистра смещения таблицы векторов VTOR. Как выглядит участок программы, который перемещает эту таблицу векторов? Нужно просто в регистр смещения записать новый адрес? Какие-то дополнительные действия нужны? Хотелось бы посмотреть пример исходника. Сначала скопировать таблицу векторов в нужное место, а потом в регистр смещения записать новый адрес. Скопировать можно как угодно, таблица векторов прерываний это просто числа в памяти. Никаких дополнительных действий не нужно. Изменено 5 сентября, 2014 пользователем menzoda Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 5 сентября, 2014 Опубликовано 5 сентября, 2014 · Жалоба Может лучше исходить из конечной цели? конечная цель такая: имеется LPC1778, имеется скомпилированный файл proga.bin. Нужно сделать так, чтобы я мог по какому-нибудь интерфейсу с ПК этот файл побайтно отправить своей программой, а в контроллере эти байты встретит чуть ранее загруженный самопальный бутлоадер, который всё принятое разложит в памяти и запустит на выполнение. С написанием программы для ПК проблем не вижу, больше вопросов по принимающей стороне, т.е. с организацией записи прошивки в МК самопальным загрузчиком. Далее предполагаю передавать прошивку по радиоканалу и тем самым иметь возможность удалённо перепрошивать девайс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
menzoda 0 5 сентября, 2014 Опубликовано 5 сентября, 2014 (изменено) · Жалоба В кратце опишу, как я это вижу. Подробности поведения загрузчика опускаю, это уже на твоей совести. - Думаем сколько секторов памяти (начиная с первого) выделить под загрузчик. - Настраиваем проект1 загрузчика так, чтобы его таблица векторов прерываний располагалась по нулевому адресу2, а остальной код не выходил за рамки отведенной памяти. - Настраиваем проект основного ПО так, чтобы его образ не выходил за рамки отведенной области, а таблица векторов прерываний находилась в начале области. - Загрузчик может работать с файлами формата Intel HEX. Файл состоит из простых текстовых строк с данными и адресом, куда эти данные записать. Это стандарт де-факто для прошивки различных устройств. Генерируется всеми средствами разработки. Можно использовать и другие форматы. - Для простоты передача управления от загрузчика к основному ПО будет происходить через безусловный переход. При необходимости этот механизм можно заменить чем-нибудь другим. - Цель безусловного перехода - обработчик прерывания сброса основного ПО. Адрес обработчика находится в известном векторе прерывания. Таблица векторов прерываний находится в начале области, отведенной под основное ПО. - Для перехода к основному ПО необходимо (именно в такой последовательности): 1. запретить все прерывания 2. привести состояние использованной периферии к начальному 3. задать в регистре смещения новое положение таблицы векторов прерываний основного ПО 4. совершить переход - Загрузчик может получать файл прошивки по любому интерфейсу. При получении файла он разбирает его формат и записывает содержимое в соответствующую область памяти. Если используется формат Intel HEX, то мы имеем явное указание куда записывать данные3. Если используется простой бинарный образ, то записываем его последовательно в начало области, отведенной под основное ПО. - Перед переходом к основному ПО загрузчик должен убедиться, что оно существует. Для этого при записи ПО подсчитываем его контрольную сумму, результат записываем в заранее определенное место. Перед переходом пробегаемся по области основного ПО и сверяем контрольную сумму. Если все хорошо - переходим, если не сошлось - остаемся в загрузчике4. - Чтобы перейти из основного ПО в загрузчик - программно сбрасываем контроллер. Вроде все верно. Если что - другие поправят. 1 Настраивать придется скрипт компоновщика (линкера). 2 Имеется ввиду адрес, к которому обращается ядро после сброса. Он обычно (но необязательно) численно равен нулю. 3 При этом все-равно нужно проверять, что мы попадаем в область основного ПО, чтобы при получении неправильного файла случайно не перетереть загрузчик. 4 Можно придумать какой-нибудь другой алгоритм определения наличия ПО. Изменено 5 сентября, 2014 пользователем menzoda Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 8 сентября, 2014 Опубликовано 8 сентября, 2014 · Жалоба Вот исходники загрузчика для LPC178X. Практически один в один по описанию из первого поста: https://github.com/blackyblack/LPC-DfuSe-Bootloader Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 8 сентября, 2014 Опубликовано 8 сентября, 2014 · Жалоба LPC так легко взламывают. Чтобы не быть голословным, что "плохие процессоры "эль" взламывают, а хорошие процессоры "ка" - не взламывают", можно увидеть ссылочки на проделанные работы? И порядок цен интересен. Не корысти ради, а из любопытства, когда нам клиенты наши собственные прошивки принесут. Исправленные и дополненные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 30 сентября, 2014 Опубликовано 30 сентября, 2014 · Жалоба Пока в исходник загрузчика глубоко не влазил. Хочу попробовать что-либо записать во флеш из программы. т.е. если написать вот так: adres = (unsigned int*)0x20000200; //область оперативной памяти *adres = 0x12345678; то всё нормально - в ячейку с указанным адресом записывается число, а если написать вот так adres = (unsigned int*)0x1000; //область флеш-памяти *adres = 0x12345678; то ничего не записывается. Тут нужно предварительно какие-то настройки делать. В мануале что-то написано, но нет примеров. Хотелось бы увидеть самый простой пример включения возможности записи в ячейку флеш. МК LPC1778 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 30 сентября, 2014 Опубликовано 30 сентября, 2014 · Жалоба В мануале что-то написано, но нет примеров. Хотелось бы увидеть самый простой пример включения возможности записи в ячейку флеш. МК LPC1778 У них нет возможности записи в ячейку. Вы можете записать только блок. Пример там писать не стали - вся запись сводится к загрузке 4 регистров и вызвове одной функции IAP. Читайте раздел Flash Memory до просветления. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 30 сентября, 2014 Опубликовано 30 сентября, 2014 (изменено) · Жалоба У них нет возможности записи в ячейку. Вы можете записать только блок. Пример там писать не стали - вся запись сводится к загрузке 4 регистров и вызвове одной функции IAP. Читайте раздел Flash Memory до просветления. Но ведь хочется спросить и тут разжёваный ответ получить :rolleyes: Спасибо за направляющий ответ, буду копать. Как в общих чертах происходит запись блока? Какие шаги нужно проделать? Изменено 30 сентября, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 30 сентября, 2014 Опубликовано 30 сентября, 2014 · Жалоба Но ведь хочется спросить и тут разжёваный ответ получить :rolleyes: Спасибо за направляющий ответ, буду копать. Как в общих чертах происходит запись блока? Какие шаги нужно проделать? Прочитать сраницу из flash, изменить байтик, (возможно очистить flash), записать станицу во flash. Все подробности в application note (а такой есть 99%) на ваш процессор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 6 октября, 2014 Опубликовано 6 октября, 2014 (изменено) · Жалоба Покопался в настройках линкера, нашёл настройки линкера: 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. - Для простоты передача управления от загрузчика к основному ПО будет происходить через безусловный переход. ...... - Цель безусловного перехода - обработчик прерывания сброса основного ПО. Адрес обработчика находится в известном векторе прерывания. Таблица векторов прерываний находится в начале области, отведенной под основное ПО. В каком известном векторе прерывания находится адрес обработчика? Как узнать этот адрес? - Для перехода к основному ПО необходимо (именно в такой последовательности): 1. запретить все прерывания 2. привести состояние использованной периферии к начальному 3. задать в регистре смещения новое положение таблицы векторов прерываний основного ПО 4. совершить переход Написал маленькую тестовую программу без подключения библиотек и лишних файлов unsigned int *VTOR int main() { VTOR = (unsigned int*)0xE000ED08; //адрес регистра смещения таблицы *VTOR = 0x7000; //смещение адреса таблицы веторов прерываний asm ("B 0x7000"); //адрес перехода } Т.е. 1. Прерывания не разрешал, близко к ним не подходил в этом коде. 2. Переферию не трогал 3. С этим вопрос - как узнать адрес? 4. По какому адресу переходить? Как его узнать? UP1: в прикреплённом архиве проект основного ПО и второй проект тестовой программы, которая должна запускть основное ПО ______________________________________________.rar Изменено 6 октября, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
menzoda 0 8 октября, 2014 Опубликовано 8 октября, 2014 (изменено) · Жалоба В каком известном векторе прерывания находится адрес обработчика? Как узнать этот адрес? Первый вектор таблицы содержит адрес вершины стека, второй - адрес обработчика прерываний сброса, подробнее смотри в документации ARM на своё ядро (искать по словам vector table). Написал маленькую тестовую программу без подключения библиотек и лишних файлов Во-первых, ты переходишь по адресу в первом векторе таблицы, а это адрес вершины стека, так что надо переходить по второму. Во-вторых, ты переходишь в этот вектор, а надо прочитать значение из этого вектора и перейти уже по нему. Исходя из твоего третьего скриншота, тебе надо прочитать содержимое по адресу 0x7004, судя по скриншоту оно было равно 0x8105, и перейти в этот самый 0x8105. Изменено 8 октября, 2014 пользователем menzoda Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
toweroff 1 8 октября, 2014 Опубликовано 8 октября, 2014 · Жалоба :bb-offtopic: ДЕЙЛ, я, конечно, ничего против не имею, но такая боевая расцветка темы оформления каждый день по несколько часов сидения у монитора глаза не заворачивает на затылок? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 8 октября, 2014 Опубликовано 8 октября, 2014 · Жалоба Во-первых, ты переходишь по адресу в первом векторе таблицы, а это адрес вершины стека, так что надо переходить по второму. Во-вторых, ты переходишь в этот вектор, а надо прочитать значение из этого вектора и перейти уже по нему. Исходя из твоего третьего скриншота, тебе надо прочитать содержимое по адресу 0x7004, судя по скриншоту оно было равно 0x8105, и перейти в этот самый 0x8105. Написал две строки *VTOR = 0x380000; //смещение таблицы относительно начала области кода (0x0000) 0x7000 передвинуты на 7 бит влево, т.к. смещение записывается в битах 28:7 asm ("B 0x8105"); Нивкакую не работает. Что ещё упустил и как правильно написать для перехода к программе, начинающейся с адреса 0x7000? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться