xelax 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба Столкнулся с очень интересным эффектом. Есть два кода, с моей точки зрения, которые должны работать идентично. Но первый случай не работает, второй работает безупречно. 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? :07: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
forever failure 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба В первом случае в условии проверка на ненулевое значение, а во втором - на положительное. Может в этом разница ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Johnny81 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба И чем собственно коснтрукция ? : ; для компилятора отличается от if else? :07: ? : возвращает результат, if else - нет. Больше вроде бы ничем. Собственно в строчке LDS R24,0x00CE , насколько я понял, и возвращается результат операции UDR1 = data. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба но которая(мне кажется) ломает функционал uart начисто Нескромный вопрос: tty у Вас volatile? Просто не могу себе представить ситуацию, когда селектором устройств является не volatile переменная... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xelax 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба В первом случае в условии проверка на ненулевое значение, а во втором - на положительное. Может в этом разница ? Да собственно говоря в if можно и на равенство 0 проверять, асм будет такой же (постоянство радует :) ). Меня просто напрягает, свободное обращение с регистром уарта UDR. Ведь и запись и чтение этого регистра запускают определённые физические процессы в уарте. А тут захотелось ему, он взял и вычитал значение из этого регистра в R24. Неприятное явление. ЗЫ В IAR и тот и другой случаи работают нормально. ? : возвращает результат, if else - нет. Больше вроде бы ничем. Собственно в строчке LDS R24,0x00CE , насколько я понял, и возвращается результат операции UDR1 = data. 0x00CE это адрес UDR регистра, я не понимаю как это строчка может сообщать о результате операции. :07: Нескромный вопрос: 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Johnny81 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба 0x00CE это адрес UDR регистра, я не понимаю как это строчка может сообщать о результате операции. :07: Ну вероятно GGC полагает, что результатом операции a=b является значение "a" после операции присваивания. А "а" у вас - UDR1 - вероятно помеченный volatile или еще как-то. Вот его значение и вычитывается... И еще вопросик - я не въеду, где в приведенном вами дизасме происходит сравнение tty c 0? Или вы привели только кусочек? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба я не понимаю как это строчка может сообщать о результате операции. :07: tty ? (UDR1 = data) : (UDR0 = data); Выполняется (UDR1 = data) и результат выражения - это значение UDR1, которое надо предварительно прочитать, из-за того, что оно описано volatile. А то, что результат больше никому не нужен - это уже совсем другая история. Мораль: хочешь, чтобы оно просто записало в порт, так и скажи компилеру, а проктология - не компьютерная наука. :) Так что это фича. И лишнее доказательство того, что компилер не может оградить программиста от ошибок. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xelax 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба И еще вопросик - я не въеду, где в приведенном вами дизасме происходит сравнение 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 Это дизасм библиотечки, так что нет всех адресов :laughing: Ок. В принципе понял свою ошибку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Johnny81 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба Выполняется (UDR1 = data) и результат выражения - это значение UDR1, которое надо предварительно прочитать, из-за того, что оно описано volatile. А то, что результат больше никому не нужен - это уже совсем другая история. Кстати, по-идее даже просто запись UDR1=data должна приводить к вычитыванию UDR1 :) Т.е. получается что на один шаг оптимизатор срабатывает (выкидывая чтение в данном случае), а вот на два шага - в случае tty ? UDR1 = data : UDR0 = data - уже нет... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба Т.е. получается что на один шаг оптимизатор срабатывает (выкидывая чтение в данном случае), а вот на два шага - в случае tty ? UDR1 = data : UDR0 = data - уже нет... Вот автор сказал, что ИАР выкинул лишнее чтение, а мне грустно: если компилер таким изящным манером исправил логическую ошибку программиста (согласитесь, ошибка ведь была), то где гарантия, что не бывает обратных ситуаций, т.е. абсолютно правильные с точки зрения логики действия программера цензурируются оптимизатором и это рождает ошибку. В общем, я все больше начинаю понимать gcc :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xelax 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба Вот автор сказал, что ИАР выкинул лишнее чтение, а мне грустно: если компилер таким изящным манером исправил логическую ошибку программиста (согласитесь, ошибка ведь была), то где гарантия, что не бывает обратных ситуаций, т.е. абсолютно правильные с точки зрения логики действия программера цензурируются оптимизатором и это рождает ошибку. В общем, я все больше начинаю понимать gcc :) А собственно компилятор ошибок и не исправляет, если уж на то пошло. А скорее всего это строчки убираются в процессе оптимизации. Так что я бы не стал обвинять ни iar ни gcc. Просто как показала практика у iar оптимизация тщательней делается :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Johnny81 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба Вот автор сказал, что ИАР выкинул лишнее чтение... В общем, я все больше начинаю понимать gcc :) Я собственно имел в виду, что обе строчки UDR1 = data; tty ? UDR1 = data : UDR0 = data; Должны приводить к вычитыванию UDR1... Только в первом случае это чтение оптимизится, а во втором нет... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
msalov 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба А собственно компилятор ошибок и не исправляет, если уж на то пошло. А скорее всего это строчки убираются в процессе оптимизации. Так что я бы не стал обвинять ни iar ни gcc. Просто как показала практика у iar оптимизация тщательней делается :) Никакая оптимизация не должна выкидывать чтение volatile переменной. Обсуждение было в теме http://electronix.ru/forum/index.php?showtopic=54275 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Johnny81 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба Никакая оптимизация не должна выкидывать чтение volatile переменной. Ну тогда получается, что конструкции вида РЕГИСТР = значение; должны приводить к записи регистра и его последующему чтению. Т.е. запись регистра без чтения на С вообще невозможна :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xelax 0 1 декабря, 2008 Опубликовано 1 декабря, 2008 · Жалоба Никакая оптимизация не должна выкидывать чтение volatile переменной. Зачем доводить идею до абсурда. РЕГИСТР = значение; должны приводить к записи регистра и его последующему чтению. Т.е. запись регистра без чтения на С вообще невозможна :) А в случае с уартом в avr, будет полная неразбериха в линии. :) И ещё смысл делать read для write-only регистров :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться