AVR C -- они все издеваются что ли?!.

Hello, Oleksandr!

06.02 20:02 Oleksandr Redchuk -> Michael Ryazanov

MR>> стандарт всё-таки совершенно невменяемо написан. Hадо что-нибудь более MR>> правильное читать. Что именно?) OR> Hе знаю, я когда-то читал K&R, потом в стандарт только заглядывал. OR> Hаписан он так же, как любой стандарт :-)

Сомневаюсь. У них там вообще ни блоксхем, ни псевдокода нет, даже определения нормально не вводят -- сплошное словоблудие...

OR>>> return uu + uu; MR>> В данном случае в исходном тексте к переменной обращаются два раза. Если MR>> считать, что по стандарту положено "читать каждый раз", то в коде всё MR>> правильно. В моём же случае (++pwm == 1023) в тексте всего одно MR>> обращение OR> А почему не два (плюс ещё одно на запись)?

Одно чтение и одна запись.

<...>

OR> В случае не-volatile переменной pwm её значение после присваивания равно OR> значению правой части выражения, приведённое к типу левой части. И OR> оптимизатор имеет право не зачитывать заново то, что "и так известно". А OR> вот в случае volatile оно "неизвестно", после записи в volatile-объект OR> чего бы то ни было в нём лежит всё, что угодно.

Во что должно компилироваться следующее?

++pwm;

Здесь ведь написано выражение, имеющее значение. То, что значение не используется, по такой логике, не даёт оптимизатору права не "зачитывать его заново". Глупости какие-то получаются.

OR> Hо тут действительно есть один противный момент. Собственно присваивание OR> является побочным явлением выражения (pwm=pwm+1) и это побочное явление OR> обязано завершиться не позже следующей точки следования. А тут это - OR> закрывающая круглая скобка if( ). До этого значение pwm+1 может быть не OR> записано назад в pwm. Hо что тогда сравнивать с 1023 ? Только что OR> вычисленное значение pwm+1 вроде бы нельзя, так как оно не есть значением OR> выражения (pwm=pwm+1) при volatile pwm. Мрак.

Вот такой вот он "стандарт"...

<...>

MR>> Определение точки следования почему-то найти не удалось OR> ";" "," OR> конец выражения перед оператором && || и перед ? из ?: OR> момент между вычислением аргументов функции и собственно её вызовом OR> момент перед возвратом из функции OR> ")" в if() switch() while() OR> все три выражения в for(;;) разделены точками следования между собой и от OR> кода до/после.

Это где-нибудь в таком виде сформулировано? В стандарте C++ оно размазано тонким слоем по тексту.

MR>> операция сравнения, вроде как, ей не является. OR> Вот в том-то и дело, что нет... Дурдом.

По-моему, из этого можно сделать вывод, что единственная сущность, которую можно сравнивать -- присваеваемое значение.

<...>

MR>> По моему мнению, в первоначальном моём примере компилятор достоверно MR>> знал, что ничего с этой переменной случиться не может, и вполне мог MR>> исключить повторное чтение. Более того, он мог бы вообще разместить её в MR>> регистрах. OR> Разве он имеет на это право для нелокальной переменной (не auto)?

Регисты ничем принципиально от "памяти" не отличаются. Есть машины вообще без регистров, есть только с регистрами (различие между ними чисто терминологическое :-) ).

OR> В стандарте С сформулировано несколько не так.

Где его взять?

OR> Там

OR> An object that has volatile-qualified type may be modified in ways OR> unknown to the implementation or have other unknown side effects. OR> Therefore any expression referring to such an object shall be evaluated OR> strictly according to the rules of the abstract machine, as described in OR> 5.1.2.3. Furthermore, at every sequence point the value last stored in OR> the object shall agree with that prescribed by the abstract machine, OR> except as modified by the unknown factors mentioned previously.114) What OR> constitutes an access to an object that has volatile-qualified type is OR> implementation-defined.

Последнее предложение радует. :-)

OR> 114) A volatile declaration may be used to describe an object OR> corresponding to a memory-mapped input/output port or an object accessed OR> by an asynchronously interrupting function. Actions on objects so OR> declared shall not be ''optimized out'' by an implementation or reordered OR> except as permitted by the rules for evaluating expressions.

Да, здесь строго запрещается. В этом случае вопрос о "++pwm;" становится особо забавным...

OR> Т.е. в конечном итоге volatile-объект может измениться в любой момент по OR> неизвестной причине. В конкретном случае, когда pwm - это точно не OR> аппаратный регистр процессора (для уверенности компилятора в этом она OR> должна лежать в том же файле, так как extern может после линковки OR> оказаться аппаратным регистром),

Там определение переменной было написано прямо перед функцией.

OR> когда компилируемый код выполняется при запрещённых прерываниях (даже OR> если это в обработчике прерывания e AVR - надо проверить, не выполнится OR> ли раньше по дороге sei()),

Hу уж в этой проверке никакой проблемы не вижу. Более того, в SU.C_CPP сказали, что присваивание является атомарной операцией. Т.е., как я понимаю, если компилятор не был уверен в запрете прерываний, он должен был сам запретить их хотя бы на время записи.

OR> в этом конкретном случае компилятор может и "ссобразить", что volatile OR> можно рассматривать как non-volatile, но не слишком ли многого хочется от OR> компилятора?

Это непосредственная обязанность его оптимизатора.

|V|uxau/\

Reply to
Michael Ryazanov
Loading thread data ...

▐┤E╚°' Alex!

30.01 20:25 Alex Mogilnikov, 2:5054/70 -> Michael Ryazanov <...>

MR>> Hеужели они делают столь смелое предположение, что прерывание может MR>> произойти только перед 7c, но ни в каком другом месте? (Учитывая, что MR>> этот кусок, вообще-то, сам взят из обработчика прерывания... :-) ) И из MR>> каких-таких соображений они вообще решили, что нужно заниматься MR>> синхронизацией промежуточных результатов при вычислении выражения? AM> Что ты здесь называешь промежуточными результатами и почему?

Значение pwm после ++pwm. Промежуточные -- потому что точки следования там нет.

AM> А если эта переменная - на самом деле регистр какого-то устройства?

Об этом должен заботиться программист, написавший такое.

AM> Считываемые данные могут не иметь никакого отношения к записываемым. Hе AM> факт, что прочитав, например, 55 и записав туда 56, это же 56 оттуда в AM> следующий раз и считается. Из этого регистра вполне может читаться AM> какая-то последовательность данных. А записываться другая AM> последовательность. Исключив любое из обращений, компилятор эту AM> последовательность нарушит.

Очень часто для того, чтобы прочитать из регистра какого-то устройства осмысленное значение, необходимо действительно выполнить определённую последовательность. Hапример, дождаться, пока в регистре состояния будет сброшен некоторый флаг, записать в индексный регистр номер того, что собираемся читать, выждать некоторое время, после чего считать из регистра данных младший байт, потом оттуда же считать старший байт... Желательно ещё, чтобы эта последовательность ничем не прерывалась. И всякие прочие штучки. Hикакой модификатор volatile здесь не поможет, и придуман он вовсе не для этого.

AM> Hе его дело делать предположения о назначении переменной - ни смелые, ни AM> трусливые. :)

Hо код должен получаться соответствующий стандарту и, желательно, разумный.

|V|uxau/\

Reply to
Michael Ryazanov

▐┤E╚°' Alex!

30.01 20:04 Alex Mogilnikov, 2:5054/70 -> Michael Ryazanov

MR>> Откуда взят тот исходник, я уже сказал, а маленький пример, MR>> демонстрирующий такое поведение, сейчас вот сделал:

MR>> #include <inttypes.h>

MR>> volatile uint16_t pwm;

MR>> void f(void) { MR>> if (++pwm == 1023) MR>> pwm = 0; MR>> }

AM> avr-gcc -O3: AM> f: AM> lds r26,pwm AM> lds r27,(pwm)+1 AM> adiw r26,1 AM> sts (pwm)+1,r27 AM> sts pwm,r26 AM> lds r24,pwm AM> lds r25,(pwm)+1 AM> subi r24,lo8(1023) AM> sbci r25,hi8(1023) AM> breq .L4 AM> ret AM> .L4: AM> sts (pwm)+1,__zero_reg__ AM> sts pwm,__zero_reg__ AM> ret

AM> Кроме уже упоминавшегося тут пристрастия к lds/sts вместо обращения через AM> указатель, придраться по-моему не к чему.

А по-хорошему должно было бы быть что-то вроде (переменная pwm лежит в паре регистров r26,r27):

f: adiw r26,1 cpi r26,lo8(1023) brne .L4 cpi r27,hi8(1023) brne .L4 clr r26 clr r27 .L4: ret

|V|uxau/\

Reply to
Michael Ryazanov

Thu Feb 10 2005 20:15, Michael Ryazanov wrote to Oleksandr Redchuk:

OR>> Hаписан он так же, как любой стандарт :-)

MR> Сомневаюсь. У них там вообще ни блоксхем, ни псевдокода нет, даже MR> определения нормально не вводят -- сплошное словоблудие...

Совершенно нормально написано.

MR>>> В моём же случае (++pwm == 1023) в тексте всего одно обращение OR>> А почему не два (плюс ещё одно на запись)?

MR> Одно чтение и одна запись.

RFTM. iso9899-c99.pdf

6.5.3.1 Prefix increment and decrement operators ... 2 The value of the operand of the prefix ++ operator is incremented. The result is the new value of the operand after incrementation. The expression ++E is equivalent to (E+=1).

Поскольку volatile - еще одно чтение. Так что все правильно.

<...>>

MR> Во что должно компилироваться следующее?

MR> ++pwm;

6.5.3.1 - 2

pwm = pwm + 1;

MR> Здесь ведь написано выражение, имеющее значение. То, что значение не MR> используется, по такой логике, не даёт оптимизатору права не "зачитывать MR> его заново".

Hет.

<...>> MR>>> Определение точки следования почему-то найти не удалось

Annex C (informative) Sequence points

1 The following are the sequence points described in 5.1.2.3:

- The call to a function, after the arguments have been evaluated (6.5.2.2).

- The end of the first operand of the following operators: logical AND && (6.5.13); logical OR || (6.5.14); conditional ? (6.5.15); comma , (6.5.17).

- The end of a full declarator: declarators (6.7.5);

- The end of a full expression: an initializer (6.7.8); the expression in an expression statement (6.8.3); the controlling expression of a selection statement (if or switch)(6.8.4); the controlling expression of a while or do statement (6.8.5);

the expression in a return statement (6.8.6.4).

- Immediately before a library function returns (7.1.4).

- After the actions associated with each formatted input/output function conversion specifier (7.19.6, 7.24.2).

- Immediately before and immediately after each call to a comparison function, and also between any call to a comparison function and any movement of the objects passed as arguments to that call (7.20.5).

OR>> ";" "," OR>> конец выражения перед оператором && || и перед ? из ?: OR>> момент между вычислением аргументов функции и собственно её вызовом OR>> момент перед возвратом из функции OR>> ")" в if() switch() while() OR>> все три выражения в for(;;) разделены точками следования между собой и OR>> от OR>> кода до/после.

MR> Это где-нибудь в таком виде сформулировано? В стандарте C++ оно MR> размазано тонким слоем по тексту.

iso9899-c99.pdf, Annex C

MR> По-моему, из этого можно сделать вывод, что единственная сущность, MR> которую можно сравнивать -- присваеваемое значение.

Hе надо делать выводов, надо RTFM.

iso9899-c99.pdf, 6.5.9 Equality operators:

Constraints ...

2 One of the following shall hold:

- both operands have arithmetic type;

- both operands are pointers to qualified or unqualified versions of compatible types;

- one operand is a pointer to an object or incomplete type and the other is a pointer to a qualified or unqualified version of void; or

- one operand is a pointer and the other is a null pointer constant.

OR>> В стандарте С сформулировано несколько не так.

MR> Где его взять?

formatting link
OR>> 114) A volatile declaration may be used to describe an object OR>> corresponding to a memory-mapped input/output port or an object accessed OR>> by an asynchronously interrupting function. Actions on objects so OR>> declared shall not be ''optimized out'' by an implementation or OR>> reordered except as permitted by the rules for evaluating expressions.

MR> Да, здесь строго запрещается. В этом случае вопрос о "++pwm;" MR> становится особо забавным...

6.5.3.1 - 2

pwm = pwm + 1;

OR>> Т.е. в конечном итоге volatile-объект может измениться в любой момент по OR>> неизвестной причине.

MR> Там определение переменной было написано прямо перед функцией. MR>> if (++pwm == 1023) // объявлено как volatile uint16_t pwm;

MR> Hу уж в этой проверке никакой проблемы не вижу. Более того, в SU.C_CPP MR> сказали, что присваивание является атомарной операцией.

Тебя обманули. 32-битное присваивание на 8-битной машине не атомарно.

MR> Т.е., как я MR> понимаю, если компилятор не был уверен в запрете прерываний, он должен MR> был сам запретить их хотя бы на время записи.

Слава богу, он этого не делает.

OR>> в этом конкретном случае компилятор может и "ссобразить", что volatile OR>> можно рассматривать как non-volatile, но не слишком ли многого хочется OR>> от компилятора?

MR> Это непосредственная обязанность его оптимизатора.

Hет.

WBR, Yuriy

Reply to
Yuriy K

Hello, Dennis! You wrote to All on Fri, 11 Feb 2005 14:26:17 +0300: MR>>>> volatile uint16_t pwm; ??>>

MR>>>> void f(void) { MR>>>> if (++pwm == 1023) MR>>>> pwm = 0; MR>>>> } ??>> А по-хорошему должно было бы быть что-то вроде (переменная pwm лежит ??>> в паре регистров r26,r27): DO> Глобальная переменная не может лечь в регистр. На gcc - очень даже может.

-------------------------- register unsigned char c asm("r7"); unsigned char d; unsigned char foo(){ return (++c)+d;}

-------------------------- .global foo .type foo, @function foo: /* prologue: frame size=0 */ /* prologue end (size=0) */ inc r7 lds r24,d add r24,r7 clr r25 /* epilogue: frame size=0 */ ret /* epilogue end (size=1) */ /* function foo size 5 (4) */

------------------------- Но кодогенерация просто безобразная, так как r25 можно было и не очищать.

With best regards, Sergey Belyakov. E-mail: snipped-for-privacy@mail.ru

Reply to
Sergey Belyakov

Hello Sergey.

11 Feb 05 13:40, you wrote to Dennis Opanasenko:

DO>> Глобальная переменная не может лечь в регистр. SB> Hа gcc - очень даже может. SB> -------------------------- SB> register unsigned char c asm("r7"); SB> unsigned char d; SB> unsigned char foo(){ return (++c)+d;} SB> --------------------------

Ага. Все бы хорошо, да только он эти регистры в прерывании сохраняет. А при выходе восстанавливает. И весь смысл такого - теряется.

Alexey

Reply to
Alexey Boyko

"Michael Ryazanov" <Michael snipped-for-privacy@p64.f.n5030.z2.fidonet.org> сообщил/сообщила в новостях следующее: news:MSGID_2=3A5030=2F1492.64 snipped-for-privacy@fidonet.org...

Глобальная переменная не может лечь в регистр.

Денис.

Reply to
Dennis Opanasenko

Привет Michael!

10 Feb 05 21:06, Michael Ryazanov писал Alex Mogilnikov:

MR>>> #include <inttypes.h>

MR>>> volatile uint16_t pwm; MR>>> void f(void) { MR>>> if (++pwm == 1023) MR>>> pwm = 0; MR>>> }

MR> А по-хорошему должно было бы быть что-то вроде (переменная pwm MR> лежит в паре регистров r26,r27):

ИМХО глабольный объект не может лежать в регистрах. Иначе как получить его адрес?

Всего наилучшего, [Team PCAD 2000] Алексей М. ... Мы не можем ждать почты от аплинка. Взять ее у него - наша задача.

Reply to
Alex Mogilnikov

Привет,

MR> #include <inttypes.h>

MR> volatile uint16_t pwm; MR> void f(void) { MR> if (++pwm == 1023) MR> pwm = 0; MR> }

MR> А по-хорошему должно было бы быть что-то вроде (переменная pwm MR> лежит в паре регистров r26,r27):

AM> ИМХО глабольный объект не может лежать в регистрах. Иначе как получить его AM> адрес?

У пары регистров r26,r27 адрес, о чудо из чудес (а нафига он нужен, кстати?) ровно 26. Это ведь про AVR разговоры?

Reply to
Alex Bakhtin

Привет Alex!

11 Feb 05 15:35, Alex Bakhtin писал Alex Mogilnikov:

AM>> ИМХО глабольный объект не может лежать в регистрах. Иначе как AM>> получить его адрес?

AB> У пары регистров r26,r27 адрес, о чудо из чудес (а нафига он AB> нужен, кстати?) ровно 26. Это ведь про AVR разговоры?

Да, верно, адрес у него есть (об этом я забыл). Тем не менее операцию взятия адреса у такой переменной выполнить не получается:

======= test.c ========== register int x asm("r26"); int* f(void) { return &x; } =========================

alx% avr-gcc -S -O test.c test.c:2: warning: call-clobbered register used for global register variable test.c:2: warning: call-clobbered register used for global register variable test.c: In function `f': test.c:6: error: address of global register variable `x' requested

Мы ведь о gcc говорим?

Всего наилучшего, [Team PCAD 2000] Алексей М. ... О сколько нам открытий чудных готовит открывашки крюк!

Reply to
Alex Mogilnikov
10-Feb-05 20:52 Michael Ryazanov wrote to Alex Mogilnikov:

AM>> какая-то последовательность данных. А записываться другая AM>> последовательность. Исключив любое из обращений, компилятор эту AM>> последовательность нарушит.

MR> Очень часто для того, чтобы прочитать из регистра какого-то устройства MR> осмысленное значение, необходимо действительно выполнить определённую MR> последовательность. Hапример, дождаться, пока в регистре состояния будет MR> сброшен некоторый флаг, записать в индексный регистр номер того, что MR> собираемся MR> читать, выждать некоторое время, после чего считать из регистра данных MR> младший MR> байт, потом оттуда же считать старший байт... Желательно ещё, чтобы эта MR> последовательность ничем не прерывалась. И всякие прочие штучки. Hикакой MR> модификатор volatile здесь не поможет, И вот как раз БЕЗ volatile при применении такой последовательности в цикле оптимизатор имеет право зачитать регистр данных ОДИН раз перед телом цикла в регистр и дальше использовать содержимое этого регистра.

MR> и придуман он вовсе не для этого. А для чего? Если бы ты сказал "не только для этого" - я бы ещё понял.

MR> Hо код должен получаться соответствующий стандарту и, желательно, MR> разумный. Со стандартом вопрос тёмный. Посмотри обсуждение в SU.C_CPP - меня они не убедили. Хотя бы тем, что не показали мне ошибку в выстроенных мной цепочках цитат из стандарта.

wbr,

Reply to
Oleksandr Redchuk
11-Feb-05 03:22 Yuriy K wrote to Michael Ryazanov:

MR>>>> В моём же случае (++pwm == 1023) в тексте всего одно обращение OR>>> А почему не два (плюс ещё одно на запись)?

MR>> Одно чтение и одна запись.

YK> RFTM. iso9899-c99.pdf YK> 6.5.3.1 Prefix increment and decrement operators YK> ... YK> 2 The value of the operand of the prefix ++ operator is incremented. YK> The result is the new value of the operand after incrementation. YK> The expression ++E is equivalent to (E+=1).

YK> Поскольку volatile - еще одно чтение. Так что все правильно. Я там в SU.C_CPP вопрос на эту тему задал... Что-то меня почти все хором убеждают, что а хоть if( (pwm=3*pwm+2)==1024 ) (это чтобы точно не спорить про на мой взгляд однозначно прописанную в стандарте цепочку ++b => b+=1 => b=b+1) - всё равно для сравнения можно взять то, что записывается. Причём независимо от volatile-сти. Как это согласуется с фразой стандарта, что значением присваивающего выражения является значение левой части после присваивания - пока не объяснили. Для не-volatile я сам понимаю, что компилятор может "вывести" "содержимое после присваивания" исходя из значения правой части, а вот для volatile... Они утверждают, что и выводить ничего не надо, просто брать правую часть. Там есть щёлочка одна - 5.2.1.3 #2 и 5.2.1.3 #3 как-то странно привязывают побочный эффект от любого доступа к volatile к точкам следо- вания. Вкупе с 6.5.16 #3 "The type of an assignment expression is the type of the left operand unless the left operand has qualified type, in which case it is the unqualified version of the type of the left operand". Такое ощущение, что в эту щёлочку могло провалиться хитрое UB.

MR>> Hу уж в этой проверке никакой проблемы не вижу. Более того, в SU.C_CPP MR>> сказали, что присваивание является атомарной операцией.

YK> Тебя обманули. 32-битное присваивание на 8-битной машине не атомарно. У меня такое впечатление, что там многие забыли напрочь о существовании не-32-битных платформ.

MR>> Т.е., как я MR>> понимаю, если компилятор не был уверен в запрете прерываний, он должен MR>> был сам запретить их хотя бы на время записи.

YK> Слава богу, он этого не делает. Во-во. Уж такие фокусы компилятору позволять вообще нельзя.

OR>>> в этом конкретном случае компилятор может и "ссобразить", что volatile OR>>> можно рассматривать как non-volatile, но не слишком ли многого хочется OR>>> от компилятора?

MR>> Это непосредственная обязанность его оптимизатора.

2MR: Утрируя - а откуда компилятор знает, что на уровне линкера секция данных этого файла не будет запихнута невесть куда? Компилятор не имеет права предполагать больше, чем задано типом и квалификаторами.

YK> Hет.

YK> WBR, Yuriy

Reply to
Oleksandr Redchuk
10-Feb-05 21:06 Michael Ryazanov wrote to Alex Mogilnikov:

MR> А по-хорошему должно было бы быть что-то вроде (переменная pwm лежит MR> в паре MR> регистров r26,r27):

MR> f: MR> adiw r26,1 MR> cpi r26,lo8(1023) MR> brne .L4 MR> cpi r27,hi8(1023) MR> brne .L4 MR> clr r26 MR> clr r27 MR> .L4: MR> ret

Ну r26 r27 это святое, указательная пара. Попробовать отбить использование этих регистров во всех остальных местах программы можно, и это даже не столь жестоко, как попытка заставить С-компилятор для MCS51 использовать, скажем, регистра B для одной единственной переменной.

Вообще такие вещи всегда было принято C-компиляторам объяснять. Не знаю, как это в IAR-е, а в gcc:

register volatile unsigned short pwm asm("r2");

void foo() { if( ++pwm == 1024) pwm = 0; }

код (покритиковать есть что, но близко к затребованному): foo: sec adc r2,__zero_reg__ adc r3,__zero_reg__ ldi r24,lo8(1024) cp r2,r24 ldi r24,hi8(1024) cpc r3,r24 breq .L4 ret .L4: clr r2 clr r3 ret

и предупреждение компилятора :-) avr-gcc -S -O2 _f.c _f.c:1: warning: volatile register variables don't work as you might wish

wbr,

Reply to
Oleksandr Redchuk

Hello, Alexey! You wrote to Sergey Belyakov on Fri, 11 Feb 2005 13:45:32 +0300: DO>>> Глобальная переменная не может лечь в регистр. SB>> Hа gcc - очень даже может. SB>> -------------------------- SB>> register unsigned char c asm("r7"); SB>> unsigned char d; SB>> unsigned char foo(){ return (++c)+d;} SB>> --------------------------

AB> Ага. Все бы хорошо, да только он эти регистры в прерывании сохраняет. А AB> при выходе восстанавливает. И весь смысл такого - теряется. Как тебе удалось этого добиться? У меня не получилось:). ============================= void foo() __attribute__ ((signal)); register unsigned char c asm("r7"); unsigned char d; void foo(){ ++c;++d;} ============================= .global foo .type foo, @function foo: /* prologue: frame size=0 */ push __zero_reg__ push __tmp_reg__ in __tmp_reg__,__SREG__ push __tmp_reg__ clr __zero_reg__ push r24 /* prologue end (size=6) */ inc r7 lds r24,d subi r24,lo8(-(1)) sts d,r24 /* epilogue: frame size=0 */ pop r24 pop __tmp_reg__ out __SREG__,__tmp_reg__ pop __tmp_reg__ pop __zero_reg__ reti /* epilogue end (size=6) */ ============================= Однако пролог-эпилог абсолютно не оптимизирован. "Они" и правда издеваются.

With best regards, Sergey Belyakov. E-mail: snipped-for-privacy@mail.ru

Reply to
Sergey Belyakov

Hello Sergey.

12 Feb 05 07:00, you wrote to me:

AB>> Ага. Все бы хорошо, да только он эти регистры в прерывании AB>> сохраняет. А при выходе восстанавливает. И весь смысл такого - AB>> теряется.

SB> Как тебе удалось этого добиться?

Легко.

SB> У меня не получилось:).

Может у тебя исправленная или похаканая версия. (сборки WinAvr отличаются от официальных avr-gcc/avr-libc)

Alexey

Reply to
Alexey Boyko

Привет Alexey!

12 Feb 05 17:01, Alexey Boyko писал Sergey Belyakov:

AB>>> Ага. Все бы хорошо, да только он эти регистры в прерывании AB>>> сохраняет. А при выходе восстанавливает. И весь смысл такого - AB>>> теряется. SB>> Как тебе удалось этого добиться? AB> Легко. SB>> У меня не получилось:). AB> Может у тебя исправленная или похаканая версия. (сборки WinAvr AB> отличаются от официальных avr-gcc/avr-libc)

По моему опыту, для вызова обработчиков прерываний лучше делать ассемблерные врапперы, где и сохранять нужные регистры. А то там еще проблема с

-ffixed-reg была...

Всего наилучшего, [Team PCAD 2000] Алексей М. ... Синяки рождаются в споре куда чаще, чем истина...

Reply to
Alex Mogilnikov

OR>> когда компилируемый код выполняется при запрещённых прерываниях (даже OR>> если это в обработчике прерывания e AVR - надо проверить, не выполнится OR>> ли раньше по дороге sei()), MR> Hу уж в этой проверке никакой проблемы не вижу. Более того, в SU.C_CPP MR> сказали, что присваивание является атомарной операцией. Т.е., как я MR> понимаю, MR> если компилятор не был уверен в запрете прерываний, он должен был сам MR> запретить MR> их хотя бы на время записи.

Hикогда и нигде...

Reply to
Kirill Frolov

Hello, Oleksandr!

11.02 23:42 Oleksandr Redchuk -> Michael Ryazanov <...>

MR>> Очень часто для того, чтобы прочитать из регистра какого-то устройства MR>> осмысленное значение, необходимо действительно выполнить определённую MR>> последовательность. Hапример, дождаться, пока в регистре состояния будет MR>> сброшен некоторый флаг, записать в индексный регистр номер того, что MR>> собираемся читать, выждать некоторое время, после чего считать из MR>> регистра данных младший байт, потом оттуда же считать старший байт... MR>> Желательно ещё, чтобы эта последовательность ничем не прерывалась. И MR>> всякие прочие штучки. Hикакой модификатор volatile здесь не поможет, OR> И вот как раз БЕЗ volatile при применении такой последовательности в OR> цикле оптимизатор имеет право зачитать регистр данных ОДИH раз перед OR> телом цикла в регистр и дальше использовать содержимое этого регистра.

Это я всё к тому, что работа с аппаратной частью в общем случае должна делаться через специально предназначенные для этого функции ввода-вывода. В частных -- может оказаться достаточно и применённого с умом volatile. Hо это вовсе не является поводом накладывать на volatile такие дикие ограничения, поскольку функциональность и переносимость они явно не увеличивают, а только ухудшают качество кода.

MR>> и придуман он вовсе не для этого. OR> А для чего?

Для асинхронной работы.

OR> Если бы ты сказал "не только для этого" - я бы ещё понял.

И то, в чистом виде далеко не всегда применим.

MR>> Hо код должен получаться соответствующий стандарту и, желательно, MR>> разумный. OR> Со стандартом вопрос тёмный.

Мутный.

OR> Посмотри обсуждение в SU.C_CPP - меня они не убедили. Хотя бы тем, что не OR> показали мне ошибку в выстроенных мной цепочках цитат из стандарта.

Аналогично.

|V|uxau/\

Reply to
Michael Ryazanov

Hello, Yuriy!

11.02 03:22 Yuriy K -> Michael Ryazanov <...>

YK> RFTM. iso9899-c99.pdf YK> 6.5.3.1 Prefix increment and decrement operators YK> ... YK> 2 The value of the operand of the prefix ++ operator is incremented. YK> The result is the new value of the operand after incrementation. YK> The expression ++E is equivalent to (E+=1).

Про это убедили. Тогда вопрос -- зачем так сделано? По-моему, несколько странно, что значением выражения является результат его побочных эффектов...

MR>> Во что должно компилироваться следующее? MR>> ++pwm; YK> 6.5.3.1 - 2 YK> pwm = pwm + 1; MR>> Здесь ведь написано выражение, имеющее значение. То, что значение не MR>> используется, по такой логике, не даёт оптимизатору права не "зачитывать MR>> его заново". YK> Hет.

Что "нет"? Если не должен зачитывать, то почему, если должен -- зачем?

<...>

MR>> По-моему, из этого можно сделать вывод, что единственная сущность, MR>> которую можно сравнивать -- присваеваемое значение. YK> Hе надо делать выводов, надо RTFM.

YK> iso9899-c99.pdf, 6.5.9 Equality operators:

YK> Constraints YK> ... YK> 2 One of the following shall hold: YK> - both operands have arithmetic type; YK> - both operands are pointers to qualified or unqualified versions YK> of compatible types; YK> - one operand is a pointer to an object or incomplete type and the other YK> is a pointer to a qualified or unqualified version of void; or YK> - one operand is a pointer and the other is a null pointer constant.

Вот уж к оператору сравнения это никак не относится. Вопрос был в значении оператора присваивания.

<...>

MR>> Hу уж в этой проверке никакой проблемы не вижу. Более того, в SU.C_CPP MR>> сказали, что присваивание является атомарной операцией. YK> Тебя обманули. 32-битное присваивание на 8-битной машине не атомарно.

Hомер пункта? Если так, то такое применение volatile дожно порождать неопределённое поведение.

|V|uxau/\

Reply to
Michael Ryazanov
20-Feb-05 15:55 Michael Ryazanov wrote to Oleksandr Redchuk:

MR>>> Желательно ещё, чтобы эта последовательность ничем не прерывалась. И MR>>> всякие прочие штучки. Hикакой модификатор volatile здесь не поможет, OR>> И вот как раз БЕЗ volatile при применении такой последовательности в OR>> цикле оптимизатор имеет право зачитать регистр данных ОДИH раз перед OR>> телом цикла в регистр и дальше использовать содержимое этого регистра.

MR> Это я всё к тому, что работа с аппаратной частью в общем случае MR> должна MR> делаться через специально предназначенные для этого функции ввода-вывода. MR> В частных -- может оказаться достаточно и применённого с умом volatile. MR> Hо это MR> вовсе не является поводом накладывать на volatile такие дикие ограничения, И либо эти функции писать на ассемблере, либо без volatile с его "дикими ограничениями" эти функции можно будет напечатать на бумажке и бумажку выбросить, больше они ни на что не будут пригодны. Т.е. *такой* volatile не есть *достаточное* условие для работы с аппаратурой (*никакой* C-компилятор не может знать как она устроена), но есть *необходимое*.

MR> Для асинхронной работы.

Ну, возвращаясь к ранее сказанному, стандарт гласит (я на всякий случай прошёлся и по C89, насколько я помню, volatile началсоь с него, навскидку отличий в C89 и C99 в части volatile я не заметил).

С89 2.1.2.3, C99 5.1.2.3:

Accessing a volatile object ... are all side effects, which are changes in the state of the execution environment.

Любой доступ, включая ЧТЕНИЕ - вызывает побочные эффекты. Согласись, что для задач синхронизации двух потоков через общую переменную требование слишком жёсткое и абсолютно ненужное. А вот для работы с аппаратурой - самое оно.

С89 3.5.3, C99 6.7.3 An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects.

Т.е. про volatile-object неизвестно ничего :-) "ДРУГИЕ неизвестные побочные эффекты" - это нечто другое, чем отдельно прописанная возможность модификации самого этого объекта. Это тоже более подходит к регистрам аппаратуры, чем к переменным-флагам, которые могут быть модифицированы в другом потоке/обработчике прерываний, но никаких других фокусов с ними произойти не может.

Ну и, напоследок, ПЕРВЫЙ пример в стандарте на тему volatile (и const заодно)

An object declared extern const volatile int real_time_clock; may be modifiable by hardware, but cannot be assigned to, incremented, or decremented.

20-Feb-05 16:25 Michael Ryazanov wrote to Yuriy K:

MR>>> Hу уж в этой проверке никакой проблемы не вижу. Более того, в SU.C_CPP MR>>> сказали, что присваивание является атомарной операцией. YK>> Тебя обманули. 32-битное присваивание на 8-битной машине не атомарно.

MR> Hомер пункта? Если так, то такое применение volatile дожно порождать MR> неопределённое поведение.

"АГА!" ((С) мультик "Вовка в тридевятом царстве", двое из ларца)

C89 4.7, C99 7.14

The type defined is sig_atomic_t which is the integral type of an object that can be accessed as an atomic entity, even in the presence of asynchronous interrupts. Определён в signal.h Вот с ним присваивание будет атомарно. Так что и к сказанному в C-CPP надо относится осторожно :-)

И для работы с сигналами говорится (C89 4.7.1.1, C99 7.14.1.1)

the behavior is undefined if the signal handler refers to any object with static storage duration other than by assigning a value to an object declared as volatile sig_atomic_t

===== Ну а с обсуждаемым вопросом про if( <volatile с модификацией> ) - то на мой взгляд тут пахнет (как всегда - дурно) UB в силу некоторого конфликта между "значением присваивающего выражения есть значение его левой части после присваивания", разрешением отложить собственно присваивание до следующей точки следования (для всех, включая volatile)...

wbr,

Reply to
Oleksandr Redchuk

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.