Переход к bootloader'у из скетча
- Войдите на сайт для отправки комментариев
Сб, 01/11/2014 - 15:08
Добрый день, коллеги!
Есть простая задача: из скетча произвести переход на начало бутлоадера, который начинается с 0x3800.
Пытался определить функцию перехода так:
void (*bootloader)(void)= (void(*)(void))0x3800;
При этом попадаю не в бут, а неизвестно куда.
А так:
void (*bootloader)(void)= 0x3800;
сделать не дает, пишет, что
:13: error: invalid conversion from 'int' to 'void (*)()'
Подскажите пожалуйста синтаксис, как это сделать?
Забыл добавить , что вызываю переход так:
тут посмотрите step 2
http://instructables.com/id/two-ways-to-reset-arduino-in-software/all/
но всё это фигня.
Мне не нужно аппаратно перезагрузить МК. Мне нужно попасть в бутлоадер для обновления прошивки.
Подскажите синтаксис перехода по фиксированному адресу 0x3800!?
может через ассемблер?
типа asm{ mov ax,38h
xor dx,dx
mov cs,ax
mov ip,dx}
этот пример на уровне идеи,еще нужно уточнить может есть какие подготовительные операции,например сохранить использумые регистры заранее,или вообще обращение напрямую к памяти не через cs:ip ,как в архитектуре x86
Михаил, это вариант!
Я, к сожалению, вставки на asm'e не делал, но готов рассмотреть этот вариант.
Хотя, мне всего лишь нужно узнать синтаксис переопределения адреса функции! Спецы по C - помогите пожалуйста!
могу подсказать пару вариантов,подскажу как это делаеться в x86 :
1.я так понимаю функцию нужно вызвать из бутлоадера,в определенный момент,тогда просто сохранить адресс функции в переменную,для этого есть спец инструкция на уровне ассемблера,к сожалению точного названия не помню.в нужный момент загрузить эти данные в cs:ip.насколько я помню переменные и функции обьявленные в си-шной части кода,без проблемм используються в асм-ной
2.есть т.н вектор прерываний который содержит массив указателей для всех прерываний процессора.и есть там такое прерывание номер 1(номер точно не помню,но используеться дебаггерами для пошагового выполнения кода).прелесть этого прерывания в том что его можно ручками включить в любой момент,для этого даже флаг есть в регистре флагов.так вот идея в том что бы в массив адрессов прерываний подсунуть адресс вашей фунции на место адресса прерывания номер 1.после исполнения нужного,вернуть все на место
итого вам нужно:
1.узнать как и можно ли делать асм-шные встаки в коде ардуино(поидее можно так как это си подобный язык)
2.узнать какой асм инструкцией вытянуть адресса функций или сразу ее аналог для RISC архитектуры
3.узнать адресс вектора прерываний и как обращаться к регистру флагов в RISC архитектуре
4.номер прерывания для пошагового выполнения инструкций
может, это поможет
Вот это, видимо, то что мне нужно. Спасибо!
Однако,
почему то не работает.
Светодиод сиглизирует о переходе в bl. Но бут не отрабатывает.
8( Даже и не знаю как отлаживать.
p.s. Адрес на 0x7000 менял. У меня 2К-boot.
Вот зараза! Если меняю адрес на 0x0000, то программа просто перезагружается!
А как в бут зайти - не пойму!
Вот зараза! Если меняю адрес на , то программа просто перезагружается!
Ну да, 0x0000 - это app_start
Так что делать то?
Подскажите синтаксис перехода по фиксированному адресу 0x3800!?
Если вы прочитали, то что я предложил, то заметили бы синтаксис перехода к адресу 0 :
void(* resetFunc) (void) = 0; //declare reset function @ address 0
...
resetFunc(); //call reset
Уважаемый toc!
Я прочитал, что вы предложили!
А теперь попробуйте сами откомпилировать приведенный вами пример кода, заменив ноль на 0x3800.
Я писал об этой ошибке в самомо первом посте.
Нашел решение. Все работает.
Изначально задача стояла: перезагрузить МК для запуска bootloader'a.
Задача красиво решается при помощи watchdog. Собственно говоря, это его основное предназначение - перезагрузка МК. Через 4 секунды после выполнения этого кода произойдет перезагрузка МК, как будто нажали reset:
Решение по мотивам прочтения : http://habrahabr.ru/post/189744/
Спасибо всем за помощь!
А чем, тогда, Вас не устроило предложение в ответе #2?
ясно - нас наипали, расходимся... нихрена никуда переходить не нужно было - нужно было программно/аппаратно перезагрузить контроллер.