MrYuran 16 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба Столкнулся (уже не первый раз) с неприятной особенностью MSPGCC в части работы с переменными типа char. при подсчёте контрольной суммы пакета иногда возникают сбои. static char volatile Uart0Buffer[8]; static unsigned char Csumm; ... Csumm=1; for (i=0;i<6;i++) { Csumm += ~Uart0Buffer[i]; // вычисление контр. суммы } if(!((Uart0Buffer[6]-Csumm) & 0xff)) // контр. сумма верна и вообще Последнее условие раньше выглядело if(Uart0Buffer[6] == Csumm) и работало через раз, пока не наложил байтовую маску. Такие вот дела. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба Последнее условие раньше выглядело if(Uart0Buffer[6] == Csumm) и работало через раз, пока не наложил байтовую маску. Такие вот дела.Покажите листинг для обоих случаев. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба Попробовал сделать листинг objdump-ом, херь какая-то. Сплошной листинг без меток и разбивки на секции... А ведь раньше нормально всё было... Может, elf неправильно делается, ключи там какие добавить или чё Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба А ведь раньше нормально всё было... Может, elf неправильно делается, ключи там какие добавить или чё Если это под виндой, то вероятнее всего причина в этом: avr-objdump.exe -S switch not working. Мне помогло. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба static char volatile Uart0Buffer[8]; static unsigned char Csumm; .... Csumm += ~Uart0Buffer; // вычисление контр. суммы Может стоило так: static volatile unsigned char Uart0Buffer[8]; Csumm += (unsigned char)~Uart0Buffer; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба Мне помогло. Не совсем понял, что помогло: поменять концы файлов или пересобрать GCC с заплаткой? Самое интересное, что раньше-то всё было. Взял для интереса давнишний elf, сделал листинг - всё есть. (ну кроме строк исходника). Причём размер того эльфа превышает размер бинарника раза в 4, а мой теперешний эльф почти совпадает с бинарником. Похоже, чего-то туда недопаковалось Может стоило так: Да, как-то упустил unsigned... Вполне возможно, что из-за этого... То есть без старшего бита проходит, а со старшим - нет. 0хFF не проходил 100%. Тогда странно, почему маска помогла? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
msalov 0 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба Да, как-то упустил unsigned... Вполне возможно, что из-за этого... То есть без старшего бита проходит, а со старшим - нет. 0хFF не проходил 100%. Тогда странно, почему маска помогла? Возможно тут имеет место приведение к int при операции сравнения двух разных типов То есть имемм (int)((signed char)0xFF) == 0xFFFF (int)((unsigned char)0xFF) == 0x00FF отсюда получаем что не равны. Наложение маски даёт ((0xFFFF - 0x00FF) = 0xFF00) & 0x00FF -> 0 Статья в тему: A sign of confusion, By Dan Saks Если ошибаюсь - поправте пожалуйста. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба Не совсем понял, что помогло: поменять концы файлов или пересобрать GCC с заплаткой?Пересобрать с заплаткой. В результатах работы objdump -S появились строки исходника.Самое интересное, что раньше-то всё было. Взял для интереса давнишний elf, сделал листинг - всё есть. (ну кроме строк исходника). Причём размер того эльфа превышает размер бинарника раза в 4, а мой теперешний эльф почти совпадает с бинарником. Похоже, чего-то туда недопаковалось Потерялся ключ -gdwarf-2?Тогда странно, почему маска помогла?Перед сравнением производится расширение до int, у char расширяется старший бит, у unsigned char старший байт остается нулем. Маска отсекает расширившийся знак. Статья в тему: A sign of confusion, By Dan Saks Да, очень в тему. Спасибо. Познавательно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
diper 0 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба Возможно тут имеет место приведение к int при операции сравнения двух разных типов То есть имемм (int)((signed char)0xFF) == 0xFFFF (int)((unsigned char)0xFF) == 0x00FF отсюда получаем что не равны. Наложение маски даёт ((0xFFFF - 0x00FF) = 0xFF00) & 0x00FF -> 0 Статья в тему: A sign of confusion, By Dan Saks Если ошибаюсь - поправте пожалуйста. Вычитание должно быть сделано в unsigned char, а уже потом быть преобразовано в int. Что будет если убрать volatile ? Имхо компилятор при виде volatile впадает в истерику и наровит все преобразовать в int... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба Вычитание должно быть сделано в unsigned char, а уже потом быть преобразовано в int.Обоснуйте, почему в данном случае не должны применяться integer promotion rules? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
diper 0 23 октября, 2008 Опубликовано 23 октября, 2008 · Жалоба Обоснуйте, почему в данном случае не должны применяться integer promotion rules? Хм. До сегодняшнего момента был в этом уверен, видимо не натыкался... Пойду перечитаю матчасть. :07: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
msalov 0 24 октября, 2008 Опубликовано 24 октября, 2008 · Жалоба Хм. До сегодняшнего момента был в этом уверен, видимо не натыкался... Пойду перечитаю матчасть. :07: В ANSI C99 читаем If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.48) All other types are unchanged by the integer promotions. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 24 октября, 2008 Опубликовано 24 октября, 2008 · Жалоба В продолжение темы об особенностях сравнения: Есть у меня счётчик системных тиков Time, и есть Timer, который защёлкивает текущее значение в определённый момент. Затем происходит сравнение if(Time-Timer>(RegDelay+10)) {DoSomething()} То есть отсчитывается задержка и выполняется определённое действие. Timer и Time - unsigned int. Как мне кажется (и вроде бы так и работает), при переполнении Time всё будет продолжать работать как надо. Нет ли тут подводных граблей? (имеется в виду "проблема 2000 года") И что произойдёт, если в Timer загонять время для будущего запуска действия (Timer=Time+Delay), а потом сравнивать if(Time>Timer) (Это я сейчас так сделал, а потом озаботился) Time и Timer теперь unsigned long, но и он когда-то переполнится... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 24 октября, 2008 Опубликовано 24 октября, 2008 · Жалоба В продолжение темы об особенностях сравнения: Есть у меня счётчик системных тиков Time, и есть Timer, который защёлкивает текущее значение в определённый момент. Затем происходит сравнение if(Time-Timer>(RegDelay+10)) {DoSomething()} То есть отсчитывается задержка и выполняется определённое действие. Timer и Time - unsigned int. Как мне кажется (и вроде бы так и работает), при переполнении Time всё будет продолжать работать как надо. Нет ли тут подводных граблей? (имеется в виду "проблема 2000 года") И что произойдёт, если в Timer загонять время для будущего запуска действия (Timer=Time+Delay), а потом сравнивать if(Time>Timer) (Это я сейчас так сделал, а потом озаботился) Time и Timer теперь unsigned long, но и он когда-то переполнится... Это вполне нормальный способ отсчета задержек и периодов времени. Я везде его применяю. Но у него есть два недостатка: 1) величина измеряемого периода ограничена разрядностью переменной. Например, у меня везде отсчеты идут в миллисекундах. Даже если период прерывания в котором переменная инкрементируется отличается от 1мс, то все равно она увеличивается на значение равное периоду, выраженному в миллисекундах. Поэтому 16-и разрядный unsigned int дает промежуток времени всего лишь 65,5с, а 32-х разрядный unsigned long немногим более 1,5 месяцев. 2) на архитектурах с разрядностью меньшей, чем используемая переменная, нужно предпринимать дополнительные действия по обеспечению атомарности доступа к такой переменной. Т.е. приходится перед считыванием ее значения запрещать прерывание, в котором эта переменная инкрементируется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
diper 0 24 октября, 2008 Опубликовано 24 октября, 2008 · Жалоба В ANSI C99 читаем Видимо во времена когда начинал изучать С и английски знал хуже решил не вникать в такие малопонятные детали :) а потом спасала привычка не использовать signed типы. чет стыдно мне :( Посыпал голову пеплом Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться