//-----------------------------------------------------------------------------
///
/// \brief  Intern EEPROM
///
///         Access to internal eeprom.
///
/// \date   20211214
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//-----------------------------------------------------------------------------


//---Includes------------------------------------------------------------------


//---Own------------------------------

#include <lepto/log.h>
#include <biwak/biwak.h>            // exception
#include <biwak/exception.h>
#include <biwak/eeprom_intern.h>
#include <HALWrapper/stm32_eeprom.h>
#include <string.h>                 // memcpy
#include <biwak/systick.h>          // usleep


//---Implementation------------------------------------------------------------

#if ! defined(DATA_EEPROM_BASE)
   #define DATA_EEPROM_BASE      0x08080000
   #define DATA_EEPROM_END       0x08080FFF
#endif

#if ! defined(FLASH_SR_BSY)
   // STM32G0 has an BSY1
   #define FLASH_SR_BSY FLASH_SR_BSY1
#endif

#if defined(DATA_EEPROM_BASE)


CEepromIntern::CEepromIntern( )
         :CFlash( (address_t)DATA_EEPROM_BASE, (size_t)( ( DATA_EEPROM_END - DATA_EEPROM_BASE ) + 1 ) )
{
   init();
#if IS_ENABLED( CONFIG_BIWAK_MEMORY_MAPPED_FLASH )
   setMemoryMapped();
   #else
      // BIWAK_MEMORY_MAPPED_FLASH must be set
      lFatal("BWK MMF NS");
   #endif
   // Must be aligned
   lAssert( ((address_t)getStartAddress() % (address_t)erasePageSize()) == 0 );

   return;
}

CEepromIntern::~CEepromIntern( )
{
   return;
}

void CEepromIntern::init()
{
   // Internal flash does not need to be initialized, you are probably already
   // running on it
   #if defined(__HAL_RCC_EEPROM_CLK_ENABLE)
      __HAL_RCC_EEPROM_CLK_ENABLE();
   #endif
   //setNVInterrupt( EEPROM_IRQn , true, NVI_DEFAULT_PRIORITY);
   //__HAL_FLASH_CLEAR_FLAG( FLASH_FLAG_OPTVERR | FLASH_FLAG_PGSERR );

   return;
}

int CEepromIntern::writeData(address_t address, const void *data, int size)
{
   lDebug ("### Write: 0x%X; %d bytes", address, size);
   int sta=0;
   memcpy((void *)address, data, size);
   return(sta);
}

int CEepromIntern::readData(address_t address, void *data, int size)
{
   lDebug ("### Read: 0x%X", address);
   memcpy(data, (void *)address, size);
   return(0);
}

//extern "C" void usleep(int val);
int CEepromIntern::erasePage(address_t page, int count)
{
   static bool keysWritten=false;
   if(!keysWritten)
   {
      // unlock data eeprom memory and registers
      #if defined ( STM32L4 ) || defined ( STM32G4 )
         FLASH->PDKEYR = 0x89ABCDEF; // FLASH_PEKEY1
         FLASH->PDKEYR = 0x02030405; // FLASH_PEKEY2
      #elif defined ( STM32G0 ) || ( STM32G4 ) || defined ( STM32F0 )
      #elif defined ( STM32F1 ) || defined ( STM32F3 )
         FLASH->KEYR = 0x89ABCDEF;
         FLASH->KEYR = 0x02030405;
      #else
         FLASH->PEKEYR = 0x89ABCDEF; // FLASH_PEKEY1
         FLASH->PEKEYR = 0x02030405; // FLASH_PEKEY2
      #endif
      //FLASH->PRGKEYR = 0x8C9DAEBF;
      //FLASH->PRGKEYR = 0x13141516;
      keysWritten=true;
   }

   #pragma GCC diagnostic push
   #pragma GCC diagnostic ignored "-Wvolatile"

   // only auto-erase if neccessary (when content is non-zero)
   #if defined(STM32L0)
   FLASH->PECR &= ~FLASH_PECR_FIX; // clear FIX
   #elif defined(STM32L1)
   FLASH->PECR &= ~FLASH_PECR_FTDW; // clear FTDW
   #endif

   #pragma GCC diagnostic pop

   usleep(1000);
   return(0);
}

void CEepromIntern::lock() const
{
   // check for end of programming
   while( FLASH->SR & FLASH_SR_BSY )
   {}; // loop while busy

   #pragma GCC diagnostic push
   #pragma GCC diagnostic ignored "-Wvolatile"

   #if defined(STM32L4) || defined ( STM32G4 ) || defined ( STM32F0 )
      // Dont know what to do
   #elif defined ( STM32F1 ) || defined ( STM32F3 ) || defined ( STM32G0 )
      FLASH->CR |= FLASH_CR_LOCK;
   #else
      // lock data eeprom memory and registers
      FLASH->PECR |= FLASH_PECR_PELOCK;
   #endif

   #pragma GCC diagnostic pop
}

#if 0
IRQ_Funcion_imp ( FLASH_IRQHandler )
{
   HAL_FLASH_IRQHandler();

   return;
}
#endif

#endif

//---fin-----------------------------------------------------------------------
