реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Как создать таблицу векторов прерываний в boot-области?
Xenia
сообщение Jan 13 2009, 11:55
Сообщение #1


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



IAR: как создать таблицу векторов прерываний в boot-области?

Обычно таким вопросом не задаются, т.к. таблица прерываний создается автоматически в самом начале CODE-сегмента. Устанавливая перед фунциями-обработчиками прерываний прагму "#pragma vector=", мы тем самым вызываем заполнение ячейки этой таблицы, соответствующей указанному номеру вектора.

Но как быть, если таких таблиц нужно две? Для самого приложения (расположенного в нижних адресах flash-памяти) и загрузчика (расположенного в boot-области). Когда загрузчик перепрошивает приложение (нижние адреса), то он нуждется в своей собственной таблице прерываний, т.к. своими действиями он затирает таблицу векторов, обслуживающую приложение. Т.е. в данном случае должен иметь автономию от приложения.

Ситуация усугубляется еще и тем, что объем application-области на всех видах микропроцессоров превышает объем оперативной памяти (SRAM), из-за чего невозможно сначала принять новую прошивку целиком, а потом заняться прошивкой, не используя прерываний. Вот и приходится прошивать по-странично: страничку (256 байт) принимаю, записываю, читаю по USB прошивку для следующей страницы и т.д. К сожалению, загрузчик у меня USB-ый, а без использования прерываний работать по USB-каналу, по-видимому, невозможно. Вот и получается, что загрузчику нужна собственная таблица векторов прерываний, независимая от таблицы того приложения, которое он перепрошивает.

Из описания микропроцессора (ATmega647) вроде бы следует, что переключение между нижней и верхней таблицами прерываний осуществляется битом IVSEL регистра MCUCR:
Цитата
2. When the IVSEL bit in MCUCR is set, Interrupt Vectors will be moved to the start of the Boot Flash Section. The address of each Interrupt Vector will then be the address in this table added to the start address of the Boot Flash Section.

С этим, кажется, проблем нет. Дело осталось за малым - как создать такую таблицу средствами IAR? На ассемблере у меня такой проблемы просто бы не возникло.

Как помещать функции в boot-область я поняла - пишешь перед каждой из них прагму "#pragma local="BOOT"", предварительно создав кодовый сегмент с именем BOOT в опциях линкера или конфигурационном файле. Но как создать таблицу векторов прерываний, состоящих из одних команд rjmp?

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

Думала над возможностью сделать два отдельных проекта для приложения и для загрузчика, в каждом из которых CODE-сегмент определен по-разному. И таблицы векторов прерываний тогда будут отдельные. Но возникает проблема объединить обе прошивки в одну, а я таких средств не знаю. Тем более что мой программатор не позволяет дописывать прошивку в кристалл, а полностью стирает всю предыдущую информацию перед прошивкой.

Кроме того, опции линкера одни и те же для всех модулей проекта, а потому в одном проекте я объединить обе программы не могу.

Возникшие затруднения самостоятельно разрешить не смогла, а потому обращаюсь к вам за советом.

Сообщение отредактировал Xenia - Jan 13 2009, 12:02
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Jan 13 2009, 12:05
Сообщение #2


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



В линкере создаете сегмент типа MY_BOOT говорите где ему начинаться и какой он размер имеет, в программе говорите что эти данные надо размещать в сегменте MY_BOOT, нужно еще будет задействовать специальные директивы (__root) для того что бы компилятор не выкинул этот кусок.
Go to the top of the page
 
+Quote Post
sergik_vrn
сообщение Jan 13 2009, 12:10
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 152
Регистрация: 11-10-05
Из: Воронеж
Пользователь №: 9 491



Цитата(Xenia @ Jan 13 2009, 14:55) *
IAR: как создать таблицу векторов прерываний в boot-области?
С этим, кажется, проблем нет. Дело осталось за малым - как создать такую таблицу средствами IAR? На ассемблере у меня такой проблемы просто бы не возникло.

Как помещать функции в boot-область я поняла - пишешь перед каждой из них прагму "#pragma local="BOOT"", предварительно создав кодовый сегмент с именем BOOT в опциях линкера или конфигурационном файле. Но как создать таблицу векторов прерываний, состоящих из одних команд rjmp?

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

Цитата
Думала над возможностью сделать два отдельных проекта для приложения и для загрузчика, в каждом из которых CODE-сегмент определен по разному. И таблицы векторов прерываний тогда будут отдельные.

совершенно логичное рассуждение

Цитата
Но возникает проблема объединить обе прошивки в одну, а я таких средств не знаю. Тем более что мой программатор не позволяет дописывать прошивку в кристалл, полностью стирая предыдущую информацию перед прошивкой.

вообще-то, после того, как написан и отлажен бут-сектор, прошивать пользовательскую программу можно (и нужно) с его помощью (не используя "Ваш программатор")
Go to the top of the page
 
+Quote Post
Xenia
сообщение Jan 13 2009, 13:08
Сообщение #4


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(MALLOY2 @ Jan 13 2009, 15:05) *
В линкере создаете сегмент типа MY_BOOT говорите где ему начинаться и какой он размер имеет, в программе говорите что эти данные надо размещать в сегменте MY_BOOT, нужно еще будет задействовать специальные директивы (__root) для того что бы компилятор не выкинул этот кусок.


Ну, а я создала сегмент с названием BOOT, а не MY_BOOT - велика ли разница? Вот что я уже раньше писала:
Цитата
Как помещать функции в boot-область я поняла - пишешь перед каждой из них прагму "#pragma local="BOOT"", предварительно создав кодовый сегмент с именем BOOT в опциях линкера или конфигурационном файле. Но как создать таблицу векторов прерываний, состоящих из одних команд rjmp?

Как видите, размещать код в boot-области я умею, и сразу про это написала, чтобы не вызывать лишних разговоров. Но судя о вашему ответу, это все-таки произошло.

За совет использвать директиву __root спасибо, попробую с ней разобраться. Тем не менее, не ясно как писать эту таблицу. Если вам это кажется очевидным, но напишите хотя бы начало такой таблицы на первые два вектора прерывания. Как это должно выглядеть, чтобы компилятор не послал меня далеко и надолго?

====================

Цитата(sergik_vrn @ Jan 13 2009, 15:10) *
для размещения векторов прерываний есть предопределенный сегмент INTVEC. если Вы будете создавать векторы стандартным образом, компилятор автоматически положит их по нужному смещению в этом сегменте. если понадобится изменить расположение сегмента, это делается с помощью настроек линкера


Такое решение не годится, т.к. сегмент INTVEC (как и любой другой сегмент) являтся НЕПРЕРЫВНЫМ, а мне по условию задачи нужны две РАЗНЫЕ таблицы прерывания в РАЗНЫХ областях памяти.
Вопреки вашим словам, компилятор "стандартным образом" все кладет в начало одного и того же INTVEC-сегмента, а система проекта не позволяет одному модулю назначить один INTVEC-сегмент, а другому другой. Причина в том, что расположение сегментов определяется в опциях линкера и является ОБЩИМ для всего проекта, на сколько бы текстовых файлов он ни был поделен. Поэтому я никак не могу одну функцию-обработчик асооциированть с нижнией областью flash-памяти, а другую с верхней. Компилятор понимает только одну ЕДИНСТВЕННУЮ таблицу прерываний, всегда соответствующую сегменту INTVEC, которых не может быть две штуки.

Сообщение отредактировал Xenia - Jan 13 2009, 13:12
Go to the top of the page
 
+Quote Post
sergik_vrn
сообщение Jan 13 2009, 13:12
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 152
Регистрация: 11-10-05
Из: Воронеж
Пользователь №: 9 491



Цитата(Xenia @ Jan 13 2009, 16:08) *
Так решение не годится, т.е. сегмент INTVEC (как и любой другой сегмент) являтся НЕПРЕРВНЫМ, а мне по условию задачи нужны две РАЗНЫЕ таблицы прерывания в РАЗНЫХ оболастях памяти.

Вы не поняли мой ответ. основной смысл был не в том, какой сегмент использовать (это так, комментарий по ходу дела), а в том, что Вам надо сделать именно ДВА проекта, а не пытаться объединить бут-сектор вместе с основной программой в один проект. Даже не могу представить, для чего такое извращение может понадобиться, ибо насчет загрузки я пояснял, если Вы запишете бутлоадер Вашим программатором, после этого основную программу грузить этим же программатором (стирая бутсектор) не потребуется
Go to the top of the page
 
+Quote Post
Xenia
сообщение Jan 13 2009, 13:30
Сообщение #6


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(sergik_vrn @ Jan 13 2009, 16:12) *
Вы не поняли мой ответ. основной смысл был не в том, какой сегмент использовать (это так, комментарий по ходу дела), а в том, что Вам надо сделать именно ДВА проекта, а не пытаться объединить бут-сектор вместе с основным в один проект.


Как сделать два проекта, я и сама знаю. Но моя проблема именно в том, что мне нужна СРАЗУ ПОЛНАЯ прошивка с нижней и верхней областью. В этом и состоял мой вопрос. На ассемблере могу сделать это играючи, а вот на IARе возникают непреодолимые проблемы из-за того, что тому никак нельзя растолковать, что таблиц прерывания может быть две.
Еще раз повторяю, что в данном разделе обсуждаются возможности применения компилятора IAR, и мой вопрос целиком относится к этой теме. Перевод моего вопроса в плоскость "зачем всё это мне нужно" - флейм не по теме. Тем более что я уже достаточно подробно объяснила причины, по которым мне нужно работающее приложение и одновременно возможность его перепрошивки в будущем, когда оно устареет или в нем обнаружатся ошибки.

Цитата(sergik_vrn @ Jan 13 2009, 16:12) *
Даже не могу представить, для чего такое извращение может понадобиться. Насчет загрузки я тоже пояснил, если Вы запишете бутлоадер Вашим программатором, после этого основную программу грузить этим де программатором (стирая бутсектор) не потребуется


Такой подход не технологичен. Микропроцессоры можно прошивать скопом еще до стадии впаивания в плату, после чего изделия сразу становятся рабочими и доступными для тестирования. А мертвые изделия, с каждым из которых надо потом индивидуально возиться с допрошивкой, создают массу проблем.
Опять же я не смогу перед руководством доказать необходимость программирования за два этапа. Мне резонно скажут, что я дура, если не могу прошить микропроцессор за один раз (в трудозатратах мое руководство толк понимает, а в программировании не сечет).

Сообщение отредактировал Xenia - Jan 13 2009, 13:40
Go to the top of the page
 
+Quote Post
sergik_vrn
сообщение Jan 13 2009, 13:45
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 152
Регистрация: 11-10-05
Из: Воронеж
Пользователь №: 9 491



Цитата(Xenia @ Jan 13 2009, 16:30) *
Как сделать два проекта, я и сама знаю. Но моя проблема именно в том, что мне нужна СРАЗУ ПОЛНАЯ прошивка с нижней и верхней областью. В этом и состоял мой вопрос. На ассемблере могу сделать это играючи, а вот на IARе возникают непреодолимые проблемы из-за того, что тому никак нельзя растолковать, что таблиц прерывания может быть две.

думаю, растолковать трудно именно потому, что никто до Вас подобной проблемой не озадачивался

Цитата
Еще раз повторяю, что в данном разделе обсуждаются возможности применения компилятора IAR, и мой вопрос целиком относится к этой теме. Перевод моего вопроса в плоскость "зачем всё это мне нужно" - флейм не по теме.

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

Цитата
Тем более что я уже достаточно подробно объяснила причины, по которым мне нужно работающее приложение и одновременно возможность его перепрошивки в будущем, когда оно устареет или в нем обнаружатся ошибки.

это не требуется объяснять, у всех то же самое

Цитата
Такой подход не технологичен. Микропроцессоры можно прошивать скопом еще до стадии впаивания в плату, после чего изделия сразу становятся рабочими и доступными для тестирования. А мертвые изделия, к каждым из которых надо индивидуально возиться с допрошивкой, создают массу проблем.
Опять же я не смогу пред руководством доказать необходимость программирования за два этапа. Мне резонно скажут, что я дура, если не могу прошить микропроцессор за один раз.

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

Возвращаясь к нашим баранам:
1 вариант: напишите ассемблерную вставку, куда включите вызовы всех необходимых Вам прерываний, вставку разместите в нужном сегменте. после этого начинайте воевать с объединением настроек компилятора и линкера
2 вариант: объедините готовые скомпилированные прошивки в один исполняемый файл после линковки. если прошивка меняется редко (а судя по описанной технологии так и есть), это можно сделать чуть ли не вручную
Go to the top of the page
 
+Quote Post
Xenia
сообщение Jan 13 2009, 14:06
Сообщение #8


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(sergik_vrn @ Jan 13 2009, 16:45) *
2 вариант: объедините готовые скомпилированные прошивки в один исполняемый файл после линковки. если прошивка меняется редко (а судя по описанной технологии так и есть), это можно сделать чуть ли не вручную


И про это я уже думала. HEX-прошивки действительно можно объединить вручную. Только есть одна закавыка. В программе приложения имеется команда, которая АКТИВИЗИРУЕТ загрузчик. Т.е. фактически это простой вызов функции из boot-области, откуда возврата больше не будет до окончания прошивки. И вот этот вызов мне будет сложно реализовать, т.к. при раздельном приготовлении проектов такие вызовы делать нельзя. В противном случае будет непонятно, как мне активизировать загрузчик в случае возникшей необходимости.

С этим же вопросом связан еще и другой: функции поддержки обмена по USB-каналу (а они достаточно объемные!) можно было бы держать ТОЛЬКО в загрузчике (boot-области), а приложение попросту бы ими пользовалось. Но такое можно организовать только в том случае, если приложение и загрузчик удастся объединить в одном проекте.

Может у вас все-таки появятся какие-нибудь мысли, чтобы не разъединять программу на два проекта? Тем более, что мне от верхней таблицы прерывания нужны всего лишь 2 вектора: USB_General_vect и USB_Endpoint_Pipe_vect. Остальные прерывания я на время прошивки блокирую, включая таймеры. Понимаете? Всего-то два джампа на нужных местах решило бы мою прблему.

Сообщение отредактировал Xenia - Jan 13 2009, 14:11
Go to the top of the page
 
+Quote Post
sergik_vrn
сообщение Jan 13 2009, 14:30
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 152
Регистрация: 11-10-05
Из: Воронеж
Пользователь №: 9 491



Цитата(Xenia @ Jan 13 2009, 17:06) *
И про это я уже думала. HEX-прошивки действительно можно объединить вручную. Только есть одна закавыка. В программе приложения имеется команда, которая АКТИВИЗИРУЕТ загрузчик. Т.е. фактически это простой вызов функции из boot-области, откуда возврата больше не будет до окончания прошивки. И вот этот вызов мне будет сложно реализовать, т.к. при раздельном приготовлении проектов такие вызовы делать нельзя. В противном случае будет непонятно, как мне активизировать загрузчик в случае возникшей необходимости.

что-то я не до конца, видать, понял Вашу задачу. обычно загрузчик потому и называется "загрузчик", и размещается в "boot-секторе", что он загружается ДО основной программы, потом определяет необходимость перехода в специальный (загрузочный) режим, после чего либо переходит в него, либо передает управление основной программе.
в любом случае, активизация как загрузчика, так и основной программы, не представляет проблем и производится путем передачи управления по заранее оговоренному адресу (в случае выхода из загрузчика для AVR это адрес 0x0000). Например, так
Код
void (*funcptr)( void ) = 0x0000; // Set up function pointer to RESET vector.
funcptr();

В любом случае, совместная линковка и уж тем более компиляция тут никак ни причем.

Цитата
С этим же вопросом связан еще и другой: функции поддержки обмена по USB-каналу (а они достаточно объемные!) можно было бы держать ТОЛЬКО в загрузчике (boot-области), а приложение попросту бы ими пользовалось. Но такое можно организовать только в том случае, если приложение и загрузчик удастся объединить в одном проекте.

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

Цитата
Может у вас все-таки появятся какие-нибудь мысли, чтобы не разъединять программу на два проекта? Тем более, что мне от верхней таблицы прерывания нужны всего лишь 2 вектора: USB_General_vect и USB_Endpoint_Pipe_vect. Остальные прерывания я на время прошивки блокирую, включая таймеры. Понимаете? Всего-то два джампа на нужных местах решило бы мою прблему.

именно это я Вам и пытаюсь объяснить, Ваша проблема вовсе не в двух джампах, их-то разместить по определенным адресам проще всего. проблема в том, что Вы пытаетесь прикрутить проволокой решение, противоречащее идеологии компилятора. в итоге куча нетривиальных сложностей, тянущихся друг за другом. зато если пользоваться двумя разными проектами, проблема (условная) может встать только при объединении hex-файлов, все остальное легко решается средствами языка
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 13 2009, 14:41
Сообщение #10


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Xenia @ Jan 13 2009, 16:06) *
И про это я уже думала. HEX-прошивки действительно можно объединить вручную.
Ну зачем же вручную?  SRecord вам поможет.
Цитата(Xenia @ Jan 13 2009, 16:06) *
Только есть одна закавыка. В программе приложения имеется команда, которая АКТИВИЗИРУЕТ загрузчик. Т.е. фактически это простой вызов функции из boot-области, откуда возврата больше не будет до окончания прошивки. И вот этот вызов мне будет сложно реализовать, т.к. при раздельном приготовлении проектов такие вызовы делать нельзя. В противном случае будет непонятно, как мне активизировать загрузчик в случае возникшей необходимости.
Как раз это - самое простое. Вы можете вызвать функцию по указателю:


Код
void call_bootloader()
{
    void (*boot)();
    boot = (void(*)())0x1800;
    boot();
}
Вы можете указать адрес точки входа в скрипте линкера:
Код
.c:
extern void boot();

.xcl:
-Dboot=0x1800
А разделение загрузчика и приложения в разные проекты имеет и еще несколько приемуществ:
1) Вы можете использовать библиотечные функции в загрузчике не опасаясь, что они будут слинкованы в область приложения и затерты самим загрузчиком.
2) Работая над приложением вы не сможетеслучайно изменить загрузчики сделать его (и приложение) несовместимыми со старыми версиями.
3) Загрузчик предполагает, что вы будете иногда заливать приложение. А как вы собираетесть выковыривать приложение из цельного проекта?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th June 2025 - 22:15
Рейтинг@Mail.ru


Страница сгенерированна за 0.01442 секунд с 7
ELECTRONIX ©2004-2016