0
если вы на AVR — используйте ATOMIC_BLOCK.
avr-glibc позаботилась о вас и все нужные барьеры уже есть в этом макросе.

$ grep -r /usr/avr/include/util -e 'memory'
/usr/avr/include/util/atomic.h: __asm__ volatile ("" ::: «memory»);
/usr/avr/include/util/atomic.h: __asm__ volatile ("" ::: «memory»);
/usr/avr/include/util/atomic.h: __asm__ volatile ("" ::: «memory»);

приятно, когда ничего не нужно изобретать ))
  • avatar
  • rouming
  • 01 ноября 2012, 21:03
0
допустимо, если выставление флага — ровно одна инструкция. а если это присвоение маски? а если со временем мигрируете на SMP и прерываний уже будет несколько от разных процессоров? да зачем такие сложности — а если вы в будущем решите использовать вложенные прерывания на AVR? ваш код с «допустимым» volatile сразу же рассыплется.
  • avatar
  • rouming
  • 01 ноября 2012, 20:58
0
циклом вы вводите ожидание, т.е. синхронизируете один контекст выполнения с другим, значит вам _необходима_ консистентность каких-то данных при ready == 1. это значит, что вы выполняете lock-and-wait. volatile вам не дает _никаких_ гарантий, что данные будут консистенты. компилятор вправе переставить инструкции. процессор вправе выполнять их в любом порядке. вам не гарантируется _ничего_.

любой вызов static функции скорее всего заинлайнится, и компилятор опять вправе сделать перестановку. без барьера (или нового sequence point) здесь не обойтись.
  • avatar
  • rouming
  • 01 ноября 2012, 20:54
0
чувствуется в буквах какое-то сомнение )) да, вы вправе мне не верить. воспользуйтесь ассемблерным выводом вашего компилятора. или дизассемблером для готового бинаря. он врать (как я!) не будет.
  • avatar
  • rouming
  • 01 ноября 2012, 19:11
0
компилятор этого не знает.
как он должен поступить, когда вы объявляете такую функцию?

void init_my_struct(struct A *a, void *data)
{
    memcpy(a, data, sizeof(a));
}
  • avatar
  • rouming
  • 01 ноября 2012, 19:07
0
раз вы не обращаетесь к A.b то _кода_ не будет. но sizeof(A) конечно же будет равен двум интам (ну смотря на какой архитектуре вы находитесь, 4 (avr) или 8 байтам (x86)). вы объявили структуру. описали кусок памяти. на важно в каком месте программы. она всегда будет равна двум интам.
  • avatar
  • rouming
  • 01 ноября 2012, 19:01
0
еще раз. если вы думаете, что «вот сюда бы здорово добавить volatile, вроде как должен помочь», то значит у вас баг. появилась мысль о volatile — баг. все просто :)
  • avatar
  • rouming
  • 01 ноября 2012, 18:56
0
нет. вам нужно запрещать прерывания (или спин лок или что-то еще). volatile вам никак не поможет вообще.
последовательность такая:

read s_struct.member1
===== start interrupt ======
write s_struct.member1, xxx
write s_struct.member2, xxx
===== end interrupt ======
read s_struct.member2

в итоге ваша структура неконсистентна. у вас часть данных до прерывания и часть после.
  • avatar
  • rouming
  • 01 ноября 2012, 18:53
0
в случае реализации семафора в ядре — тогда только барьер памяти и атомарные инструкции. барьер компиляции ни тем более volatile без лока шины памяти не помогут.
  • avatar
  • rouming
  • 01 ноября 2012, 18:28
0
да конечно можно. вариантов масса. главное понимать, зачем вам это нужно, пометить в коде _по_месту_ что вы этим делаете, но не определять volatile переменную в каком-нибудь общем хедере и рассчитывать на то, что вся рутина и архитектурно зависимые вещи волшебным образом выполнится за вас.
  • avatar
  • rouming
  • 01 ноября 2012, 18:16
0
ну вы ведь хотите чтоб переменная _перечитывалась_ каждый раз.
или порядок инструкций был именно тот, который вы запланировали.
барьер компилятора именно это и сделает.
конечно, не нужно его пихать везде, где только хочется. речь именно о конкретном месте в коде, которое будет очевидно и автору кода и последователю, которому достался этот код.
  • avatar
  • rouming
  • 01 ноября 2012, 18:11
0
если речь действительно о разных единицах компиляции, то да, совет про extern годный:
main.cpp:
#include "my_struct.h"

extern struct my_struct s_struct;

my_struct.cpp:
#include "my_struct.h"

struct my_struct s_struct;

my_struct.h:
struct my_struct
{
...
};


_линковщик_ направит все обращения к s_struct ровно в 1 место в памяти.
  • avatar
  • rouming
  • 01 ноября 2012, 18:06
0
«сбросить все кеши в рам» — т.е. создать такой код, в котором побочные эффекты предыдущих инструкций до барьера не пересекались бы с побочными эффектами после. в примере из статьи это заставляет компилятор перечитать переменную снова и снова, или не нарушать порядок инструкций
  • avatar
  • rouming
  • 01 ноября 2012, 17:55
0
вы путаете барьер памяти и барьер компилятора. барьер компилятора никаких дополнительных инструкций не создает. это просто указание _компилятору_ сбросить все кеши в рам. а барьер памяти, да. лочит шину памяти, требует сбросить/обновить кеш процессора. но здесь я об этом не говорил.
  • avatar
  • rouming
  • 01 ноября 2012, 17:51
0
хм. простите, я не понял о чем речь. то, о чем вы говорите, напоминает упаковку структур, если речь именно о нескольких компиляторах, а не об одном. в любом случае компилятор не порождает структуру. компилятор обращается к данным в памяти. а структура просто описывает, _как_ обращаться к этим данным (по каким смещениям и каким типам).
  • avatar
  • rouming
  • 01 ноября 2012, 17:48
0
ну а вывод _ассемблерного_ кода соответственно:

$ gcc -S test.c -o - -O3
foo:
        blablabla
        ret
  • avatar
  • rouming
  • 01 ноября 2012, 17:07
0
сначала препроцессор, потом ассемблер, потом линковщик -> готовый бинарь.

void foo(void)
{
	asm volatile ("blablabla");
}

что получаем:

$ gcc -c test.c -o test.o
volatile.c: Assembler messages:
volatile.c:37: Error: no such instruction: `blablabla'
  • avatar
  • rouming
  • 01 ноября 2012, 17:01
0
к сожалению моя статья не облегчит вам изобретение велосипеда. я не вижу, чтоб были какие-нибудь toolchain в свободном доступе для stm8. gdb не поддерживает эту архитектуру, а без gdb моя заглушка совершенно бессмысленна. хотя, как я вижу из вот этого дока, есть поддержка trap, что облегчит выставление breakpoint'ов.
  • avatar
  • rouming
  • 19 октября 2012, 11:36
0
простите, такой стиль
  • avatar
  • rouming
  • 19 октября 2012, 01:05
0
> вместо слово «затычка»
вы хотели сказать заглушка? я стараюсь не использовать американизмы, либо все на русском, либо на английском. как я заметил, все стараются писать исключительно на русском, даже комментарии к коду переводят. следую внегласным правилам сообщества.
> …а заодно сохраняете флэш память (имхо)
сохранение пина мне было важней. думаю, это опция: либо пин, либо частая запись во флеш. т.е. в идеале нужно под макросами реализовать и решение, основанное на вложенных прерываниях.
  • avatar
  • rouming
  • 19 октября 2012, 01:03