Кастомный загрузчик STM32103 - перейти к основной проблеме прошивки - PullRequest
0 голосов
/ 16 апреля 2020

Я успешно реализовал загрузчик шины CAN для микросхемы STM32103C8T6 на основе примера, который я нашел здесь (lbus) https://github.com/alphalove/stm32-projects/tree/master/lbus_bootloader.

Я использовал libopencm3.

У меня это работало очень хорошо, пока я не внес небольшое изменение в код загрузчика. После этого загрузчик больше не будет запускать основную прошивку.

Загрузчик начинается с 0x08000000 и имеет значение 8 КБ. Основная прошивка начинается с 0x08002000.

Помимо прочего, загрузчик проверяет целостность основной прошивки и, если все в порядке, запускает ее, вызывая функцию run_firmware (). Эта функция отключает все периферийные устройства микросхемы, используемые в загрузчике, перед настройкой адреса таблицы векторов, инициализацией указателя основного стека и переходом к началу основной прошивки. Ниже приведен пример / фрагмент функции run_firmware ():

#define FW_ADDR    0x08002000

run_firmware() {     // Set vector table base address.
   // bunch of code to reset all peripherals

   // Set Vector Table address
   SCB_VTOR = FW_ADDR & 0xFFFF;

   // Initialise master stack pointer
   __asm__ volatile("msr msp, %0"::"g"(*(volatile uint32_t *)FW_ADDR));

   // Jump to application
   (*(void (**)())(FW_ADDR + 4))();
}

Это прекрасно работало до сегодняшнего дня, пока я не добавил некоторый дополнительный код загрузчика, который также вызывает функцию run_firmware (). Теперь вызов функции run_firmware не запускает основную прошивку, а скорее завершается ошибкой, пока сторожевой таймер не перезагрузит чип. Пока второй вызов run_firmware () находится в коде, функция больше не работает.

Это ограничение при переходе по адресу? Изменило ли добавление дополнительного вызова расположение кода run_firmware () в двоичном файле, который сейчас вызывает проблему? Что делают% 0 и "g" в ассемблере?

Если честно, код для запуска основной прошивки был black magi c, который я позаимствовал из приведенного выше примера lbus. Так что я не совсем уверен, почему это терпит неудачу.

Если вы не можете сказать ... Я человек с аппаратным видом!

Любое руководство будет наиболее ценно!

Заранее спасибо.

alex

Ответы [ 4 ]

1 голос
/ 16 апреля 2020
  1. Использовать стандартный провайд по определениям регистра STM.
  2. Ваше назначение VTOR неверно
    //FW_ADDR has to be aligned to 0x100
    SCB -> VTOR = FW_ADDR;
    __set_MSP(*(volatile uint32_t *)FW_ADDR);
Перейти к запуску приложения:
    void (*start)(void) = (void *)*(volatile uint32_t *)(FW_ADDR + 4);
    start();

или если вам нравятся странные выражения

    ((void(*)(void))(FW_ADDR + 4))();

Помните, что ваше приложение должно быть связано, чтобы соответствовать новой начальной точке.

static inline __attribute__((always_inline)) void __set_MSP(uint32_t topOfMainStack)
{
  __asm volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
}
0 голосов
/ 29 апреля 2020

Не хватает комментариев, но я подумал, что могу добавить, что есть проект github (marcinbor85 / can-prog), который поддерживает загрузку через встроенный загрузчик (rom) stm32.

Не конечно, если Алекс собирается открыть свой загрузчик с открытым исходным кодом, но есть много синих таблеток, которые могут принести пользу (включая мою!)

0 голосов
/ 17 апреля 2020

@ P_J_, спасибо за вашу помощь, это, безусловно, помогло мне понять механизм перехода на основную прошивку.

Тем не менее, я нашел обходной путь, а не правильное решение проблемы (как FW_ADDR для кажется, что основная прошивка правильно выровнена и не меняется между рабочей и нерабочей версиями загрузчика).

Я только что добавил

static inline __attribute__((always_inline)) 

в мою функцию run_firmware () и теперь это работает правильно с обоих мест, это вызывается в main (). Это будет делать сейчас!

Еще раз спасибо за ваше время!

Приветствия,

alex

0 голосов
/ 16 апреля 2020

Нет никаких ограничений для адреса перехода, за исключением того, что он должен быть помещен в начальный адрес сектора. Чтобы решить вашу проблему, убедитесь, что размер кода вашего загрузчика не превышает 8 КБ, если это так, увеличьте размер загрузчика и измените начальный адрес основного приложения

...