

#ifndef _TYPES_H_
#define _TYPES_H_
/* --- 30/08/18 - данный говнокод был закоментирован, т.к. не используется...и слава богу, что не используется...
typedef struct _FLAG_PROTECTED    // FLAG_PROTECTED - так назваемый защищенный флаг
 {                                 // Пусть имеется флаг, который могут модифицировать два потока
  unsigned char bProtected:   1;   // Один поток устанавливает флаг, информируя о том, что произошло некое событие
  unsigned char cFlags    :   7;   // Другой поток сбрасывает флаг, информируя о том, что он обнаружил, что флаг установлен и, соовтественно, знает о событии
  int  irq;  //irq id
 } FLAG_PROTECTED;                 // Защищенный флаг создан для этих целей. Первый поток - основной main()
                                   // Второй поток - прерывание. Пусть основной поток использует функцию, которая устанавливает флаг события
                                   // Так как функция сделает своё действие не атомарно, соответственно, флаг установит не атомарно,
                                   // возможно не выполнив до конца все действия. Как только функция установила флаг, уже не гарантируется, что
                                   // флаг будет установлен по выходу из функции, так как в любой момент может произойти прервание, и второй поток
                                   // (прерывание) сбросит его и выполнит сооветсвующие действия. Чтобы этого избежать, следует защитить флаг от модификации
                                   // до тех пор, пока это необходимо. Основной поток должен вызывать макрос SECURITY_FLAG_PROTECTED_MODIFY( *, #, % ), где * - переменная
                                   // типа FLAG_PROTECTED. Если переменная свободна ( не защищена ), соответсвующий бит # изменит значение на установленное в %
                                   // Как только станет известно, что больше незачем защищаять переменную, поток должен вызвать макрос SECURITY_FLAG_PROTECTED_RELEASE
                                   // Любой другой поток, даже этот же самый не сможет изменить флаг в переменной вызовом макроса SECURITY_FLAG_PROTECTED_MODIFY до тех пор, пока
                                   // не будет вызван макрос SECURITY_FLAG_PROTECTED_RELEASE(*). Причем вызывать SECURITY_FLAG_PROTECTED_RELEASE должен тот же поток, что и занял переменную
*/
 #define rNVIC_ICSR (*((volatile unsigned int*)0xE000ED04))
 #define CURRENT_CONTEXT ((rNVIC_ICSR & 0xFF)?((rNVIC_ICSR & 0xFF)-16):0)



 #define SECURITY_FLAG_PROTECTED_RELEASE(flag_protected_entry)                              {                      \
                                                             rICER0 = (1<<ICE_USB);                                 \
                                                             int cur_context = CURRENT_CONTEXT; /* volatile==volatile нельзя*/    \
                                                             if((flag_protected_entry).bProtected && (cur_context==(flag_protected_entry).irq))           \
                                                              (flag_protected_entry).bProtected=0;                    \
                                                             rISER0 = (1<<ICE_USB); }        


 
                                                               
 #define SECURITY_FLAG_PROTECTED_MODIFY(flag_protected_entry, bit, value)                              {\
                                                             rICER0 = (1<<ICE_USB);\
                                                             if(!(flag_protected_entry).bProtected)\
                                                             {   (flag_protected_entry).bProtected = 1;\
                                                                 (flag_protected_entry).irq = CURRENT_CONTEXT;\
                                                               if(value)\
                                                               {\
                                                                 if((bit)>=0 && (bit)<=6) ((flag_protected_entry).cFlags)|=(1<<(bit));\
                                                               } else\
                                                               {\
                                                                 if((bit)>=0 && (bit)<=6) ((flag_protected_entry).cFlags)&=(~(1<<(bit)));\
                                                               }\
                                                             }\
                                                             rISER0 = (1<<ICE_USB);}

                     

#endif