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

 
 
> WinAVR: Cовмещение Си и ассемблера
MaxiMuz
сообщение Feb 9 2012, 11:23
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Здраствуйте !
Использовал пример из статьи: http://we.easyelectronics.ru/AVR/avr-gcc-s...om-proekte.html
"AVR-GCC: Совмещение C и ассемблера в одном проекте ". Начал править makefile, которым я обычно пользуюсь, но при указании Assembler source files... получил error: Oops, ASRC not found !
Не понимаю что не так делаю ! В чем может быть проблема ?
Go to the top of the page
 
+Quote Post
3 страниц V  < 1 2 3  
Start new topic
Ответов (30 - 43)
MaxiMuz
сообщение Feb 19 2012, 14:58
Сообщение #31


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Непонимаю смысл вставки:
Код
asm volatile("" : "+r" (Cnt_Dl));

В конкретном случае проблема "заоптимизации" решается вставкой volatile перед register uint16_t Cnt_Dl asm("r18");
Так что в данном случае квалификатор работает, посмотрю как будет дальше ...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 19 2012, 17:51
Сообщение #32


Гуру
******

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



QUOTE (MaxiMuz @ Feb 19 2012, 16:58) *
Непонимаю смысл вставки:
CODE
asm volatile("" : "+r" (Cnt_Dl));
Она говорит о том, что в результате этой вставки значение Cnt_Dl изменится и, следовательно, компилятор должен использовать новое значение, а не полагаться на знание старого.
QUOTE (MaxiMuz @ Feb 19 2012, 16:58) *
В конкретном случае проблема "заоптимизации" решается вставкой volatile перед register uint16_t Cnt_Dl asm("r18");
Удивительный человек. В документации ясно сказано - volatile совместно с register работает непредсказуемо, использовать такую связку нельзя. Нет же, мы аккуратно разложим грабли и любовно отполируем ручку, видимо, чтобы получить по лбу побольнее.

Добавлено: извиняюсь, полистал документацию и не нашел явного упоминания запрета связки register volatile. Гугля по фразе "gcc register volatile" выдает кучу ссылок на формы и баг-репорты gcc, но ни одной ссылки на документацию. Пройдя по этим ссылкам можно узнать, что эта связка не работает, что компилятор по -Wall и/или -Wextra должен на такую конструкцию выдавать проедупреждение "volatile register variables don%'t work as you might wish" и что лечить это не собираются.


--------------------
На любой вопрос даю любой ответ
"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
MaxiMuz
сообщение Feb 19 2012, 18:19
Сообщение #33


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(Сергей Борщ @ Feb 19 2012, 20:13) *
Удивительный человек. В документации ясно сказано - volatile совместно с register работает непредсказуемо, использовать такую связку нельзя. Нет же, мы аккуратно разложим грабли и любовно отполируем ручку, видимо, чтобы получить по лбу побольнее.

Где именно это сказанно в документации ??
Согласитесь что применительно к программе-компилятору слово "непредсказуемо" имеет условный смысл! Программа работает по определенному алгоритму , и пусть этот работа этого алгоритма не задокументирована. Но нельзя сказать что здесь имеет место случайность sm.gif ..
Так вот я сейчас провожу исследование sm.gif , как именно влияет на задействование (оптимизацию ) регистровых переменных применение или неприменение volatile . За что конечно не могу сказать спасибо создателям этого компилятора. Но тем не менее уже проследил некоторые закономерности работы. Испробованы пока не все случаи... Хочу потом все это оформить в удобочитаемую форму. Если вам будет интересно , я первому сообщу как будет готово.

п.с. Да действительно соглашусь , volatile применительно к регис.перем. не хрена ни работает так, как описано в официальной документации. Пока единственное что могу добавить что его применение здесь всеже в некоторых случаях оправданно.
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Feb 20 2012, 08:54
Сообщение #34


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (MaxiMuz @ Feb 20 2012, 02:19) *
Где именно это сказанно в документации ??
Согласитесь что применительно к программе-компилятору слово "непредсказуемо" имеет условный смысл! Программа работает по определенному алгоритму , и пусть этот работа этого алгоритма не задокументирована. Но нельзя сказать что здесь имеет место случайность sm.gif ..

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


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Feb 21 2012, 19:40
Сообщение #35


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(haker_fox @ Feb 20 2012, 11:54) *
Она может принимать решения в зависимости от контекста - Вашей программы. Вот и получается случайность.

Контекста какого ? названия переменных, количество их упоминания, или всеже использование р.п. в стандартных конструкциях (for, if, case, и т.д.) , в выражениях присваивания или же в мат.выражениях ?

Сейчас столкнулся с следующей проблемой!
в заголовочном файле пишу:
Код
#ifdef __ASSEMBLER__
......
#  define GenCnt    r19
......
#else  /* !ASSEMBLER */
......
register uint8_t GenCnt asm("r19");
......
#endif /* ASSEMBLER */

компилятор мне говорит что переменная, обьявленная в Си, может быть затерта. Но я так понимаю это относится именно к Сишному куску программы.
Заглянул в код , а там в Ассемблерном куске регистор r19 везде заменен на r16 , который уже используется совместно в другом месте!
После того как я заменил Makefile на файл из стандарт.папки asmdemo все нормально скомпилировалось. На что следует обратить внимание в этом файле ? Что может влиять на использование регистровых переменных в асме ?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 21 2012, 23:53
Сообщение #36


Гуру
******

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



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


--------------------
На любой вопрос даю любой ответ
"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
slavik.ksu
сообщение Feb 22 2012, 06:08
Сообщение #37


Участник
*

Группа: Участник
Сообщений: 19
Регистрация: 15-12-11
Пользователь №: 68 876



здравствуй те уважаемые форумчане!
Перехожу на Си, ничего не понимаю, поэтому не судите строго
задача: по приходу данных по UART генерируется прерывание по "завершению приема" и загорается светодиод. В симуляции прерывание происходит а то что внутри {} игнорируется, в чем можетбыть причина?
ISR ( USART_RX_vect )
{
switch(UDR)
{
LED_PORT &= ~ (1<<LED2);break;
}
}

Полный код программы прилагаю.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 22 2012, 06:36
Сообщение #38


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Код
ISR ( USART_RX_vect )
{
   switch (UDR)
   {
      case 0: LED_PORT &= ~ (1<<LED2); break;
      case 1: .... break;
      case 2: .... break;
      ....
      default: ... break;
   }
}
Стоит создавать свою тему для вопроса никак не связанного с темой топика...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
slavik.ksu
сообщение Feb 22 2012, 06:42
Сообщение #39


Участник
*

Группа: Участник
Сообщений: 19
Регистрация: 15-12-11
Пользователь №: 68 876



Оказывается в конструкции switch строка выполняется только после меток case или default !
Спасибо за внимание! sm.gif
Go to the top of the page
 
+Quote Post
slavik.ksu
сообщение Feb 22 2012, 06:43
Сообщение #40


Участник
*

Группа: Участник
Сообщений: 19
Регистрация: 15-12-11
Пользователь №: 68 876



Оказывается в конструкции switch строка выполняется только после меток case или default !
Спасибо за внимание! sm.gif




Сообщение отредактировал slavik.ksu - Feb 22 2012, 06:43
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 22 2012, 07:49
Сообщение #41


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Смотря что имеется ввиду под словом «выполняется»
Код
#include <stdint.h>

uint8_t foo(uint8_t u)
{
    switch (u) {
        static uint8_t s = 20;
    case 0:
        return u+s;
    case 1:
        ++s;
    case 2:
        return u-s;
    default:
        break;
    }
    // s = 0; // Низзя! Тут s  не видно, она внутри блока swicth
    return 0;
}
Код
foo:
/* prologue: function */
/* frame size = 0 */
    cpi r24,lo8(1)
    breq .L4
    cpi r24,lo8(1)
    brlo .L3
    cpi r24,lo8(2)
    breq .L11
    ldi r24,lo8(0)
    ret
.L3:
    lds r24,s.1215
    ret
.L4:
    lds r25,s.1215
    subi r25,lo8(-(1))
    sts s.1215,r25
    sub r24,r25
    ret
.L11:
    lds r25,s.1215
    sub r24,r25
    ret

    .data
s.1215:
    .byte    20



Где-то уже писал — не могу найти...

switch — это такой оптимизированный условный goto в кучу меток. Все метки должны быть внутри одного выражения (statement)
Цитата(C99)
6.8.4 Selection statements
Syntax
1
selection-statement:
if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement
Как видим, особой разницы между if ( expression ) statement и swicth ( expression ) statement не наблюдается. Кто такой statement — смотрим отдельно
Цитата
6.8 Statements and blocks
statement:
labeled-statement /* сюда входит метка case */
compound-statement
...

Цитата
6.8.2 Compound statement
compound-statement:
{ block-item-listopt }
block-item-list:
block-item
block-item-list block-item
block-item:
declaration /* в любом compound statement, включая switch-евый, может быть declaration */
statement


Если выражение простое (не составное), то и switch может выглядеть вообще так:
Код
uint8_t moo(uint8_t u)
{
        // if ( u == 0 || u == 3 || u == 5 ) return 0;
        switch(u)
        case 0:
        case 3:
        case 5:
                return 0;

        return 1;
}

Код
moo:
    cpi r24,lo8(3)
    breq .L14
    cpi r24,lo8(5)
    breq .L14
    tst r24
    brne .L17
.L14:
    ldi r24,lo8(0)
    ret
.L17:
    ldi r24,lo8(1)
    ret

Тут несколько разных путей поставить нельзя, так как ';' ограничивает выражение и следующий case окажется за пределами switch.
Поэтому swicth «чуть реже, чем всегда» применяется с составными (compound statement), заключающими отдельные statement в фигурные скобки.
А в начале такого блока может и до метки что-то стоять. Главное, чтобы смысл в этом был. Как в примере выше — статическая переменная.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Feb 22 2012, 07:50
Сообщение #42


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(Сергей Борщ @ Feb 22 2012, 02:53) *
Я никогда не использовал регистровые переменные, но часто читал о магическом ключике компилятора -ffixed-reg.

Проблема не в Си коде , а данный ключик я так понимаю относится именно к Си.
Воодщемполностью заголовочный файл:
Код
#ifdef __ASSEMBLER__
#  define sreg_save r2
#  define LedTne r4
#  define GenCnt r18
#  define Cnt_Dl_low  r16
#  define Cnt_Dl_hi  r17
#else  /* !ASSEMBLER */
register uint8_t sreg_save asm("r2");
register uint8_t LedTne asm("r4");
register uint8_t GenCnt asm("r18");
volatile register uint16_t Cnt_Dl asm("r16");
#endif /* ASSEMBLER */

Часть листинга с кодами включающий ассемблерную вставку:
Код
000000a2 <__vector_6>:
;_____________________________________________________
;_______ Прерывание по сопадению каждые 64 такта
.global TIM0_COMPA_vect
TIM0_COMPA_vect:
in sreg_save, _SFR_IO_ADDR(SREG)
  a2: 2f b6        in r2, 0x3f; 63
tst LedTne
  a4: 44 20        and r4, r4
brne tca1
  a6: 11 f4        brne .+4     ; 0xac <tca1>
cbi _SFR_IO_ADDR(PORTB),Led
  a8: c0 98        cbi 0x18, 0; 24
rjmp tca2
  aa: 01 c0        rjmp .+2     ; 0xae <tca2>

000000ac <tca1>:
tca1:
dec LedTne
  ac: 4a 94        dec r4

000000ae <tca2>:
tca2:
inc GenCnt; увеличение глав.счетчика
  ae: 03 95        inc r16
cpi GenCnt,0xff
  b0: 0f 3f        cpi r16, 0xFF; 255
brne tca3; продолжение ...
  b2: 41 f4        brne .+16    ; 0xc4 <tca3>
ldi GenCnt , 0;
  b4: 00 e0        ldi r16, 0x00; 0
lds LedTne,BufLed;обновление буфера яркости св.ди.
  b6: 40 90 60 00  lds r4, 0x0060
tst LedTne; проверка на 0 !
  ba: 44 20        and r4, r4
breq tca4
  bc: 09 f0        breq .+2     ; 0xc0 <tca4>
sbi _SFR_IO_ADDR(PORTB),Led
  be: c0 9a        sbi 0x18, 0; 24

000000c0 <tca4>:
;___ Фоновые счетчики:
tca4:
subi Cnt_Dl_low,1
  c0: 01 50        subi r16, 0x01; 1
sbci Cnt_Dl_hi,0; уменьшение на 1.
  c2: 10 40        sbci r17, 0x00; 0

000000c4 <tca3>:

tca3:
out _SFR_IO_ADDR(SREG), sreg_save
  c4: 2f be        out 0x3f, r2; 63
reti
  c6: 18 95        reti

Если внимательно посмотреть на команды с регистром GenCnt , вместо обьявленного r18 везде стоит r16.
Рег. перем. sreg_save, LedTne, GenCnt в Си-программе никак не используются и регистры им соответствующие незадействованы.
Так понимаю подмена регистра может происходить из за какихто настроек Ассемблера, в чем может быть дело ?

Сообщение отредактировал MaxiMuz - Feb 22 2012, 07:57
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Feb 22 2012, 10:02
Сообщение #43


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(MaxiMuz @ Feb 22 2012, 10:50) *
Так понимаю подмена регистра может происходить из за какихто настроек Ассемблера, в чем может быть дело ?

Все, разобрался в чем дело !
Оказывается после редактирования заголовочного файла , чтобы изменения касающиеся Ассемблерной части вступили в силу, нужно сам файл (*.S) обновить !
Я еще не разобрался в механизме сборки hex-кода , но похоже что файл *.o берется линковщиком для сборки, а как раз он не был обновлен, и тупо подставлялась старая часть асм-кода. Вообще былобы интересно почитать (желательно на руском) о механизме получения hex файла.


Уважаемый slavik.ksu! , то что вы пишете конечно интересно , но хотелось чтобы в этой теме задавались вопросы касаемые именно совмесного использования Ассмеблера в WinAVR.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 22 2012, 11:16
Сообщение #44


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Кстати, да.
Если кто-то из модераторов перенесёт всё от его вопроса по мой ответ включительно в отдельную тему или, например, сюда
http://electronix.ru/forum/index.php?showt...=99905&st=0
(ну а это сообщение потрёт), то хуже не будет.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

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

 


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


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