Программирование ARM: решение проблем, FAQ IAR EWB for ARM: как из кода C сделать безусловный переход на абсолютный адрес Thu, March 28 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

IAR EWB for ARM: как из кода C сделать безусловный переход на абсолютный адрес Печать
Добавил(а) microsin   

Описывается, как сделать безусловный переход по нужному фиксированному адресу (например 0x108000) для ARM AT91SAM7X256 на языке C в среде IAR Embedded Workbench for ARM (версия 5.20).

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

Сначала я хотел сделать тупой выход из функции main - в надежде, что попаду в код модуля board_cstartup_iar.s после вызова функции main (там тупое зацикливание loop4: B loop4). Зацикливание я думал переправить на B 0x108000. Но, увы, из этого ничего не получилось - почему-то компилятор генерировал такой код, что выполнение после завершения функции main крутилось на обработке SWI_Handler, и обратно в код board_cstartup_iar.s я не попадал (пробовал вызывать функции exit(), _exit(), __exit(), abort(), пробовал просто прерывать основной цикл main - все без толку). Разбираться, как писать обработчик SWI_Handler (чтобы оттуда передать управление по адресу SWI_Handler), мне не хотелось. Поэтому я поступил проще - вызвал подпрограмму по адресу 0x108000. Сделать это можно двумя способами - применив inline ассемблер (директива asm) или указатель на функцию. Теперь примеры реализации этих двух способов. Переход с помощью команды ассемблера (первый пример) более экономен по использованию памяти, а переход с помощью указателя (второй пример) более удобен в плане документирования - адрес перехода определяется константой PGM_START_ADDRESS.

[Переход в коде директивы asm

void main()
{
   // ... тут настроечный код
   while (true)
   {
      // ... тут основной цикл main, который я прерываю,
      // когда нужно закончить работу bootloader
      // и сделать переход по адресу 0x108000
   }
   // ... код завершения, если он нужен
   //запрет всех прерываний
   AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF;
   //безусловный переход по адресу 0x108000
   asm("B 0x108000");
}

[Переход с помощью указателя на функцию]

#define PGM_START_ADDRESS 0x108000
void (*pgm_start_address)(void);

void main()
{
   // ... тут настроечный код
   while (true)
   {
      // ... тут основной цикл main, который я прерываю,
      // когда нужно закончить работу bootloader
      // и сделать переход по адресу 0x108000
   }
   // ... код завершения, если он нужен
   //запрет всех прерываний
   AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF;
   //безусловный переход по адресу 0x108000
   pgm_start_address = (void(*)(void))PGM_START_ADDRESS;
   pgm_start_address();
}

[Ссылки]

1. IAR EWB for ARM: как поменять абсолютный начальный адрес выполнения программы.

 

Комментарии  

 
0 #1 alvy 30.06.2010 22:52
Обсуждение этой темы на electronix: http://electronix.ru/forum/index.php?showtopic=62107

В частности здесь: http://electronix.ru/forum/index.php?s=&showtopic=62107&view=findpost&p=612474 описывается как использовать SWI_Handler для перехода и почему его надо использовать.
Цитировать
 

Добавить комментарий


Защитный код
Обновить

Top of Page