#include "__general_flash.h"
FLASH_EraseInitTypeDef EraseInitStruct;
extern HAL_StatusTypeDef res_hal;
unsigned CRC_Update;
//uint32_t PAGE_OFFSET = ((uint32_t)((4-1) * 0x0400));
uint32_t PAGE_NUMB = 127;


/* Записать в память данные, произвольного размера */
HAL_StatusTypeDef FLASH_Write_Data(uint32_t* Address, uint8_t* Data, int Data_size)
{
  HAL_StatusTypeDef res_hal;
  
  int data_cnt = 0;
  uint32_t adr;
  uint32_t word_data;


  res_hal = HAL_FLASH_Unlock();
  if (res_hal != HAL_OK) return res_hal;

  for (adr = *Address; adr < *Address + Data_size; adr = adr + 4)
  {

    
    word_data = (
      Data[data_cnt] |
      Data[data_cnt + 1] << 8 |
      Data[data_cnt + 2] << 16 |
      Data[data_cnt + 3] << 24);
    
    res_hal = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, adr, word_data);

    if (res_hal != HAL_OK) return res_hal;

    data_cnt += 4;
  }

  *Address += Data_size;
  res_hal = HAL_FLASH_Lock();

  return res_hal;
}



HAL_StatusTypeDef FLASH_Enable_DualBankMode(void)
{
  HAL_StatusTypeDef res_hal;
  FLASH_AdvOBProgramInitTypeDef OB_DualBank;
  
  
  res_hal = HAL_FLASH_Unlock();
  if (res_hal != HAL_OK) 
    return res_hal;
  
  res_hal = HAL_FLASH_OB_Unlock();
  if (res_hal != HAL_OK) 
    return res_hal;
  
  
  FLASH->OPTCR |= FLASH_OPTCR_DB1M;
  
  res_hal = HAL_FLASH_OB_Launch();
  if (res_hal != HAL_OK) 
    return res_hal;
  
  res_hal = HAL_FLASH_OB_Lock();
  if (res_hal != HAL_OK) 
    return res_hal;
  
  res_hal = HAL_FLASH_Lock();
  if (res_hal != HAL_OK) 
    return res_hal;
    
  
  return res_hal;
}



/* Убрать защиту */
HAL_StatusTypeDef FLASH_WriteProtection(uint32_t BankN, uint32_t WriteProtection)
{
  HAL_StatusTypeDef res_hal;
  FLASH_OBProgramInitTypeDef OBInit;
  
    // Очистка всех возможных ошибок
  FLASH->SR |= FLASH_FLAG_WRPERR  // Write Protection Error
             | FLASH_FLAG_PGSERR  // Programming Sequence Error
             | FLASH_FLAG_PGAERR  // Programming Alignment Error
             | FLASH_FLAG_OPERR;  // Operation Error
  
  res_hal = HAL_FLASH_Unlock();
  if (res_hal != HAL_OK) 
    return res_hal;
  
  res_hal = HAL_FLASH_OB_Unlock(); // Разблокировка Option Bytes
  if (res_hal != HAL_OK) 
    return res_hal;

  // Считываем текущую конфигурацию Option Bytes
  HAL_FLASHEx_OBGetConfig(&OBInit);

  // Отключаем защиту на всех секторах второго банка
  OBInit.OptionType = OPTIONBYTE_WRP;
  OBInit.WRPState = WriteProtection; // Снять защиту
  OBInit.WRPSector = OB_WRP_SECTOR_12; // Снять защиту
  OBInit.Banks = BankN; // Указываем второй банк
  res_hal = HAL_FLASHEx_OBProgram(&OBInit);
  if (res_hal != HAL_OK) 
    return res_hal;

  // Записываем изменения и перезагружаем чип
  res_hal = HAL_FLASH_OB_Launch();
  if (res_hal != HAL_OK) 
    return res_hal;
  
  // Считываем текущую конфигурацию Option Bytes
  HAL_FLASHEx_OBGetConfig(&OBInit);
  
// Блокировка Option Bytes
  res_hal = HAL_FLASH_OB_Lock(); 
  if (res_hal != HAL_OK) 
    return res_hal;
  
  res_hal = HAL_FLASH_Lock();
  if (res_hal != HAL_OK) 
    return res_hal;
  
  return res_hal;
}
//-----------------ELEMENTARY FUNCTIONS---------------------
/* functions for reading bytes/halswords/words */
uint8_t FLASH_Read_Byte(uint32_t add)
{
  return (*(__IO uint8_t*)(add));
}
uint16_t FLASH_Read_HalfWord(uint32_t add)
{
  return (*(__IO uint16_t*)(add));
}
uint32_t FLASH_Read_Word(uint32_t add)
{
  return (*(__IO uint32_t*)(add));
}
/* functions for writing bytes/halswords/words */
HAL_StatusTypeDef FLASH_Write_Byte(uint32_t Address, uint8_t Data)
{ 
  HAL_StatusTypeDef res_hal;
  
  res_hal = HAL_FLASH_Unlock();
  
  if (res_hal != HAL_OK) return res_hal;
  
  res_hal = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, Address, (uint8_t)(Data));
  
  if (res_hal != HAL_OK) return res_hal;

  res_hal = HAL_FLASH_Lock(); 
  return res_hal;
}
HAL_StatusTypeDef FLASH_Write_HalfWord(uint32_t Address, uint16_t Data)
{
  HAL_StatusTypeDef res_hal;
  
  res_hal = HAL_FLASH_Unlock();
  
  if (res_hal != HAL_OK) return res_hal;
  
  res_hal = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, (uint16_t)(Data));
  
  if (res_hal != HAL_OK) return res_hal;

  res_hal = HAL_FLASH_Lock(); 
  return res_hal;
}
HAL_StatusTypeDef FLASH_Write_Word(uint32_t Address, uint32_t Data)
{
  HAL_StatusTypeDef res_hal;
  
  res_hal = HAL_FLASH_Unlock();
  if (res_hal != HAL_OK) return res_hal;

  res_hal = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, (uint32_t)(Data)); 
  if (res_hal != HAL_OK) return res_hal;

  res_hal = HAL_FLASH_Lock(); 
  return res_hal;
}
//----------------------------------------------------------

