/**
  ******************************************************************************
  * @file    openbootloader.c
  * @author  MCD Application Team
  * @brief   OpenBootloader application entry point
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 Puya Semiconductor Co.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by Puya 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
  *
  ******************************************************************************
  */

#include "main.h"

#include "openbootloader.h"

#include "interface_conf.h"
#include "openbl_mem.h"
#include "openbl_core.h"

#if IO_INTERFACE_IWDG
  extern OPENBL_HandleTypeDef IWDG_Handle;
#endif /* IO_INTERFACE_IWDG */

#if IO_INTERFACE_WWDG
  extern OPENBL_HandleTypeDef WWDG_Handle;
#endif /* IO_INTERFACE_WWDG */

#if IO_INTERFACE_USART1
  extern OPENBL_HandleTypeDef USART1_Handle;
#endif /* IO_INTERFACE_USART1 */

#if IO_INTERFACE_USART2
  extern OPENBL_HandleTypeDef USART2_Handle;
#endif /* IO_INTERFACE_USART2 */

#if IO_INTERFACE_USART3
  extern OPENBL_HandleTypeDef USART3_Handle;
#endif /* IO_INTERFACE_USART3 */

#if IO_INTERFACE_I2C2
  extern OPENBL_HandleTypeDef I2C2_Handle;
#endif /* IO_INTERFACE_I2C2 */

#if IO_INTERFACE_I2C3
  extern OPENBL_HandleTypeDef I2C3_Handle;
#endif /* IO_INTERFACE_I2C3 */

#if IO_INTERFACE_I2C4
  extern OPENBL_HandleTypeDef I2C4_Handle;
#endif /* IO_INTERFACE_I2C4 */

#if IO_INTERFACE_SPI1
  extern OPENBL_HandleTypeDef SPI1_Handle;
#endif /* IO_INTERFACE_SPI1 */

#if IO_INTERFACE_SPI2
  extern OPENBL_HandleTypeDef SPI2_Handle;
#endif /* IO_INTERFACE_SPI2 */

#if IO_INTERFACE_USB1
  extern OPENBL_HandleTypeDef USB1_Handle;
#endif /* IO_INTERFACE_USB1 */


extern OPENBL_MemoryTypeDef FLASH_Descriptor;
extern OPENBL_MemoryTypeDef RAM_Descriptor;
extern OPENBL_MemoryTypeDef SYS_Descriptor;
extern OPENBL_MemoryTypeDef OTP_Descriptor;
extern OPENBL_MemoryTypeDef OB_Descriptor;
extern OPENBL_MemoryTypeDef FAC_Descriptor;

static uint32_t interface_detected = 0;

/**
  * @brief  Initialize open Bootloader.
  * @param  None.
  * @retval None.
  */
void OpenBootloader_Init(void)
{
  #if IO_INTERFACE_WWDG
  OPENBL_RegisterInterface(&WWDG_Handle);
  #endif /* IO_INTERFACE_WWDG */

  #if IO_INTERFACE_IWDG
  OPENBL_RegisterInterface(&IWDG_Handle);
  #endif /* IO_INTERFACE_IWDG */

  #if IO_INTERFACE_USART1
  OPENBL_RegisterInterface(&USART1_Handle);
  #endif /* IO_INTERFACE_USART1 */

  #if IO_INTERFACE_USART2
  OPENBL_RegisterInterface(&USART2_Handle);
  #endif /* IO_INTERFACE_USART2 */

  #if IO_INTERFACE_USART3
  OPENBL_RegisterInterface(&USART3_Handle);
  #endif /* IO_INTERFACE_USART3 */

  #if IO_INTERFACE_I2C2
  OPENBL_RegisterInterface(&I2C2_Handle);
  #endif /* IO_INTERFACE_I2C2 */

  #if IO_INTERFACE_I2C3
  OPENBL_RegisterInterface(&I2C3_Handle);
  #endif /* IO_INTERFACE_I2C3 */

  #if IO_INTERFACE_I2C4
  OPENBL_RegisterInterface(&I2C4_Handle);
  #endif /* IO_INTERFACE_I2C4 */

  #if IO_INTERFACE_SPI1
  OPENBL_RegisterInterface(&SPI1_Handle);
  #endif /* IO_INTERFACE_SPI1 */

  #if IO_INTERFACE_SPI2
  OPENBL_RegisterInterface(&SPI2_Handle);
  #endif /* IO_INTERFACE_SPI2 */

  #if IO_INTERFACE_USB1
  /* Register USB interfaces */
  OPENBL_RegisterInterface(&USB1_Handle);
  #endif /* IO_INTERFACE_USB1 */


  /* Initialise interfaces */
  OPENBL_Init();

  /* Initialise memories */
  OPENBL_MEM_RegisterMemory(&FLASH_Descriptor);
  OPENBL_MEM_RegisterMemory(&RAM_Descriptor);
  OPENBL_MEM_RegisterMemory(&SYS_Descriptor);
  OPENBL_MEM_RegisterMemory(&OTP_Descriptor);
  OPENBL_MEM_RegisterMemory(&OB_Descriptor);
  OPENBL_MEM_RegisterMemory(&FAC_Descriptor);
}

/**
  * @brief  DeInitialize open Bootloader.
  * @param  None.
  * @retval None.
  */
void OpenBootloader_DeInit(void)
{
  RCC_OscInitTypeDef  OscInitstruct = {0};
  RCC_ClkInitTypeDef  ClkInitstruct = {0};

  if(interface_detected == 0)
  {
    OPENBL_DeInit();
  }
  else
  {
    OPENBL_DeInit_Actice();
  }

  ClkInitstruct.ClockType       = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  ClkInitstruct.SYSCLKSource    = RCC_SYSCLKSOURCE_HSI;              /* System clock selection PLL */
  ClkInitstruct.AHBCLKDivider   = RCC_SYSCLK_DIV1;                      /* AHB clock 1 division */
  ClkInitstruct.APB1CLKDivider  = RCC_HCLK_DIV1;                        /* APB1 clock 1 division */
  ClkInitstruct.APB2CLKDivider  = RCC_HCLK_DIV2;                        /* APB2 clock 2 division */

  /* Configure Clock */
  if(HAL_RCC_ClockConfig(&ClkInitstruct, FLASH_LATENCY_0) != HAL_OK)
  {
    HAL_NVIC_SystemReset();
  }

  OscInitstruct.OscillatorType  = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSI48M;
  OscInitstruct.HSEState        = RCC_HSE_OFF;                              /* Close HSE */
  /* OscInitstruct.HSEFreq         = RCC_HSE_16_32MHz; */                     /* Choose HSE frequency of 16-32MHz */
  OscInitstruct.HSI48MState     = RCC_HSI48M_OFF;                            /* Close HSI48M */
  OscInitstruct.HSIState        = RCC_HSI_ON;                               /* Enable HSI */
  OscInitstruct.LSEState        = RCC_LSE_OFF;                              /* Close LSE */
  /* OscInitstruct.LSEDriver       = RCC_LSEDRIVE_HIGH; */                    /* Drive capability level: high */
  OscInitstruct.LSIState        = RCC_LSI_OFF;                              /* Close LSI */
  OscInitstruct.PLL.PLLState    = RCC_PLL_OFF;                               /* Open PLL */
  OscInitstruct.PLL.PLLSource   = RCC_PLLSOURCE_HSI_DIV2;                   /* PLL clock source selection HSI/2 */
  OscInitstruct.PLL.PLLPrediv   = RCC_PLL_PREDIV_DIV1;                      /* PLL clock Prediv factor */
  OscInitstruct.PLL.PLLMUL      = 9;                                        /* PLL clock source 12-fold frequency */
  OscInitstruct.PLL.PLLPostdiv  = RCC_PLL_POSTDIV_DIV1;                     /* PLL clock Postdiv factor */

  /* Configure oscillator */
  if(HAL_RCC_OscConfig(&OscInitstruct) != HAL_OK)
  {
    HAL_NVIC_SystemReset();
  }

  HAL_DeInit();
}

/**
  * @brief  This function is used to select which protocol will be used when communicating with the host.
  * @param  None.
  * @retval None.
  */
void OpenBootloader_ProtocolDetection(void)
{
  if (interface_detected == 0)
  {
    interface_detected = OPENBL_InterfaceDetection();
  }

  if (interface_detected == 1)
  {
    OPENBL_ProtocolProcess();
  }
}

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