/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * 
© Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "rtc.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include 
#include "sysdata.h"
#include "chip_temperature.h"
#include "shunt_voltage.h"
#include "shunt_temperature.h"
#include "ads1260.h"
#include "modbus.h"
#include "hsi16.h"
#include "hsi16_calibration.h"
#include "eeprom.h"
#include "ah_counter.h"
#include "battery_voltage.h"
#include "ref_voltage.h"
#include "fast_current.h"
#include "wh_counter.h"
#include "efficiency.h"
#include "esr.h"
#include "self_discharge.h"
#include "outputs.h"
#include "stm32g0xx_hal_crc.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
CRC_HandleTypeDef hcrc;
/* USER CODE BEGIN PV */
modbus_t modbusData;
static volatile uint32_t adcData[9];
static RTC_TimeTypeDef     Time;
static uint32_t conversionCounter;
static double submAhCounter;
static volatile uint32_t newADC = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_CRC_Init(void);
/* USER CODE BEGIN PFP */
bool SetFlashReadProtection(bool state);
uint8_t printprotectionstate(void);
bool SetBootFromFlashAndReadOutProtection(void);
void SaveCounter(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  uint32_t oldTime = 0;
  uint32_t newTime = 0;
  uint32_t timeDiff;
  uint32_t timeDiff10ms = 0;
  uint32_t timeDiff100ms = 0;
  uint32_t i = 0;
  uint32_t x;
  int32_t mwValueCounter;
  int silentmode =0;
  int mode_button_disable_time=0;
  uint8_t sekunde = 0;
  uint8_t sekundeOld = 0;
  uint32_t dummyDate;
  uint8_t firstStartCatcher;
  if (printprotectionstate() == 0)
  {
//    SetFlashReadProtection(true);
//    HAL_FLASH_OB_Launch();
  }
  //Wenn Speichernutzung größer 50% (debug) nötig??
  //https://community.st.com/t5/stm32-mcus-products/hard-fault-with-stm32g0b1-and-lvgl/td-p/777366
  __HAL_FLASH_PREFETCH_BUFFER_DISABLE();
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
 // printprotectionstate();
  printf("ISENSOR: Init\n");
  #ifdef DO_HSI16_CALIBRATION
  // HSI16 Frequenzkompensation Initilisierung
  HSI16_MeasurementInit();
  HSI16_GetCurve();
  orderTrimmingValues();
  #endif
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();
  //MX_USART1_UART_Init();
  MX_ADC1_Init();
  MX_RTC_Init();
  MX_CRC_Init();
  /* USER CODE BEGIN 2 */
  SYS_DATA_Init();
  WH_COUNTER_Init();
  AH_COUNTER_Init();
  startType_t startType = EEPROM_isFirstStart(&firstStartCatcher);
  sys_data.s.parameter.reserved0 = startType;
  sys_data.s.parameter.reserved1 = firstStartCatcher;
  switch(startType)
  {
	  case FIRST_START_AFTER_ERASE:					EEPROM_fullRestore(&sys_data);		  break;
	  case FIRST_START_AFTER_COMPARTIBLE_UPDATE:	EEPROM_readConfig(&sys_data);		  break;
	  case FIRST_START_AFTER_INCOMPARTIBLE_UPDATE:	EEPROM_factoryRestore(&sys_data, 0);  break;  // Preserving calibration and settings
	  case FIRST_START_ERROR:						EEPROM_fullRestore(&sys_data);		  break;
  }
  printf("read config...\n");
  EEPROM_readConfig(&sys_data);
  if(HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET)
  {
    HAL_Delay(50);
    if(HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET)
    {
      printf("factory restore...\n");
      EEPROM_factoryRestore(&sys_data, 1);
    }
  }
  // Modbus Initialisierung
  mbInit(&modbusData, sys_data.s.parameter.baudrate, sys_data.s.parameter.parityMode, sys_data.s.parameter.stopBit, &huart1);
  // STM32G0 Chiptemperatur Kalibrierung
  CHIP_TEMPERATURE_Calibration(/*&sys_data*/);
  // ADC auf STM32G0 starten
  HAL_ADCEx_Calibration_Start(&hadc1);
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcData, 9);
  // Power up Sequenz fr INA240 Strommessverstrker
  HAL_Delay(100);
  // ADS1260 Initialierung
  ADS1260_init();
  printf("ADS1260 Init\n");
  OUTPUTS_Init();
  //Display Adress with Error LED blinks
  for (int n = 0; n < sys_data.s.parameter.slave_address; n++)
  {
    HAL_GPIO_WritePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin, GPIO_PIN_SET);
    HAL_Delay(350);
    HAL_GPIO_WritePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin, GPIO_PIN_RESET);
    HAL_Delay(350);
  }
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    if (newADC == 1)
    {
      // Systemtakt 64Mhz
      // ADC Takt 64Mhz
      // ADC DIV 1
      // SAMPLE Time 160,5 Cycles
      // OVERSAMPLING 16
      // TOTAL TIME 160,5 + 12 * 16 * 8 == 22080 -->2,899 kHz
      //Neue ADC Daten mit einer Frequenz von ca. 1,9 Khz
      newADC = 0;
               // Messe genaue Spannungsreferenz aus ADS1260 um eigene Spannungsmessung damit zu kalibrieren
      REF_VOLTAGE_Exec(adcData[2]);
   
      // Differenz der Spannung Ubat- und Ushunt
      SHUNT_VOLTAGE_Exec( adcData[0]);
      BATTERY_VOLTAGE_Exec( adcData[1]);
      FAST_CURRENT_Exec( adcData[3], adcData[4]);
      sys_data.s.values.batteryPower = ((int64_t) sys_data.s.values.batteryVoltage * (int64_t)sys_data.s.values.batteryCurrent) / 1000LL;
      ESR_FAST_Exec();
      //HAL_GPIO_TogglePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin);
    }
    if (newCurrentValue == 1)
    {
      ADS1260_ConversionFinished(); 
      ESR_Exec();
      newCurrentValue = 0;
    }
    // Zeitbasis ms Systick;
    newTime = HAL_GetTick();
    timeDiff = newTime - oldTime;
    oldTime = newTime;
    timeDiff10ms += timeDiff;
    timeDiff100ms += timeDiff;
    if ((mode_button_disable_time > 0) && (timeDiff > 0))
    {
      mode_button_disable_time--;
    }
    // Zeitbasis Sekunde ber RTC
    // muss immer sowohl das Zeit- als auch das Datumsregister lesen
    // da beide Shadowregister sind sonst wird die Zeit nicht mehr geupdatet
    sekunde = hrtc.Instance->TR & 0x0000000F;
    dummyDate = hrtc.Instance->DR;
    if (sekundeOld != sekunde)
    {
      sekundeOld = sekunde;
      sys_data.s.values.onTime++;
      // Funktions Led blinken
      if (silentmode == 0)
      {
        HAL_GPIO_TogglePin(LED_FUNCTION_GPIO_Port, LED_FUNCTION_Pin);
		HAL_GPIO_TogglePin(AUX_EN_GPIO_Port, AUX_EN_Pin);
      }
      // Amperestundenzhler
      AH_COUNTER_Exec();
      WH_COUNTER_Exec();
      // LVP
      OUTPUTS_CheckLVP();
      // OVP
      OUTPUTS_CheckOVP();
      SaveCounter();
      sys_data.s.values.selfDischargeStatus = SELF_DISCHARGE_Exec();
      sys_data.s.values.efficiency = EFFICIENCY_Exec();
      // Ausgabe der Temperatur des STM32G0
      CHIP_TEMPERATURE_Exec( adcData[8]);
      SHUNT_TEMPERATURE_Exec(adcData[7]);
      sys_data.s.values.ovp_sense =  (adcData[5] * (uint64_t)sys_data.s.values.realVdd * 11 ) / 655360.0;
      sys_data.s.values.lvp_sense =  (adcData[6] * (uint64_t)sys_data.s.values.realVdd * 11 ) / 655360.0;
    }
    if(sys_data.s.parameter.command != 0)
    {
      if  (modbusData.current_query ==  MB_QUERY_NOTHING)
      {
        //printf("CMD = %d\n", sys_data.s.parameter.command);
        switch (sys_data.s.parameter.command )
        {
          case COMMAND_STORE_CONFIG:                          EEPROM_storeConfig(&sys_data,0);											  break;
          case COMMAND_FULL_RESTORE:                          EEPROM_fullRestore(&sys_data);											  break;
          case COMMAND_FACTORY_RESTORE:                       EEPROM_factoryRestore(&sys_data, 1);										  break;
          case COMMAND_RESTORE_LAST_SAVED_VALUES:             EEPROM_readConfig(&sys_data);												  break;
          case COMMAND_STORE_WITH_SERIAL_NUMBER:              EEPROM_storeConfig(&sys_data,1);											  break;	// Seriennummer schreiben
          case COMMAND_RESTART:                               NVIC_SystemReset();														  break;
          case COMMAND_BATTERY_CURRENT_OFFSET_CAL:            ADS_1260_BatteryCurrentOffsetCalibrationStart(&sys_data);					  break;
          case COMMAND_BATTERY_CURRENT_OFFSET_COMMONMODE_CAL: ADS_1260_BatteryCurrentOffsetCommonModeErrorComepensationStart(&sys_data);  break;
          case COMMAND_BATTERY_CURRENT_OFFSET_TEMP_CAL:       ADS_1260_BatteryCurrentOffsetTemperatureErrorComepensationStart();		  break;
          case COMMAND_BATTERY_CURRENT_GAIN_CAL:              ADS_1260_BatteryCurrentGainCalibrationStart(&sys_data);					  break;
          case COMMAND_BATTERY_CURRENT_GAIN_TEMP_SHUNT_CAL:   ADS_1260_BatteryCurrentGainTemperatureCalibrationShuntStart();			  break;
//        case COMMAND_BATTERY_CURRENT_GAIN_TEMP_CHIP_CAL:    ADS_1260_BatteryCurrentGainTemperatureCalibrationChipStart(); break;
          case COMMAND_SET_RDP_LEVEL0:                        SetFlashReadProtection(false);											  break;
          case COMMAND_SET_RDP_LEVEL1:                        SetFlashReadProtection(true);												  break;
          case COMMAND_SET_RDP_LEVEL1_AND_BOOTSEL:            SetBootFromFlashAndReadOutProtection();									  break;
          default:                                            printf("UNKNOWN COMMAND\n");
        }
        sys_data.s.parameter.command = 0;
      }
      else
      {
        //printf("wait with execution till modbus communnikation finished\n");
      }
    }
    if((HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET) && (mode_button_disable_time == 0))
    {
      HAL_Delay(10);
      //Taste weiterhin gedrckt?
      if(HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET)
      {
        //Ja, dann Silent Mode umschalten
        mode_button_disable_time=500;
        if (silentmode == 0)
        {
          silentmode = 1;
          HAL_GPIO_WritePin(LED_FUNCTION_GPIO_Port, LED_FUNCTION_Pin,GPIO_PIN_SET);
        }
        else
        {
          silentmode = 0;
        }
       }
    }
    // Modbus Kommunikation
    if (mbGetFrameComplete(&modbusData) == true)
    {
      if (mbSlaveCheckModbusRtuQuery(&modbusData) == RESPOND_TO_QUERY)
      {
          if (silentmode == 0)
          {
            mbSlaveProcessRtuQuery(&modbusData);
          }
      }
      else
      {
        huart1.RxState = HAL_UART_STATE_BUSY_RX;
      }
    }
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);
  /** Configure LSE Drive Capability
  */
  HAL_PWR_EnableBkUpAccess();
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_HIGH);
  HAL_PWR_DisableBkUpAccess();
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1
                              |RCC_PERIPHCLK_ADC;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
  PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLLADC;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}
/* USER CODE BEGIN 4 */
//-----------------------------------------------------------------------------
static void MX_CRC_Init(void)
{
  /* USER CODE BEGIN CRC_Init 0 */
  __HAL_RCC_CRC_CLK_ENABLE();
  /* USER CODE END CRC_Init 0 */
  /* USER CODE BEGIN CRC_Init 1 */
  /* USER CODE END CRC_Init 1 */
  hcrc.Instance = CRC;
  hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
  hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
  hcrc.Init.GeneratingPolynomial = 7;
  hcrc.Init.CRCLength = CRC_POLYLENGTH_8B;
  hcrc.Init.InitValue = 0xFF;
  hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
  hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
  hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
  if (HAL_CRC_Init(&hcrc) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CRC_Init 2 */
  /* USER CODE END CRC_Init 2 */
}
//-----------------------------------------------------------------------------
void SaveCounter(void)
{
	static uint32_t last_days;
	// Converting seconds into days
	uint32_t days = sys_data.s.values.onTime / (24U * 3600U);
	// Alle 24 Stunden führen wir ein Speicherbefehl durch um die Counter zu spiechern
	if (days != last_days)
	{
		last_days = days;
		// Here we can save our counter(s)
		EEPROM_storeConfig(&sys_data, 0);
	}
}
//------------------------------------------------------------------------------
 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
 {
    newADC = 1;
 }
/* USER CODE END 4 */
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  /* USER CODE END Error_Handler_Debug */
}
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/**
  * @brief  Set flash read protection.
  * @param  [in] state: Flash read protection state, true: enable protection, false: disable protection.
  * @retval true:  Successful operation.
  * @retval false: Operation failed.
  */
bool SetFlashReadProtection(bool state)
{
  FLASH_OBProgramInitTypeDef OptionsBytesStruct = {0};
  HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
  if(state == true)
  {
    printf("Start enable readout protection\n");
    if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_0)
    {
      OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
      OptionsBytesStruct.RDPLevel   = OB_RDP_LEVEL_1;
      if (HAL_FLASH_Unlock() != HAL_OK)
      {
        printf("Flash unlock error\n");
      }
      if (HAL_FLASH_OB_Unlock() != HAL_OK)
      {
        printf("Flash ob unlock error\n");
      }
      printf("...Flash unlock\n");
      if(HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
      {
        printf("...Enable lock error\n");
        HAL_FLASH_OB_Lock();
        return false;
      }
      HAL_FLASH_OB_Lock();
      printf("Flash Optionbyte locked\n");
      HAL_FLASH_Lock();
      printf("Flash  locked\n");
      printf("...Enable lock process finished\n");
    }
    else
    {
      printf("...Flash lock already active\n");
    }
  }
  else
  {
    if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_1)
    {
      OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
      OptionsBytesStruct.RDPLevel   = OB_RDP_LEVEL_0;
      if (HAL_FLASH_Unlock() != HAL_OK)
      {
        printf("Flash unlock error\n");
        return false;
      }
      printf("...Flash unlocked\n");
      if (HAL_FLASH_OB_Unlock() != HAL_OK)
      {
        printf("Flash ob unlock error\n");
        return false;
      }
      printf("...Flash ob unlocked\n");
      if(HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
      {
        HAL_FLASH_OB_Lock();
        printf("Flash Optionbyte programm failed\n");
        return false;
      }
      printf("Flash Optionbyte programmed\n");
      HAL_FLASH_OB_Lock();
      printf("Flash Optionbyte locked\n");
      HAL_FLASH_Lock();
      printf("Flash  locked\n");
      printf("...Disable lock process finished\n");
;
    }
  }
  return true;
}
bool SetBootFromFlashAndReadOutProtection(void)
{
  FLASH_OBProgramInitTypeDef OptionsBytesStruct = {0};
  HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
  //Konfiguriere RDP fr Readoutprotection and USER OPTION BYTE FR Boot from Flash
  OptionsBytesStruct.OptionType = OPTIONBYTE_USER | OPTIONBYTE_RDP;
  //Set Readout Protection Level 1
  OptionsBytesStruct.OptionType = OPTIONBYTE_USER|OPTIONBYTE_RDP;
  OptionsBytesStruct.RDPLevel   = OB_RDP_LEVEL_1;
  //Selecting Boot from Main Flash Memory
  OptionsBytesStruct.USERType =    OB_USER_nBOOT0 | OB_USER_nBOOT_SEL | OB_USER_nBOOT1 ;
  OptionsBytesStruct.USERConfig  = OB_USER_nBOOT0 | OB_USER_nBOOT_SEL;
  if (HAL_FLASH_Unlock() != HAL_OK)
  {
    printf("Flash unlock error\n");
  }
  if (HAL_FLASH_OB_Unlock() != HAL_OK)
  {
    printf("Flash ob unlock error\n");
  }
  printf("...Flash unlock\n");
  if(HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
  {
    printf("...Enable lock error\n");
    HAL_FLASH_OB_Lock();
    return false;
  }
  HAL_FLASH_OB_Lock();
  printf("Flash Optionbyte locked\n");
  HAL_FLASH_Lock();
  printf("Flash  locked\n");
  printf("...Enable lock process finished\n");
  return true;
}
uint8_t printprotectionstate(void)
{
  FLASH_OBProgramInitTypeDef OptionsBytesStruct = {0};
  HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
  uint8_t result = 0;
  if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_0)
  {
    //OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
    //OptionsBytesStruct.RDPLevel   = OB_RDP_LEVEL_1;
    printf("PROTECTION: OB_RDP_LEVEL_0\n");
    result = 0;
  }
  else if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_1)
  {
    printf("PROTECTION: OB_RDP_LEVEL_1\n");
    result = 1;
  }
  else if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_2)
  {
    printf("PROTECTION: OB_RDP_LEVEL_2\n");
    result = 2;
  }
  return  result;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/