Arlleex 190 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба Приветствую! Пишу сейчас загрузчик под STM32F0. Стирание и запись Flash - процессы весьма затратные по времени. Сначала хотел перетащить в ОЗУ лишь таблицу векторов и сами обработчики прерываний, а также функции стирания/записи Flash. Это чтобы события (прерывания) по тому же UART-у (это канал связи) не пропускать. Плюс события таймера и обслуживание другого канала связи. В итоге решил весь код исполнять из ОЗУ: при старте FlashLoader (код из Flash) копирует рабочий код загрузчика из Flash в ОЗУ и передает ему управление. Но попутно возник вопрос. В IAR, насколько я знаю, есть ключевое слово __ramfunc. Оно заставляет линковать функцию в ОЗУ. Ну ок. Кроме того, как я понял, IAR следит, чтобы и вложенные вызовы других функций, а также обращение к константам производилось тоже из ОЗУ. Т.е. константы, адресуемые через PC, должны быть расположены тоже в ОЗУ, а не во Flash. Так ли это? Если так, то что с косвенным доступом? Например, функция, помеченная как исполняемая из ОЗУ, вызывает другую функцию, но не прямо, а через таблицу указателей на функции. Так вот, если в IAR действительно прослеживается такое поведение, что насчет Keil? Он умеет такое или нет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 2 hours ago, Arlleex said: Сначала хотел перетащить в ОЗУ лишь таблицу векторов... Так M0 же, вектора гвоздями прибиты. И зачем вообще все тащить в ОЗУ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 2 часа назад, Arlleex сказал: Кроме того, как я понял, IAR следит, чтобы и вложенные вызовы других функций, а также обращение к константам производилось тоже из ОЗУ. Т.е. константы, адресуемые через PC, должны быть расположены тоже в ОЗУ, а не во Flash. Так ли это? Так. Даже вроде где-то в документации это отражено. Цитата Если так, то что с косвенным доступом? Например, функция, помеченная как исполняемая из ОЗУ, вызывает другую функцию, но не прямо, а через таблицу указателей на функции. На счёт косвенных не знаю, не пробовал, но если, исходить из логики, думаю __ramfunc добавляет какое-то свойство к типу указателя на функцию и при разыименовании этого указателя не из __ramfunc, скорей всего компилятор должен матюгнуться. Впрочем это нетрудно проверить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 12 минут назад, aaarrr сказал: Так M0 же, вектора гвоздями прибиты. Так remap же. 2 часа назад, Arlleex сказал: Например, функция, помеченная как исполняемая из ОЗУ, вызывает другую функцию, но не прямо, а через таблицу указателей на функции. если сам указатель имеет специальный аттрибут по аналогии с кейлосвским __packed - то, теоретически, может. Если у указателя такого аттрибута нет - то нет и физической возможости у компилятора. Честно говоря сильно сомневаюсь в такой возможности. Я бы зашел с другой стороны - пусть редактор связей (линкер) расположит в ОЗУ (подобно секции инициализированных переменных) вообще все сегменты кроме одного. В этом одном разместить тот самый начальный загрузчик, который будет копировать рабочий код в ОЗУ. Помнится, тут многие писали подобные загрузчики для атмеловских ARMов AT91RM9200, у которых код грузился из NAND во внешнее динамическое ОЗУ, в сети должны остаться примеры. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 3 минуты назад, Сергей Борщ сказал: Я бы зашел с другой стороны - пусть редактор связей (линкер) расположит в ОЗУ (подобно секции инициализированных переменных) вообще все сегменты кроме одного. В этом одном разместить тот самый начальный загрузчик, который будет копировать рабочий код в ОЗУ. У меня сейчас на XMC4700 примерно так и сделано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 34 minutes ago, Сергей Борщ said: Так remap же. Семён Семёныч! Да, как-то упустил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 1 час назад, aaarrr сказал: Так M0 же, вектора гвоздями прибиты. Сергей опередил, действительно можно (и, по-моему это единственный возможный вариант) сделать remap ОЗУ на 0x00000000. 1 час назад, aaarrr сказал: И зачем вообще все тащить в ОЗУ? А как иначе, чтобы не тормозить процессор на момент стирания и записи Flash? МК (1) даже в режиме загрузчика должен взаимодействовать с рядом стоящим МК (2), иначе тот (2) подумает, что я (1) отвалился и будет сыпать ошибки. Следовательно, МК (1), находясь в режиме загрузчика, не только обновляет прошивку по рабочему каналу связи, а еще как бы повторяет часть функционала рабочего ПО. Которое, собственно говоря, в том числе и взаимодействует с МК (2). Соответственно, очень трудно бродить по исходникам и думать, что размещать в ОЗУ, а что нет. Код то выполняется, алгоритм один, значит технически любая функция и любые константы могут быть выбраны (запрошены) из Flash. Это привело бы к торможению. Соответственно, придется копировать всю исполняемую программу в ОЗУ (включая константы) и передавать ей управление. 45 минут назад, Сергей Борщ сказал: Я бы зашел с другой стороны - пусть редактор связей (линкер) расположит в ОЗУ (подобно секции инициализированных переменных) вообще все сегменты кроме одного. В этом одном разместить тот самый начальный загрузчик, который будет копировать рабочий код в ОЗУ... Сейчас, кстати, прорабатываю эту возможность. Так и задумывал сделать. Хочу разместить начальный загрузчик во Flash. И чтобы он копировал код нужной части себя же (т.е. я хочу разработать единый бинарь в итоге). Разбираюсь с Keil-овским scatterload, надо как-то сказать, чтобы он RAM делил между переменными для кода начального загрузчика и самим загрузчиком. Как я понял, есть там ключевое слово OVERLAY. Буду копать в эту сторону. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 18 минут назад, Arlleex сказал: Хочу разместить начальный загрузчик во Flash. И чтобы он копировал код нужной части себя же (т.е. я хочу разработать единый бинарь в итоге). У меня весь загрузчик (загрузчик-прошивальщик) слинкован в ОЗУ. Целиком. А начальный загрузчик (просто загрузчик) - отдельно-скомпилированная программа, выполняющаяся из FLASH и просто копирующая загрузчик-прошивальщик в ОЗУ (со всеми проверками контрольных сумм и т.п.). Начальный загрузчик - чисто на ассемблере, простой цикл копирования с проверками. Он ещё предварительно выбирает один из двух экземпляров загрузчика-прошивальщика, который нужно копировать в ОЗУ (для возможности безопасного обновления загрузчика-прошивальщика). __ramfunc в этом случае не нужен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 13 минут назад, jcxz сказал: У меня весь загрузчик (загрузчик-прошивальщик) слинкован в ОЗУ. Целиком. А начальный загрузчик (просто загрузчик) - отдельно-скомпилированная программа... А, ну этот вариант довольно прост - его я тоже рассматриваю, но после того, какой я хочу запилить. А хочу я одним бинарником - просто хранить несколько проектов не хочется, по крайней мере пока что Вроде все должно быть достаточно просто. Слинковать функцию копирования и передачи управления во Flash. А остальной код (код основного загрузчика) линковать в область ОЗУ. Сейчас буду экспериментировать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 1 hour ago, Arlleex said: МК (1) даже в режиме загрузчика должен взаимодействовать с рядом стоящим МК (2), иначе тот (2) подумает, что я (1) отвалился и будет сыпать ошибки. А польза от этого взаимодействия есть, кроме подавления ошибок? Как-то немного натянуто выглядит, по правде говоря. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 47 минут назад, aaarrr сказал: А польза от этого взаимодействия есть, кроме подавления ошибок? Как-то немного натянуто выглядит, по правде говоря. Во многих прикладных областях есть требования по максимально-допустимому интервалу невыполнения какого-то функционала (если нужно например отслеживать некие события в реальном времени). Соответственно отсюда истекают и требования по максимально-допустимому времени старта устройства после вкл. питания и прочие подобные требования по максимально-допустимому времени неполно-функционального состояния. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 55 минут назад, aaarrr сказал: А польза от этого взаимодействия есть, кроме подавления ошибок? Как-то немного натянуто выглядит, по правде говоря. На этом МК еще управление кучкой дискретных выходов и контроль входов. Есть определенный такт обменов, в течение которого МК обязан ответить. Этот такт около 50мс, время стирания сектора - 30мс (типовое значение). Поэтому я посчитал вполне разумным перетащить все это дело в ОЗУ. Насколько страшно пропустить реальное считывание, продублировав старое состояние того же входа, я пока ответить не могу. Но лучше заложить, что пропуски невозможны, и тогда не придется в будущем исправлять загрузчик, перешивая сотни девайсов P.S. Вопрос по теме. А реально ли разместить RO-, XO-секции региона выполнения по адресу, не совпадающему с адресом региона загрузки? На картинке видно, что RO-секция (ну и XO тоже) исполняемого региона находится на том же месте, в котором она была в регионе загрузки. А я хочу поведение, показанное на том же рисунке для RW-секции. Этим я хотел указать, что выполняемый образ лежит не там, куда его прошили физически. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 7 минут назад, Arlleex сказал: А реально ли разместить RO-, XO-секции региона выполнения по адресу, не совпадающему с адресом региона загрузки? На картинке Зависит от компилятора. На CCS я делал такое. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 16 минут назад, jcxz сказал: Зависит от компилятора. На CCS я делал такое. Понял, спасибо. Буду дальше разбираться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба ИМХО, если хочется выполнять рабочий код из SRAM, то самое правильное будет: - скомпилировать рабочую прошивку с тех адресов, где она штатно будет работать. Так и отлаживать проще. - прошить её во Flash с некоторым смещением, чтобы вначале поместился начальный загрузчик. - Написать начальный загрузчик, который копирует прошивку из flash в SRAM, делает remap и передаёт ей управление. Можно, конечно, чтобы загрузчик был частью основной прошивки, но надо ли? Всё равно, при удалённом обновлении неубиваемый загрузчик лучше иметь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться