реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Самозагрузчик
inventor
сообщение Apr 7 2016, 06:34
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Подскажите как правильно сделать вот что:

имеется какой то прибор с SD картой на проце STM32
я хочу сделать для пользователя возможность самому менять прошивку.
делал такие вещи для других процов,
с ST возникли некоторые вопросы.

предположим - нужно поменять прошивку прибора,
саму прошивку - бинарник заливаю в корень SD карты.
при включении питания маленькая программа, loader смотрит:
есть ли файл с определенным именем на SD и если есть, то
записывает его в определенный раздел внутренней flash памяти
далее после того как успешно записал бинарник на flash,
стирает его на SD карте. - передает ему управление.
если файла bin нет - то loader просто передает управление программе.

саму программу Loader я хочу разместить
по адресу Flash 0x08000000
а рабочая прошивка, предположим, будет работать с адреса 0x08001000
после того, как бинарник записан по адресу 0x08001000
как мне LOADER - ом передать ему управление?
Go to the top of the page
 
+Quote Post
KRS
сообщение Apr 7 2016, 06:51
Сообщение #2


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(inventor @ Apr 7 2016, 09:34) *
после того, как бинарник записан по адресу 0x08001000
как мне LOADER - ом передать ему управление?


Самый лучший способ IMHO - сделать хардварный reset с помощью watchdog!
лоадер уже не обнаружит прошивку и передаст управление...

Но есть еще нюанс - для того что бы лоадеру обнаружить файл на SD, необходимо частично проинитить периферию..., а передавать управление основной программе после этого не хорошо!
Я ставлю метку в озу по определенному адресу (типа 0x55AAAA55) и если лоадер ее обнаруживает, то стирает и передает управление основной программе (установив адрес таблицы прерываний кончено)
Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 7 2016, 07:05
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Цитата(KRS @ Apr 7 2016, 10:51) *
Самый лучший способ IMHO - сделать хардварный reset с помощью watchdog!
лоадер уже не обнаружит прошивку и передаст управление...

Но есть еще нюанс - для того что бы лоадеру обнаружить файл на SD, необходимо частично проинитить периферию..., а передавать управление основной программе после этого не хорошо!
Я ставлю метку в озу по определенному адресу (типа 0x55AAAA55) и если лоадер ее обнаруживает, то стирает и передает управление основной программе (установив адрес таблицы прерываний кончено)


у меня вот такие вопросы, вектора должны находится по адресу 80000000
как мне сделать так чтобы у прошики эти вектора были переопределены и не накладывались
на адреса векторов у лоадера.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Apr 7 2016, 07:11
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(inventor @ Apr 7 2016, 10:05) *
у меня вот такие вопросы, вектора должны находится по адресу 80000000
как мне сделать так чтобы у прошики эти вектора были переопределены и не накладывались
на адреса векторов у лоадера.


Вся прошивка в целом линкуется с таким скриптом линкера, чтобы осталось пустое место под загрузчик. При этом вектора прошивки будут сдвинуты. Скажем на 0x8001000 - это зависит от размера загрузчика.

Есть такой регистр - VTOR, который задает положение таблицы векторов
Соответственно в загрузчике перед стартом прошивки его надо скорректировать, выставить стек и перейти по адресу сброса

Код
#define PO_START 0x8001000
SCB->VTOR = PO_START;
__set_MSP(*(uint32_t*)PO_START);
__DMB();

typedef void (* pf)();
(*((pf*)(PO_START+4)))();
Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 7 2016, 07:46
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



то есть я делаю в файле линкера для прошивки исправления:
define symbol __ICFEDIT_intvec_start__ = 0x08001000;
define symbol __ICFEDIT_region_ROM_start__ = 0x08001000;
про компиляции программы моя программа и векторы должны начинаться с адреса 0x08001000

теперь в лоадере я должен передать управление по новому адресу вектора сброса: 0x08001000
правильно я понял?

вернее вектор старта + 4, там вроде в начале адрес стека идет

Сообщение отредактировал IgorKossak - Apr 7 2016, 18:33
Причина редактирования: бездумное цитирование
Go to the top of the page
 
+Quote Post
jcxz
сообщение Apr 7 2016, 08:07
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(inventor @ Apr 7 2016, 12:34) *
саму программу Loader я хочу разместить
по адресу Flash 0x08000000
а рабочая прошивка, предположим, будет работать с адреса 0x08001000
после того, как бинарник записан по адресу 0x08001000
как мне LOADER - ом передать ему управление?

В 0x1000 байт не впихнёте работу с файловой системой однозначно. Чтобы загрузчик был маленький, нужно работу с ФС вынести в основное ПО.
Например: основное ПО обнаружив файл с новой прошивкой, формирует в ОЗУ информацию о цепочке кластеров файла прошивки и ставит флаг наличия. Дальше - перегружается (WDT). Дальше - загрузчик видит флаг, считывает прошивку из цепочки кластеров и шьёт её во флеш программ. Стартует новое ПО. Новое ПО, видя что обновилось, стирает исходный файл прошивки. Всё.
Если нужно чтобы операция обновления ПО была устойчива к сбоям питания, то флаг и инфу о цепочку кластеров нужно сохранять в энергонезависимой памяти.
Как передать управление из загрузчика в основное ПО тут уже 100500 раз обсуждалось и не ранее чем позавчера очередной раз. Учитесь искать.
Go to the top of the page
 
+Quote Post
KRS
сообщение Apr 7 2016, 08:09
Сообщение #7


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(inventor @ Apr 7 2016, 10:46) *
вернее вектор старта + 4, там вроде в начале адрес стека идет

да! и стек надо тоже проинитить
у меня такой код, но это для LPC и IAR (просто у IAR в r1 = 0x1000 после присваивания VTOR)
Код
        VTOR = (unsigned)0x1000;
        asm ("ldm r1, {r0,r1}\n"
             "mov r13, r0\n"
             "mov r15, r1");
        while(1);



Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 7 2016, 10:13
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Цитата(jcxz @ Apr 7 2016, 11:07) *
В 0x1000 байт не впихнёте работу с файловой системой однозначно.


а 4 k не влезет но
в 22 киболайт вполне влезает.
с рюшками, uart для отладки и светодиодами
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 7 2016, 13:54
Сообщение #9


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(inventor @ Apr 7 2016, 07:34) *
имеется какой то прибор с SD картой на проце STM32
я хочу сделать для пользователя возможность самому менять прошивку.

У меня есть такой загрузчик. Ему требуется примерно 12K флэша. Я зарезервировал 16К, то есть, приложение компилируется так, чтобы начинаться с 16К.
Файловая система на FatFS, с которой выброшено все, кроме чтения (файл прошивки я не удаляю). Есть варианты для SPI и SDIO доступа к карте.
Если при старте карта и файл с определенным именем на ней обнаружены, загрузчик считывает версию образа и сравнивает с текущей версией прошивки. Прошивка для этого содержит соответствующие поля, которые как данные расположены непосредственно за таблицей векторов. Загрузчик, конечно, знает, что и как искать. Если на карте новая версия, производится запись образа во флэш и его запуск. Во всех остальных случаях загрузчик запускает имеющуюся прошивку сразу.
Go to the top of the page
 
+Quote Post
romas2010
сообщение Apr 7 2016, 15:07
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 25-11-11
Пользователь №: 68 515



Цитата(inventor @ Apr 7 2016, 09:34) *
Подскажите как правильно сделать вот что:
.........
саму программу Loader я хочу разместить
по адресу Flash 0x08000000
а рабочая прошивка, предположим, будет работать с адреса 0x08001000
после того, как бинарник записан по адресу 0x08001000
как мне LOADER - ом передать ему управление?


1) делаете 2 отдельных проекта-загрузчика и основной программы. В каждом проекте задаете свой стартовый адрес (меню keil project->options for target->IROM1),чтобы компилятор генерировал код с данного адреса
2) в код загрузчика добавляете функцию
Код
__asm void run_main_programm()
{
     mov32 r0,#MY_PROGRAMM_START_ADRESS
     ldr r1,[r0]
     mov sp,r1
     ldr pc,[r0,#4]
}

3) прошили, выход из загрузчика
Код
   VTOR=MY_PROGRAM_START_ADRESS;
   run_main_programm();


перед присваиванием VTOR запрещаем прерывания всей используемой в загрузчике периферии+еще запрещаем их в контролеере NVIC

Ну вот собственно и все...не забудьте закоментировать в функции system_init() в коде основной программы строку типа VTOR=FLASH_BASE_ADDRESS, потому как вы уже ему присвоили свою таблицу в коде загрузчика
Go to the top of the page
 
+Quote Post
x893
сообщение Apr 7 2016, 20:01
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Цитата(KnightIgor @ Apr 7 2016, 16:54) *
У меня есть такой загрузчик. Ему требуется примерно 12K флэша. Я зарезервировал 16К, то есть, приложение компилируется так, чтобы начинаться с 16К.
Файловая система на FatFS, с которой выброшено все, кроме чтения (файл прошивки я не удаляю). Есть варианты для SPI и SDIO доступа к карте.
Если при старте карта и файл с определенным именем на ней обнаружены, загрузчик считывает версию образа и сравнивает с текущей версией прошивки. Прошивка для этого содержит соответствующие поля, которые как данные расположены непосредственно за таблицей векторов. Загрузчик, конечно, знает, что и как искать. Если на карте новая версия, производится запись образа во флэш и его запуск. Во всех остальных случаях загрузчик запускает имеющуюся прошивку сразу.

Вот бы его на github'е увидеть !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Apr 7 2016, 21:06
Сообщение #12


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(KnightIgor @ Apr 7 2016, 16:54) *
У меня есть такой загрузчик...


в своё время сделал немного по другому.
прошивка сама себя меняет. есть понятие версия фулл, инкрементальная, модуля. каждый модуль может существовать во флэше несколько экземпляров.
загрузчик подымает последнюю устойчивую версию и все модули которые в него входят. собирает статистику, и содержит маленький проверенный код
записи во флэш. каналы апдэйтов - куча = микроСД, изернет, модбас, вайфай.

благо флэша - как у дурака махорки sm.gif

как то так
(круглый)

Сообщение отредактировал kolobok0 - Apr 7 2016, 21:07
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Apr 8 2016, 05:37
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(kolobok0 @ Apr 8 2016, 00:06) *
в своё время сделал немного по другому.
прошивка сама себя меняет. есть понятие версия фулл, инкрементальная, модуля. каждый модуль может существовать во флэше несколько экземпляров.
загрузчик подымает последнюю устойчивую версию и все модули которые в него входят. собирает статистику, и содержит маленький проверенный код
записи во флэш. каналы апдэйтов - куча = микроСД, изернет, модбас, вайфай.

благо флэша - как у дурака махорки sm.gif


Гм, т.е. вы сделали dll на МК. Главный вопрос - зачем cranky.gif ?

И еще кучка вопросов по реализации, интересно sm.gif
* как тестировали? По идее надо проверять каждую версию с каждым набором версий других модулей
* как линковали? Каждый модуль - как отдельный проект?
* у вас код запускался из flash? Тогда как разруливались несколько экземпляров модулей (адреса же фиксированные на этапе линковки)? Или вы копировали в ОЗУ? Или не применяли команды, которые работают с фиксированными адресами, только по смещению?
* где жила системная библиотека (общая для всех модулей)?
* что происходит с глобальными и статическими переменными? У каждого модуля фиксированный регион RAM? Или все хранится в куче?
* межмодульное взаимодействие как было организовано? Т.е. как позвать функцию из другого модуля?
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 8 2016, 09:26
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(x893 @ Apr 7 2016, 21:01) *
Вот бы его на github'е увидеть !

Не ставил себе такую задачу. Да и там наверняка уже куча такого добра. Для меня выложить проект будет сложно, т.к. его придется вычленить из моей, как модно говорить, экосистемы. Другими словами, мой загрузчик ссылается на много чего из наработаного кода, а этот код частично организован в общие библиотеки, и т.п.
Go to the top of the page
 
+Quote Post
bugdesigner
сообщение Apr 8 2016, 09:55
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 123
Регистрация: 12-06-15
Из: Земля
Пользователь №: 87 133



Вот мой скелет бутлоадераю Выделено под него 16К флеш. В любом случае прийдется выделить целое количество секторов, тк стереть часть сектора невозможно.
CODE
#define APP_ADDRESS (uint32_t)0x08004000

typedef void (*pFunction)(void);
pFunction Jump_To_App;
uint32_t JumpAddr;

int main(void)
{
init_hw(); // Hardware init

upgrade_firmware();

if(check_firmware())
{
// Jump to application
JumpAddr = *(__IO uint32_t*) (APP_ADDRESS + 4);
Jump_To_App = (pFunction) JumpAddr;
// Initialize application's Stack Pointer
__set_MSP(*(__IO uint32_t*) APP_ADDRESS);
Jump_To_App();
}
else Fault();

return 0;
}

APP_ADDRESS - адрес, с которого начинается основное приложение.

upgrade_firmware() - процедура записи приложения в флеш - ищем на SD, если находим, сверяем версию (чтоб не перезписывать одно и то же), обновляем.
check_firmware() - проверяем наличие / валидность приложения. Я, например, считаю CRC, Вы можете изобрести другой метод (напимер ЭЦП).
Fault() - говорит сам за себя - приложения нет / повреждено - "моргаем красным светодиодом".

Основное приложение пишется как обычно, только адрес заггрузки указывается равный APP_ADDRESS.
В Keil это делается в опциях проекта. Project -> Options for target -> Target поле IROM1 = 0x08004000
Кроме этого нужно указать адрес таблицы векторов прерываний равный APP_ADDRESS. Делается это правкой файла system_*.c.
Ищем строку #define VECT_TAB_OFFSET 0x0 и заменяем на свой оффсет #define VECT_TAB_OFFSET 0x4000
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Apr 8 2016, 14:07
Сообщение #16


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Непомнящий Евгений @ Apr 8 2016, 08:37) *
...* как тестировали? ..Каждый модуль - как отдельный проект?...у вас код запускался из flash?
...Или не применяли команды, которые работают с фиксированными адресами, только по смещению?
* где жила системная библиотека (общая для всех модулей)?
...Или все хранится в куче?
... как позвать функцию из другого модуля?


- стандартный отладчик только на уровне азма конечно же, кроме загрузчика. юзается в основном дебажный вывод и мощная система логгирования при
фатальных ошибках.
- каждый модуль отдельный проект, работает из флэша.
- вся адресация относительная.
- все библиотеки = модули(фрииртос, фаты, стандартная либа, менеджэр памяти - их вообщето два, но для модулей - так-же в модуле отдельном)
- куча используется
- загрузчик делает позднее связывание модулей. т.е. есть понятия импортируемых и экспортируемых функций, необходимых аппаратных прерываний,
версии модуля и запрос версии.
- функции зовутся как обычно (в тексте это имеет маленький префикс - вот и всё отличие)

зачем = повышенная отказоустойчивость. и минимум требований к фазе дистанционной апгрэйта кода.

(круглый)



Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 12 2016, 12:44
Сообщение #17


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Сделал, но чего то не получается запустить основную программу
в чем может быть проблема?

утилитой ST Link проверяю - файл записался и лежит правильно в памяти
Загрузчик у меня такой:
CODE

#define FILE_NAME "loader.bin"
#define APP_ADDRESS (uint32_t)0x08008000


do {
/* Монтируем. Если нет файла - выходим на загрузку */
if ((rc = f_mount(0, &fatfs)) == 0) {
PRINTF("INFO: mount OK\r\n");
} else {
PRINTF("ERROR: mount fs\n");
break;
}

/* Открыть на чтение */
rc = f_open(&fil, FILE_NAME, FA_READ);
if (rc == 0) {
PRINTF("INFO: Loader file %s open OK\n", FILE_NAME);
} else {
PRINTF("INFO: Loader file %s doesn't exist. Continue booting", FILE_NAME);
break;
}

/* стираем секторы 2...4*/
FLASH_Unlock();
delay_ms(50);

if(FLASH_COMPLETE == FLASH_EraseSector(FLASH_Sector_2, VoltageRange_3)) {
PRINTF("Erase sector OK\n");
led_toggle(LED3);
}

if(FLASH_COMPLETE == FLASH_EraseSector(FLASH_Sector_3, VoltageRange_3)) {
PRINTF("Erase sector OK\n");
led_toggle(LED3);
}

if(FLASH_COMPLETE == FLASH_EraseSector(FLASH_Sector_4, VoltageRange_3)) {
PRINTF("Erase sector OK\n");
led_toggle(LED3);
}


/* Читаем файл и записываем в секторы flash */
bytes = 0;
addr = APP_ADDRESS;
do {
bw = 0;
rc = f_read(&fil, buf, sizeof(buf), &bw);
if (rc == 0 && bw > 0) {
bytes += bw;
for(i = 0; i < bw; i++) {
FLASH_ProgramByte(addr, buf[i]);
addr++;
}
PRINTF("%d bytes written\n", bytes);
led_toggle(LED4);
delay_ms(50);
}
} while (bw);

rc = f_close(&fil);

// Стираем файл
/* Если файл существует - удалим его */
// rc = f_unlink(FILE_NAME);

} while (0);

/* Disable all interrupts */
RCC->CIR = 0x00000000;

/* Делаем старт по адресу */
JumpAddr = *(__IO uint32_t*) (APP_ADDRESS + 4);
Jump_To_App = (pFunction) JumpAddr;

/* Initialize application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APP_ADDRESS);
Jump_To_App();


Я вижу отладчиком, что до джампа он доходит - а дальше аут

основная прога использует такой скрипт линкера, где установлены адреса:

define symbol __ICFEDIT_intvec_start__ = 0x08008000;
define symbol __ICFEDIT_region_ROM_start__ = 0x08008000;

+ сделал коментарий в вызове из ассемблера SystenInit() - так это уже сделано в загрузчике
компилю образ проги и получаю бинарник program.bin

CODE
;Reset_Handler

; LDR R0, =SystemInit
; BLX R0
LDR R0, =__iar_program_start
BX R0


В чем может быть еще засада?
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 12 2016, 12:52
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(inventor @ Apr 12 2016, 15:44) *
Я вижу отладчиком, что до джампа он доходит - а дальше аут

А поподробнее? В окне дизассемблера нашли инструкцию, которая делает не то, что нужно? Посмотрели значения соответствующих регистров?
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Apr 12 2016, 13:11
Сообщение #19


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Цитата(kolobok0 @ Apr 8 2016, 17:07) *
- загрузчик делает позднее связывание модулей. т.е. есть понятия импортируемых и экспортируемых функций, необходимых аппаратных прерываний,
версии модуля и запрос версии.

А вот это самодельное или от линукс-арм прикрутили?
Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 12 2016, 13:12
Сообщение #20


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Цитата(scifi @ Apr 12 2016, 15:52) *
А поподробнее? В окне дизассемблера нашли инструкцию, которая делает не то, что нужно? Посмотрели значения соответствующих регистров?

делает branch BLX R8
тока в R8 почему то 0x08009f85
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 12 2016, 13:37
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(inventor @ Apr 12 2016, 16:12) *
тока в R8 почему то 0x08009f85

А это хорошо или плохо? Мы же не знаем точку входа в вашу основную программу. Может быть, она там и есть.
Советую отладчиком пройти по этой инструкции и посмотреть, куда она выводит. И кейл, и яр позволяют загрузить отладочную информацию для двух программ (загрузчика и основной программы), то есть переход будет прозрачным для отладчика. Весьма вероятно, что падает основная программа, потому что вы что-то не учли.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Apr 12 2016, 14:26
Сообщение #22


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Kabdim @ Apr 12 2016, 16:11) *
А вот это..


самодельное.
Go to the top of the page
 
+Quote Post
KRS
сообщение Apr 12 2016, 14:26
Сообщение #23


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(inventor @ Apr 12 2016, 15:44) *
Код
    /* Disable all interrupts */
       RCC->CIR = 0x00000000;
    
      /* Делаем старт по адресу */
    JumpAddr = *(__IO uint32_t*) (APP_ADDRESS + 4);
    Jump_To_App = (pFunction) JumpAddr;

    /* Initialize application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) APP_ADDRESS);
    Jump_To_App();


Так делать некорректно!
Во первых не устанавливается новый адрес таблицы векторов ( VTOR )
Во вторых указатель стека будет модифицирован и не будет соответствовать тому что лежит по APP_ADDRESS

И если хотите отлаживать приложение без бутлоадера (если это разные проекты) то надо у IAR в макросах установить запись VTOR - тогда можно без проблем отлаживать.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Apr 12 2016, 14:49
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(KRS @ Apr 12 2016, 17:26) *
Во первых не устанавливается новый адрес таблицы векторов ( VTOR )

По-моему, это все же дело приложения, а не загрузчика.

Цитата(KRS @ Apr 12 2016, 17:26) *
Во вторых указатель стека будет модифицирован и не будет соответствовать тому что лежит по APP_ADDRESS

Где?
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 12 2016, 15:03
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(aaarrr @ Apr 12 2016, 17:49) *
Где?

Строго говоря, компилятору разрешается крутить указатель стека в любой момент, причём в любую сторону. Так что я бы сказал, что такой способ установки указателя стека предполагает некое везение. Ассемблерный код здесь идеологически более правильный. Как обычно, агитирую за свой вариант biggrin.gif
Код
static const uint16_t jump2fw[] =
{
    0xF850, 0xDB04, /* LDR.W SP, [R0], #4   */
    0x6800,         /* LDR.W R0, [R0]       */
    0x4700,         /* BX R0                */
};
((void (*)(int))(1 + (int)jump2fw))(0x08010000);
Go to the top of the page
 
+Quote Post
KRS
сообщение Apr 12 2016, 15:41
Сообщение #26


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(aaarrr @ Apr 12 2016, 17:49) *
По-моему, это все же дело приложения, а не загрузчика.

Нет - загрузчика! Потому что старт приложения происходит по RESET вектору который лежит в таблице прерываний, соотв. VTOR обязан указывать туда...




Цитата(scifi @ Apr 12 2016, 18:03) *
Как обычно, агитирую за свой вариант biggrin.gif


Ну можно и встроенным асмом обойтись...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Apr 12 2016, 16:49
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(KRS @ Apr 12 2016, 18:41) *
Нет - загрузчика! Потому что старт приложения происходит по RESET вектору который лежит в таблице прерываний, соотв. VTOR обязан указывать туда...

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

Цитата(scifi @ Apr 12 2016, 18:03) *
Как обычно, агитирую за свой вариант biggrin.gif

А я - за свой sm.gif
Код
    __set_MSP(*((uint32_t *)IMAGE_START));
    (*((void (**)(void))(IMAGE_START + 4)))();
Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 13 2016, 06:49
Сообщение #28


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Сделал самозагрузчик,
забыл вызвать функцию NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8000); в основной программе
теперь у меня такой вопрос
вот мой загрузчик грузит только то, что есть на внутренней flash
как быть с теми функциями и данными, которые должны располагаться
на RAM памяти? кто должен их располагать правильно?
надо ли так же перераспределить и память RAM, между загрузчиком и основной программой?
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 13 2016, 06:59
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(aaarrr @ Apr 12 2016, 19:49) *
А я - за свой sm.gif
Код
    __set_MSP(*((uint32_t *)IMAGE_START));
    (*((void (**)(void))(IMAGE_START + 4)))();

Скобок много - в глазах рябит biggrin.gif
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 13 2016, 07:54
Сообщение #30


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(inventor @ Apr 13 2016, 07:49) *
вот мой загрузчик грузит только то, что есть на внутренней flash
как быть с теми функциями и данными, которые должны располагаться
на RAM памяти? кто должен их располагать правильно?
надо ли так же перераспределить и память RAM, между загрузчиком и основной программой?

Ничего специально делать не нужно. Если у Вас основная программа не bare bones (иными словами, написана в рамках среды разработки и с использованием стандартных библиотек среды), то перед переходом в main() втихую вызывается инициализация RAM. Она прочищает/устанавливает необходимые области/переменный RAM. Все, что пользовал загрузчик, будет бесследно "перезатерто".

Цитата(aaarrr @ Apr 12 2016, 17:49) *
Код
    __set_MSP(*((uint32_t *)IMAGE_START));
    (*((void (**)(void))(IMAGE_START + 4)))();

Вставлю свои 5 копеек: в ассемблерном стартовом файле я дописал:

Код
VTOR            EQU     (0xE000E000 + 0x0D08)                
StartMainApp    PROC   ; R0 - parameter with the APP vector table address
                EXPORT  StartMainApp               [WEAK]
                LDR     R1, =VTOR                  ; Load VTOR register address
                STR     R0, [R1]                   ; Store to VTOR to relocate the vector table
                LDR     SP, [R0]                   ; Reinit the user stack
                LDR     R0, [R0, #4]               ; Get the user entry point...
                BX      R0                         ; ... and jump to it
                ENDP

В С-шном файле вызов выглядит как:
Код
extern StartMainApp(uint32_t vector);
...
StartMainApp(0x08000000 + 0x4000); // для моего случая программы с 16К

Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 13 2016, 08:03
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (scifi @ Apr 12 2016, 18:03) *
Ассемблерный код здесь идеологически более правильный.

Ассемблерный код в данном случае, как телеге пятое колесо sad.gif.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 13 2016, 08:10
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(zltigo @ Apr 13 2016, 11:03) *
Ассемблерный код в данном случае, как телеге пятое колесо sad.gif.

Я ж не заставляю. У нас свободная страна. Каждый волен иметь своих тараканов в голове laughing.gif
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 13 2016, 09:00
Сообщение #33


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(scifi @ Apr 13 2016, 09:10) *
Я ж не заставляю. У нас свободная страна. Каждый волен иметь своих тараканов в голове laughing.gif

ОТ: о какой стране речь? wink.gif
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 13 2016, 09:41
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(KnightIgor @ Apr 13 2016, 12:00) *
ОТ: о какой стране речь? wink.gif

А, ну да. Разъехались, панимаишь, по свету. Космополиты laughing.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 13 2016, 09:47
Сообщение #35


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (scifi @ Apr 13 2016, 12:41) *
А, ну да. Разъехались, панимаишь, по свету. Космополиты laughing.gif

К делу отношения не имеет, но я никуда не "разъехались", я сейчас на родине. А писать стараюсь всегда максимально четко и без привлечения лишних сущностей и заплаток. В данном случае вызов пишется на чистейшем как слеза Си. Посему и пятое колесо не нужно.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 13 2016, 09:50
Сообщение #36


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(zltigo @ Apr 13 2016, 12:47) *
В данном случае вызов пишется на чистейшем как слеза Си. Посему и пятое колесо не нужно.

Вы свою версию вызова не привели. Все уже предъявили, а Вы скрываете rolleyes.gif Код - в студию!
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 13 2016, 10:03
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (scifi @ Apr 13 2016, 12:50) *
Вы свою версию вызова не привели. Все уже предъявили, а Вы скрываете rolleyes.gif Код - в студию!

Абсолютно совпадает с той, котрую я ранее поддержал.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 13 2016, 10:14
Сообщение #38


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(zltigo @ Apr 13 2016, 13:03) *
Абсолютно совпадает с той, котрую я ранее поддержал.

Наверное, поддержали мысленно, потому что здесь не видно. Ну да ладно.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 13 2016, 10:21
Сообщение #39


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Коль все предъявили, тогда и я...: rolleyes.gif
Код
/* Адрес таблицы */
      SCB->VTOR = APPL_ADDR;
    
/* Указатель на приложение */
      pFunc_t JumpAppl = (pFunc_t)(*(__IO uint32_t *)(APPL_ADDR + 4));
      __set_MSP(*(__IO uint32_t *)APPL_ADDR);
      JumpAppl();
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 13 2016, 10:35
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(ViKo @ Apr 13 2016, 13:21) *
Коль все предъявили, тогда и я...: rolleyes.gif
Код
      __set_MSP(*(__IO uint32_t *)APPL_ADDR);
<-- компилятор может изменить значение указателя стека
      JumpAppl();

Выше было сказано: где гарантия, что компилятор не изменит значение указателя стека перед переходом?
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 13 2016, 10:43
Сообщение #41


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(scifi @ Apr 13 2016, 13:35) *
Выше было сказано: где гарантия, что компилятор не изменит значение указателя стека перед переходом?

Я, что, своего загрузчика не знаю? rolleyes.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 13 2016, 11:14
Сообщение #42


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (scifi @ Apr 13 2016, 11:50) *
Все уже предъявили, а Вы скрываете
Не все еще.
CODE
struct application
{
    struct vectors
    {
        typedef void( *handler )( void );
        uint32_t    MSP_init;
        handler     Reset_vector;
        handler     Core_handler[14];
        handler     MCU_handler[MCU_VECTORS];
    }       Vectors;
    uint32_t Size;                          // application size, 4-byte words
};

extern application const Application;

....
            {
                // set vectors table to application vectors
                SCB->VTOR = (uintptr_t)&Application.Vectors;
                __set_MSP(Application.Vectors.MSP_init);
                Application.Vectors.Reset_vector();
            }

// в скрипте линкера:
    .application (NOLOAD):
    {
        Application = .;
    } > APPLICATION



--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Apr 13 2016, 16:28
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(scifi @ Apr 13 2016, 13:35) *
Выше было сказано: где гарантия, что компилятор не изменит значение указателя стека перед переходом?

Повторюсь: раз приложение стартует после загрузчика, то все эти требования излишни. Стек и VTOR может поставить и самостоятельно. Реально нужен только переход.
Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 22 2016, 18:59
Сообщение #44


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



В догонку.
все работает, загрузчик загружает, с одним НО...
если в начале кода делаю инициализацию USB - виснет
коментирую USB - запускается.
в чем может быть проблема?
платка дискавери с stm407
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 22 2016, 19:13
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(inventor @ Apr 22 2016, 21:59) *
если в начале кода делаю инициализацию USB - виснет
коментирую USB - запускается.

Не помню, говорили вам или нет. Переход на основную программу хорошо делать сразу после сброса. Именно для того, чтобы МК был в состоянии как после сброса. А если прыгаете туда абы как с инициализированными кусками периферии, то сами и разбирайтесь в своём зоопарке.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 12:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.0196 секунд с 7
ELECTRONIX ©2004-2016