/*
 * user_flash.c
 *
 *  Created on: May 30, 2018
 *      Author: sparr1
 */
#include "stm32g0xx_hal.h"
#include "ext_var.h"
#include "main.h"
#include "ext_fun.h"
/* Base address of the Flash sectors */

//#define FLASH_USER_START_ADDR   (FLASH_BASE + (4 * FLASH_PAGE_SIZE))   /* Start @ of user Flash area */
//#define FLASH_USER_END_ADDR     (FLASH_BASE + FLASH_SIZE - 1)   /* End @ of user Flash area */
#define FLASH_USER_START_ADDR  0x0801F800
#define FLASH_USER_END_ADDR    0x0801FFFF


#define DATA_64                 ((uint64_t)0x1234567812345678)
#define DATA_32                 ((uint32_t)0x12345678)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/



uint32_t FirstPage = 0, NbOfPages = 0;
uint32_t Address = 0, PageError = 0;
__IO uint32_t data32 = 0 , MemoryProgramStatus = 0;
//static FLASH_EraseInitTypeDef EraseInitStruct = {0};

/*Variable used for Erase procedure*/



/*Variable used for Erase procedure*/
//static FLASH_EraseInitTypeDef EraseInitStruct;


void Internal_Flash_Read(unsigned long int *, unsigned int);
void Write_Params(void);
void Read_Params(void);

//static uint32_t GetPage(uint32_t Addr)
//{
//  return (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;;
//}

void Internal_Flash_Program(unsigned char* FirmwareBytePAcket,unsigned short PacketSize)
{

	unsigned short  PacketLength=0;
	uint64_t   ProgramWord=0;
	//unsigned int   ProgramWord=0;
//	unsigned int    Address=0;
//    unsigned char   ProgramByte=0;
    Address = FLASH_USER_START_ADDR;
    HAL_FLASH_Unlock();

	  FLASH_PageErase(0, 63);
	  CLEAR_BIT(FLASH->CR, FLASH_CR_PER);

     for(PacketLength=0;PacketLength<PacketSize;PacketLength+=8)
     {

    	 ProgramWord=0;
    	 ProgramWord=FirmwareBytePAcket[PacketLength+7] & 0xFF;
    	 ProgramWord<<=8;
    	 ProgramWord|=(FirmwareBytePAcket[PacketLength+6] & 0xFF );
    	 ProgramWord<<=8;
    	 ProgramWord|=(FirmwareBytePAcket[PacketLength+5] & 0xFF);
    	 ProgramWord<<=8;
    	 ProgramWord|=(FirmwareBytePAcket[PacketLength+4] & 0xFF);

    	 ProgramWord<<=8;
    	 ProgramWord|=(FirmwareBytePAcket[PacketLength+3] & 0xFF);
    	 ProgramWord<<=8;
    	 ProgramWord|=(FirmwareBytePAcket[PacketLength+2] & 0xFF);
    	 ProgramWord<<=8;
    	 ProgramWord|=(FirmwareBytePAcket[PacketLength+1] & 0xFF);
    	 ProgramWord<<=8;
    	 ProgramWord|=(FirmwareBytePAcket[PacketLength] & 0xFF);


    	 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, ProgramWord) == HAL_OK)
    	 {
    		 Address = Address + 8;
    	 }
    	 else
    	 {
			  /* Error occurred while writing data in Flash memory.
				 User can add here some code to deal with this error */
			  /*
				FLASH_ErrorTypeDef errorcode = HAL_FLASH_GetError();
			   */
			  Error_Handler();
    	 }

     }
     HAL_FLASH_Lock();
}
//void Internal_Flash_Program(unsigned long int* ram_addr,unsigned int size)
//{
//	unsigned int addr=0,bal_size=0;
//
//
//	  HAL_FLASH_Unlock();
//
//
//	  FLASH_PageErase(0, 63);
//	  CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
////	  /* Fill EraseInit structure*/
////	  EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
////	  EraseInitStruct.Page        = FirstPage;
////	  EraseInitStruct.NbPages     = NbOfPages;
////
////	  /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
////	     you have to make sure that these data are rewritten before they are accessed during code
////	     execution. If this cannot be done safely, it is recommended to flush the caches by setting the
////	     DCRST and ICRST bits in the FLASH_CR register. */
////	  if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
////	  {
////	    /*
////	      Error occurred while page erase.
////	      User can add here some code to deal with this error.
////	      PageError will contain the faulty page and then to know the code error on this page,
////	      user can call function 'HAL_FLASH_GetError()'
////	    */
////	    /* Infinite loop */
////	    while (1)
////	    {
////	      /* Make LED4 blink (100ms on, 2s off) to indicate error in Erase operation */
////	    	LED1R_ON;
////	    }
////	  }
//
//
//	  Address = FLASH_USER_START_ADDR;
//
//
//		bal_size=size%8;
//		if(bal_size) size=size+bal_size;
//
//
//	  while (Address < FLASH_USER_END_ADDR)
//	  {
//
//
//		  if(addr>=(size/8))break;
//	    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, *ram_addr++) == HAL_OK)
//	    {
//	      Address = Address + 4;
//	      addr++;
//	    }
//	   else
//	    {
//	       Error occurred while writing data in Flash memory.
//	         User can add here some code to deal with this error
//
//	    }
//	  }
//
//	   Lock the Flash to disable the flash control register access (recommended
//	     to protect the FLASH memory against possible unwanted operation) ********
//	  HAL_FLASH_Lock();
//	unsigned int addr=0,bal_size;
////	char buff[50];
//
//	 Unlock the Flash to enable the flash control register access ************
//	HAL_FLASH_Unlock();
//	 Erase the user Flash area
//    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) **********
////FLASH_Erase_Sector(FLASH_SECTOR_11,VOLTAGE_RANGE_3);
//
//	 Program the user Flash area word by word
//    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) **********
//
//	bal_size=size%4;
//	if(bal_size) size=size+bal_size;
//
//	Address = FLASH_USER_START_ADDR;
//
//	while (Address < FLASH_USER_END_ADDR)
//	{
//		if(addr>=(size/4))break;
//		if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, Address, *ram_addr++) == HAL_OK)
//		{
//			Address = Address + 4;
//			addr++;
//		}
//		else
//		{
//			 Error occurred while writing data in Flash memory.
//         	 User can add here some code to deal with this error
//			while (1)
//			{
//				//HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
////				  sprintf(buff,"internal flash error.....\r\n");
////					HAL_UART_Transmit(&huart6, (uint8_t*)buff, strlen(buff),500);
//			}
//		}
//	}
//	HAL_FLASH_Lock();
//}
void Internal_Flash_Read(unsigned long int * addr_toread, unsigned int size)
{
	unsigned int addr=0,bal_size;

	bal_size=size%4;
	if(bal_size)
	size=size+bal_size;

	Address = FLASH_USER_START_ADDR;
	MemoryProgramStatus = 0x0;

	while (Address < FLASH_USER_END_ADDR)
	{
		if(addr>=(size/4))break;
		*addr_toread = *(__IO uint32_t *)Address;
		addr_toread++;addr++;
	    Address = Address + 4;
	}
}
void Read_Params(void)
{
	Internal_Flash_Read((unsigned long int*)&configparameters, sizeof(struct configuration_para));

//	if(configparameters.magic_value!=0xAA55)
//	{
//		configparameters = default_params;
//	}
//	else
//	{
//		OCPP=OCPP;
//	}
}
void Write_Params(void)
{
	Internal_Flash_Program((unsigned char*)&configparameters, sizeof(struct configuration_para));
}

