Цитата(Rst7 @ Feb 16 2009, 12:12)

Лучше бы - не ядро править, а в компиляторы вменяемые способы работы с многобайтовыми переменными добавили. В смысле - чтобы оно само умело загрузку-выгрузку short/long в критическую секцию оборачивать. А то макросы-костыли класса ATOMIC_STORE_SHORT/ATOMIC_LOAD_SHORT уже достали, читабельности коду они аж никак не добавляют

Одно другому не мешает. Не поленились же ещё в 8086 запретить прерывания на одну команду после записи SS. Тут тоже можно было не кучу регистров в кристалл вставлять, а запрет прерывания при обращении к младшему байту.
Что касается атомарнсти, так
dxp что-то в таком духе давным давно показывал (только там не шаблон был, а просто класс для одного конкретного типа, в те времена IAR ещё шаблоны не поддерживал).
foo.cpp:
Код
#include <stdint.h>
#include <avr/interrupt.h>
class crit_sect {
uint8_t _sreg;
public:
crit_sect() : _sreg(SREG) { cli(); }
~crit_sect() { SREG = _sreg; }
};
// не претендуя на полноту
template<typename T> class atomic {
volatile T t;
public:
inline operator T () {
T temp;
{ crit_sect cs;
temp = t;
}
return temp;
}
inline atomic<T>& operator = (const T ti) {
{ crit_sect cs;
t = ti;
}
return *this;
}
inline atomic<T>& operator++() {
{ crit_sect cs;
++t;
}
return *this;
}
};
atomic<uint16_t> va, vb;
uint16_t c;
void foo() {
vb = va + c;
++va;
}
avr-gcc -Os -mmcu=atmega88 -S foo.cpp
foo.s:
Код
// operator++ не захотел инлайнить, счёл слишком толстой функцией, ключи крутить лень
// да и не нужно, главное принцип
_ZN6atomicIjEppEv:
movw r30,r24
in r18,95-0x20
cli
ld r24,Z
ldd r25,Z+1
adiw r24,1
std Z+1,r25
st Z,r24
out 95-0x20,r18
movw r24,r30
ret
/* function atomic<T>& atomic<T>::operator++() [with T = unsigned int] size 12 (11) */
_Z3foov:
in r24,95-0x20
cli
lds r18,va
lds r19,(va)+1
out 95-0x20,r24
lds r24,c
lds r25,(c)+1
add r18,r24
adc r19,r25
in r24,95-0x20
cli
sts (vb)+1,r19
sts vb,r18
out 95-0x20,r24
ldi r24,lo8(va)
ldi r25,hi8(va)
rcall _ZN6atomicIjEppEv
movw r30,r24
in r18,95-0x20
cli
ld r24,Z
ldd r25,Z+1
out 95-0x20,r18
sbiw r24,5
brne .L6
sts (c)+1,__zero_reg__
sts c,__zero_reg__
.L6:
ret
Собственно, никто ведь не заставляет писать "если на С++, то до конца". Можно использовать только то, что генерирует код не толще тех макросов, о которіх шла речь, но удобнее в использовании.
====
мдя...
1) подсунть в качестве T структуру так просто не удаётся (в варианте с исключённым operator++, естественно)
2) ну да, ну да, в обработчике прерывания доступ тоже будет обрамляться запретом/восстановлением прерываний. Но и если компелятор будет сам уметь оборачивать обращение прямо и вражений, то ему ещё придётся объяснять, что вот тут-то оборачивать и не надо.
А так - просто добавить в шаблон
Код
public:
T noatomic_get() { return t; }
void noatomic_assign(T i) { t = i; }
и в обработчиках пользоваться ими.
Эх, нет в жизни совершенства! (С) Лис.