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

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Russian to

Threaded View
Re: AVR C -- они все издеваются что ли?!.
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/\

Re: AVR C -- они все издеваются что ли?!.
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,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


Re: AVR C -- они все издеваются что ли?!.
Mon Feb 21 2005 10:32, Oleksandr Redchuk wrote to Michael Ryazanov:

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

 OR> Т.е. *такой* volatile не есть *достаточное* условие для работы
 OR> с аппаратурой (*никакой* C-компилятор не может знать как она устроена),
 OR> но есть *необходимое*.

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

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

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

Именно. Бывают регистры, сбрасывающие взведенные флаги при _чтении_.

WBR, Yuriy.


Re: AVR C -- они все издеваются что ли?!.
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,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


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

 MR>> И avr-gcc, который со всякими ключами оптимизациями делает вообще
 MR>> такое:

 MR>>   5a: 80 91 60 00    lds   r24, 0x0060
 MR>>   5e: 99 27          eor   r25, r25
 SM> <...>

 SM> И как ты этого добился?

   Извиняюсь, что не совсем понятно написал. Это были просто примеры плохого
кода, генерируемого данными компиляторами. Все они получены из разных исходных
текстов.

 SM> Вот мой пример:
 SM> === Cut ===
 SM> #include <inttypes.h>
 SM> uint8_t led_status = 0;
 SM> int main() {
 SM>   led_status <<= 1;
 SM>   led_status |= 1;
 SM>   return led_status;
 SM> }
 SM> === Cut ===
<...>
 SM> При добавлении "volatile" к "led_status", делает так:

 SM>   led_status <<= 1;
 SM>   64: 80 91 60 00  lds r24, 0x0060
 SM>   68: 88 0f        add r24, r24
 SM>   6a: 80 93 60 00  sts 0x0060, r24
 SM>   led_status |= 1;
 SM>   6e: 80 91 60 00  lds r24, 0x0060
 SM>   72: 81 60        ori r24, 0x01 ; 1
 SM>   74: 80 93 60 00  sts 0x0060, r24
 SM>   return led_status;
 SM>   78: 80 91 60 00  lds r24, 0x0060
 SM> }

   Кто может пояснить тайный смысл этого ритуала -- сохраненять и тут же
загружать значение переменной посреди вычислений? Особенно в том куске:

            if (++pwm == 1023) // объявлено как volatile uint16_t pwm;
  6a: 80 91 61 00    lds   r24, 0x0061
  6e: 90 91 62 00    lds   r25, 0x0062
  72: 01 96          adiw  r24, 0x01   ; 1
  74: 90 93 62 00    sts   0x0062, r25
  78: 80 93 61 00    sts   0x0061, r24
  7c: 80 91 61 00    lds   r24, 0x0061
  80: 90 91 62 00    lds   r25, 0x0062
  84: 8f 5f          subi  r24, 0xFF   ; 255
  86: 93 40          sbci  r25, 0x03   ; 3
  88: a9 f4          brne  .+42        ; 0xb4

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

                                                                      |V|uxau/\

Re: AVR C -- они все издеваются что ли?!.
Sat Jan 29 2005 18:38, Michael Ryazanov wrote to Sergey Mudry:

 SM>> При добавлении "volatile" к "led_status", делает так:

 SM>>   led_status <<= 1;
 SM>>   64: 80 91 60 00  lds r24, 0x0060
 SM>>   68: 88 0f        add r24, r24
 SM>>   6a: 80 93 60 00  sts 0x0060, r24
 SM>>   led_status |= 1;
 SM>>   6e: 80 91 60 00  lds r24, 0x0060
 SM>>   72: 81 60        ori r24, 0x01 ; 1
 SM>>   74: 80 93 60 00  sts 0x0060, r24
 SM>>   return led_status;
 SM>>   78: 80 91 60 00  lds r24, 0x0060
 SM>> }

 MR>    Кто может пояснить тайный смысл этого ритуала -- сохраненять и тут же
 MR> загружать значение переменной посреди вычислений?

RTFM volatile.

 MR> Особенно в том куске:
 MR> if (++pwm == 1023) // объявлено как volatile uint16_t pwm;

RTFM volatile.

 MR> И из
 MR> каких-таких соображений они вообще решили, что нужно заниматься
 MR> синхронизацией промежуточных результатов при вычислении выражения?

RTFM volatile.

WBR, Yuriy


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

 SM>>> При добавлении "volatile" к "led_status", делает так:

 SM>>>   led_status <<= 1;
 SM>>>   64: 80 91 60 00  lds r24, 0x0060
 SM>>>   68: 88 0f        add r24, r24
 SM>>>   6a: 80 93 60 00  sts 0x0060, r24
 SM>>>   led_status |= 1;
 SM>>>   6e: 80 91 60 00  lds r24, 0x0060
 SM>>>   72: 81 60        ori r24, 0x01 ; 1
 SM>>>   74: 80 93 60 00  sts 0x0060, r24
 SM>>>   return led_status;
 SM>>>   78: 80 91 60 00  lds r24, 0x0060

 MR>>    Кто может пояснить тайный смысл этого ритуала -- сохраненять и тут же
 MR>> загружать значение переменной посреди вычислений?

 YK> RTFM volatile.

 MR>> Особенно в том куске:
 MR>> if (++pwm == 1023) // объявлено как volatile uint16_t pwm;

 YK> RTFM volatile.

 MR>> И из каких-таких соображений они вообще решили, что нужно заниматься
 MR>> синхронизацией промежуточных результатов при вычислении выражения?

 YK> RTFM volatile.

   Точные ссылки давайте, вежливый вы наш.

                                                                      |V|uxau/\

Re: AVR C -- они все издеваются что ли?!.
Mon Jan 31 2005 21:23, Michael Ryazanov wrote to Yuriy K:

 SM>>>> При добавлении "volatile" к "led_status", делает так:
 MR>>> И из каких-таких соображений они вообще решили, что нужно заниматься
 MR>>> синхронизацией промежуточных результатов при вычислении выражения?

 YK>> RTFM volatile.

 MR>    Точные ссылки давайте, вежливый вы наш.

Любая книжка по С.

WBR, Yuriy.


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

29 Jan 05 18:38, Michael Ryazanov писал Sergey Mudry:

 MR>    Кто может пояснить тайный смысл этого ритуала -- сохраненять и тут
 MR> же загружать значение переменной посреди вычислений? Особенно в том
 MR> куске:

 MR>             if (++pwm == 1023) // объявлено как volatile uint16_t pwm;
 MR>   6a: 80 91 61 00    lds   r24, 0x0061
 MR>   6e: 90 91 62 00    lds   r25, 0x0062
 MR>   72: 01 96          adiw  r24, 0x01   ; 1
 MR>   74: 90 93 62 00    sts   0x0062, r25
 MR>   78: 80 93 61 00    sts   0x0061, r24
 MR>   7c: 80 91 61 00    lds   r24, 0x0061
 MR>   80: 90 91 62 00    lds   r25, 0x0062
 MR>   84: 8f 5f          subi  r24, 0xFF   ; 255
 MR>   86: 93 40          sbci  r25, 0x03   ; 3
 MR>   88: a9 f4          brne  .+42        ; 0xb4

    Тайный смысл должен знать программист, объявивший переменную pwm как
volatile. Этим он именно указал компилятору, что тот должен каждый раз заново
вычитывать ее из памяти. И при каждой модификации записывать. Если еще точнее,
volatile запрещает оптимизатору исключать "ненужные" обращения к переменной. И
компилятор эти указания безропотно выполняет.

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

    Что ты здесь называешь промежуточными результатами и почему?

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

Всего наилучшего,                                 [Team PCAD 2000]
Алексей М.
... Слепой Пью, Глухой Ем...

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

 MR>>>> Существуют в природе хоть какие-нибудь нормальные компиляторы C для
 MR>>>> AVR?
 AV>>> Да - IAR
 MR>> Честно говоря, качать 58 Мб не очень хочется,
 AV> Hу не хочется, так не качай. Мы-то тут при чем?
 AV> Ты спросил, я ответил,

   Спасибо.

 AV> а уж что с этим ответом делать - дело твое.
 MR>> Хотя, если он действительно  нормальный, и к нему есть лекарство от
 MR>> жадности... ?
 AV> Лекарство, разумеется, есть:
 AV> http://briefcase.yahoo.com
 AV> id: ru_embedded00
 AV> pass: sobaka
 AV> Что касается нормальности, то у каждого свои критерии, однако то, что
 AV> этот компилятор для AVR лучший из существующих - это точно.

   Тогда буду качать...

                                                                      |V|uxau/\

Re: AVR C -- они все издеваются что ли?!.
31-Jan-05 21:27 Michael Ryazanov wrote to Askold Volkov:

 AV>> Что касается нормальности, то у каждого свои критерии, однако то, что
 AV>> этот компилятор для AVR лучший из существующих - это точно.

MR>    Тогда буду качать...

Качай, он пожалуй действительно самый лучший.
Только предупреждаю, что он тоже в полном соответствии со стандартом С и
в полной противоположности с твоим мнением считает, что
квалифицированную как volatile переменную надо перезачитывать даже если
в него писали "только что":

extern volatile unsigned uu;
unsigned foo(unsigned u) {
        uu = u;
        return uu;
}

   3          unsigned foo(unsigned u) {
   4                 uu = u;
\   __nearfunc unsigned int foo(unsigned int);
\                     foo:
\   00000000   ....                       LDI     R30,uu
\   00000002   8300                       ST      Z,R16
\   00000004   8311                       STD     Z+1,R17
   5                 return uu;
\   00000006   8100                       LD      R16,Z
\   00000008   8111                       LDD     R17,Z+1
\   0000000A   9508                       RET
   6          }

wbr,
p.s. поищи всё-таки нормальную книжку по C, если стандарт читать неохота,
чтобы понимать что означают всякие volatile и почему, скажем, на такое:

extern const volatile unsigned uu;

unsigned foo(void) {
        return uu + uu;
}

тем же IAR-ом генерится такой код:

   3          unsigned foo(void) {
   4                 return uu + uu;
\   __nearfunc unsigned int foo();
\                     foo:
\   00000000   ....                       LDI     R30,uu
\   00000002   8120                       LD      R18,Z
\   00000004   8131                       LDD     R19,Z+1
\   00000006   8100                       LD      R16,Z
\   00000008   8111                       LDD     R17,Z+1
\   0000000A   0F02                       ADD     R16,R18
\   0000000C   1F13                       ADC     R17,R19
\   0000000E   9508                       RET
   5          }

--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


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

 AV>>> Что касается нормальности, то у каждого свои критерии, однако то, что
 AV>>> этот компилятор для AVR лучший из существующих - это точно.
 MR>> Тогда буду качать...
 OR> Качай, он пожалуй действительно самый лучший.

   Скачал. Hо пока ещё не смотрел.

 OR> Только предупреждаю, что он тоже в полном соответствии со стандартом С и
 OR> в полной противоположности с твоим мнением считает, что квалифицированную
 OR> как volatile переменную надо перезачитывать даже если в него писали
 OR> "только что":
<...>
 OR> p.s. поищи всё-таки нормальную книжку по C, если стандарт читать неохота,

   Я бы лучше стандарт почитал (или его разбор/комментарии к нему), потому что
в книжках бывает не написано или написано не то. (Примечание, добавленное после
написания всего письма: стандарт всё-таки совершенно невменяемо написан. Hадо
что-нибудь более правильное читать. Что именно?)

 OR> чтобы понимать что означают всякие volatile и почему, скажем, на такое:

 OR> extern const volatile unsigned uu;

 OR> unsigned foo(void) {
 OR>         return uu + uu;
 OR> }

 OR> тем же IAR-ом генерится такой код:

 OR>    3          unsigned foo(void) {
 OR>    4                 return uu + uu;
 OR> \   __nearfunc unsigned int foo();
 OR> \                     foo:
 OR> \   00000000   ....                       LDI     R30,uu
 OR> \   00000002   8120                       LD      R18,Z
 OR> \   00000004   8131                       LDD     R19,Z+1
 OR> \   00000006   8100                       LD      R16,Z
 OR> \   00000008   8111                       LDD     R17,Z+1
 OR> \   0000000A   0F02                       ADD     R16,R18
 OR> \   0000000C   1F13                       ADC     R17,R19
 OR> \   0000000E   9508                       RET
 OR>    5          }

   В данном случае в исходном тексте к переменной обращаются два раза. Если
считать, что по стандарту положено "читать каждый раз", то в коде всё
правильно. В моём же случае (++pwm == 1023) в тексте всего одно обращение к
переменной.
   Вообще, в стандарте C++, что у меня есть (файл ansi_iso_iec_14882_1998.pdf),
по делу нашёл следующее:


*1.9 Program execution*
<...>
5 A conforming implementation executing a wellformed program shall produce the
same observable behavior as one of the possible execution sequences of the
corresponding instance of the abstract machine with the same program and the
same input. However, if any such execution sequence contains an undefined
operation, this International Standard places no requirement on the
implementation executing that program rule,<...>
<...>
6 The observable behavior of the abstract machine is its sequence of reads and
writes to volatile data and calls to library I/O functions.


Из этого вроде как следует, что последовательности чтения и записи
volatile-объектов должны количественно совпадать для любого компилятора и любой
машины. Больше никакого внятного упоминания о том, каковы же эти
последовательности должны быть, найти не удалось.


<...>
11 The least requirements on a conforming implementation are: - At sequence
points, volatile objects are stable in the sense that previous evaluations are
complete and subsequent evaluations have not yet occurred.


Только то, что между точками следованя volatile-объекты должны принять
состояние, соответствующее уже выполненным вычислениям, т.е. их значения нужно
записать. Определение точки следования почему-то найти не удалось, но операция
сравнения, вроде как, ей не является.


*5 Expressions*
<...>
4 Except where noted, the order of evaluation of operands of individual
operators and subexpressions of individual expressions, and the order in which
side effects take place, is unspecified. Between the previous and next sequence
point a scalar object shall have its stored value modified at most once by the
evaluation of an expression. Furthermore, the prior value shall be accessed
only to determine the value to be stored.
The requirements of this paragraph shall be met for each allowable ordering of
the subexpressions of a full expression; otherwise the behavior is undefined.
[Example:
i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented
-end example]


Тут у меня какие-то проблемы с пониманием около первого слова stored. Если
кто-нибудь с хорошим знанием этого языка :-) переведёт, буду благодарен.
Зато тут есть важное слово only. Его трактовка, конечно, зависит от того, что
считать точкой следования, и что они подразумевают под "прежним значением", но
на определённые мысли это наводит.


*7.1.5.1 The cv-qualifiers*
<...>
8 [Note: volatile is a hint to the implementation to avoid aggressive
optimization involving the object because the value of the object might be
changed by means undetectable by an implementation. See 1.9 for detailed
semantics. In general, the semantics of volatile are intended to be the same in
C++ as they are in C. ]


Вот тут вот прошу обратить внимание на слово hint. Т.е. это всего лишь намёк
избегать "агрессивной" оптимизации. Что считать "агрессивной", и насколько
важно её избегать, найти, опять же, не удалось. По моему мнению, в
первоначальном моём примере компилятор достоверно знал, что ничего с этой
переменной случиться не может, и вполне мог исключить повторное чтение. Более
того, он мог бы вообще разместить её в регистрах.

А вот, кстати, между прочим. Программа


#include <stdio.h>

int i = 0;

int& f(void) {
   puts("f()");
   return i;
}

int main(void) {
   int j = -1;
   printf("i = %d, j = %d\n", i, j);
   j = ++f();
   printf("i = %d, j = %d\n", i, j);
   j = f()++;
   printf("i = %d, j = %d\n", i, j);

   return 0;
}


выдаёт следующее:


i = 0, j = -1
f()
i = 1, j = 1
f()
i = 2, j = 1


От добавления volatile результат не меняется, хотя в любом случае тут уж явно
не до оптимизации -- вызов функции может повлечь побочные эффекты, поэтому не
должен пропускаться.

В RU.C_CPP что ли спросить?..

                                                                      |V|uxau/\

Re: AVR C -- они все издеваются что ли?!.
3-Feb-05 01:19 Michael Ryazanov wrote to Oleksandr Redchuk:

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

OR>>    return uu + uu;
MR>    В данном случае в исходном тексте к переменной обращаются два раза.
MR> Если считать, что по стандарту положено "читать каждый раз", то в коде всё
MR> правильно. В моём же случае (++pwm == 1023) в тексте всего одно обращение
 А почему не два (плюс ещё одно на запись)?
Один раз в тексте написано - ещё не означает одно обращение.
По стандарту ++pwm эквивалентно pwm+=1, что в свою очередь эквивалентно
pwm = pwm + 1. Дальше, (pwm=pwm+1) это "присваивающее выражение".
ISO/IEC 9899:1999 aka C99, 6.5.16:
 "An assignment expression has the value of the left operand
  after the assignment"
а не
  "value to be assigned to the left operand"
Т.е. значением всего выражения является не "то, что будет присвоено", а "то,
что содержится после присваивания", в лучшем случае "нечто, равное тому,
что будет лежать в левом операнде после присваивания".
В случае не-volatile переменной pwm её значение после присваивания
равно значению правой части выражения, приведённое к типу левой части.
И оптимизатор имеет право не зачитывать заново то, что "и так известно".
А вот в случае volatile оно "неизвестно", после записи в volatile-объект
чего бы то ни было в нём лежит всё, что угодно.

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

MR> At sequence
MR> points, volatile objects are stable in the sense that previous evaluations
MR> are complete and subsequent evaluations have not yet occurred.

MR> Только то, что между точками следованя volatile-объекты должны принять
MR> состояние, соответствующее уже выполненным вычислениям, т.е. их значения
MR> нужно записать.
 Нет, *это* требование - "записать всё" - работает для любых переменных.
 Для volatile должно закончиться всё, включая "закешированное" в регистрах
или в памяти компилятора значение - предыдущие оценки закончились, следующие
ещё не начались ( a = 5; if( a == 5) {} )

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

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

MR> *7.1.5.1 The cv-qualifiers*
MR> <...>
MR> 8 [Note: volatile is a hint to the implementation to avoid aggressive
MR> optimization involving the object because the value of the object might
MR> be
MR> changed by means undetectable by an implementation. See 1.9 for detailed
MR> semantics. In general, the semantics of volatile are intended to be the
MR> same in
MR> C++ as they are in C. ]

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

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

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

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

Т.е. в конечном итоге volatile-объект может измениться в любой момент по
неизвестной причине.
В конкретном случае, когда pwm - это точно не аппаратный регистр процессора
(для уверенности компилятора в этом она должна лежать в том же файле,
так как extern может после линковки оказаться аппаратным регистром), когда
компилируемый код выполняется при запрещённых прерываниях (даже если
это в обработчике прерывания e AVR - надо проверить, не выполнится ли раньше
по дороге sei()), в этом конкретном случае компилятор может и "ссобразить",
что volatile можно рассматривать как non-volatile, но не слишком ли многого
хочется от компилятора?

MR> В RU.C_CPP что ли спросить?..
 Да наверное. Нехорошее какое-то вышло сочетание проверки значения
volatile-объекта с отсутствием точки следования.

wbr,
--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


Re: 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/\

Re: AVR C -- они все издеваются что ли?!.
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);
Quoted text here. Click to load it
    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>    Где его взять?

http://www.google.com/search?q=iso9899-c99.pdf

 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


Re: AVR C -- они все издеваются что ли?!.
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/\

Re: AVR C -- они все издеваются что ли?!.
Sun Feb 20 2005 16:25, Michael Ryazanov wrote to Yuriy K:

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

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

read (pwm) to (temp)
temp = temp+1
write(temp) to (pwm)

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

 <...>>
 MR>>> По-моему, из этого можно сделать вывод, что единственная сущность,
 MR>>> которую можно _сравнивать_ (выделенo YK)
 MR>>> -- присваеваемое значение.
 YK>> Hе надо делать выводов, надо RTFM.
 YK>> iso9899-c99.pdf, 6.5.9 Equality operators:
 MR>    Вот уж к оператору сравнения это никак не относится. Вопрос был в
 MR> значении оператора присваивания.

??? Ты бы определился с вопросом, что-ли. :-)

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

 MR>    Hомер пункта?

Атомарность не гарантируется вообще, кроме единственного исключения.

7.14
...
2 The type defined is   sig_atomic_t
which is the (possibly volatile-qualified) integer type of an object that
can be accessed as an atomic entity, even in the presence
of asynchronous interrupts.

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

Какое именно применение? Приводи пример.

WBR, Yuriy.


Re: AVR C -- они все издеваются что ли?!.
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)=10%24 ) (это чтобы точно не спорить про на мой взгляд
однозначно прописанную в стандарте цепочку ++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

--
/* Oleksandr Redchuk, Brovary, Ukraine */
/* real '\x40' real '\x2E' kiev '\x2E' ua     */


Re: AVR C -- они все издеваются что ли?!.
Hемедленно нажми на RESET, Michael Ryazanov!


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

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



Re: AVR C -- они все издеваются что ли?!.
▐┤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/\

Site Timeline