Переход к bootloader'у из скетча

select2
Offline
Зарегистрирован: 31.10.2012

Добрый день, коллеги!

Есть простая задача: из скетча произвести переход на начало бутлоадера, который начинается с 0x3800.

Пытался определить функцию перехода так:

void (*bootloader)(void)= (void(*)(void))0x3800; 

При этом попадаю не в бут, а неизвестно куда.

А так:

void (*bootloader)(void)= 0x3800; 

сделать не дает, пишет, что
:13: error: invalid conversion from 'int' to 'void (*)()'
 

Подскажите пожалуйста синтаксис, как это сделать?

select2
Offline
Зарегистрирован: 31.10.2012

Забыл добавить , что вызываю переход так:

bootloader();

 

toc
Offline
Зарегистрирован: 09.02.2013

тут посмотрите step 2
http://instructables.com/id/two-ways-to-reset-arduino-in-software/all/

но всё это фигня.

select2
Offline
Зарегистрирован: 31.10.2012

Мне не нужно аппаратно перезагрузить МК. Мне нужно попасть в бутлоадер для обновления прошивки.

Подскажите синтаксис перехода по фиксированному адресу 0x3800!?

mixail844
Offline
Зарегистрирован: 30.04.2012

может через ассемблер?
типа asm{ mov ax,38h
xor dx,dx
mov cs,ax
mov ip,dx}
этот пример на уровне идеи,еще нужно уточнить может есть какие подготовительные операции,например сохранить использумые регистры заранее,или вообще обращение напрямую к памяти не через cs:ip ,как в архитектуре x86

select2
Offline
Зарегистрирован: 31.10.2012

Михаил, это вариант!

Я, к сожалению, вставки на asm'e не делал, но готов рассмотреть этот вариант.

Хотя, мне всего лишь нужно узнать синтаксис переопределения адреса функции! Спецы по C - помогите пожалуйста!

mixail844
Offline
Зарегистрирован: 30.04.2012

могу подсказать пару вариантов,подскажу как это делаеться в x86 :
1.я так понимаю функцию нужно вызвать из бутлоадера,в определенный момент,тогда просто сохранить адресс функции в переменную,для этого есть спец инструкция на уровне ассемблера,к сожалению точного названия не помню.в нужный момент загрузить эти данные в cs:ip.насколько я помню переменные и функции обьявленные в си-шной части кода,без проблемм используються в асм-ной
2.есть т.н вектор прерываний который содержит массив указателей для всех прерываний процессора.и есть там такое прерывание номер 1(номер точно не помню,но используеться дебаггерами для пошагового выполнения кода).прелесть этого прерывания в том что его можно ручками включить в любой момент,для этого даже флаг есть в регистре флагов.так вот идея в том что бы в массив адрессов прерываний подсунуть адресс вашей фунции на место адресса прерывания номер 1.после исполнения нужного,вернуть все на место

итого вам нужно:
1.узнать как и можно ли делать асм-шные встаки в коде ардуино(поидее можно так как это си подобный язык)
2.узнать какой асм инструкцией вытянуть адресса функций или сразу ее аналог для RISC архитектуры
3.узнать адресс вектора прерываний и как обращаться к регистру флагов в RISC архитектуре
4.номер прерывания для пошагового выполнения инструкций

vdk
Offline
Зарегистрирован: 14.04.2013

может, это поможет

select2
Offline
Зарегистрирован: 31.10.2012

Вот это, видимо, то что мне нужно. Спасибо!

Однако,

void *bl = (void *) 0x7800;
goto *bl;

почему то не работает.

Светодиод сиглизирует о переходе в bl. Но бут не отрабатывает.

8( Даже и не знаю как отлаживать.

p.s. Адрес на 0x7000 менял. У меня 2К-boot.

select2
Offline
Зарегистрирован: 31.10.2012

Вот зараза! Если меняю адрес на 0x0000, то программа просто перезагружается!

А как в бут зайти - не пойму!

vdk
Offline
Зарегистрирован: 14.04.2013

select2 пишет:

Вот зараза! Если меняю адрес на , то программа просто перезагружается!

Ну да, 0x0000 - это app_start

select2
Offline
Зарегистрирован: 31.10.2012

Так что делать то?

toc
Offline
Зарегистрирован: 09.02.2013

select2 пишет:

Подскажите синтаксис перехода по фиксированному адресу 0x3800!?

Если вы прочитали, то что я предложил, то заметили бы синтаксис перехода к адресу 0 :

void(* resetFunc) (void) = 0; //declare reset function @ address 0
...
resetFunc(); //call reset

select2
Offline
Зарегистрирован: 31.10.2012

Уважаемый toc!

Я прочитал, что вы предложили!

А теперь попробуйте сами откомпилировать приведенный вами пример кода, заменив ноль на 0x3800.

Я писал об этой ошибке в самомо первом посте.

select2
Offline
Зарегистрирован: 31.10.2012

Нашел решение. Все работает.

Изначально задача стояла: перезагрузить МК для запуска bootloader'a.

Задача красиво решается при помощи watchdog. Собственно говоря, это его основное предназначение - перезагрузка МК. Через 4 секунды после выполнения этого кода произойдет перезагрузка МК, как будто нажали reset:

#include <avr/wdt.h>

wdt_reset();        
wdt_enable(WDTO_4S);
while (1)

Решение по мотивам прочтения : http://habrahabr.ru/post/189744/
Спасибо всем за помощь!

faraddin
Offline
Зарегистрирован: 11.08.2013

А чем, тогда, Вас не устроило предложение в ответе #2?

Kлапаyций 99.99
Offline
Зарегистрирован: 11.10.2014

ясно - нас наипали, расходимся... нихрена никуда переходить не нужно было - нужно было программно/аппаратно перезагрузить контроллер.