Цитата(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 эти все перестановки кода обсуждались. Тему неплохо почистили от ругни, но суть оталась :-)
Уже нужно было где-то процитировать - тогда нашлась в последнем сообщении опечатка, исправлялсь, поэтому дата у него оторванная от остальных.