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

STM32F0 и вызов встроенного бутлодера

А вот интересно, у кого-нибудь получился вот такой трюк: http://www.youtube.com/watch?v=cvKC-4tCRgw ?

Решил попробовать на f0-дисковери (контроллер stm32f051). Открыл руководство по бутлодеру:

3 Kbytes starting from address

0x1FFFEC00, contain the bootloader

firmware.

Сдампил содержимое:

7806 0020 35ee ff1f edec ff1f edec ff1f
00f0 02f8 00f0 40f8 0ca0 30c8 0838 2418
2d18 a246 671e ab46 5446 5d46 ac42 01d1
00f0 32f8 7e46 0f3e 0fcc ...

Здорово, первая чиселка 0х20000678 похожа на адрес из рамы, очевидно - указатель куда надо стек поместить. А дальше, с адреса 0x1FFFEC00 + 4 (как раз куда этот чел с видео прыгает) - мура какая-то (0х1FFFEE35), подозреваю, что это некая таблица с адресами. На видео - тоже самое. Дизассемблер видит в этом месте инструкцию arm режима: " mrc 15, 1, r1, cr5, cr15, {7} " - в доках что-то про сопроцессор (какой нафиг сопроцессор?). Вообшем я сделал вывод, что по адресу System Memory + 4 инструкции нету и, тогда вопрос, зачем туда переходить?

Ну ладно, думаю, почему не попробовать:

void __early_init(void)
{
    uint32_t *key = ( uint32_t * ) SRAM_BASE;
    void ( *BootLoader )( void ) = ( void ( * )( void ) ) 0x1FFFEC04;

    if( *key == 0xDEADC0DE )
    {
        *key = 0;

        __set_PRIMASK( 1 );
        __set_MSP( 0x20000678 );
        __set_CONTROL( 0 );
        BootLoader();
    }

    stm32_clock_init();
}

Как и предполагалось - переход по адресу 1FFFEC04 и на этой самой инструкции mrc - провал в хард фолт.

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


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

Младший бит в адресах переходов - признак Thumb mode, поэтому команду надо было начинать дизассемблировать с адреса 0х1FFFEE34.

 

Кроме передачи управления нужно ещё переключить мэппинг памяти, за это отвечают биты MEM_MODE[1:0] в регистре SYSCFG->CFGR1.

 

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


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

Между прочим, в AN2602 написано следующее:

In addition to patterns described below, user can execute bootloader by performing a jump to system memory from user code. Before jumping to Bootloader user must:

• Disable all peripheral clocks

• Disable used PLL

• Disable interrupts

• Clear pending interrupts

Ну и правильно сказал SSerge: нужно добавить 1 к адресу.

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


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

Ну и правильно сказал SSerge: нужно добавить 1 к адресу.

Я, наверное, не совсем точно выразился. Во избежание заблуждений надо бы уточнить.

Специально ничего добавлять не нужно, линкер об этом уже позаботился и по адресу 0x1FFFEC04 положил адрес перехода с установленным в 1 младшим битом. Сами адреса памяти, по которым будет производится выборка команд, естественно будут чётными.

 

Эту единичку надо учитывать при интерпретации программы "в уме" и при вычислении адресов перехода "вручную" из указателей на память данных.

 

Это всё досталось в наследство от предыдущих ARM, которые имели два набора команд (32-битные ARM и 16-битные Thumb) и младшим битом загружаемого в PC значения указывалось что нужно переключиться в Thumb.

У кортексов набор команд только один, Thumb-2, переключать нечего, но установленный младший бит в адресах переходов остался "для совместимости".

 

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


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

Младший бит в адресах переходов - признак Thumb mode, поэтому команду надо было начинать дизассемблировать с адреса 0х1FFFEE34.

 

Кроме передачи управления нужно ещё переключить мэппинг памяти, за это отвечают биты MEM_MODE[1:0] в регистре SYSCFG->CFGR1.

 

А, ну точно, надо ж не на 0x1FFFEC04 прыгать, а на адрес, который там хранится.

 

В общем-то, я как делаю: из основной программы по команде выключаю все прерывания, записываю по нулевому адресу рамы ключ, ремаплю нулевой адрес на System Flash (Mem_MODE = 01) и делаю сброс. После сброса - попадаю в __early_init(). Вот поправил указатель:

void __early_init(void)
{
...
    void ( *BootLoader )( void ) = ( ( void * )( void ) ) ( *( ( uint32_t * ) 0x1FFFEC04 ) );
...
}

Хард флотов больше нет, но контроллер после выполнения BootLoader() прыгает то в ресет то в рандомную функцию и через stlink не прогается - приходится стирать прошивку через бутлоадер.

Изменено пользователем Cosworth

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


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

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

static const uint16_t jump2fw[] =
{
    0x6801, // ldr r1, [r0, #0]
    0x468D, // mov sp, r1
    0x6840, // ldr r0, [r0, #4]
    0x4700, // bx r0
};

((void (*)(int))(1 + (int)jump2fw))(FIRMWARE_ADDRESS);

В данном случае FIRMWARE_ADDRESS - это 0, потому что загрузчик, очевидно, ожидает, что его код замапен на нулевой адрес.

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


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

до кучи мой рецепт перехода:

extrn "C" void func();
void test()
{
   func();
}
// В командную строку линкера добавляем -Wl,--defsym,func=адрес

Переход на функцию по указателю (как в вопросе) делал бы так:

extern "C" void (*bootloader)();
void test()
{
    bootloader();
}
// В командную строку линкера добавляем -Wl,--defsym,bootloader=0x1FFFEC04

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


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

до кучи мой рецепт перехода:

Я имел в виду переход на начало прошивки с загрузкой указателя стека и точки входа (так, как стартует Cortex).

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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