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

 
 
7 страниц V  < 1 2 3 4 > »   
Reply to this topicStart new topic
> STM32 flash, помогите разобраться
ViKo
сообщение Jul 1 2014, 10:18
Сообщение #16


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

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



Как бы тогда перекинуть функцию записи в ОЗУ, и выполнить?
Go to the top of the page
 
+Quote Post
scifi
сообщение Jul 1 2014, 10:22
Сообщение #17


Гуру
******

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



Цитата(ViKo @ Jul 1 2014, 14:18) *
Как бы тогда перекинуть функцию записи в ОЗУ, и выполнить?

Вот так, к примеру:
Код
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))(&fw_start);

Самый переносимый способ. Функцию можно сделать очень компактной, так что особого напряга быть не должно.
Go to the top of the page
 
+Quote Post
A. Fig Lee
сообщение Jul 1 2014, 11:06
Сообщение #18


Знающий
****

Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467



Цитата(ViKo @ Jul 1 2014, 06:18) *
Как бы тогда перекинуть функцию записи в ОЗУ, и выполнить?

Или пользоватся встроенным бутлоадером, или сделать свой.
Основную программу разместить по другому аддрессу.
Тогда и внешняя РАМ не надо


--------------------
Верить нельзя никому, даже себе. Мне - можно.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 1 2014, 11:07
Сообщение #19


Гуру
******

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



Цитата(scifi @ Jul 1 2014, 13:22) *
Самый переносимый способ. Функцию можно сделать очень компактной, так что особого напряга быть не должно.

Но не самый "прямой".
Код
__attribute__(("section"(".ramfunc")))
void somefunc()
{
     ......

}

*.ld:
......
    .data :
    {
        . = ALIGN(4);
        _sdata = .;                /* start of .data label */
        *(.ramfunc)
        *(.ramfunc.*)
        *(.data)
        *(.data.*)
        . = ALIGN(4);
        _edata = .;                /* end of .data label */
    } > RAM AT > TEXT
    _sidata = LOADADDR(.data);    /* start of initialized data label */

И все. Тело функции будет скопировано перед запуском main() заодно с инициализированными данными (как и ваше, кстати), но обращаться к ней можно напрямую - линкер при обращении к этой функции будет подставлять правильный адрес в ОЗУ, и не нужно писать эту функцию в машинных кодах. Для других компиляторов можно сделать аналогично.
Но сколько работаю с разными Cortex, пока что ни разу функция в ОЗУ не потребовалась.


--------------------
На любой вопрос даю любой ответ
"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
ViKo
сообщение Jul 1 2014, 11:13
Сообщение #20


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

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



Да, можно разместить "прошивальщик" в конце flash, например. И не трогать этот сектор никогда.
Go to the top of the page
 
+Quote Post
A. Fig Lee
сообщение Jul 1 2014, 11:15
Сообщение #21


Знающий
****

Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467



Цитата(ViKo @ Jul 1 2014, 07:13) *
Да, можно разместить "прошивальщик" в конце flash, например. И не трогать этот сектор никогда.

Нет, прошивальщик должен всегда стартовать по нулевому аддрессу, с рестарта. Иначе смысл теряется.
А вот программа может быть где угодно


--------------------
Верить нельзя никому, даже себе. Мне - можно.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jul 1 2014, 11:18
Сообщение #22


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

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



Цитата(A. Fig Lee @ Jul 1 2014, 14:15) *
Нет, прошивальщик должен всегда стартовать по нулевому аддрессу, с рестарта. Иначе смысл теряется.
А вот программа может быть где угодно

Так стартовать можно, куда задашь. По нулевому адресу расположена таблица startup.
Хорошо, стартанул я в загрузчик. Настроил все нужные режимы, чтобы принять новую прошивку. Жду... а ее нет. Подождал, свалил в основную программу. Так?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 1 2014, 11:25
Сообщение #23


Гуру
******

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



Цитата(ViKo @ Jul 1 2014, 14:18) *
По нулевому адресу расположена таблица startup.
Таблица векторов прошивальщика. Приложение со своей собственной таблицей может располагаться где угодно. При старте запускается прошивальщик, он проверяет целостность приложения, переключает VTOR на вектора приложения (для Cortex-M0 копирует вектора приложения в ОЗУ и делает ремап), грузит указатель стека из векторов приложения и передает управление на вектор Reset приложения. Приложение может отсутствовать вообще (или быть испорченным, недозаписанным), в этом случае прошивальщик весело мигая светодиодом ожидает новую прошивку для приложения, записывает ее и делает рестарт. После рестарта прошивальщик проверяет целостность... (далее читать с начала).


--------------------
На любой вопрос даю любой ответ
"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
ViKo
сообщение Jul 1 2014, 11:34
Сообщение #24


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

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



Цитата(Сергей Борщ @ Jul 1 2014, 14:25) *
При старте запускается прошивальщик, он проверяет целостность приложения, переключает VTOR на вектора приложения (для Cortex-M0 копирует вектора приложения в ОЗУ и делает ремап), грузит указатель стека из векторов приложения и передает управление на вектор Reset приложения.

А если приложение целое, но хочу зашить новую прошивку? Чем подтолкнуть?
А целостность как определить - CRC посчитать? А размеры кода откуда узнать, хранить во flash, рядом с CRC?

В конце flash сектора большие, по 128 KB (речь идет про STM32F20x). Значит, загрузчик надо расположить в начальных секторах, или в OTP (страшно!).
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 1 2014, 11:48
Сообщение #25


Гуру
******

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



Цитата(ViKo @ Jul 1 2014, 14:34) *
А если приложение целое, но хочу зашить новую прошивку? Чем подтолкнуть?
Я делаю программный сброс из приложения. А загрузчик после обновления делает сброс по собаке. При старте загрузчика проверяю источник сброса и если он программный - ухожу на обновление, если нет - проверяю целостность и запускаю приложение.
Цитата(ViKo @ Jul 1 2014, 14:34) *
А целостность как определить - CRC посчитать?
Да, тем более что у STM32 есть и аппаратный расчет CRC и DMA.
Цитата(ViKo @ Jul 1 2014, 14:34) *
А размеры кода откуда узнать, хранить во flash, рядом с CRC?
Я размер храню сразу после области векторов приложения. У меня его туда линкет прописывает:
Код
    .text :
    {
        _image_start = .;
        KEEP(*(.isr_vector))

        LONG((_image_end - _image_start) / 4);    /* application size, in 4-byte words */
      
    ....................
    } > TEXT

    .data :
    {
        . = ALIGN(4);
        _sdata = .;                /* start of .data label */
        *(.ramfunc)
        *(.ramfunc.*)
        *(.data)
        *(.data.*)
        . = ALIGN(4);
        _edata = .;                /* end of .data label */
    } > RAM AT > TEXT
    _sidata = LOADADDR(.data);    /* start of initialized data label */

    .crc :
    {
        . = . + 4;        /* reserve space for CRC */
        _image_end = .;
    } > TEXT



Цитата(ViKo @ Jul 1 2014, 14:34) *
Значит, загрузчик надо расположить в начальных секторах, или в OTP (страшно!).
Разумеется в начальных секторах. Чтобы всегда, после заливки чего угодно он всегда стартовал первым и имел возможность залить другое приложения. Я предусматриваю одну из свободных ног для принудительного запуска загрузчика - если залито приложение, которое хотя и целое, но тем не менее нерабочее, то сняв питание, закоротив эту ногу и подав питание снова, я из кирпича получаю готовое к обновлению устройство.


--------------------
На любой вопрос даю любой ответ
"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
ViKo
сообщение Jul 1 2014, 12:15
Сообщение #26


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

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



В секторе 0 расположить загрузчик, основную программу начать с сектора 1.
А таблицей векторов нельзя ли одной обойтись? Запретить все прерывания при загрузке, и шабаш?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 1 2014, 12:22
Сообщение #27


Гуру
******

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



Цитата(ViKo @ Jul 1 2014, 15:15) *
В секторе 0 расположить загрузчик, основную программу начать с сектора 1.
Именно.
Цитата(ViKo @ Jul 1 2014, 15:15) *
А таблицей векторов нельзя ли одной обойтись? Запретить все прерывания при загрузке, и шабаш?
Не вижу смысла. Вектора приложения все равно каким-то образом должны попасть на свое место - или через VTOR или через ремап. При этом содержимое векторов загрузчика никакой роли уже не имеет. Никаких плюсов от неиспользования прерываний в загрузчике нет.


--------------------
На любой вопрос даю любой ответ
"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
doom13
сообщение Jul 1 2014, 13:16
Сообщение #28


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

Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539



Цитата(Сергей Борщ @ Jul 1 2014, 14:48) *
Я предусматриваю одну из свободных ног для принудительного запуска загрузчика - если залито приложение, которое хотя и целое, но тем не менее нерабочее, то сняв питание, закоротив эту ногу и подав питание снова, я из кирпича получаю готовое к обновлению устройство.

И вчём смысл такого решения, если всё равно необходимо будет разобрать всё устройство (что порой бывает не просто), чтобы добраться до платы с процессором. Там уже что ножку коротить, что программатор подключить, особой разницы нету.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 1 2014, 13:32
Сообщение #29


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(doom13 @ Jul 1 2014, 17:16) *
И вчём смысл такого решения, если всё равно необходимо будет разобрать всё устройство (что порой бывает не просто), чтобы добраться до платы с процессором. Там уже что ножку коротить, что программатор подключить, особой разницы нету.
Это нормальное решение. Сам так всегда делаю.
Часто у устройств есть клавиатура или кнопочки, поэтому и без разбора прибора всё прекрасно получается.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
doom13
сообщение Jul 1 2014, 13:41
Сообщение #30


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

Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539



Цитата(demiurg_spb @ Jul 1 2014, 16:32) *
Это нормальное решение. Сам так всегда делаю.
Часто у устройств есть клавиатура или кнопочки, поэтому и без разбора прибора всё прекрасно получается.

Т.е. данная кнопка выносится на корпус и доступна любому пользователю? На мой взгляд, не есть хорошее решение. Если бы какой-то Master мог сделать это по внешней технологической команде, тогда ещё приемлемо.
Go to the top of the page
 
+Quote Post

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

 


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


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