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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> 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
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

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 08:42
Рейтинг@Mail.ru


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