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

Вызов функций и процедур

Возник вопрос оптимизации размера программы.

Имеется устройство, ПО которого состоит из двух частей:
1. Программа "загрузчик", которая содержит процедуры функции:
- инициализация периферии и работу с ней.
- работа с протоколом
- шифрования/расшифровка данных.

- логика работы "загрузчика"


2. Программа "прошивка", которая содержит процедуры функции:
- инициализация периферии и работу с ней.
- работа с протоколом
- шифрования/расшифровка данных.

- логика работы "прошивки"
- данные для работы "прошивки"

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

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

2. Программа "прошивка", которая содержит процедуры функции:
- логика работы "прошивки"
- данные для работы "прошивки"

Но возникает вопрос, как вызывать процедуры и функции из разных программ? И как это лучше сделать? "загрузчик" и "прошивка" пишутся отдельно и выглядят как разные программы, только вот сборка осуществляется в разные участки памяти микроконтроллера.

Не подскажите что почитать или где можно посмотреть об этом?

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


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

Не ясно, где располагаются загрузчик с прошивкой (флеш NOR или NAND, флеш-диск и т.д.), т.е можно ли напрямую выполнять подпрограммы загрузчика из доступной области памяти или требуется копирование, разжатие, расшифровка и т.д. Можно собрать требуемые подпрограммы принципиально позиционно-независимыми и перемещаемыми, чтобы выдернуть их в ОЗУ, можно предусмотреть формирование в процессе сборки табличек для релокации (на основе соотв. сегмента из например ELF-файла, из которого формируется загрузчик - это зависит от используемой платформы, я делал такое для MIPS), которые используются для настройки подпрограмм после копирования в ОЗУ. Да, и достаточно ли будет ОЗУ для размещения в нём требуемого?

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

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


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

16 minutes ago, GeorgK said:

Не ясно, где располагаются загрузчик с прошивкой (флеш NOR или NAND, флеш-диск и т.д.), т.е можно ли напрямую выполнять подпрограммы загрузчика из доступной области памяти или требуется копирование, разжатие, расшифровка и т.д. Можно собрать требуемые подпрограммы принципиально позиционно-независимыми и перемещаемыми, чтобы выдернуть их в ОЗУ, можно предусмотреть формирование в процессе сборки табличек для релокации (на основе соотв. сегмента из например ELF-файла, из которого формируется загрузчик - это зависит от используемой платформы, я делал такое для MIPS), которые используются для настройки подпрограмм после копирования в ОЗУ. Да, и достаточно ли будет ОЗУ для размещения в нём требуемого?

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

Ну если более детально то выглядит приблизительно так:
"Загрузчик" располагается с адреса 0x8000000
"Прошивка" с адреса 0x8008000

Разработка ведется в Keil.
Вызвать метод по указанному адресу у меня проблем не вызывает. Проблема в том каким методом, при изменении в общих процедурах и функциях, менять указатели на процедуры и функции. Я понял что Вы предлагаете вычитывать это из ELF файлов, то есть написать некую внешнную программу которая будет вызываться по окончанию компиляции "загрузчика", и формировать некий файл описания на основе ELF файла, для последующего использования в "Прошивке"? Я правильно понимаю?

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


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

7 минут назад, Macslim сказал:

Проблема в том каким методом, при изменении в общих процедурах и функциях, менять указатели на процедуры и функции. Я понял что Вы предлагаете вычитывать это из ELF файлов

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

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


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

4 minutes ago, mantech said:

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

То есть сделать таблицу с нужными указателями на нужные функции? Хм.. мне нравится. Спасибо!

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


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

3 часа назад, Macslim сказал:

Но возникает вопрос, как вызывать процедуры и функции из разных программ?

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

2 часа назад, Macslim сказал:

То есть сделать таблицу с нужными указателями на нужные функции? Хм.. мне нравится. Спасибо!

Не понятен смысл: зачем это всё нужно? Реально не хватает флеша? Это выглядит нереалистичным.

И какова была изначальная причина деления ПО на 2 части?

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


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

3 часа назад, jcxz сказал:

И какова была изначальная причина деления ПО на 2 части?

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

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


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

Как обычно, потом окажется, что той "инициализации периферии и работы с ней", реализованной в загрузчике, не хватит при внесении в ПО новых фич и придется в основном ПО писать патч-функции и не факт что их объем, в конечном счете, не превысит первоначальный... Также на ровном месте создаются явные зависимости между загрузчиком и основным ПО, которые, как сейчас может показаться, не должны привести к сложностям. Однако, ИМХО, это ложное предположение... Я бы на месте ТС пока что отложил эту идею и покопался в текущей реализации загрузчика/основного ПО на предмет банального оптимизирующего рефакторинга исходников. Ну а по теме можно посмотреть как, например, в LPC/XMC-микроконтроллерах реализованы так называемые IAP ROM-function. Это примерно то же самое, что Вы, @Macslim, хотите.

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


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

7 часов назад, Macslim сказал:

сделать таблицу с нужными указателями на нужные функции?

Тут всё это подробно расписано.

Но минусы такого подхода вам уже расписали. Лучше до последнего не прибегать к вызову функций из загрузчика в основной программе. Они должны быть максимально независимыми. В идеале основная программа вообще не должна ничего знать о существовании загрузчика.

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


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

16 hours ago, Darth Vader said:

Тут всё это подробно расписано.

Но минусы такого подхода вам уже расписали. Лучше до последнего не прибегать к вызову функций из загрузчика в основной программе. Они должны быть максимально независимыми. В идеале основная программа вообще не должна ничего знать о существовании загрузчика.

Большое спасибо за ссылку!

Ну собственно, сейчас так и есть, "прошивка" не знает о существовании "загрузчика".

По поводу почему программа разделена на "загрузчик" и "прошивку"? Это сделано из-за того что устройство меняет функционал, в зависимости от "прошивки". То есть, через протокол можно менять "прошивку". Например устройство с 4 реле может работать как 4 канала реле, или как два канала управления моторами. То есть аппаратная часть не меняется, а вот логика работы устройства за счет замены "прошивки" меняется кардинально.

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


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

52 минуты назад, Macslim сказал:

По поводу почему программа разделена на "загрузчик" и "прошивку"? Это сделано из-за того что устройство меняет функционал, в зависимости от "прошивки". То есть, через протокол можно менять "прошивку". Например устройство с 4 реле может работать как 4 канала реле, или как два канала управления моторами. То есть аппаратная часть не меняется, а вот логика работы устройства за счет замены "прошивки" меняется кардинально.

И что? Это нисколько не мешает менять всю прошивку целиком. И не оправдывает деления на части и усложнения её.

Есть такой механизм: "условная компиляция", которая позволяет собирать одни и те же исходники под отличающийся функционал.

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


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

1 minute ago, jcxz said:

И что? Это нисколько не мешает менять всю прошивку целиком. И не оправдывает деления на части и усложнения её.

Есть такой механизм: "условная компиляция", которая позволяет собирать одни и те же исходники под отличающийся функционал.

Это понятно. Но как в таком случае менять прошивку если нет доступа до устройства (например под водой или под землей)?

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


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

50 минут назад, Macslim сказал:

Это понятно. Но как в таком случае менять прошивку если нет доступа до устройства (например под водой или под землей)?

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

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


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

59 минут назад, jcxz сказал:

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

Не всегда лишнему корпусу на плате найдется места, равно как и ног у МК... А еще все зависит от девайса: где-то не допустимо отстраняться от основного функционала, отводя время для сервисных функций (в том числе на обновление ПО), а где-то вполне допустимо. А еще, например, способ с приемом прошивки в основном ПО и непосредственно прошивкой в загрузчике не совсем, ИМХО, безопасен - мало ли прошьют ПО с багом, не позволяющим больше скачать прошивку? У меня в последних > 10 устройствах, например, загрузчик - это полноценная программа, по максимуму отлаженная для приема, прошивки и запуска основного ПО. Она не меняется, поэтому нет возможности каким-либо образом запороть железку - пара "клиентское ПО на ПК для обновления"/"загрузочное ПО для МК" остаются статичными в разработке, а посему - стабильными. А коль уж загрузчик весьма сложен, то можно и логику обновления самих загрузчиков реализовать.

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


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

19 минут назад, Arlleex сказал:

Не всегда лишнему корпусу на плате найдется места, равно как и ног у МК... А еще все зависит от девайса: где-то не допустимо отстраняться от основного функционала, отводя время для сервисных функций (в том числе на обновление ПО), а где-то вполне допустимо.

Так и я не говорил про "лишний корпус". Всё зависит от требований, предъявляемых к функционирования устройства: если ОЗУ много и внезапные перезагрузки не страшны - можно принимать в ОЗУ; если много флешь программ - можно в неё (если это не мешает нормальной работе устройства).

У меня, в одном проекте, как-то было много лишнего ОЗУ, а в SPI-флеши - мало места. И требоваось безопасное обновление (устойчивое к перезагрузкам). Так я сделал приём прошивки в ОЗУ (по рабочему протоколу), рестарт в загрузчик. А уже в загрузчике: проверку образа (в ОЗУ), запись его в верхнюю часть флеши программ (нерабочая область флеши), перезапись в рабочую область флеши. Получилось безопасное обновление и дополнительного внешнего чипа флеши не потребовалось.

Ну а если нет времени на "отстранение от основного функционала на обновление", то и обновление невозможно.

 

Цитата

А еще, например, способ с приемом прошивки в основном ПО и непосредственно прошивкой в загрузчике не совсем, ИМХО, безопасен - мало ли прошьют ПО с багом, не позволяющим больше скачать прошивку? У меня в последних > 10 устройствах, например, загрузчик - это полноценная программа, по максимуму отлаженная для приема, прошивки и запуска основного ПО. Она не меняется

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

 

Цитата

поэтому нет возможности каким-либо образом запороть железку

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

Цитата

- пара "клиентское ПО на ПК для обновления"/"прикладное ПО для МК" остаются статичными в разработке, а посему - стабильными. А коль уж загрузчик весьма сложен, то можно и логику обновления самих загрузчиков реализовать.

Вот вот...

 

PS: Обсуждали же это всё уже. И не один раз. Все плюсы и минусы разных подходов известны.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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