У меня есть система с процессором MPC8548. Моя работа заключается в том, чтобы отправить вторую (внешнюю) программу на работающую прошивку и выполнить ее.
У меня настроен кросс-компилятор для сборки базовой прошивки и внешнего кода.
Мне удалось отправить отдельную программу во время выполнения (я не уверен, что это правильно, ноКажется, это работает). Вот как я это сделал: в оригинальной прошивке я освободил место для внешнего кода, вставив множество nop
инструкций, начиная с определенного адреса памяти в разделе .text
. После этого во время выполнения я скопировал полученный внешний код (скомпилированный код с использованием gcc, файл .o
) по этому адресу памяти, используя memcpy
. Затем в оригинальной прошивке я сделал указатель на функцию, указывая на эту ячейку памяти и вызвал ее.
Это внешний простой код:
int external_main(void)
{
int x = 11;
return x;
}
И вот как я его назвалв исходной прошивке:
int (*extFuncPtr)(void);
extFuncPtr = &external_start;
int x = extFuncPtr();
external_start
указано в разделе .text
скрипта компоновщика (это начальный адрес инструкции nop
) и в коде, объявленном как extern unsigned char external_start;
Я распечатал эту область памяти и внешний код там, и он успешно работает (если я загружаю туда какой-то мусор, он вылетает).
Моя проблема в том, что я не могу получить какие-либо возвращаемые данные из внешнегокод. Значение x
будет мусором. Я попытался передать int*
в качестве параметра функции, но он все еще пуст. Я также пытался что-то написать по фиксированному адресу (во внешнем коде) и прочитать тот же адрес в прошивке, но это тоже не сработало.
У меня вопрос, возможно ли получить какие-либо данные? из внешнего кода? Возможно, я что-то делаю не так или что-то упущено.
Есть ли другие способы решения этой проблемы?
EDIT 1 Это сгенерированная сборка внешнего кода(вызывая objdump):
00000000 <external_main>:
0: 94 21 ff e0 stwu r1,-32(r1)
4: 93 e1 00 1c stw r31,28(r1)
8: 7c 3f 0b 78 mr r31,r1
c: 39 20 00 0b li r9,11
10: 91 3f 00 08 stw r9,8(r31)
14: 81 3f 00 08 lwz r9,8(r31)
18: 7d 23 4b 78 mr r3,r9
1c: 39 7f 00 20 addi r11,r31,32
20: 83 eb ff fc lwz r31,-4(r11)
24: 7d 61 5b 78 mr r1,r11
28: 4e 80 00 20 blr
Если я добавлю эту функцию external_main
в прошивку, она выдаст те же инструкции. И когда я его вызываю, это выглядит так:
6dbdc: 4b ff 74 b5 bl 65090 <external_main>
6dbe0: 90 7f 00 3c stw r3,60(r31)
И это сгенерированные инструкции части указателя функции:
6dbb8: 3d 20 00 15 lis r9,21
6dbbc: 39 29 18 ec addi r9,r9,6380
6dbc0: 91 3f 00 34 stw r9,52(r31)
6dbc4: 81 3f 00 34 lwz r9,52(r31)
6dbc8: 7d 29 03 a6 mtctr r9
6dbcc: 4e 80 04 21 bctrl
6dbd0: 90 7f 00 38 stw r3,56(r31)
EDIT 2
Итак, я много чего пробовал, чтобы увидеть, в чем может быть проблема, включая загрузку всей основной прошивки в качестве внешней программы (она также вводит прошивку в прошивку во время выполнения). Я вызвал функцию, которая возвращает число, и это сработало. Поэтому я начал очищать вторичную прошивку (выбрасывая все ненужное), постоянно проверяя, работает ли она по-прежнему или нет. И он работал до тех пор, пока размер двоичного файла не стал меньше 16 килобайт.
Когда размер внешней программы меньше 16 КБ, он просто не работает (не может получить никаких возвращаемых значений), но когда он равен 16или выше, это работает. Он возвращает значения, также если я передам указатель на массив в качестве входного параметра (выделенный в базовой прошивке) и заполню его во внешнем коде, когда он вернет, массив будет там, заполнен.
Дон 'Я не знаю, почему это происходит, но это работает. Внешний код в любом случае не будет меньше 16 КБ, так что это победа в моей книге. Если у кого-то есть идея, почему он так себя ведет, я буду рад это услышать.