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

 
 
> Вопрос по IAR, Настройки среды программирования
d7d1cd
сообщение Nov 8 2013, 18:19
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Привет всем. Подскажите, возможно ли настроить IAR так, чтобы он сделал компиляцию кода (например какой-то отдельной функции или всего кода) строго в определенный участок флешь памяти (от сих до сих, так сказать)?
Go to the top of the page
 
+Quote Post
5 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 62)
Xenia
сообщение Nov 8 2013, 18:35
Сообщение #2


Гуру
******

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



Цитата(d7d1cd @ Nov 8 2013, 22:19) *
Подскажите, возможно ли настроить IAR так, чтобы он сделал компиляцию кода (например какой-то отдельной функции или всего кода) строго в определенный участок флешь памяти (от сих до сих, так сказать)?


Дописать перед функцией pragma location, а в опциях линкера (ExtraOptions) определить это место, как сегмент.
Например, так было достигнуто размещение функции ReadFuse() в загрузочной оласти:
Код
#pragma location="BOOT"
void ReadFuse() { ... }

Сам сегмент был определен так:
Код
-D_..X_FLASH_BOOT=F000
-Z(CODE)BOOT=_..X_FLASH_BOOT-_..X_FLASH_END

Вместо BOOT можно написать какое-то другое слово, а вместо F000 другой адрес.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 9 2013, 04:51
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



При попытке компиляции IAR выдает ошибку Fatal Error[e163]: The command line symbol "_..X_FLASH_END" in -Z(CODE)BOOT=_..X_FLASH_BOOT-_..X_FLASH_END is not defined.

Сообщение отредактировал d7d1cd - Nov 9 2013, 15:38
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 9 2013, 15:56
Сообщение #4


Гуру
******

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



Цитата(d7d1cd @ Nov 9 2013, 08:51) *
Спасибо за ответ. Что значит 2 точки в коде:
Код
-D_..X_FLASH_BOOT=F000
-Z(CODE)BOOT=_..X_FLASH_BOOT-_..X_FLASH_END

То есть задается только адрес начала размещения?

Нет, здесь задается именно сегмент памяти от сих до сих, где будут размещены ВСЕ функции, которые к данному сегменту приписаны. Т.е. если у вас несколько функций приписаны к сегменту BOOT, то все они в него попадут друг за дружкой. И тогда строго формально нельзя будет предсказать, с какого адреса одна из тех функций начинается, хотя практически линкер укладывает их тела в тот сегмент в порядке упоминания в тексте программы. Поэтому, чтобы разместить функцию строго по определенному адресу, вам придется сделать уникальный сегмент только для нее! Тогда уж она точно окажется в том ряду первой и попадет на начало сегмента.

Точки и подчеркивание, думаю, нечего не означают, просто придают именам уникальность, чтобы те случайно не совпали с именами каких-то объектов в программе.
Т.е.
_..X_FLASH_BOOT
- это одно имя целиком, а директива D (от слова define) лишь приписывает ей значение.
Само же определение сегмента задано во второй строке, после директивы Z.

Вообще-то, я сама глубоко с этим не разбиралась, а просто механически переделала под свое имя (BOOT) определение какого-то другого сегмента в том же самом стиле (это видно в xcl-файле для данного типа МК). Рисковать не хотелось, а надо было сделать по-быстрому.

Думаю, что в данном случае вполне годилось бы самое примитивное определение без всяких дефиниций:
-Z(CODE)BOOT=F000-F100
где задается имя сегмента, а его границы выставлены прямо в числах.

Определения имени границ сегментов нужны в файле конфигурации только затем, чтобы связать все сегменты в одну цепочку. Поэтому там каждое имя повторяется по меньшей мере 2 раза - в качестве конца предыдущего сегмента и начале последующего. Мой случай был в этом отношении примитивным, т.к. загрузочная область была заведомо пуста. В вашем случае дело может вылиться в то, что придется переписывать файл конфигурации под себя. Тогда его надо скопировать его в свой проект из:
\Program Files\IAR Systems\Embedded Workbench 6.5\430\config\lnk430f5529.xcl
(так этот файл называется для MSP430F5529, но у вас может быть другой МК)
переключить проект на него вместо умолчания, а потом внести в него исправления. Редактировать исходный файл конфигурации нельзя, можно только копию!

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

Однако разбираться в том файле, уж тем более редактировать его, довольно противно. А потому попытайте сначала самый легкий способ - на числах, вдруг сработает?

Цитата(d7d1cd @ Nov 9 2013, 08:51) *
А что будет, если скомпилированный код не умещается от указанного места расположения до конца флешь памяти?

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

Цитата(d7d1cd @ Nov 9 2013, 08:51) *
При попытке компиляции IAR выдает ошибку Fatal Error[e163]: The command line symbol "_..X_FLASH_END" in -Z(CODE)BOOT=_..X_FLASH_BOOT-_..X_FLASH_END is not defined.

Дефиниции границ сегментов могут довольно сильно отличаться по именам у разных МК. Советую вам найти xcl-файл именно для своего типа МК и сделать определение, подобное тому, как там определены сегменты кода.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 9 2013, 17:31
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(Xenia @ Nov 9 2013, 19:56) *
А потому попытайте сначала самый легкий способ - на числах, вдруг сработает?

Определил сегмент так:
Код
-Z(CODE)BOOT=F002-F0FF

И все получилось! Компилятор расположил код функции с адреса 0xF002. Спасибо.

По расположению кода теперь разобрался. Есть другой вопрос. В функции я использую переменные. Как указать компилятору при определении переменной, что эта переменная должна быть физически расположена по адресу 0x0200, например? Или как указать, что массив данных должен начинаться с адреса 0x0421?
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 9 2013, 20:19
Сообщение #6


Гуру
******

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



Цитата(d7d1cd @ Nov 9 2013, 21:31) *
По расположению кода теперь разобрался. Есть другой вопрос. В функции я использую переменные. Как указать компилятору при определении переменной, что эта переменная должна быть физически расположена по адресу 0x0200, например? Или как указать, что массив данных должен начинаться с адреса 0x0421?


Точно так же! Только на этот раз "pragma location" прописывается не перед функцией, а перед определением переменной или массива. Только просите память не из сегмента CODE, а из сегмента DATA. У нас на форуме на такой вопрос уже отвечали:
http://electronix.ru/forum/index.php?s=&am...t&p=1020355
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 10 2013, 10:30
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Попытался указать переменной конкретный адрес. Ничего не получается. В опциях линкера я указал:
Код
-Z(DATA)VARIABLE=0200-020F

В коде прописал:
Код
#pragma location = "VARIABLE"
char data = 1;

Однако при выполнении кода в симуляторе я вижу, что цифра 1 попадает в регистр R14, а не в диапазон 0x0200-0x020F. Ошибок нет. Что не так то опять?

P.S. Посмотрел файл io430x24x.h. Есть там много строк, подобных этой:
Код
/* ADC12 Interrupt Flag */
__no_init volatile unsigned short ADC12IFG @ 0x01A4;

Как я понимаю, здесь переменной ADC12IFG "назначается" адрес 0x01A4. Неужели я не могу так же в программе назначить свои переменные?

Сообщение отредактировал d7d1cd - Nov 10 2013, 11:41
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 10 2013, 12:25
Сообщение #8


Гуру
******

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



Цитата(d7d1cd @ Nov 10 2013, 14:30) *
В коде прописал:
Код
#pragma location = "VARIABLE"
char data = 1;

Однако при выполнении кода в симуляторе я вижу, что цифра 1 попадает в регистр R14, а не в диапазон 0x0200-0x020F. Ошибок нет. Что не так то опять?

Если у вас переменная в регистр попала, то это локальная переменная, объявленная внутри блока из фигурных скобок. Такие переменные называются "автоматическими", имеют ограниченное время жизни, а потому и располагаются на стеке или в регистрах. А чтобы застолбить переменную или массив в памяти, они должны быть глобальными, т.е. объявленными вне функций или с декларатором static.

Цитата(d7d1cd @ Nov 10 2013, 14:30) *
Посмотрел файл io430x24x.h. Есть там много строк, подобных этой:
Код
/* ADC12 Interrupt Flag */
__no_init volatile unsigned short ADC12IFG @ 0x01A4;

Как я понимаю, здесь переменной ADC12IFG "назначается" адрес 0x01A4.
Неужели я не могу так же в программе назначить свои переменные?

А вы попробуйте. Думаю, что вполне можете и так. Только внутри фигурных скобок этого не делайте.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 10 2013, 13:42
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Сделал объявление переменной глобально, то есть вне функции. Все хорошо, но работает только с атрибутом __no_init:
Код
#pragma location = "VARIABLE"
__no_init volatile char data;

int main( void )
{
  data = 1;
}

Далее я попробовал сделать как в стандартном файле. Все тоже заработало, но тоже только с атрибутом __no_init:
Код
__no_init volatile char X @ 0x0210;

int main( void )
{
  data = 1;
}

В принципе то, что объявление переменных выше указанными способами не предусматривает их инициализации, мне и надо. По удобству я считаю, что второй способ лучше.
С объявлением глобальных переменных тоже теперь ясно. А можно ли локальную переменную объявить так, чтобы она была связана с конкретным регистром?
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 10 2013, 13:53
Сообщение #10


Гуру
******

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



Цитата(d7d1cd @ Nov 10 2013, 17:42) *
Все хорошо, но работает только с атрибутом __no_init
В принципе то, что объявление переменных выше указанными способами не предусматривает их инициализации, мне и надо. По удобству я считаю, что второй способ лучше.
С объявлением глобальных переменных тоже теперь ясно.

Так оно и быть должно. Все обнуляемые переменные и массивы попадают в сегмент NEAR_Z (у других МК может называться по иному), который обнуляется при запуске (в процедуре startup). А раз у вас данные расположены в другом/самодельном сегменте, то инициализации они не получат. То, что аттрибут __no_init требуется синтаксически не знала (в старых версиях не был обязателен).

Цитата(d7d1cd @ Nov 10 2013, 17:42) *
А можно ли локальную переменную объявить так, чтобы она была связана с конкретным регистром?

Полагаю, что нельзя.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 10 2013, 14:04
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Хорошо. А возможно ли какой-то локальной переменной присвоить значение какого-то регистра? И еще: при объявлении локальной переменной ей назначается какой-то регистр. Возможно ли сделать так, чтобы значение этого регистра предварительно было сохранено в стеке, а после окончания работы функции восстановлено из него?
Go to the top of the page
 
+Quote Post
SSerge
сообщение Nov 10 2013, 14:45
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(d7d1cd @ Nov 10 2013, 21:04) *
Возможно ли сделать так, чтобы значение этого регистра предварительно было сохранено в стеке, а после окончания работы функции восстановлено из него?

Оставьте эту работу компилятору, это его проблемы.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 10 2013, 14:53
Сообщение #13


Гуру
******

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



Цитата(d7d1cd @ Nov 10 2013, 18:04) *
Хорошо. А возможно ли какой-то локальной переменной присвоить значение какого-то регистра? И еще: при объявлении локальной переменной ей назначается какой-то регистр. Возможно ли сделать так, чтобы значение этого регистра предварительно было сохранено в стеке, а после окончания работы функции восстановлено из него?


На этот вопрос мне трудно дать конкретный ответ, т.к. нас с вами разделяют архитектуры: я - преимущественно AVR-щица, а вы - пользователь MSP430. Обмениваться опытом нам позволяет лишь общий компилятор IAR, и то лишь в той мере, в которой существует подобие между реализациями для этих двух архитектур.

Согласно стандартам языка C/C++, вы имеете возможность добавить декларатор "register", если хотите, чтобы локальная переменная заводилась не на стеке, а в регистре:
register char data;
или
char register data;

Только эта декларация является лишь пожеланием, которое компилятор может проигнорировать, даже не выдав по этому поводу никакого сообщения. Что же касается массивов, то это почти безнадега. То, насколько у компилятора есть возможности удовлетворить данное пожелание, сильно зависит от числа свободных регистров в данной архитектуре. В архитектуре AVR имеется 32 регистра, и хотя младшие из них специализированы, то все равно остается дофига других. В таких случаях компилятор довольно охотно удовлетворяет просьбу "register", хотя и трудно заранее предвидеть, какой по номеру регистр он для этой цели выберет. А, скажем, на архитектуре x86 такие пожелания удовлетворяются крайне редко, т.к. там всего 7 регистров, причем, совсем не лишних. Поэтому мне трудно предсказать, насколько компилятор для MSP430 окажется покладистым.

Еще в AVR-ном варианте есть возможность зарезервировать отдельные регистры (начиная с R15 и ниже) под глобальные переменные. Например:
__regvar __no_init volatile long data@12; // data занимает 4 регистра: R12,R13,R14,R15
Но эти же же регистры приходится изымать из обращения в опциях проекта, чтобы компилятор их не использовал.
При этом пользоваться можно только библиотекой clib (которая регистры R5-R15 либо не использует, либо сохраняет/восстанавливает их значения), а библиотекой dlib пользоваться нельзя.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 10 2013, 14:57
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(SSerge @ Nov 10 2013, 18:45) *
Оставьте эту работу компилятору, это его проблемы.


Я понимаю, но у меня задача очень специфическая. Нашел я тут как делать вставки на ассемблере:
Код
int main( void )
{
  
  int AAA;
  asm("MOV.W R15, &AAA");
    
}


Однако тут компилятор выдает ошибку:
Цитата
Error[Og005]: Unknown symbol in inline assembly: "AAA"


Если же переменную ААА объявить глобально (вне функции main), то ошибки нет. Хотя в справке к IAR переменная объявлена локально. Почему же ошибка?
Go to the top of the page
 
+Quote Post
rezident
сообщение Nov 11 2013, 20:28
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(d7d1cd @ Nov 10 2013, 19:57) *
Если же переменную ААА объявить глобально (вне функции main), то ошибки нет. Хотя в справке к IAR переменная объявлена локально. Почему же ошибка?

Компилятор строку с inline assembler сам не разбирает. Он просто вставляет ее в текст объектного (ассемблерного) модуля. А поскольку в вашем примере переменная AAA в Си-шном модуле нигде более не используется, то оптимизатор компилятора выкидывает ее за ненадобностью. И вот когда объектный модуль попадает "на стол" к линкеру, то линкер приходит в недоумение, что это за объект AAA вдруг обнаружился? Т.к. компилятор про объект AAA ничего (адрес объекта) линкеру не сообщил и более того - совсем выкинул из программы.
Вообще ассемблерные вставки в Си это перманентное зло. Если вам нужно что-то особенное, оптимизированные под свои задачи, то используйте отдельные законченные функции, полностью написанные на ассемблере. О том, как правильно писать такие функции и о правилах передачи аргументов в/из asm-функций из/в Си-функции, описано в документации. А вставлять отдельные ассемблерные команды посреди Си-шного исходника бросьте сразу, еще не начиная rolleyes.gif

Ну и еще раз напомню про отличия типов переменных. Тип переменной влияет на ее размещение в памяти и область видимости.
Переменные типа global (глобальная) и static (статическая) размещаются в памяти данных, т.е. под них выделяются ячейки памяти с постоянным адресом.
Переменные типа auto (автоматическая или локальная) размещаются на стеке или в РОН (по усмотрению компилятора), но постоянного адреса в памяти они не имеют.
Переменные типа register (регистровая) в принципе могут быть как глобальными (если объявлена вне функции с указанием конкретного регистра) так и локальными (объявлена без указания регистра внутри функции). Переменные типа register это тип данных с наиболее быстрым доступом. А для того, чтобы доступ к ним был быстрым, предполагается, что размещаться они должны в РОН. Но проблема состоит в том, что если заранее в опциях проекта для переменных типа register не зарезервировать конкретные регистры (в IAR EW430 возможно резервировать только R4 и R5), то компилятор обращается с ними очень вольно и в большинстве случаев пилюет на такую декларацию с высокой колокольни, трактуя локальные register как обычные переменные auto.
Область видимости global - вся программа.
Область видимости static - данный конкретный модуль или функция, если static объявлена внутри функции.
Область видимости auto - функция или блок оператора в котором она объявлена.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 12 2013, 05:02
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Уважаемый rezident, объяснения как всегда на высоте! Спасибо!
Хочется подробнее узнать про функции, написанные полностью на ассемблере. Как я полагаю в этих функциях для переменных можно будет использовать любые РОН, а не только R4 и R5. Подскажите ссылку на документацию (если возможно - на русском языке).
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 12 2013, 09:33
Сообщение #17


Гуру
******

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



Цитата(d7d1cd @ Nov 12 2013, 09:02) *
Хочется подробнее узнать про функции, написанные полностью на ассемблере. Как я полагаю в этих функциях для переменных можно будет использовать любые РОН, а не только R4 и R5. Подскажите ссылку на документацию (если возможно - на русском языке).

IAR поддерживает сборку проекта, состоящего из C/C++ и ассеблерных файлов/модулей, различая их по расширению.

Книжек о том, как програмировать на этих языках для MSP430, можно легко надыбать в интернете, но мой совет будет простой: написать на языке C функцию, нуждающуюся в переложении на ассемблер, в отдельном файле, откомпилировать проект с установкой, чтобы выдавало ассемблерный листинг. После чего редактируешь листинг по своему вкусу, использя те регистры, какие хочется, а затем подменяешь в проекте второй файл на асемблерный.

Я, кстати, сама так МК-шному ассемблеру училась - книг не читала, а писала по образу и подобию того, как компилятор компилирует сишные образцы. Правда, к этому времени я на других ассемблерах уже умела программировать - это, видимо, тоже помогало. А из книг было достаточно таблицы инструкций и IAR-ского руководства EW430_AssemblerReference.pdf

Думаю, что самая большая тут трудность не в том, чтобы на ассемблеру выучиться, а в том, чтобы соблюсти условности, позволяющие линкеру связывать объектные модули от двух разных языков. Т.к. проблема чаще возникает в том, что на ассемблере порой приходится искать доступ к глобальным переменным и массивам, определенным в сишной части проекта.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 12 2013, 10:01
Сообщение #18


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(Xenia @ Nov 12 2013, 13:33) *
...написать на языке C функцию, нуждающуюся в переложении на ассемблер, в отдельном файле, откомпилировать проект с установкой, чтобы выдавало ассемблерный листинг. После чего редактируешь листинг по своему вкусу, используя те регистры, какие хочется, а затем подменяешь в проекте второй файл на ассемблерный.

Если Вас не затруднит, можете сделать пошаговое описание выше сказанного? Просто я в IAR совсем новичок. Ранее программировал только на C++Builder.
Например, на С написать функцию, которая принимает 2 параметра и возвращает сумму квадратов этих параметров. Как потом реализацию этой функции вывести в ассемблерный листинг?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Nov 13 2013, 06:34
Сообщение #19


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(d7d1cd @ Nov 12 2013, 14:01) *
Как потом реализацию этой функции вывести в ассемблерный листинг?

Поставить в настройках галочку (вкладка compiler output или что-то в этом роде), будет формироваться .lst

Прикрепленное изображение


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 13 2013, 09:09
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Создал я проект, добавил в него файл. В этом файле создал функцию. Сделал компиляцию этого файла при установленной галочке Output assembler file. В итоге я получил файл с реализацией моей функции на ассемблере. Как я понимаю, я могу теперь отредактировать этот файл по своему усмотрению, поменять алгоритм реализации функции, использовать любые регистры.
Пока я с этим файлом ничего делать не буду. Подскажите, как мне из кода на С++ вызвать мою функцию, расположенную теперь в ассемблерном файле?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Nov 13 2013, 09:26
Сообщение #21


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Прямо так и вызывать, предварительно объявив прототип.
Цитата
поменять алгоритм реализации функции, использовать любые регистры.

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


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 13 2013, 10:19
Сообщение #22


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Попробовал следовать Вашему совету. Файл с функцией на ассемблере поместил в отдельную папку. Далее добавил этот файл в проект. Перед функцией main поместил прототип функции, которая находится в ассемблерном виде. При попытке запуска, компилятор выдает ошибку компиляции ассемблерного файла, хотя я в нем абсолютно ничего не менял. Скажите, что я не так делаю?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Nov 13 2013, 10:53
Сообщение #23


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(d7d1cd @ Nov 13 2013, 14:19) *
Скажите, что я не так делаю?

Видимо, что-то не так sm.gif
А что за ошибка?

Я в ассемблере не слишком шарился, обычно си хватало.
Есть пара проектов, но сейчас времени нет искать.
Может, как-нибудь эту функцию надо глобально расшарить директивами? Типа паблик или что-то в этом роде
РТФМ, там много интересного


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 13 2013, 11:02
Сообщение #24


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Ошибка Bad instruction. Возникает в строке ассемблерного файла с якобы инструкцией ERROR. Кто знает, подскажите. пожалуйста, как осуществить желаемое...

P.S. В полученном ассемблерном файле есть комментарий (после этой непонятной инструкции ERROR). Там написано, что-то типа "Этот модуль использует возможности С++ не совместимые с кодом ассемблера..."

Сообщение отредактировал d7d1cd - Nov 13 2013, 11:53
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 14 2013, 07:48
Сообщение #25


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Сделал я проект. Прикладываю его сюда. В этом проекте я получаю ассемблерный листинг, который потом не компилируется. Люди добрые, посмотрите, подскажите...
Прикрепленные файлы
Прикрепленный файл  Poligon.zip ( 17.02 килобайт ) Кол-во скачиваний: 21
 
Go to the top of the page
 
+Quote Post
rezident
сообщение Nov 14 2013, 15:20
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(d7d1cd @ Nov 14 2013, 12:48) *
Сделал я проект. Прикладываю его сюда. В этом проекте я получаю ассемблерный листинг, который потом не компилируется. Люди добрые, посмотрите, подскажите...

В мнемонике ассемблера MSP430 нет команды ERROR. Она вставляется в листинг видимо как раз специально с той целью, чтобы этот asm потом не компилировали biggrin.gif
Я не знаю ни C++, ни как вставлять в проект для С++ ASM-функции. Специально только для этого курить документацию IAR мне лениво sm.gif
Но вот мой вариант вашего проекта без каких-либо "плюсов", pure C т.с. Функция DivisionOnTwo вырезана из вашего листинга и оформлена как законченная самостоятельная ASM-функция, которая вызывается из Си-шного модуля. Проект компилируется без ошибок и даже работает (в симуляторе).
Обратите внимание, что прототип функции DivisionOnTwo описан с квалификатором external.
Прикрепленные файлы
Прикрепленный файл  Poligon_c.zip ( 248.15 килобайт ) Кол-во скачиваний: 22
 
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 14 2013, 17:28
Сообщение #27


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Спасибо всем за помощь! Наконец то я победил компилятор. Как мне подсказал rezident, необходимо функцию, которую надо переложить на ассемблер, написать в проекте на С (но не на С++). Тогда получается пригодный для компиляции ассемблерный листинг. Его я правлю как мне необходимо и добавляю к проекту на С++. Прототип функции, которая находится в ассемблере, необходимо объявить с квалификатором extern "C".
Почитав руководство к компилятору, я узнал, что при передаче в функцию параметров, всегда используются конкретные регистры, так же, как и при возврате функциями каких-либо значений.

Сообщение отредактировал d7d1cd - Nov 15 2013, 07:49
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 17 2013, 09:56
Сообщение #28


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



И снова здравствуйте. Теперь я умею в одном проекте использовать код на С++ и на ассемблере. Но вот возник вопрос...
У меня в проекте 3 функции, написанные на С++. Все они не принимают параметров и не возвращают их (работают с глобальными переменными). Вызываются они одна за другой. Настроив линкер, я указал, что функции у меня расположены в определенной области памяти. В отладчике я вижу, что мои функции расположились в указанной мной области памяти в таком же порядке, как происходит их вызов.
Далее я самую первую функцию пишу на ассемблере, так же указав сегмент расположения этой функции. Порядок вызова функций я не меняю, однако после всего этого я вижу, что функция, написанная на ассемблере, расположилась в памяти после функций, написанных на С++ (хотя вызывается первая).
Подскажите, почему эта функция на С++ была первая в памяти, а на ассемблере стала последней? И еще: конечно это не особо критично, но подскажите, возможно ли указать линкеру не только расположение функций, но и порядок их размещения в памяти?
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 17 2013, 10:47
Сообщение #29


Гуру
******

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



Цитата(d7d1cd @ Nov 17 2013, 13:56) *
Подскажите, почему эта функция на С++ была первая в памяти, а на ассемблере стала последней? И еще: конечно это не особо критично, но подскажите, возможно ли указать линкеру не только расположение функций, но и порядок их размещения в памяти?


У IAR компиляторы языка С/С++ и языка ассемблера раздельные! В вашем случае это icc430.exe и a430.exe. Поэтому сишные функции окажутся откомпилированными в одном объектном модуле, а ассемблерные функции в другом. А дальше все зависит от того, в каком порядке их соберет линкер. Видимо у него make такой, что первыми в очереди на сборку идут сишные модули, а ассемблерные за ними.

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

P.S. А не все ли вам равно, в каком порядке функции следуют внутри сегмента кода? Зарекаться на этот порядок в проектах, в общем-то, неприлично.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 17 2013, 11:08
Сообщение #30


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(Xenia @ Nov 17 2013, 14:47) *
У IAR компиляторы языка С/С++ и языка ассемблера раздельные! В вашем случае это icc430.exe и a430.exe. Поэтому сишные функции окажутся откомпилированными в одном объектном модуле, а ассемблерные функции в другом. А дальше все зависит от того, в каком порядке их соберет линкер. Видимо у него make такой, что первыми в очереди на сборку идут сишные модули, а ассемблерные за ними.

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

P.S. А не все ли вам равно, в каком порядке функции следуют внутри сегмента кода? Зарекаться на этот порядок в проектах, в общем-то, неприлично.

Ну во поводу постскриптума: мне все равно, по сути... А поменяв порядок следования в Workspace, все получилось! Спасибо за совет.
Пока делал это, обнаружил следующую проблему. В функции на С++, для которой указано конкретное расположение, используется операция деления. Из отладчика я увидел, что операция деления - это тоже функция. И ее линкер размещает не в моем сегменте. Как сделать так, чтобы было в моем?
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 17 2013, 12:01
Сообщение #31


Гуру
******

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



Цитата(d7d1cd @ Nov 17 2013, 15:08) *
Пока делал это, обнаружил следующую проблему. В функции на С++, для которой указано конкретное расположение, используется операция деления. Из отладчика я увидел, что операция деления - это тоже функция. И ее линкер размещает не в моем сегменте. Как сделать так, чтобы было в моем?


Функция деления выбирается из библиотеки. Компилятор ее не компилирует, т.к. библиотека уже находится в скомпилированном виде. А, значит, и сегмент у той функции такой, в каком компилировалась библиотека. И если сегменты вашего кода и библиотеки называются по разному, то и функциям никак не быть вместе.

В тех же случаях, когда библиотечная функция обособлена (не вызывает в своем теле других библиотечных функций), то вы можете взять ее код из сорцов библиотеки и присоединить к своему коду. Тогда она откомпилируется вместе с вашим кодом и окажется вашем сегменте. А по правилам линковки библиотека линкуется последней, а потому к коду будет пришит вами скомпилированный экземпляр, а не библиотечный.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 17 2013, 12:49
Сообщение #32


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(Xenia @ Nov 17 2013, 16:01) *
...вы можете взять ее код из сорцов библиотеки и присоединить к своему коду. Тогда она откомпилируется вместе с вашим кодом и окажется вашем сегменте. А по правилам линковки библиотека линкуется последней, а потому к коду будет пришит вами скомпилированный экземпляр, а не библиотечный.

Как же мне это сделать (взять код из сорцов библиотеки), если, как Вы сказали, библиотека уже скомпилирована? Можно попросить привести примерчик?
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 17 2013, 13:13
Сообщение #33


Гуру
******

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



Цитата(d7d1cd @ Nov 17 2013, 16:49) *
Как же мне это сделать (взять код из сорцов библиотеки), если, как Вы сказали, библиотека уже скомпилирована? Можно попросить привести примерчик?

Если у вас полная версия, то исходники библиотек она тоже должна включать. Лежат тут:
\IAR Systems\Embedded Workbench X.x\430\src\lib\
Только сам компиятор в эти исходники не лазает, а пользуется уже скомпилированным вариантом под конкретно ваш МК:
\IAR Systems\Embedded Workbench X.x\430\lib\
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 22 2013, 07:29
Сообщение #34


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



И снова здравствуйте. Подскажите, пожалуйста, как в одном заголовочном файле объявить константы и для модуля С++ и для модуля на ассемблере? Пытался разместить в таком файле следующие константы:
Код
#define VAR (0x0200)
__no_init volatile int Variable @ VAR;

Если такой заголовочный файл добавить в модуль на С++, то компиляция ошибок не вызывает. А вот в модуле на ассемблере происходит ругань на вторую строку.

Стандартные заголовочные файлы при их инклуде к модулю на любом языке при компиляции ошибок не создают. Я так же хочу сделать свой модуль...
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 22 2013, 11:23
Сообщение #35


Гуру
******

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



Цитата(d7d1cd @ Nov 22 2013, 11:29) *
Подскажите, пожалуйста, как в одном заголовочном файле объявить константы и для модуля С++ и для модуля на ассемблере? Пытался разместить в таком файле следующие константы:
Код
#define VAR (0x0200)
__no_init volatile int Variable @ VAR;

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


Стандартные заголовочные файлы только потому "интернациональны", что содержат в себе условную компиляцию:
Код
#ifdef  __IAR_SYSTEMS_ICC__
   для C/C++ компилятора
#endif

#ifndef __IAR_SYSTEMS_ASM__
   для ассемблера
#endif

Тогда как определения констант через #define оба компилятора понимают одинаково хорошо (через один и тот же препроцессор текст проходит).
Отсюда и рекомендация: определять общие константы через #define в начале хидера, а если приходится что-то добавлять специфическое, отчего у одного из компиляторов возникает несварение желудка, то ставите это под условие __IAR_SYSTEMS_ICC__или __IAR_SYSTEMS_ASM__.

Поэтому ваш пример будет выглядеть как-то так:
Код
  #define VAR  0x0200
#ifdef  __IAR_SYSTEMS_ICC__
  __no_init volatile int Variable @ VAR;
#endif

Тогда оба компилятора получат одинаковые знания про константу VAR, но ассемблер не увидит сишную строку, которая его станет раздражать.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 22 2013, 16:36
Сообщение #36


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Спасибо, Xenia. Я пока не пробовал в компиляторе, но уже полностью Вам доверяю.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 23 2013, 16:53
Сообщение #37


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Все получилось. Спасибо. Есть еще вопрос по расположению кода. Есть 2 функции. Мне необходимо чтобы точки входа в эти функции располагались строго по определенным адресам (например, точка входа в первую функцию по адресу 0xFC60, во вторую - по адресу 0xFC64). Возможно ли такое?
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 23 2013, 18:01
Сообщение #38


Гуру
******

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



Цитата(d7d1cd @ Nov 23 2013, 20:53) *
Спасибо. Есть еще вопрос по расположению кода. Есть 2 функции. Мне необходимо чтобы точки входа в эти функции располагались строго по определенным адресам (например, точка входа в первую функцию по адресу 0xFC60, во вторую - по адресу 0xFC64). Возможно ли такое?


За чем дело стало? Повторите снова тот же приём. Вы же уже раньше определяли сегмент
-Z(CODE)BOOT=F002-F0FF
и у вас всё получилось. Так определите теперь две таких штуки. С разными именами сегментов, конечно.

Вот только если точки входа так близко расположены: 0xFC60 и 0xFC64, вы врядли запихаете первую из функций в 4 байта. Следовательно у вас там есть место только для jmp-перехода. На C такого кода не написать, а на ассемблере - вполне. Напишите на ассемблере два джампа и вставьте пустые байты данных между ними, если это потребуется, чтобы второй джамп пришелся на 0xFC64. Тогда это будет всего один сегмент. Опять же на ассемблере гораздо проще расположить код в требуемых местах памяти.

Тем не менее, сдается мне, что вы собираетесь таким вычурным способом писать таблицу прерываний для загрузочного режима sm.gif. И если моя догадка верна, то всего этого делать не надо. А надо создать другой проект под бутовую часть, т.е. писать загрузчик в чистом виде, так чтобы и таблица прерываний, и кодовый сегмент были в верхней памяти. А уж потом объедините нижнюю часть кода (от проекта приложения) и верхнюю часть кода (от проекта загрузчика) на уровне нех-прошивки или бинарного кода.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 24 2013, 07:04
Сообщение #39


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Я пытался свою задачу выполнить следующим образом. В проекте на С++ в файле main я создал 2 функции. Для этих функций я задал сегмент расположения, который начинался с адреса 0xFC60. В телах этих функций я вызываю по 1 функции, которые содержат нужный рабочий код, и больше ничего. Сами эти функции я по порядку вызываю в функции main(). Выглядит это так:
Код
// Сегмент CODEPLACE начинается с адреса 0xFC60

#pragma location = "CODEPLACE"
void _Function1()
{
  Function1();      // Часть рабочего кода расположена в этой функции
}

#pragma location = "CODEPLACE"
void _Function2()
{
  Function2();      // Часть рабочего кода расположена в этой функции
}

int main()
{
  _Function1();      // У этой функции адрес вызова всегда должен быть 0xFC60
  _Function2();      // У этой функции адрес вызова всегда должен быть 0xFC64
}

Все задуманное работает... но только в конфигурации Debug. В конфигурации Release линкер располагает мои функции _Function1() и _Function2() не в начале сегмента CODEPLACE, а в конце. Соответственно, при изменении рабочего кода, адреса этих функций меняются. Может как то можно решить эту проблему?
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 24 2013, 17:58
Сообщение #40


Гуру
******

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



Цитата(d7d1cd @ Nov 24 2013, 11:04) *
Все задуманное работает... но только в конфигурации Debug. В конфигурации Release линкер располагает мои функции _Function1() и _Function2() не в начале сегмента CODEPLACE, а в конце. Соответственно, при изменении рабочего кода, адреса этих функций меняются. Может как то можно решить эту проблему?


Проблема решается просто: ... так и оставайтесь в конфигурации Debug, если она вас устраивает sm.gif. Лично я именно так всегда и пишу. Или сравните между собой обе конфигурации по каждому из параметров и найдите разницу, которая дает этот эффект.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Nov 25 2013, 15:21
Сообщение #41


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



А чем, собственно, отличаются конфигурации Debug и Release? Только опциями проекта?
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 25 2013, 21:12
Сообщение #42


Гуру
******

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



Цитата(d7d1cd @ Nov 25 2013, 19:21) *
А чем, собственно, отличаются конфигурации Debug и Release? Только опциями проекта?


Полагаю, что да. Ведь один же компилятор это компилит. Значит, либо в опциях разница или файл конфигурации другой (последний тоже в опциях задается, но по умолчанию может оказаться разным).
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Dec 28 2013, 15:06
Сообщение #43


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Привет всем. Снова вопрос по среде программирования. Есть проект на ассемблере. В проекте 2 файла. Один главный, второй с функциями (умножение, деление и т. д.). Оба файла добавлены в проект. Из первого файла функции второго видно посредством PUBLIC и EXTERN-ов.

Теперь вопрос. Во втором файле много функций, но в первом файле используется, например, одна. Однако при компиляции проекта, в исполняемый файл попадают все функции из 2 файла (хотя, повторюсь, используется только одна). Возможно ли сделать так, чтобы в конечный файл прошивки компилировались только используемые функции?
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Jan 1 2014, 13:25
Сообщение #44


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Разобрался в своем вопросе. Необходимо перед объявлением функции указать сегмент и флаг NOROOT:
Код
RSEG     CODE:NOROOT
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Jan 4 2014, 09:09
Сообщение #45


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Решил один вопрос, появился другой. Задам тут, может так быстрее сам решу или знающие люди подскажут.
Итак, вопрос. Есть директива ассемблера RSEG. Она указывает в каком сегменте памяти должен располагаться код, который идет после директивы. Имя сегмента и его "область действия" я могу задать либо в опциях линкера либо в конфигурационном файле .xcl. Если под код не будет хватать места, то при сборке линкер выдаст ошибку. А нельзя ли как то указать линкеру два сегмента для размещения кода? Когда в одном сегменте закончится место, линкер будет располагать оставшийся код во втором сегменте.

Сообщение отредактировал d7d1cd - Jan 4 2014, 09:10
Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 4 2014, 15:31
Сообщение #46


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(d7d1cd @ Jan 4 2014, 14:09) *
А нельзя ли как то указать линкеру два сегмента для размещения кода? Когда в одном сегменте закончится место, линкер будет располагать оставшийся код во втором сегменте.

Вам просто нужно для сегмента CODE указать несколько диапазонов адресов, перечислив их через запятую. Вот там я пояснял как правильно отредактировать XCL-файл.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Jan 4 2014, 17:15
Сообщение #47


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Спасибо за помощь!
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Jan 6 2014, 13:29
Сообщение #48


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Уже устал биться с линкером. Помогите...
У меня в проекте на ассемблере 2 файла (1 и 2). В 1 основные функции программы, во 2 так сказать рутинные функции (умножение, деление и прочее). Функции из файла 2 вызываются в 1 файле посредством директив PUBLIC и EXTERN. XCL-файл я использую свой. Его содержимое, состоящее из одной строки, такое:
Код
-Z(CODE)CODE=FC60-FFDF,9668-97EB          // Весь мой код должен быть в этих диапазонах адресов

Перед каждой функцией в файлах 1 и 2 я указываю сегмент размещения. Делаю это вот так (на примере функции умножения):
Код
RSEG    CODE:NOROOT:REORDER:SORT
Mul16u16uTo32u:                            
        DINT
        NOP
        MOV     R12, &MPY
        MOV     R13, &OP2
        MOV     &RESLO, R12
        MOV     &RESHI, R13
        EINT
        RET

Все было хорошо, пока мой код был мал. Линкер его размещал начиная с адреса FC60. Я думал, что когда закончится место в диапазоне FC60-FFDF, то линкер начнет размещать код в диапазоне 9668-97EB. Однако этого не произошло. Когда размер скомпилированного кода стал превышать размер диапазона FC60-FFDF, то линкер выдал мне ошибку:
Цитата
Linking
Error[e16]: Segment CODE (size: 0x384 align: 0x1) is too long for segment definition. At least 0x4 more bytes needed. The problem
occurred while processing the segment placement command "-Z(CODE)CODE=FC60-FFDF,9668-97EB", where at the moment of
placement the available memory ranges were "CODE:fc60-ffdf,CODE:9668-97eb"
Reserved ranges relevant to this placement:
9668-97eb CODE
fc60-ffdf CODE
Error while running Linker

Total number of errors: 1
Total number of warnings: 0

Я попробовал изменить порядок диапазонов адресов в XCL-файле. Однако это не помогло. Линкер выдает ту же ошибку. Что самое интересное, после изменения порядка адресов в XCL-файле, я убрал некоторые строки кода (чтобы "все стало помещаться"). После компиляции ошибки не стало, однако линкер все равно размещает код в диапазоне FC60-FFDF, хотя в XCL-файле этот диапазон прописан после диапазона 9668-97EB. Подскажите, что за напасть и как с ней бороться... smile3046.gif

P.S. Для информации:
CODE
NOROOT, ROOT
NOROOT means that the segment part is discarded by the linker if no symbols in this segment part are referred to.
Normally, all segment parts except startup code and interrupt vectors should set this flag.
The default mode is ROOT which indicates that the segment part must not be discarded.

REORDER, NOREORDER
REORDER allows the linker to reorder segment parts. For a given segment, all segment parts must specify the same state for this flag.
The default mode is NOREORDER which indicates that the segment parts must remain in order.

SORT, NOSORT
SORT means that the linker sorts the segment parts in decreasing alignment order. For a given segment,
all segment parts must specify the same state for this flag. The default mode is NOSORT
which indicates that the segment parts are not sorted.


Сообщение отредактировал d7d1cd - Jan 6 2014, 13:35
Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 6 2014, 13:52
Сообщение #49


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(d7d1cd @ Jan 6 2014, 18:29) *
Я попробовал изменить порядок диапазонов адресов в XCL-файле. Однако это не помогло. Линкер выдает ту же ошибку. Что самое интересное, после изменения порядка адресов в XCL-файле, я убрал некоторые строки кода (чтобы "все стало помещаться"). После компиляции ошибки не стало, однако линкер все равно размещает код в диапазоне FC60-FFDF, хотя в XCL-файле этот диапазон прописан после диапазона 9668-97EB. Подскажите, что за напасть и как с ней бороться... smile3046.gif

Приложите в сообщению весь ваш XCL-файл полностью.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Jan 6 2014, 14:59
Сообщение #50


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(rezident @ Jan 6 2014, 17:52) *
Приложите в сообщению весь ваш XCL-файл полностью.

Приложил...
Прикрепленные файлы
Прикрепленный файл  Segments.zip ( 189 байт ) Кол-во скачиваний: 13
 
Go to the top of the page
 
+Quote Post
SM
сообщение Jan 6 2014, 15:30
Сообщение #51


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Сделайте еще одну секцию с кодом, с другим именем, и вынесете в нее часть кода. На сколько я знаю, нельзя одну секцию разделить на два диапазона адресов, должно быть две разные секции.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Jan 6 2014, 15:46
Сообщение #52


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(SM @ Jan 6 2014, 19:30) *
Сделайте еще одну секцию с кодом, с другим именем, и вынесете в нее часть кода. На сколько я знаю, нельзя одну секцию разделить на два диапазона адресов, должно быть две разные секции.

Я понимаю, что можно так сделать. Но ведь хочется эту работу возложить на линкер. Тем более было тут сообщение уважаемого rezidenta:
Цитата
Вам просто нужно для сегмента CODE указать несколько диапазонов адресов, перечислив их через запятую. Вот там я пояснял как правильно отредактировать XCL-файл.
Go to the top of the page
 
+Quote Post
SM
сообщение Jan 6 2014, 16:57
Сообщение #53


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(d7d1cd @ Jan 6 2014, 19:46) *
Я понимаю, что можно так сделать. Но ведь хочется эту работу возложить на линкер.


Вообще, обычно линкеры не могут сами разбивать секцию на части, потому что не знают, как это корректно делать, в каком месте. Возможно, конечно, у IAR есть подсекции функций, или еще какие то механизмы для указания линкеру, как ему можно разбить секцию, но я этих механизмов в рамках IAR-а не знаю. В любом случае, требуются какие то директивы/указания, в каком месте секции можно разрывать - линкер сам этого не знает, и поэтому ругается.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Jan 6 2014, 17:16
Сообщение #54


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(SM @ Jan 6 2014, 20:57) *
Вообще, обычно линкеры не могут сами разбивать секцию на части, потому что не знают, как это корректно делать, в каком месте. Возможно, конечно, у IAR есть подсекции функций, или еще какие то механизмы для указания линкеру, как ему можно разбить секцию, но я этих механизмов в рамках IAR-а не знаю. В любом случае, требуются какие то директивы/указания, в каком месте секции можно разрывать - линкер сам этого не знает, и поэтому ругается.

Тогда для чего придуманы флаги для директивы RSEG (REORDER, SORT)? Про NOROOT знаю для чего: если данный код не используется, то линкер не вставляет его в готовую прошивку.
Go to the top of the page
 
+Quote Post
SM
сообщение Jan 6 2014, 19:17
Сообщение #55


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(d7d1cd @ Jan 6 2014, 21:16) *
Тогда для чего придуманы флаги для директивы RSEG (REORDER, SORT)? Про NOROOT знаю для чего: если данный код не используется, то линкер не вставляет его в готовую прошивку.


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

PS повторюсь, я не слышал, чтобы у IAR был механизм подсекций для процедур/функций - именно поэтому, вроде, на сколько я помню, секция внутри каждого модуля едина (для того и придумана, чтобы код/данные можно было прерывать, перемежать, в т.ч. в макросах, а потом все стало едиными цельными и гарантировано последовательными кусками), а вот куски секции, собираемые из разных модулей, линкер может менять местами, сортировать, выкидывать, и т.д.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Feb 27 2014, 15:30
Сообщение #56


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Итак, у меня снова возник вопрос по системе программирования.
Как известно, чтобы разместить код или переменную в определенной области памяти, необходимо в настройках линкера или в XCL-файле определить сегмент. А возможно ли это сделать прямо в файле с программой?
Go to the top of the page
 
+Quote Post
rezident
сообщение Feb 27 2014, 15:38
Сообщение #57


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(d7d1cd @ Feb 27 2014, 20:30) *
А возможно ли это сделать прямо в файле с программой?

Сделать что "это"? Переменные вы и так обязаны объявлять в своей программе.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Feb 27 2014, 16:09
Сообщение #58


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(rezident @ Feb 27 2014, 19:38) *
Сделать что "это"? Переменные вы и так обязаны объявлять в своей программе.

Я пишу на ассемблере. Чтобы разместить код функции по определенному адресу, я пишу:
Код
RSEG    MySegment
Mul16u16uTo32u:                            
        ...
        RET

А в файле XCL или в опциях линкера и прописываю:
Код
-Z(CODE)MySegment=1200-1300

Так вот: нельзя ли обойтись без файла XCL и опций линкера и описание сегмента расположить в файле, где расположен код функции.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Feb 27 2014, 16:54
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(d7d1cd @ Feb 27 2014, 20:09) *
[code]RSEG MySegment
Так вот: нельзя ли обойтись без файла XCL и опций линкера и описание сегмента расположить в файле, где расположен код функции.

Может и можно - посмотрите в документации есть ли у IAR директива ASEG или аналогичная.
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Feb 27 2014, 16:56
Сообщение #60


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Цитата(_Артём_ @ Feb 27 2014, 20:54) *
Может и можно - посмотрите в документации есть ли у IAR директива ASEG или аналогичная.

ASEG есть. И ASEGN есть. Какую директиву использовать? Не особо я силен в англицком. Подскажите в чем отличие этих директив друг от друга и от директивы RSEG? Вот их описание в документации:
CODE
Beginning an absolute segment
Use ASEG to set the absolute mode of assembly, which is the default at the beginning of
a module.
If the parameter is omitted, the start address of the first segment is 0, and subsequent
segments continue after the last address of the previous segment.
Note: If a move of an immediate value to an absolute address, for example
mov #0x1234, 0x300
is made in a relocatable or absolute segment, the offset is calculated as if the code begun
at address 0x0000. The assembler does not take into account the placement of the
segment.

Beginning a named absolute segment
Use ASEGN to start a named absolute segment located at the address address.
This directive has the advantage of allowing you to specify the memory type of the
segment.

Beginning a relocatable segment
Use RSEG to start a new segment. The assembler maintains separate location counters
(initially set to zero) for all segments, which makes it possible to switch segments and
mode anytime without having to save the current program location counter.
Up to 65536 unique, relocatable segments can be defined in a single module.

Beginning a common segment
Use COMMON to place data in memory at the same location as COMMON segments from
other modules that have the same name. In other words, all
COMMON segments of the
same name start at the same location in memory and overlay each other.
Obviously, the
COMMON segment type should not be used for overlaid executable code.
A typical application would be when you want several different routines to share a
reusable, common area of memory for data.
It can be practical to have the interrupt vector table in a
COMMON segment, thereby
allowing access from several routines.
The final size of the
COMMON segment is determined by the size of largest occurrence of
this segment. The location in memory is determined by the XLINK
-Z command; see
the IAR Linker and Library Tools Reference Guide.
Use the
align parameter in any of the above directives to align the segment start
address.


Сообщение отредактировал d7d1cd - Feb 27 2014, 17:28
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Feb 27 2014, 17:23
Сообщение #61


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(d7d1cd @ Feb 27 2014, 20:56) *
ASEG есть точно. Как ей правильно пользоваться?

Ну вы спросили - вы же msp программируете, у меня и компилятора под них нет.
В AVR так(для примера):
Код
ASEG INTVEC
ORG 0h

Для msp наверное что-то похожее, подробнее смотрите в Assembler Reference.
P.S. Cо скриптом как-то правильнее...
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Feb 28 2014, 13:39
Сообщение #62


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



Вроде разобрался как использовать директиву ASEG:
Код
ASEG     0x1240; Указываю для функции Proc адрес начала 0х1240
Proc:
         CLR         R12
         CALL        #Proc2
         MOV         R14, R12
         RET

Все вроде хорошо, но в XCL файле я мог указать диапазон адресов для сегмента. А здесь так видимо нельзя сделать. Или я не прав?

P.S. Со скриптом - это с использованием XCL файла и директивы RSEG?

Сообщение отредактировал d7d1cd - Feb 28 2014, 13:40
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Mar 11 2014, 13:20
Сообщение #63


Местный
***

Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199



При создании проекта на ассемблере я вижу, что есть подключенный файл multiplier.xcl. Я понимаю, что он нужен для использования аппаратного умножителя. Вопрос: как это осуществить?
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 3rd August 2025 - 11:05
Рейтинг@Mail.ru


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