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

Как бы тогда перекинуть функцию записи в ОЗУ, и выполнить?

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


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

Как бы тогда перекинуть функцию записи в ОЗУ, и выполнить?

Вот так, к примеру:

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);

Самый переносимый способ. Функцию можно сделать очень компактной, так что особого напряга быть не должно.

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


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

Как бы тогда перекинуть функцию записи в ОЗУ, и выполнить?

Или пользоватся встроенным бутлоадером, или сделать свой.

Основную программу разместить по другому аддрессу.

Тогда и внешняя РАМ не надо

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


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

Самый переносимый способ. Функцию можно сделать очень компактной, так что особого напряга быть не должно.

Но не самый "прямой".

__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, пока что ни разу функция в ОЗУ не потребовалась.

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


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

Да, можно разместить "прошивальщик" в конце flash, например. И не трогать этот сектор никогда.

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


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

Да, можно разместить "прошивальщик" в конце flash, например. И не трогать этот сектор никогда.

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

А вот программа может быть где угодно

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


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

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

А вот программа может быть где угодно

Так стартовать можно, куда задашь. По нулевому адресу расположена таблица startup.

Хорошо, стартанул я в загрузчик. Настроил все нужные режимы, чтобы принять новую прошивку. Жду... а ее нет. Подождал, свалил в основную программу. Так?

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


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

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

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


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

При старте запускается прошивальщик, он проверяет целостность приложения, переключает VTOR на вектора приложения (для Cortex-M0 копирует вектора приложения в ОЗУ и делает ремап), грузит указатель стека из векторов приложения и передает управление на вектор Reset приложения.

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

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

 

В конце flash сектора большие, по 128 KB (речь идет про STM32F20x). Значит, загрузчик надо расположить в начальных секторах, или в OTP (страшно!).

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


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

А если приложение целое, но хочу зашить новую прошивку? Чем подтолкнуть?
Я делаю программный сброс из приложения. А загрузчик после обновления делает сброс по собаке. При старте загрузчика проверяю источник сброса и если он программный - ухожу на обновление, если нет - проверяю целостность и запускаю приложение.

А целостность как определить - CRC посчитать?
Да, тем более что у STM32 есть и аппаратный расчет CRC и DMA.

А размеры кода откуда узнать, хранить во 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

 

 

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

 

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


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

В секторе 0 расположить загрузчик, основную программу начать с сектора 1.

А таблицей векторов нельзя ли одной обойтись? Запретить все прерывания при загрузке, и шабаш?

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


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

В секторе 0 расположить загрузчик, основную программу начать с сектора 1.
Именно.

А таблицей векторов нельзя ли одной обойтись? Запретить все прерывания при загрузке, и шабаш?
Не вижу смысла. Вектора приложения все равно каким-то образом должны попасть на свое место - или через VTOR или через ремап. При этом содержимое векторов загрузчика никакой роли уже не имеет. Никаких плюсов от неиспользования прерываний в загрузчике нет.

 

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


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

Я предусматриваю одну из свободных ног для принудительного запуска загрузчика - если залито приложение, которое хотя и целое, но тем не менее нерабочее, то сняв питание, закоротив эту ногу и подав питание снова, я из кирпича получаю готовое к обновлению устройство.

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

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


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

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

Часто у устройств есть клавиатура или кнопочки, поэтому и без разбора прибора всё прекрасно получается.

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


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

Это нормальное решение. Сам так всегда делаю.

Часто у устройств есть клавиатура или кнопочки, поэтому и без разбора прибора всё прекрасно получается.

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

 

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


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

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

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

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

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

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

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

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

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

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