|
Что это фича или баг?, avr-gcc 4.1.2 WinAvr 20070525 |
|
|
|
Dec 1 2008, 07:46
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Столкнулся с очень интересным эффектом. Есть два кода, с моей точки зрения, которые должны работать идентично. Но первый случай не работает, второй работает безупречно. Код tty ? (UDR1 = data) : (UDR0 = data);
disasm code: +000023EA: 91E010C5 LDS R30,0x10C5 Load direct from data space +000023EC: 91F010C6 LDS R31,0x10C6 Load direct from data space +000023EE: 0FE9 ADD R30,R25 Add without carry +000023EF: 1DF1 ADC R31,R1 Add with carry +000023F0: 8180 LDD R24,Z+0 Load indirect with
+000023F1: 938000CE STS 0x00CE,R24 Store direct to data space +000023F3: 918000CE LDS R24,0x00CE Load direct from data space Код if (tty > 0) UDR1 = data; else UDR0 = data;
disasm come: +000023E8: 91E010C5 LDS R30,0x10C5 Load direct from data space +000023EA: 91F010C6 LDS R31,0x10C6 Load direct from data space +000023EC: 0FE9 ADD R30,R25 Add without carry +000023ED: 1DF1 ADC R31,R1 Add with carry +000023EE: 8180 LDD R24,Z+0 Load indirect with
+000023EF: 938000CE STS 0x00CE,R24 Store direct to data space При дизасме в первом случае, вижу на мой взгляд абсолютно бесполезную строчку Код LDS R24,0x00CE Load direct from data space но которая(мне кажется) ломает функционал uart начисто (проявляется следующим образом: из регистра приёмника вычитывается байт, который был вычитан до этого. То есть вижу иногда в общем пакете по два одинаковых байта). Кто-нибудь может пояснить значение этой строчки??? Рботающий и неработающий коды отличаются только ей. И чем собственно коснтрукция ? : ; для компилятора отличается от if else?
|
|
|
|
|
Dec 1 2008, 08:21
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(forever failure @ Dec 1 2008, 11:00)  В первом случае в условии проверка на ненулевое значение, а во втором - на положительное. Может в этом разница ? Да собственно говоря в if можно и на равенство 0 проверять, асм будет такой же (постоянство радует  ). Меня просто напрягает, свободное обращение с регистром уарта UDR. Ведь и запись и чтение этого регистра запускают определённые физические процессы в уарте. А тут захотелось ему, он взял и вычитал значение из этого регистра в R24. Неприятное явление. ЗЫ В IAR и тот и другой случаи работают нормально. Цитата(Непомнящий Евгений @ Dec 1 2008, 11:09)  ? : возвращает результат, if else - нет. Больше вроде бы ничем.
Собственно в строчке LDS R24,0x00CE , насколько я понял, и возвращается результат операции UDR1 = data. 0x00CE это адрес UDR регистра, я не понимаю как это строчка может сообщать о результате операции.  Цитата(_Pasha @ Dec 1 2008, 11:10)  Нескромный вопрос: tty у Вас volatile? Просто не могу себе представить ситуацию, когда селектором устройств является не volatile переменная... К моему стыду действительно не volatile. Эта переменная часть структуры, описывающей уарт Код typedef struct { /** \brief tty - One of the defines UART_CHANNEL_0 or UART_CHANNEL_1. Which defines a number of UART. */ uint8_t tty; ...... ..... ..... } UartDescriptor_t;
|
|
|
|
|
Dec 1 2008, 09:03
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(xelax @ Dec 1 2008, 12:21)  я не понимаю как это строчка может сообщать о результате операции.  Код tty ? (UDR1 = data) : (UDR0 = data); Выполняется (UDR1 = data) и результат выражения - это значение UDR1, которое надо предварительно прочитать, из-за того, что оно описано volatile. А то, что результат больше никому не нужен - это уже совсем другая история. Мораль: хочешь, чтобы оно просто записало в порт, так и скажи компилеру, а проктология - не компьютерная наука.  Так что это фича. И лишнее доказательство того, что компилер не может оградить программиста от ошибок.
|
|
|
|
|
Dec 1 2008, 09:12
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(Непомнящий Евгений @ Dec 1 2008, 11:23)  И еще вопросик - я не въеду, где в приведенном вами дизасме происходит сравнение tty c 0? Или вы привели только кусочек? Да это кусок был... вот более полная версия  , с сравнением : Код 7c: 90 91 00 00 lds r25, 0x0000 80: 80 91 00 00 lds r24, 0x0000 84: 89 17 cp r24, r25 86: 01 f0 breq .+0 ; 88: e0 91 00 00 lds r30, 0x0000 8c: f0 91 00 00 lds r31, 0x0000 90: e9 0f add r30, r25 92: f1 1d adc r31, r1 94: 80 81 ld r24, Z 96: 80 93 ce 00 sts 0x00CE, r24 Это дизасм библиотечки, так что нет всех адресов  Ок. В принципе понял свою ошибку.
|
|
|
|
|
Dec 1 2008, 09:28
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Непомнящий Евгений @ Dec 1 2008, 13:15)  Т.е. получается что на один шаг оптимизатор срабатывает (выкидывая чтение в данном случае), а вот на два шага - в случае tty ? UDR1 = data : UDR0 = data - уже нет... Вот автор сказал, что ИАР выкинул лишнее чтение, а мне грустно: если компилер таким изящным манером исправил логическую ошибку программиста (согласитесь, ошибка ведь была), то где гарантия, что не бывает обратных ситуаций, т.е. абсолютно правильные с точки зрения логики действия программера цензурируются оптимизатором и это рождает ошибку. В общем, я все больше начинаю понимать gcc
|
|
|
|
|
Dec 1 2008, 09:54
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(_Pasha @ Dec 1 2008, 12:28)  Вот автор сказал, что ИАР выкинул лишнее чтение, а мне грустно: если компилер таким изящным манером исправил логическую ошибку программиста (согласитесь, ошибка ведь была), то где гарантия, что не бывает обратных ситуаций, т.е. абсолютно правильные с точки зрения логики действия программера цензурируются оптимизатором и это рождает ошибку. В общем, я все больше начинаю понимать gcc  А собственно компилятор ошибок и не исправляет, если уж на то пошло. А скорее всего это строчки убираются в процессе оптимизации. Так что я бы не стал обвинять ни iar ни gcc. Просто как показала практика у iar оптимизация тщательней делается
|
|
|
|
|
Dec 1 2008, 10:30
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(_Pasha @ Dec 1 2008, 12:28)  Вот автор сказал, что ИАР выкинул лишнее чтение... В общем, я все больше начинаю понимать gcc  Я собственно имел в виду, что обе строчки Код UDR1 = data;
tty ? UDR1 = data : UDR0 = data; Должны приводить к вычитыванию UDR1... Только в первом случае это чтение оптимизится, а во втором нет...
|
|
|
|
|
Dec 1 2008, 10:44
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(gotty @ Dec 1 2008, 13:33)  Никакая оптимизация не должна выкидывать чтение volatile переменной. Ну тогда получается, что конструкции вида Код РЕГИСТР = значение; должны приводить к записи регистра и его последующему чтению. Т.е. запись регистра без чтения на С вообще невозможна
|
|
|
|
|
Dec 1 2008, 10:51
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(gotty @ Dec 1 2008, 13:44)  Никакая оптимизация не должна выкидывать чтение volatile переменной. Зачем доводить идею до абсурда. Цитата(Непомнящий Евгений @ Dec 1 2008, 13:44)  Код РЕГИСТР = значение; должны приводить к записи регистра и его последующему чтению. Т.е. запись регистра без чтения на С вообще невозможна  А в случае с уартом в avr, будет полная неразбериха в линии. И ещё смысл делать read для write-only регистров
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|