реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3  
Reply to this topicStart new topic
> Оператор "printf" и функция "putchar" для работы с символьным LCD
ReAl
сообщение Mar 20 2010, 18:38
Сообщение #31


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Сергей Борщ @ Mar 20 2010, 13:11) *
Фу. union в таком применении - грязный хак.
продолжая уклоняться - если уж всё равно плюсы, то можно попробовать http://electronix.ru/forum/index.php?showt...mp;#entry535341


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 20 2010, 18:51
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Сергей Борщ @ Mar 20 2010, 14:11) *
Фу. union в таком применении - грязный хак.

Сразу не заметил sad.gif этой реплики - никакого хака, это его прямое предназначение.
Цитата
Как раз таки и не дающий никакой дополнительной свободы компилятору

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

Нималейших прав у него нету использовать какую-либо информацию о других членах union.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 20 2010, 21:59
Сообщение #33


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(zltigo @ Mar 20 2010, 01:08) *
Абсолютно лишняя, ибо пока выполняется обработчик она измениться за его пределами не может. для Tail volatile нужен, Head - нет.
Вспомнил, зачем Head должен быть volatile. Долго же в мозгу зрело, не давало покоя - ну не совсем же сдуру я его делал volatile! Если компилятор достаточно умный и решит встроить uart_t::send (например, если он вызывается только из одной точки программы), то без volatile он имеет полное право закешировать в основном коде Head в регистре и обработчик вместо одного байта будет каждый раз выстреливать весь буфер от начала до конца.

Кстати, и буфер тоже должен быть volatile. В противном случае компилятор имеет полное право перенести запись в буфер после изменения Head и разрешения прерывания.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 20 2010, 22:13
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Сергей Борщ @ Apr 21 2010, 00:00) *
то без volatile он имеет полное право закешировать в основном коде Head в регистре...

Это по любому глобальная переменная. Даже при встраивании функции область работы с этой переменной и область cуществования локальной переменной Tmp четко определена телом бывшей функции и при выходе за ее пределы должна быть синхронизирована с памятью. Если этого не будет сделано, то компилятор не умный, а вовсе даже с ошибками.
Даже допустим, что компилятор плюет на все и всех, но даже в этом случае uart_t::send должна встроися в некий вечный цикл, причем ничего особо кроме вызова send() не делающий, дабы была куча неиспользуемых регистров и компилятор мог ими разбрасываться. Что-то за уши притянутое.
Цитата
Кстати, и буфер тоже должен быть volatile. В противном случае компилятор имеет полное право перенести запись в буфер после изменения Head и разрешения прерывания.

Ну это вообще понесло sad.gif
Вместо:
Код
  TxBuffer[ TxHead ] = byte;
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);

Сделать
Код
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);
  TxBuffer[ TxHead ] = byte;

Может он тогда имеет право и вообще генерить любые побочные эффекты и точки следования ему не указ?


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 21 2010, 07:31
Сообщение #35


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(zltigo @ Apr 21 2010, 01:28) *
Это по любому глобальная переменная. Даже при встраивании функции область работы с этой переменной и область cуществования локальной переменной Tmp четко определена телом бывшей функции и при выходе за ее пределы должна быть синхронизирована с памятью. Если этого не будет сделано, то компилятор не умный, а вовсе даже с ошибками.
Переменная не volatile и компилятор имеет право делать с ней что угодно, если это не меняет observable behaviour. Глобальность и время жизни переменной тут совершенно не при чем. Стандарт не нарушен. Компилятор не виноват.
Цитата(zltigo @ Apr 21 2010, 01:28) *
Что-то за уши притянутое.
Ну и что? "Никто не знает, что может прийти в голову этим пчелам" (с). Имеются ввиду и программисты и компилятор. Потенциально бага есть. Предположенное мной поведение компилятора не противоречит стандарту. Значит отмахиваться от его возможности только потому, что "сегодняшний мой компилятор в моих программах так не делает" - это положить самому себе граблю. Не факт, что он не будет так делать никогда. И все ради чего? Ради экономии пары volatile и одной временной переменной? На сегодняшнем результате компиляции это никак не скажется, это только увеличит исходный текст. Но сделает его безопасным.
Цитата(zltigo @ Apr 21 2010, 01:28) *
Ну это вообще понесло sad.gif
Вместо:
Код
  TxBuffer[ TxHead ] = byte;
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);

Сделать
Код
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);
  TxBuffer[ TxHead ] = byte;
Нет. Такого он не имеет права делать, ибо TxHead, как мы договорились, volatile. А вот такое - вполне:
Код
  uint8_t * ptr = &TxBuffer[ TxHead ];
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);
    *ptr = byte;
И уже делает. Не в этом конкретно случае, но подобные оптимизации встречал.
Цитата(zltigo @ Apr 21 2010, 01:28) *
Может он тогда имеет право и вообще генерить любые побочные эффекты и точки следования ему не указ?
К точке следования должны закончиться побочные эффекты. TxBuffer не volatile, значит запись в нее не дает побочных эффектов. Компилятор имеет полное право момент записи отложить. При кроссфайловой оптимизации запись вообще может быть выкинута, ибо компилятор может увидеть, что чтения из этой переменной в этом потоке выполнения нет.

В чем я не прав?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 24 2010, 21:28
Сообщение #36


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(zltigo @ Apr 21 2010, 01:28) *
Это по любому глобальная переменная. Даже при встраивании функции область работы с этой переменной и область cуществования локальной переменной Tmp четко определена телом бывшей функции и при выходе за ее пределы должна быть синхронизирована с памятью. Если этого не будет сделано, то компилятор не умный, а вовсе даже с ошибками.

Код
#include <avr/io.h>
uint8_t i;
inline void ppi() {
        uint8_t temp = i + 1;
        i = temp;
}

void foo(uint8_t n) {
        while(n--) {
                ppi();
                PORTB = 0;
        }
}

Код
foo:
    tst r24
    breq .L6
    lds r18,i
    mov r25,r24
.L5:
    out 56-32,__zero_reg__
    subi r25,lo8(-(-1))
    brne .L5
    add r18,r24
    sts i,r18
.L6:
    ret

Всегда считал, что тут всё правильно. Хотя тут нет ни намёка на работу с i "в пределах тела бывшей функции".
Аналогично при встраивании uart::send при отправке строки вполне может на первом байте разрешить прерывания (записать в UDR - не важно), но обновить head в глобальной переменной только в конце строки.

Цитата(zltigo @ Apr 21 2010, 01:28) *
Вместо:
Код
  TxBuffer[ TxHead ] = byte;
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);

Сделать
Код
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);
  TxBuffer[ TxHead ] = byte;

Может он тогда имеет право и вообще генерить любые побочные эффекты и точки следования ему не указ?
Ну аж так нельзя, так как у массива индекс выходит другой. А со сгенерированным компилятором временным указателем или индексом, сохраняющем предыдущее значение - вполне.
Точки следования не к этому. Вон в примере выше от точек следования в ppi() вообще ничего не осталось. И инвариантный код из цикла оптимизатором выносится с полным правом это делать, хоть при этом точки следования и меняются местами - от _независимых_ операций.
Там в стандарте есть такое слово "observable behavior", такая перестановка
Код
  uint8_t * ptr = &TxBuffer[ TxHead ];
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);
    *ptr = byte;
для не-volatile TxBuffer "видимое поведение" не меняет. А если ещё и TxHead не-volatile, то можно и так:
Код
    UCSRB |= (1<<UDRIE);
    TxBuffer[ TxHead ] = byte;
    TxHead = Tmp;
и тут даже внтренняя переменная для индекса/адреса не нужна. И в этом смысле TxHead должен быть volatile как у Сергея, так и в 11-том сообщении автора темы.

Как-то очередной версией копилятора в scmRTOS
Код
class TCritSect
{
public:
    TCritSect () : StatusReg( SREG ) { cli(); }
    ~TCritSect() { SREG = StatusReg; }
private:
    TStatusReg StatusReg;
};

    INLINE inline dword GetTickCount() { TCritSect cs; return Kernel.SysTickCount; }
при не-volatile на тот момент SysTickCount начало компилироваться не как
Код
   dword tmp;
   cs.StatusReg = SREG;
   cli();
   tmp = Kernel.SysTickCount;
   SREG = cs.StatusReg;
   return tmp;
а как
Код
   cs.StatusReg = SREG;
   cli();
   SREG = cs.StatusReg;
   return Kernel.SysTickCount;

Тут http://forum.sources.ru/index.php?showtopic=201904 эти все перестановки кода обсуждались. Тему неплохо почистили от ругни, но суть оталась :-)
Уже нужно было где-то процитировать - тогда нашлась в последнем сообщении опечатка, исправлялсь, поэтому дата у него оторванная от остальных.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 24 2010, 22:39
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Сергей Борщ @ Apr 21 2010, 00:14) *
Вспомнил, зачем Head должен быть volatile.
Кстати, и буфер тоже должен быть volatile.
....

Можешь попытаться заставить любой из компиляторов такое сделать? Я не стебаюсь, просто мне никак заставить сделать такое не удалось, а поисследовать поведение и пути обхода без огульного применения volatile, очень хочется.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 9th July 2025 - 00:27
Рейтинг@Mail.ru


Страница сгенерированна за 0.01431 секунд с 7
ELECTRONIX ©2004-2016