// v 1.0 from 14/10/2020
// Сычев А.
#ifndef FLASH_API_PROTECTION_H
#define FLASH_API_PROTECTION_H 

 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№                                                       №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№                    ЗАЩИТА СЕКТОРОВ                    №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№                                                       №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 #pragma pack( push, 1 )
 typedef enum
 {
      // flash_getprotect
      flash_sector_unprotected      = 0,     // не защищен
      flash_sector_protected        = 1,     // защищен
      //--------------------------------
      flash_sector_protect_nomodify = 0,     // не модифицировать биты защиты: общий/частный
      flash_sector_protect_modify   = 0x7f,  // модифицировать общий бит защиты
      flash_sector_protect_pick     = 1,     // отметить сектор для операции снятия/установки защиты
 }
 flash_api_protect_bits;
 #pragma pack( pop )

 #pragma pack( push, 1 )
 struct flash_sectors_st
 {
        union
        {
            __FLASH_DWORD loprotect;        // биты защиты секторов 0-31

            __FLASH_BYTE  bytes[1];         // для внутреннего пользования

            struct
            {
                __FLASH_DWORD s0  : 1;      // AT45: на весь сектор 0 выделен один бит. Либо секторы 0a,0b защищены, либо нет.
                __FLASH_DWORD s1  : 1;
                __FLASH_DWORD s2  : 1;
                __FLASH_DWORD s3  : 1;
                __FLASH_DWORD s4  : 1;
                __FLASH_DWORD s5  : 1;
                __FLASH_DWORD s6  : 1;
                __FLASH_DWORD s7  : 1;
                __FLASH_DWORD s8  : 1;
                __FLASH_DWORD s9  : 1;
                __FLASH_DWORD s10 : 1;
                __FLASH_DWORD s11 : 1;
                __FLASH_DWORD s12 : 1;
                __FLASH_DWORD s13 : 1;
                __FLASH_DWORD s14 : 1;
                __FLASH_DWORD s15 : 1;
                __FLASH_DWORD s16 : 1;
                __FLASH_DWORD s17 : 1;
                __FLASH_DWORD s18 : 1;
                __FLASH_DWORD s19 : 1;
                __FLASH_DWORD s20 : 1;
                __FLASH_DWORD s21 : 1;
                __FLASH_DWORD s22 : 1;
                __FLASH_DWORD s23 : 1;
                __FLASH_DWORD s24 : 1;
                __FLASH_DWORD s25 : 1;
                __FLASH_DWORD s26 : 1;
                __FLASH_DWORD s27 : 1;
                __FLASH_DWORD s28 : 1;
                __FLASH_DWORD s29 : 1;
                __FLASH_DWORD s30 : 1;
                __FLASH_DWORD s31 : 1;
            };
        };

        union
        {
            __FLASH_DWORD hiprotect;        // биты защиты секторов 32-63

            struct
            {
                __FLASH_DWORD s32 : 1;
                __FLASH_DWORD s33 : 1;
                __FLASH_DWORD s34 : 1;
                __FLASH_DWORD s35 : 1;
                __FLASH_DWORD s36 : 1;
                __FLASH_DWORD s37 : 1;
                __FLASH_DWORD s38 : 1;
                __FLASH_DWORD s39 : 1;
                __FLASH_DWORD s40 : 1;
                __FLASH_DWORD s41 : 1;
                __FLASH_DWORD s42 : 1;
                __FLASH_DWORD s43 : 1;
                __FLASH_DWORD s44 : 1;
                __FLASH_DWORD s45 : 1;
                __FLASH_DWORD s46 : 1;
                __FLASH_DWORD s47 : 1;
                __FLASH_DWORD s48 : 1;
                __FLASH_DWORD s49 : 1;
                __FLASH_DWORD s50 : 1;
                __FLASH_DWORD s51 : 1;
                __FLASH_DWORD s52 : 1;
                __FLASH_DWORD s53 : 1;
                __FLASH_DWORD s54 : 1;
                __FLASH_DWORD s55 : 1;
                __FLASH_DWORD s56 : 1;
                __FLASH_DWORD s57 : 1;
                __FLASH_DWORD s58 : 1;
                __FLASH_DWORD s59 : 1;
                __FLASH_DWORD s60 : 1;
                __FLASH_DWORD s61 : 1;
                __FLASH_DWORD s62 : 1;
                __FLASH_DWORD s63 : 1;
            };
        };
 };
 #pragma pack( pop )

 #pragma pack( push, 1 )
 typedef struct
 {
      // @sectors:
      // бит со значением flash_sector_protected означает, что сектор защищен от стирания/записи
      // бит со значением flash_sector_nomodify означает, что сектор не защищен
      struct flash_sectors_st sectors;

      __FLASH_BYTE protection_enabled : 1;  // 0 - защита секторов отключена, 1 - включена
      __FLASH_BYTE _reserved          : 7;
 }
 flash_api_getprotect_t;
 #pragma pack( pop )

 #pragma pack( push, 1 )
 typedef struct
 {
      // @sectors:
      // бит со значением flash_sector_protect_pick означает, что нужно защищитить сектор от стирания/записи
      // бит со значением flash_sector_nomodify означает, что не нужно менять статус защиты сектора
      struct flash_sectors_st sectors;

      __FLASH_BYTE protection_enabled: 1;  // 0 (flash_sector_unprotected) - защита секторов отключена,
                                           // 1 (flash_sector_protected) - включена

      __FLASH_BYTE protection_modify : 7;  // 0b0000000 (flash_sector_protect_nomodify) - не изменять бит защиты,
                                           // 0b1111111 (flash_sector_protect_modify) - изменить бит защиты
 }
 flash_api_protect_t;
 #pragma pack( pop )

 #pragma pack( push, 1 )
 typedef struct
 {
      // @sectors:
      // бит со значением flash_sector_protect_pick означает, что нужно снять защиту с сектора
      // бит со значением flash_sector_nomodify означает, что не нужно менять статус защиты сектора
      struct flash_sectors_st sectors;

      __FLASH_BYTE protection_enabled: 1;  // 0 (flash_sector_unprotected) - защита секторов отключена,
                                           // 1 (flash_sector_protected) - включена

      __FLASH_BYTE protection_modify : 7;  // 0b0000000 (flash_sector_protect_nomodify) - не изменять бит защиты,
                                           // 0b1111111 (flash_sector_protect_modify) - изменить бит защиты
 }
 flash_api_unprotect_t;
 #pragma pack( pop )

 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№                                                       №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№                    ЧТЕНИЕ/ЗАПИСЬ                      №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№                                                       №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№

 typedef __FLASH_DWORD flash_address_t;
 typedef __FLASH_DWORD flash_size_t;

 // режим стирания для flash_erase()
 typedef enum
 {
     fem_byaddress,
     fem_bypage,
     fem_byblock,
     fem_bysector,
 }
 flash_erase_mode_t;

 // режим записи для flash_write()
 typedef enum
 {
     fwm_safewrite,   // безопасная запись
     fwm_fastwrite,   // быстрая запись
     fwm_compatible,  // промежуточный режим м/у быстрой и безопасной записью
 }
 flash_write_mode_t;

 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№                                                       №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№                   ДОПОЛНИТЕЛЬНО                       №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№                                                       №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
 // №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№

 typedef enum
 {   // ЗАПРОС              // РАЗМЕР БУФЕРА      // ПОЛУЧИТЬ:
     fsvc_getVendorId,      //       2            // ID производителя
     fsvc_getDeviceId,      //       2            // ID устройства (__flash_deviceid_t)
     fsvc_getExtInfo,       //       *            // расширенную информацию производителя
     fsvc_getExtInfoLen,    //       1            // длинну расширенной информации производителя
     fsvc_getDataCapacity,  //       4            // доступная емкость устройства (в байтах)
     fsvc_getFullCapacity,  //       4            // полная емкость устройства (в байтах)
     fsvc_getCapacity,      //       4            // заявляемая емкость устройства по документации (MBit-s)
     fsvc_getProtect,       //       1            // информацию о защите секторов  (общий бит защиты 0x00 или 0x01)
     fsvc_getSectorsCount,  //       2            // количество секторов
     fsvc_getPagesCount,    //       2            // количество страниц
     fsvc_getBlocksCount,   //       2            // количество блоков
     fsvc_getPageSize,      //       2            // размер страницы
     fsvc_getReadyState,    //       1            // готовность устройства
     fsvc_getMinAddress,    //       4            // минимально возможный линейный адрес
     fsvc_getMaxAddress,    //       4            // максимально возможный линейный адрес
 }
 flash_service_info_t;

 typedef struct
 {
    flash_address_t minAddress;
    flash_address_t maxAddress;
    flash_size_t    maxSectors;
    flash_size_t    sectorSize;
    const char *    pChipDescription;  // textual flash-chip description
 }
 flash_properties_t;

 // flash_api_descriptor_t
 // Дескриптор API чипа энергонезависимой памяти
 typedef struct
 {
     struct
     {
     // flash_protect - установить защиту секторов     
     flash_err_t  (*flashProtect)( flash_api_protect_t * content );

     // flash_protect - снять защиту секторов     
     flash_err_t  (*flashUnprotect)( flash_api_protect_t * content );

     // flash_initialize - инициализация драйвера и API работы с устройством
     flash_err_t  (*flashInitialize)( bool detectMode );

     // flash_getready - проверка готовности устройства (со стандартным таймаутом)
     flash_err_t  (*flashGetReady)();

     // flash_service - функция получения общих сведений об флеш-памяти.
     flash_err_t  (*flashService)( flash_service_info_t si, void * pdata, __FLASH_WORD * pbufsize );
     
     // flash_protect_ex - установить/снять защиту секторов
     flash_err_t  (*flashProtectEx)( flash_api_protect_t * content, flash_api_protect_bits mode );

     // flash_getprotect - получить информацию о защищенных секторах.
     flash_err_t  (*flashGetProtect)( flash_api_getprotect_t * content );

     // flash_erase - мультирежимное стирание данных
     flash_err_t  (*flashErase)( flash_erase_mode_t mode, __FLASH_DWORD start, __FLASH_DWORD count );

     // flash_write - мультирежимная запись данных по адресу
     flash_err_t  (*flashWrite)( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size, flash_write_mode_t mode );

     // flash_read - чтение данных по адресу
     flash_err_t  (*flashRead)( flash_address_t address, __FLASH_BYTE * pBuffer, flash_address_t size );

     // flash_sleepmode - переход в режим пониженного энергопотребления
     flash_err_t  (*flashSleepMode)();

     // flash_wakeup - выход из режима пониженного энергопотребления
     flash_err_t  (*flashWakeup)();

     // flash_finalize - деинициализация драйвера
     flash_err_t  (*flashFinalize)( bool bHibernate, bool bForce );
     }
     routines;

     const flash_properties_t * flashProperties;
 }
 flash_api_descriptor_t;

#endif