Main - это просто функция. Вы можете переименовать его и написать другой основной, который вызывает любой из них.
Если вы не хотите переименовывать main в исходном коде, вы можете изменить его имя с помощью define или ключа компилятора:
cc -Dmain=main1 ...
(для первой программы) и
cc -Dmain=main2 ...
(для второго). Основной селектор:
int main(void) {
if(x) return main1();
else return main2();
}
Затем свяжите все вместе и загрузите на свой контроллер.
Но есть проблема с ISR: вы не можете назначить две подпрограммы одному вектору irq. Если векторы жестко закодированы в каком-либо месте флэш-памяти (как в большинстве 8-битных контроллеров), вы не можете переключать ISR. Вам нужно написать оболочку ISR, узнающую, какая программа запущена, и вызывающую соответствующий ISR.
UPD
Вторая проблема заключается в том, что статически связанные переменные из первой и второй программ будут находиться в оперативной памяти одновременно, пока используется только один их набор. Это может привести к исчерпанию оперативной памяти (небольшое количество которой часто присутствует в микроконтроллере) слишком рано.
UPD2
О, теперь я действительно понимаю. Если вы хотите связать и загрузить их отдельно, вы должны иметь дело с картами компоновщика. В этом случае одинаковые имена символов (например, многие из основных) не проблема. В карте компоновщика вы должны определить известную точку входа [установить ее в абсолютный адрес], с которой начинается любой код приложения. Код запуска (обычно это код сборки) должен быть связан с этого адреса. От селектора вы должны решить и перейти непосредственно к определенному месту. (Делайте это только для загрузчика, если ваше приложение также является селектором).
Точка входа, предоставляемая компоновщиком, может быть доступна программой как внешняя функция:
int app2_start(void);
{
.... /* condition check */
app2_start(); /* this symbol defined in linker map, not in any source */
}
Но это не адрес его main (), потому что C RTL действительно выполняет много инициализаций (стек, инициализированные переменные, куча, IO и т. Д.), Прежде чем main () может запуститься.
Есть более распространенный способ, с помощью которого загрузчик решает, должен ли он запускаться сам или приложение, потому что, если код приложения не работает, boodloader может стать недоступным.