/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"
#include "rtc.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "stdint.h"
#include "stdbool.h"

#include "stm32f1xx_hal.h"
#include "modDelay.h"
#include "modFlash.h"
//#include "DPC_Timeout.h"
#include "fatfs.h"
#include "generalDefines.h"
#include "libBuffer.h"
#include "libCRC.h"


#define LoByte(param) ((uint8_t *)&param)[0]
#define HiByte(param) ((uint8_t *)&param)[1]

#define LoLoWord(param) ((uint16_t *)&param)[0]
#define LoHiWord(param) ((uint16_t *)&param)[1]
#define HiLoWord(param) ((uint16_t *)&param)[2]
#define HiHiWord(param) ((uint16_t *)&param)[3]

#define LoWord(param) ((uint32_t *)&param)[0]
#define HiWord(param) ((uint32_t *)&param)[1]

#define __DEEP_DISCHARGE_RATIO	0.8						//As a percent of undervoltage
#define __STATUS_POWER_ON 1
#define __STATUS_POWER_OFF 2
#define __STATUS_CHARGE_ON 3							//Pilot contact exist
#define __STATUS_CELL_UNDERVOLTAGE 4					//Cell below discharge level
#define __STATUS_OVERLOAD 5								//Load current too high
#define __STATUS_OVERHEATING 6							//Temp too high
#define __STATUS_CHARGING_OVERVOLTAGE 7					//Cell voltage above max level
#define __STATUS_CHARGING_DISCONNECT 8					//Pilot contact disconnect
#define __STATUS_HEATING_ON 9							//
#define __STATUS_HEATING_OFF 10							//
#define __STATUS_TAKE_BRUSH 11							//Brush is in the upper state
#define __STATUS_ERROR_1 12
#define __STATUS_ERROR_2 13

#define __GLSTATUS_SHUTDOWN 1
#define __GLSTATUS_IDLE 2
#define __GLSTATUS_WORKING 3
#define __GLSTATUS_CHARGING 4
#define __GLSTATUS_ERROR 5


#define __DEFAULT_BATTERY_RESISTANCE 0.0
#define __BACKUP_TIMEOUT 30000
#define __GRT_PERIOD 600000//3600000
#define __DELAY_FOR_SIM 30000
//#define __GRT_PERIOD 600000

#define _ON 1
#define _OFF 0

#define __BLINK_INIT 			1000
#define __BLINK_GSM_AND_SD_OK 	500
#define __BLINK_SD_OK_NO_GSM 	250
#define __BLINK_GSM_OK_NO_SD 	750
#define __BLINK_ERROR			100

#define __SD_BUFFER_MAX_VAL		8
#define __SS_BUFFER_MAX_VAL		8

#define __FILENAME_UPDATE_TIMEOUT 10000


__IO uint8_t USB_On_Flag;

__IO uint32_t SS_status_ptr;

__IO uint64_t _global_clock;


SPI_HandleTypeDef hspi1;

TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim6;

#define __MA_WIN_SIZE (500)
#define __MA_ARRAY_QTY 2

uint32_t SD_Storage_Switch;

typedef enum {
	BOOT_INIT = 0,
	BOOT_DELAY,
	BOOT_SIZE_CHECK,
	BOOT_SIZE_ZERO,
	BOOT_SIZE_WRONG,
  BOOT_SIZE_OK,
	BOOT_CRC_CHECK,
	BOOT_CRC_OK,
	BOOT_CRC_ERROR,
	BOOT_ERASE,
	BOOT_ERASE_ERROR,
	BOOT_ERASE_SUCCES,
	BOOT_COPYAPP,
	BOOT_COPYAPP_ERROR,
	BOOT_COPYAPP_SUCCES,
	BOOT_DONE,
	BOOT_REBOOT,
	BOOT_ERROR
} bootLoaderState;

uint8_t   bootloaderStateCurrent;
uint8_t   bootloaderStateNext;
uint32_t  bootloaderDelayLastTick;
uint32_t  bootloaderDelayTime;
uint8_t*  newAppAdress;
uint32_t  newAppSize;
uint32_t  newAppCRC;
int32_t   indexPointer;
uint8_t   yAxisOffset;

/* Private function prototypes -----------------------------------------------*/
void Total_DeInit();
void SystemClock_Config(void);
static void MX_GPIO_Init(void);


static void MX_SPI1_Init(void);
static void MX_TIM6_Init(void);
static void MX_TIM2_Init(void);

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//	testsi++;


  if (htim->Instance == TIM2)
    {
  	  TimeoutMng();
  	  _global_clock++;
    }
  else if (htim->Instance == TIM6)
    {

    }
}
/* USER CODE END 0 */


IWDG_HandleTypeDef handleIWDG;

void mainWatchDogReset(void) {

	HAL_IWDG_Refresh(&handleIWDG);

}
void mainWatchDogInitAndStart(void) {


  handleIWDG.Instance = IWDG;
  handleIWDG.Init.Prescaler = IWDG_PRESCALER_64;
 // handleIWDG.Init.Window = 4095;
  handleIWDG.Init.Reload = 4095;
  if (HAL_IWDG_Init(&handleIWDG) != HAL_OK) {
    Error_Handler();
  }
//  HAL_IWDG_
//  if(HAL_IWDG_Start(&handleIWDG) != HAL_OK) {
//    Error_Handler();
//  }

}

void heart_beat(){
	static uint32_t timer = 0;
	if(( (HAL_GetTick()) - timer ) > __BLINK_SD_OK_NO_GSM) {
		  //HAL_GPIO_TogglePin(HL3_GPIO_Port, HL3_Pin);
		  HAL_GPIO_TogglePin(HL3_GPIO_Port, HL5_Pin);
		//  HAL_GPIO_TogglePin(HL3_GPIO_Port, HL1_Pin);
		  //HAL_GPIO_TogglePin(HL2_GPIO_Port, HL2_Pin);
		  timer = HAL_GetTick();
	}
}

void Total_DeInit(){
	MX_FATFS_DeInit();
	HAL_TIM_Base_DeInit(&htim2);
	HAL_TIM_Base_DeInit(&htim6);
	MX_USB_DEVICE_DeInit();
	//HAL_UART_DeInit(&huart2);
	HAL_SPI_DeInit(&hspi1);
	//HAL_SPI_DeInit(&hspi3);
	//HAL_DAC_DeInit(&hdac);
	//HAL_ADC_DeInit(&hadc2);
	HAL_RTC_DeInit(&hrtc);

	  __HAL_RCC_GPIOE_CLK_DISABLE();
	  __HAL_RCC_GPIOC_CLK_DISABLE();
	  __HAL_RCC_GPIOA_CLK_DISABLE();
	  __HAL_RCC_GPIOB_CLK_DISABLE();
	  __HAL_RCC_GPIOD_CLK_DISABLE();
}




int main(void)
{

	/* USER CODE BEGIN 1 */
	SCB->VTOR = ADDR_FLASH_PAGE_104;
	/* 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();
	//  modFlashJumpToBootloader();
	//jumpToBootLoader();

	//HAL_Delay(2000);

	/* USER CODE BEGIN SysInit */

	/* USER CODE END SysInit */

	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	//  HAL_GPIO_WritePin(GSM_RST_GPIO_Port, GSM_RST_Pin, GPIO_PIN_RESET);

	HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_SET);
	HAL_Delay(200);
	HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_RESET);
	HAL_Delay(200);
	HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_SET);
	HAL_Delay(200);
	HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_RESET);
	HAL_Delay(200);

	yAxisOffset			   = 0;
	newAppAdress           = (uint8_t*)ADDR_FLASH_PAGE_52;
	indexPointer           = 0;
	newAppSize             = buffer_get_uint32(newAppAdress, &indexPointer);
	newAppCRC              = buffer_get_uint16(newAppAdress, &indexPointer);
	bootloaderStateCurrent = BOOT_INIT;
	bootloaderStateNext    = BOOT_INIT;
	bootloaderDelayTime    = 100;

	//	jumpToBootLoader();

	MX_RTC_Init();

	SD_Storage_Switch = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR11);

	//SD_Storage_Switch=1;

	if (SD_Storage_Switch){
		MX_SPI1_Init();
		MX_USB_DEVICE_Init();
		MX_FATFS_Init();
		MX_TIM6_Init();
		MX_TIM2_Init();
	}


	//  MX_SPI3_Init();





	//jumpToBootLoader();// here it works
  /* USER CODE BEGIN 2 */



  /* USER CODE BEGIN WHILE */

	bootloaderDelayLastTick = HAL_GetTick();

	while (1)
	{


		if (SD_Storage_Switch){
			heart_beat();
		}
		else {
			switch(bootloaderStateCurrent) {
				case BOOT_INIT:
	//			  modDisplayShowInfo(DISP_MODE_BOOTLOADER,emptyData);
					HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
				  bootloaderDelayTime    = 200;
				  bootloaderStateCurrent = BOOT_DELAY;
				  bootloaderStateNext    = BOOT_SIZE_CHECK;
					break;
				case BOOT_DELAY:
					if(modDelayTick1ms(&bootloaderDelayLastTick,bootloaderDelayTime))
						bootloaderStateCurrent = bootloaderStateNext;
					break;
				case BOOT_SIZE_CHECK:
					HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_RESET);

					if(newAppSize == 0)
						bootloaderStateNext = BOOT_SIZE_ZERO;
					else if(newAppSize > NEW_APP_MAX_SIZE)
						bootloaderStateNext = BOOT_SIZE_WRONG;
					else
						bootloaderStateNext = BOOT_SIZE_OK;


				  bootloaderDelayTime    = 100;
				  bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_SIZE_ZERO:
					bootloaderStateNext    = BOOT_REBOOT;

				  bootloaderDelayTime    = 100;
				  bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_SIZE_WRONG:
					bootloaderStateNext    = BOOT_REBOOT;

					bootloaderDelayTime    = 100;
				  bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_SIZE_OK:
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
					bootloaderDelayTime    = 1000;
					bootloaderStateNext    = BOOT_CRC_CHECK;
					bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_CRC_CHECK:
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);

					if(newAppCRC != libCRCCalcCRC16(newAppAdress + indexPointer, newAppSize))
						bootloaderStateNext = BOOT_CRC_ERROR;
					else
						bootloaderStateNext = BOOT_CRC_OK;

					bootloaderDelayTime    = 100;
					bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_CRC_OK:
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
					bootloaderDelayTime    = 1000;
					bootloaderStateNext    = BOOT_ERASE;
					bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_CRC_ERROR:

					bootloaderStateNext    = BOOT_REBOOT;

					bootloaderDelayTime    = 100;
				  bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_ERASE:
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
					// Code to erasing main flash
					if(modFlashEraseMainAppData() == HAL_OK)
						bootloaderStateNext    = BOOT_ERASE_SUCCES;
					else
						bootloaderStateNext    = BOOT_ERASE_ERROR;

					bootloaderDelayTime    = 100;
				  bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_ERASE_ERROR:
					HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_SET);

					bootloaderStateNext    = BOOT_ERROR;

					bootloaderDelayTime    = 1000;
				  bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_ERASE_SUCCES:
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
					bootloaderStateNext    = BOOT_COPYAPP;
					//bootloaderStateNext = BOOT_DELAY;
					bootloaderDelayTime    = 1000;
					bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_COPYAPP:
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);
					// Code to copy new app to main flash
					if(modFlashCopyNewAppToMainApp(0, newAppAdress + indexPointer, newAppSize) == HAL_OK){
						bootloaderStateNext    = BOOT_COPYAPP_SUCCES;
					}
					else{
						bootloaderStateNext    = BOOT_COPYAPP_ERROR;
					}


					bootloaderDelayTime    = 100;
					bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_COPYAPP_ERROR:
					HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_RESET);
					bootloaderStateNext    = BOOT_ERROR;
					bootloaderDelayTime    = 1000;
					bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_COPYAPP_SUCCES:
					HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_SET);

					modFlashEraseNewAppData();
					modFlashEraseSettingsData();

					bootloaderStateNext    = BOOT_DONE;

					bootloaderDelayTime    = 1000;
					bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_DONE:
					HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_RESET);

					bootloaderStateNext    = BOOT_REBOOT;

					bootloaderDelayTime    = 5000;
				    bootloaderStateCurrent = BOOT_DELAY;
					break;
				case BOOT_REBOOT:
					jumpToMainApplication();
					break;
				case BOOT_ERROR:

					HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_SET);

					// Do nothing but keep showing error.
					bootloaderStateNext    = BOOT_INIT;
					bootloaderDelayTime    = 5000;
					bootloaderStateCurrent = BOOT_DELAY;
					break;
				default:
					break;
			}
		}
	}
  /* 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};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV5;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_PLL2;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL2_ON;
  RCC_OscInitStruct.PLL2.PLL2MUL = RCC_PLL2_MUL8;
  RCC_OscInitStruct.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV5;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC
                              |RCC_PERIPHCLK_USB;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV3;




  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the Systick interrupt time
  */
  __HAL_RCC_PLLI2S_ENABLE();
}

static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 71;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

static void MX_TIM6_Init(void)
{

  /* USER CODE BEGIN TIM6_Init 0 */

  /* USER CODE END TIM6_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM6_Init 1 */

  /* USER CODE END TIM6_Init 1 */
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 71;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 999;
  htim6.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM6_Init 2 */

  /* USER CODE END TIM6_Init 2 */

}



/**
  * @brief SPI1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOE, Output_2_Pin|Output_3_Pin|Output_4_Pin|Output_5_Pin
                          |GSM_RST_Pin|HL4_Pin|HL5_Pin|HL3_Pin|HL2_Pin|Output_0_Pin
                          |Output_1_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(SPI3_CS_GPIO_Port, SPI3_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(Charging_GPIO_Port, Charging_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : Output_2_Pin Output_3_Pin Output_4_Pin Output_5_Pin
                           HL3_Pin HL2_Pin Output_0_Pin Output_1_Pin */
  GPIO_InitStruct.Pin = Output_2_Pin|Output_3_Pin|Output_4_Pin|Output_5_Pin
		  |HL5_Pin|HL3_Pin|HL4_Pin|HL2_Pin|Output_0_Pin|Output_1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pin : PE6 */
  GPIO_InitStruct.Pin = GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pin : SD_CD_Pin */
  GPIO_InitStruct.Pin = SD_CD_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(SD_CD_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : SPI3_CS_Pin */
  GPIO_InitStruct.Pin = SPI3_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(SPI3_CS_GPIO_Port, &GPIO_InitStruct);

//	GPIO_InitStruct.Pin = LTC6804_CS_Pin;
//GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
//GPIO_InitStruct.Pull = GPIO_NOPULL;
//GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
//GPIO_InitStruct.Alternate = 0;
//HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : Input_1_Pin Input_2_Pin Input_3_Pin */
  GPIO_InitStruct.Pin = Input_1_Pin|Input_2_Pin|Input_3_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pin : GSM_RST_Pin */
  GPIO_InitStruct.Pin = GSM_RST_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GSM_RST_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : SD_CS_Pin */
  GPIO_InitStruct.Pin = SD_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(SD_CS_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : Charging_Pin */
  GPIO_InitStruct.Pin = Charging_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(Charging_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

void jumpToMainApplication(void) {
	HAL_RCC_DeInit();
	HAL_DeInit();
	SysTick->CTRL = 0;
	SysTick->LOAD = 0;
	SysTick->VAL = 0;
	NVIC_SystemReset();
}

/* 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 */
  __disable_irq();
  while (1)
  {

  }
  /* 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,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
