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

 
 
> C+ASM - помогите, Не понимаю, чего ему не нравится
Kitsok
сообщение Mar 5 2008, 05:45
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136



Всем приветы!

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

Имеется IAR 4.41, пытаюсь сделать ассемблерную вставку, не выходит:

Код
static inline portDISABLE_INTERRUPTS(void)
{      
  asm (" STMDB    SP!, {R0}");
  asm (" MRS    R0, CPSR");
  asm (" ORR R0,R0,#0x80");
  asm (" MSR CPSR,R0");
  asm (" LDMIA    SP!, {R0}");
}


В ответ получаю
Код
Error[Og006]: Syntax error in inline assembly: "Error[401]: Operand syntax error" c:\PTJoy\new\firmware\ptjoy\FreeRTOS\Source\portable\IAR\SAM7S256\portmacro.h 93
Error[Og006]: Syntax error in inline assembly: "Error[401]: Operand syntax error" c:\PTJoy\new\firmware\ptjoy\FreeRTOS\Source\portable\IAR\SAM7S256\portmacro.h 94
Error[Og006]: Syntax error in inline assembly: "Error[401]: Operand syntax error" c:\PTJoy\new\firmware\ptjoy\FreeRTOS\Source\portable\IAR\SAM7S256\portmacro.h 95


По-хорошему, нужно делать #define'ом, но там то-же самое, только без номеров строк wink.gif

Ткните пожалуйста, что я делаю не так. Процессор - ARM7.

Спасибо!
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 17)
tag
сообщение Mar 5 2008, 06:31
Сообщение #2


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

Группа: Свой
Сообщений: 151
Регистрация: 21-02-06
Пользователь №: 14 561



Код
  asm (" MRS    R0, CPSR");
  asm (" ORR R0,R0,#0x80");
  asm (" MSR CPSR,R0");


В этих командах у Вас ошибка синтаксиса, посмотрите manual.
Go to the top of the page
 
+Quote Post
Kitsok
сообщение Mar 5 2008, 06:46
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136



Цитата(tag @ Mar 5 2008, 09:31) *
В этих командах у Вас ошибка синтаксиса, посмотрите manual.


Смотрю ассемблерный листинг, сгенерированный этим-же компилятором:
Код
vPortEnterCritical:
        MRS      R0,CPSR
        ORR      R0,R0,#0xC0
        MSR      CPSR_c,R0


и не вижу разницы...
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Mar 5 2008, 07:05
Сообщение #4


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Ассемблерную строку надо заканчивать символом \n
См. в описании компилятора главу INLINE ASSEMBLER.
Пример из описания:
Код
bool flag;
void foo()
{
  while (!flag)
  {
    asm(" ldr r2,[pc,#0] \n"     /* r2 = address of flag */
    " b .+8 \n"                        /* jump over constant */
    " DCD flag \n"                   /* address of flag */
    " ldr r3,[pc,#0] \n"            /* r3 = address of PIND */
    " b .+8 \n"                        /* jump over constant */
    " DCD PIND \n"                /* address of PIND */
    " ldr r0,[r3] \n"                 /* r0 = PIND */
    " str r0,[r2]");                  /* flag = r0 */
  }
}

Хотя может и не в этом дело.
Go to the top of the page
 
+Quote Post
Kitsok
сообщение Mar 5 2008, 07:08
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136



Цитата(IgorKossak @ Mar 5 2008, 10:05) *
Ассемблерную строку надо заканчивать символом \n
См. в описании компилятора главу INLINE ASSEMBLER.


Да пробовал и с \n:

Код
static inline portDISABLE_INTERRUPTS(void)
{      
  asm (" STMDB    SP!, {R0}\n");
  asm (" MRS    R0, CPSR\n");
  asm (" ORR R0,R0,#0x80\n");
  asm (" MSR CPSR,R0\n");
  asm (" LDMIA    SP!, {R0}\n");
}


Ошибки те-же в тех-же местах.
ЗЫ большие-маленькие мнемоники я тоже пробовал, и названия регистров тоже wink.gif
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Mar 5 2008, 07:15
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 877
Регистрация: 26-01-05
Из: Екатеринбург
Пользователь №: 2 206



Цитата(Kitsok @ Mar 5 2008, 12:08) *
Ошибки те-же в тех-же местах.


а у меня ваш код без проблем откомпилировался:
Код
# IAR ARM ANSI C/C++ Compiler V4.41A/W32 EVALUATION    05/Mar/2008  12:09:03 #   \                                 In segment CODE, align 4, keep-with-next
    266          void portDISABLE_INTERRUPTS(void)
    267          {      
    268            asm (" STMDB    SP!, {R0}");
   \                     ??portDISABLE_INTERRUPTS:
   \   00000000   01002DE9           STMDB    SP!, {R0}
    269            asm (" MRS    R0, CPSR");
   \   00000004   00000FE1           MRS    R0, CPSR
    270            asm (" ORR R0,R0,#0x80");
   \   00000008   800080E3           ORR R0,R0,#0x80
    271            asm (" MSR CPSR,R0");
   \   0000000C   00F029E1           MSR CPSR,R0    
    272            asm (" LDMIA    SP!, {R0}");
   \   00000010   0100BDE8           LDMIA    SP!, {R0}
    273          }
   \   00000014   0EF0A0E1           MOV      PC,LR          ;; return


А почему вы не хотите:
Код
void portDISABLE_INTERRUPTS_1(void)
{      
    __set_CPSR(__get_CPSR() | 0x80);
}


?


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Mar 5 2008, 07:21
Сообщение #7


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Взял Вашу функцию один к одному, скомпилировал, ни одной ошибки.
Правда у меня версия 5.11, но не думаю, чтобы так сильно всё отличалось.

Нашел в чём дело.
Если в настройках компилятора устанавливаю Code->Processor mode->Thumb, то возникает ошибка 401.
С ARM всё нормально.
Go to the top of the page
 
+Quote Post
Kitsok
сообщение Mar 5 2008, 07:31
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136



Цитата(IgorKossak @ Mar 5 2008, 10:21) *
Взял Вашу функцию один к одному, скомпилировал, ни одной ошибки.
Правда у меня версия 5.11, но не думаю, чтобы так сильно всё отличалось.

Нашел в чём дело.
Если в настройках компилятора устанавливаю Code->Processor mode->Thumb, то возникает ошибка 401.
С ARM всё нормально.


Вот похоже, что в этом и дело.

В итоге вот так скомпилялось, а работает или нет - буду проверять wink.gif

Код
__arm __interwork static inline __disable_IRQ( void );


__arm __interwork static inline __disable_IRQ(void)
{      
  asm (" stmdb    SP!, {r0}\n");
  asm (" mrs    r0, CPSR\n");
  asm (" orr r0,r0,#0x80\n");
  asm (" msr CPSR,r0\n");
  asm (" ldmia SP!, {r0}\n");
}

#define portDISABLE_INTERRUPTS() __disable_IRQ()
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Mar 5 2008, 07:35
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 877
Регистрация: 26-01-05
Из: Екатеринбург
Пользователь №: 2 206



более правильный код для запрещения прерываний на АРМ такой:
Код
    do
    {
        __set_CPSR(StatusReg | (1<<7));
    }
    while (!(__get_CPSR() & (1<<7)));


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post
Kitsok
сообщение Mar 5 2008, 07:54
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136



Цитата(Andy Mozzhevilov @ Mar 5 2008, 10:35) *
более правильный код для запрещения прерываний на АРМ такой:
Код
    do
    {
        __set_CPSR(StatusReg | (1<<7));
    }
    while (!(__get_CPSR() & (1<<7)));


Дык у меня thumb, а __?et_CPSR - intrinsic, поэтому, видимо, все функции, вызывающие такой запрет нужно компилять с __intrinsic. А в чем разница с моим-то? wink.gif Вон, родной __disable_interrupt вообще даже R0 в стеке не сохраняет.
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Mar 5 2008, 08:15
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 877
Регистрация: 26-01-05
Из: Екатеринбург
Пользователь №: 2 206



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


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 5 2008, 10:08
Сообщение #12


Гуру
******

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



Цитата(Andy Mozzhevilov @ Mar 5 2008, 09:35) *
более правильный код для запрещения прерываний на АРМ такой:
Еще более оптимальный такой (исправлен):
Код
    while (!(__get_CPSR() & (1<<7)))
    {
        __set_CPSR(StatusReg | (1<<7));
    }
Цитата(Andy Mozzhevilov @ Mar 5 2008, 10:15) *
Не могу сейчас быстро найти соответсвующий раздел документации.
Atmel Application Note Rev. 1156A-08/98
Цитата(Kitsok @ Mar 5 2008, 09:54) *
Дык у меня thumb, а __?et_CPSR - intrinsic, поэтому, видимо, все функции, вызывающие такой запрет нужно компилять с __intrinsic.
Доступ к CPSR имеют только команды ARM-режима (MSR, MRS). Из THUMB режима могут быть вызваны ARM-функции, скомпилированные с атрибутом __interwork. __intrinsic - ключевое слово для функций, реализованных внутри компилятора (для которых компилятор генерит код сам в процессе компиляции) и не должно использоваться для пользовательских функций. Генерируемый для __intrinsic - функций код может отличаться в зависимости от аргументов, режима компиляции и кучи других параметров. Для той же __disable_interrupt() в ARM-режиме генерится непосредственно MSR, MCR, а в THUMB-режиме - вызов соответствующей ARM-функции.


--------------------
На любой вопрос даю любой ответ
"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
Kitsok
сообщение Mar 5 2008, 11:33
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136



Вот на этом while'е оно и встанет wink.gif Точка с запятой там явно лишняя.
Да, __intrinsic перепутал естественно с __interwork.

Вроде работает, спасибо!

Начинаем битву с FIQ, но это уже тема совсем другого топика wink.gif
Go to the top of the page
 
+Quote Post
repairDV
сообщение Mar 5 2008, 12:35
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 578
Регистрация: 7-11-06
Из: Хабаровск
Пользователь №: 22 044



А этот ассемблер, который внутри процедуры Си, полнофункциональный? Условные - безусловные переходы на метки поддерживает?


--------------------
Маленький нанайца. А-а. А-а. Оморочком плыл. Маленький проточка. Осетра ловил.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 5 2008, 12:41
Сообщение #15


Гуру
******

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



Цитата(Kitsok @ Mar 5 2008, 13:33) *
Вот на этом while'е оно и встанет wink.gif Точка с запятой там явно лишняя.
Угу. Делал быстро из кода Andy, упустил.
Цитата(repairDV @ Mar 5 2008, 14:35) *
А этот ассемблер, который внутри процедуры Си, полнофункциональный? Условные - безусловные переходы на метки поддерживает?
Нет. Это даже не ассемблер, а так, некий костыль чтобы вставить NOP. Даже в документации написано что-то вроде "ну есть нечто похожее на ассемблер, но лучше и не пытайтесь его использовать sad.gif". В этом смысле инлайн-ассемблер GCC - просто произведение искусства.


--------------------
На любой вопрос даю любой ответ
"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
GetSmart
сообщение Mar 5 2008, 14:04
Сообщение #16


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(Сергей Борщ)
Цитата(repairDV @ Mar 5 2008 @ 14:35)
А этот ассемблер, который внутри процедуры Си, полнофункциональный? Условные - безусловные переходы на метки поддерживает?
Нет. Это даже не ассемблер, а так, некий костыль чтобы вставить NOP.
Странно. У меня поддерживал всегда. Постоянно оптимизированные циклы строчил на асме. IAR 4.20.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
repairDV
сообщение Mar 5 2008, 14:15
Сообщение #17


Знающий
****

Группа: Свой
Сообщений: 578
Регистрация: 7-11-06
Из: Хабаровск
Пользователь №: 22 044



Цитата(GetSmart @ Mar 6 2008, 00:04) *
Странно. У меня поддерживал всегда. Постоянно оптимизированные циклы строчил на асме. IAR 4.20.

Это хорошо. У меня, правда, IAR для NEC. Простеньких, только для датчиков давления. Но, может быть, придётся по-серьёзному с ним работать.
Для примера: CodeWarrior позволяет писать полнофункциональные программы в ассемблере внутри Си-функций. Очень удобно. Стиль написания приблизительно похож на тот, который здесь приводился.


--------------------
Маленький нанайца. А-а. А-а. Оморочком плыл. Маленький проточка. Осетра ловил.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 5 2008, 15:44
Сообщение #18


Гуру
******

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



Цитата(GetSmart @ Mar 5 2008, 16:04) *
Нет. Это даже не ассемблер, а так, некий костыль чтобы вставить NOP.Странно. У меня поддерживал всегда. Постоянно оптимизированные циклы строчил на асме. IAR 4.20.
Ну, я собственно пересказал вот это:
Цитата
Inline assembler sequences have no well-defined interface with the surrounding code generated from your C or C++ code. This makes the inline assembler code fragile, and will possibly also become a maintenance problem if you upgrade the compiler in the future. In addition, there are several limitations to using inline assembler:
● The compiler’s various optimizations will disregard any effects of the inline sequences, which will not be optimized at all
● The directives CODE16 and CODE32 will cause errors; several other directives cannot be used at all
● Alignment cannot be controlled; this means, for example, that DC32 directives may be misaligned
● Auto variables cannot be accessed
● Alternative register names, mnemonics, and operators are not supported; read more about the -j assembler option in the ARM® IAR Assembler Reference Guide.
Inline assembler is therefore often best avoided. If there is no suitable intrinsic function available, we recommend the use of modules written in assembler language instead of inline assembler, because the function call to an assembler routine normally causes less performance reduction.
Интересно, чем "will cause errors" отличается от "cannot be used at all" smile.gif Про метки и переходы я, похоже, погорячился.


--------------------
На любой вопрос даю любой ответ
"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

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 18:30
Рейтинг@Mail.ru


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