Xenia 45 13 января, 2009 Опубликовано 13 января, 2009 (изменено) · Жалоба 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-сегмент определен по-разному. И таблицы векторов прерываний тогда будут отдельные. Но возникает проблема объединить обе прошивки в одну, а я таких средств не знаю. Тем более что мой программатор не позволяет дописывать прошивку в кристалл, а полностью стирает всю предыдущую информацию перед прошивкой. Кроме того, опции линкера одни и те же для всех модулей проекта, а потому в одном проекте я объединить обе программы не могу. Возникшие затруднения самостоятельно разрешить не смогла, а потому обращаюсь к вам за советом. Изменено 13 января, 2009 пользователем Xenia Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Гость MALLOY2 13 января, 2009 Опубликовано 13 января, 2009 · Жалоба В линкере создаете сегмент типа MY_BOOT говорите где ему начинаться и какой он размер имеет, в программе говорите что эти данные надо размещать в сегменте MY_BOOT, нужно еще будет задействовать специальные директивы (__root) для того что бы компилятор не выкинул этот кусок. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergik_vrn 0 13 января, 2009 Опубликовано 13 января, 2009 · Жалоба IAR: как создать таблицу векторов прерываний в boot-области? С этим, кажется, проблем нет. Дело осталось за малым - как создать такую таблицу средствами IAR? На ассемблере у меня такой проблемы просто бы не возникло. Как помещать функции в boot-область я поняла - пишешь перед каждой из них прагму "#pragma local="BOOT"", предварительно создав кодовый сегмент с именем BOOT в опциях линкера или конфигурационном файле. Но как создать таблицу векторов прерываний, состоящих из одних команд rjmp? для размещения векторов прерываний есть предопределенный сегмент INTVEC. если Вы будете создавать векторы стандартным образом, компилятор автоматически положит их по нужному смещению в этом сегменте. если понадобится изменить расположение сегмента, это делается с помощью настроек линкера Думала над возможностью сделать два отдельных проекта для приложения и для загрузчика, в каждом из которых CODE-сегмент определен по разному. И таблицы векторов прерываний тогда будут отдельные. совершенно логичное рассуждение Но возникает проблема объединить обе прошивки в одну, а я таких средств не знаю. Тем более что мой программатор не позволяет дописывать прошивку в кристалл, полностью стирая предыдущую информацию перед прошивкой. вообще-то, после того, как написан и отлажен бут-сектор, прошивать пользовательскую программу можно (и нужно) с его помощью (не используя "Ваш программатор") Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 45 13 января, 2009 Опубликовано 13 января, 2009 (изменено) · Жалоба В линкере создаете сегмент типа MY_BOOT говорите где ему начинаться и какой он размер имеет, в программе говорите что эти данные надо размещать в сегменте MY_BOOT, нужно еще будет задействовать специальные директивы (__root) для того что бы компилятор не выкинул этот кусок. Ну, а я создала сегмент с названием BOOT, а не MY_BOOT - велика ли разница? Вот что я уже раньше писала: Как помещать функции в boot-область я поняла - пишешь перед каждой из них прагму "#pragma local="BOOT"", предварительно создав кодовый сегмент с именем BOOT в опциях линкера или конфигурационном файле. Но как создать таблицу векторов прерываний, состоящих из одних команд rjmp? Как видите, размещать код в boot-области я умею, и сразу про это написала, чтобы не вызывать лишних разговоров. Но судя о вашему ответу, это все-таки произошло. За совет использвать директиву __root спасибо, попробую с ней разобраться. Тем не менее, не ясно как писать эту таблицу. Если вам это кажется очевидным, но напишите хотя бы начало такой таблицы на первые два вектора прерывания. Как это должно выглядеть, чтобы компилятор не послал меня далеко и надолго? ==================== для размещения векторов прерываний есть предопределенный сегмент INTVEC. если Вы будете создавать векторы стандартным образом, компилятор автоматически положит их по нужному смещению в этом сегменте. если понадобится изменить расположение сегмента, это делается с помощью настроек линкера Такое решение не годится, т.к. сегмент INTVEC (как и любой другой сегмент) являтся НЕПРЕРЫВНЫМ, а мне по условию задачи нужны две РАЗНЫЕ таблицы прерывания в РАЗНЫХ областях памяти. Вопреки вашим словам, компилятор "стандартным образом" все кладет в начало одного и того же INTVEC-сегмента, а система проекта не позволяет одному модулю назначить один INTVEC-сегмент, а другому другой. Причина в том, что расположение сегментов определяется в опциях линкера и является ОБЩИМ для всего проекта, на сколько бы текстовых файлов он ни был поделен. Поэтому я никак не могу одну функцию-обработчик асооциированть с нижнией областью flash-памяти, а другую с верхней. Компилятор понимает только одну ЕДИНСТВЕННУЮ таблицу прерываний, всегда соответствующую сегменту INTVEC, которых не может быть две штуки. Изменено 13 января, 2009 пользователем Xenia Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergik_vrn 0 13 января, 2009 Опубликовано 13 января, 2009 · Жалоба Так решение не годится, т.е. сегмент INTVEC (как и любой другой сегмент) являтся НЕПРЕРВНЫМ, а мне по условию задачи нужны две РАЗНЫЕ таблицы прерывания в РАЗНЫХ оболастях памяти. Вы не поняли мой ответ. основной смысл был не в том, какой сегмент использовать (это так, комментарий по ходу дела), а в том, что Вам надо сделать именно ДВА проекта, а не пытаться объединить бут-сектор вместе с основной программой в один проект. Даже не могу представить, для чего такое извращение может понадобиться, ибо насчет загрузки я пояснял, если Вы запишете бутлоадер Вашим программатором, после этого основную программу грузить этим же программатором (стирая бутсектор) не потребуется Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 45 13 января, 2009 Опубликовано 13 января, 2009 (изменено) · Жалоба Вы не поняли мой ответ. основной смысл был не в том, какой сегмент использовать (это так, комментарий по ходу дела), а в том, что Вам надо сделать именно ДВА проекта, а не пытаться объединить бут-сектор вместе с основным в один проект. Как сделать два проекта, я и сама знаю. Но моя проблема именно в том, что мне нужна СРАЗУ ПОЛНАЯ прошивка с нижней и верхней областью. В этом и состоял мой вопрос. На ассемблере могу сделать это играючи, а вот на IARе возникают непреодолимые проблемы из-за того, что тому никак нельзя растолковать, что таблиц прерывания может быть две. Еще раз повторяю, что в данном разделе обсуждаются возможности применения компилятора IAR, и мой вопрос целиком относится к этой теме. Перевод моего вопроса в плоскость "зачем всё это мне нужно" - флейм не по теме. Тем более что я уже достаточно подробно объяснила причины, по которым мне нужно работающее приложение и одновременно возможность его перепрошивки в будущем, когда оно устареет или в нем обнаружатся ошибки. Даже не могу представить, для чего такое извращение может понадобиться. Насчет загрузки я тоже пояснил, если Вы запишете бутлоадер Вашим программатором, после этого основную программу грузить этим де программатором (стирая бутсектор) не потребуется Такой подход не технологичен. Микропроцессоры можно прошивать скопом еще до стадии впаивания в плату, после чего изделия сразу становятся рабочими и доступными для тестирования. А мертвые изделия, с каждым из которых надо потом индивидуально возиться с допрошивкой, создают массу проблем. Опять же я не смогу перед руководством доказать необходимость программирования за два этапа. Мне резонно скажут, что я дура, если не могу прошить микропроцессор за один раз (в трудозатратах мое руководство толк понимает, а в программировании не сечет). Изменено 13 января, 2009 пользователем Xenia Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergik_vrn 0 13 января, 2009 Опубликовано 13 января, 2009 · Жалоба Как сделать два проекта, я и сама знаю. Но моя проблема именно в том, что мне нужна СРАЗУ ПОЛНАЯ прошивка с нижней и верхней областью. В этом и состоял мой вопрос. На ассемблере могу сделать это играючи, а вот на IARе возникают непреодолимые проблемы из-за того, что тому никак нельзя растолковать, что таблиц прерывания может быть две. думаю, растолковать трудно именно потому, что никто до Вас подобной проблемой не озадачивался Еще раз повторяю, что в данном разделе обсуждаются возможности применения компилятора IAR, и мой вопрос целиком относится к этой теме. Перевод моего вопроса в плоскость "зачем всё это мне нужно" - флейм не по теме. ну извините, такое уж видимо свойство человеческой натуры. с другой стороны, при требуемом Вами подходе (ответ строго на поставленный вопрос) могут быть получены результаты типа "где я нахожусь"- "на воздушном шаре", как описано в известном анекдоте Тем более что я уже достаточно подробно объяснила причины, по которым мне нужно работающее приложение и одновременно возможность его перепрошивки в будущем, когда оно устареет или в нем обнаружатся ошибки. это не требуется объяснять, у всех то же самое Такой подход не технологичен. Микропроцессоры можно прошивать скопом еще до стадии впаивания в плату, после чего изделия сразу становятся рабочими и доступными для тестирования. А мертвые изделия, к каждым из которых надо индивидуально возиться с допрошивкой, создают массу проблем. Опять же я не смогу пред руководством доказать необходимость программирования за два этапа. Мне резонно скажут, что я дура, если не могу прошить микропроцессор за один раз. позволю себе с Вами не согласиться, поскольку технологии бывают разные. у нас, например, прошивка программы является одной из стадий проверки работоспособности собранной железки. кроме того, прошивать сырые чипы до запайки далеко не всегда есть оптимальный вариант. впрочем, это уже как раз не мое дело. Возвращаясь к нашим баранам: 1 вариант: напишите ассемблерную вставку, куда включите вызовы всех необходимых Вам прерываний, вставку разместите в нужном сегменте. после этого начинайте воевать с объединением настроек компилятора и линкера 2 вариант: объедините готовые скомпилированные прошивки в один исполняемый файл после линковки. если прошивка меняется редко (а судя по описанной технологии так и есть), это можно сделать чуть ли не вручную Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 45 13 января, 2009 Опубликовано 13 января, 2009 (изменено) · Жалоба 2 вариант: объедините готовые скомпилированные прошивки в один исполняемый файл после линковки. если прошивка меняется редко (а судя по описанной технологии так и есть), это можно сделать чуть ли не вручную И про это я уже думала. HEX-прошивки действительно можно объединить вручную. Только есть одна закавыка. В программе приложения имеется команда, которая АКТИВИЗИРУЕТ загрузчик. Т.е. фактически это простой вызов функции из boot-области, откуда возврата больше не будет до окончания прошивки. И вот этот вызов мне будет сложно реализовать, т.к. при раздельном приготовлении проектов такие вызовы делать нельзя. В противном случае будет непонятно, как мне активизировать загрузчик в случае возникшей необходимости. С этим же вопросом связан еще и другой: функции поддержки обмена по USB-каналу (а они достаточно объемные!) можно было бы держать ТОЛЬКО в загрузчике (boot-области), а приложение попросту бы ими пользовалось. Но такое можно организовать только в том случае, если приложение и загрузчик удастся объединить в одном проекте. Может у вас все-таки появятся какие-нибудь мысли, чтобы не разъединять программу на два проекта? Тем более, что мне от верхней таблицы прерывания нужны всего лишь 2 вектора: USB_General_vect и USB_Endpoint_Pipe_vect. Остальные прерывания я на время прошивки блокирую, включая таймеры. Понимаете? Всего-то два джампа на нужных местах решило бы мою прблему. Изменено 13 января, 2009 пользователем Xenia Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergik_vrn 0 13 января, 2009 Опубликовано 13 января, 2009 · Жалоба И про это я уже думала. HEX-прошивки действительно можно объединить вручную. Только есть одна закавыка. В программе приложения имеется команда, которая АКТИВИЗИРУЕТ загрузчик. Т.е. фактически это простой вызов функции из boot-области, откуда возврата больше не будет до окончания прошивки. И вот этот вызов мне будет сложно реализовать, т.к. при раздельном приготовлении проектов такие вызовы делать нельзя. В противном случае будет непонятно, как мне активизировать загрузчик в случае возникшей необходимости. что-то я не до конца, видать, понял Вашу задачу. обычно загрузчик потому и называется "загрузчик", и размещается в "boot-секторе", что он загружается ДО основной программы, потом определяет необходимость перехода в специальный (загрузочный) режим, после чего либо переходит в него, либо передает управление основной программе. в любом случае, активизация как загрузчика, так и основной программы, не представляет проблем и производится путем передачи управления по заранее оговоренному адресу (в случае выхода из загрузчика для AVR это адрес 0x0000). Например, так void (*funcptr)( void ) = 0x0000; // Set up function pointer to RESET vector. funcptr(); В любом случае, совместная линковка и уж тем более компиляция тут никак ни причем. С этим же вопросом связан еще и другой: функции поддержки обмена по USB-каналу (а они достаточно объемные!) можно было бы держать ТОЛЬКО в загрузчике (boot-области), а приложение попросту бы ими пользовалось. Но такое можно организовать только в том случае, если приложение и загрузчик удастся объединить в одном проекте. кто Вам такое сказал? не слушайте его больше :) по-моему на этом форуме уже обсуждали подобную задачу. При известных адресах функций (после линковки бутсектора) оформите вызовы на них аналогично вышеописанному и пользуйтесь. Если нет желания связываться с вбиванием адресов, создайте промежуточную константную таблицу адресов этих функций, проинициализируйте ее в бут-секторе и расположите по заранее оговоренному стандартному адресу внутри сектора Может у вас все-таки появятся какие-нибудь мысли, чтобы не разъединять программу на два проекта? Тем более, что мне от верхней таблицы прерывания нужны всего лишь 2 вектора: USB_General_vect и USB_Endpoint_Pipe_vect. Остальные прерывания я на время прошивки блокирую, включая таймеры. Понимаете? Всего-то два джампа на нужных местах решило бы мою прблему. именно это я Вам и пытаюсь объяснить, Ваша проблема вовсе не в двух джампах, их-то разместить по определенным адресам проще всего. проблема в том, что Вы пытаетесь прикрутить проволокой решение, противоречащее идеологии компилятора. в итоге куча нетривиальных сложностей, тянущихся друг за другом. зато если пользоваться двумя разными проектами, проблема (условная) может встать только при объединении hex-файлов, все остальное легко решается средствами языка Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 13 января, 2009 Опубликовано 13 января, 2009 · Жалоба И про это я уже думала. HEX-прошивки действительно можно объединить вручную.Ну зачем же вручную? SRecord вам поможет.Только есть одна закавыка. В программе приложения имеется команда, которая АКТИВИЗИРУЕТ загрузчик. Т.е. фактически это простой вызов функции из boot-области, откуда возврата больше не будет до окончания прошивки. И вот этот вызов мне будет сложно реализовать, т.к. при раздельном приготовлении проектов такие вызовы делать нельзя. В противном случае будет непонятно, как мне активизировать загрузчик в случае возникшей необходимости.Как раз это - самое простое. Вы можете вызвать функцию по указателю: void call_bootloader() { void (*boot)(); boot = (void(*)())0x1800; boot(); } Вы можете указать адрес точки входа в скрипте линкера: .c: extern void boot(); .xcl: -Dboot=0x1800 А разделение загрузчика и приложения в разные проекты имеет и еще несколько приемуществ: 1) Вы можете использовать библиотечные функции в загрузчике не опасаясь, что они будут слинкованы в область приложения и затерты самим загрузчиком. 2) Работая над приложением вы не сможетеслучайно изменить загрузчики сделать его (и приложение) несовместимыми со старыми версиями. 3) Загрузчик предполагает, что вы будете иногда заливать приложение. А как вы собираетесть выковыривать приложение из цельного проекта? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться