// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_boot/boot.h"

#include <array>

#include "FreeRTOS.h"
#include "pw_boot_cortex_m/boot.h"
#include "pw_malloc/malloc.h"
#include "pw_preprocessor/compiler.h"
#include "pw_string/util.h"
#include "pw_sys_io_stm32cube/init.h"
#include "pw_system/init.h"
#include "stm32f7xx.h"
#include "task.h"

namespace {

std::array<StackType_t, configMINIMAL_STACK_SIZE> freertos_idle_stack;
StaticTask_t freertos_idle_tcb;

std::array<StackType_t, configTIMER_TASK_STACK_DEPTH> freertos_timer_stack;
StaticTask_t freertos_timer_tcb;

std::array<char, configMAX_TASK_NAME_LEN> temp_thread_name_buffer;

RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {
    .PeriphClockSelection = RCC_PERIPHCLK_CLK48,
    .PLLI2S = {},
    .PLLSAI =
        {
            .PLLSAIN = 192,
            .PLLSAIQ = 4,
            .PLLSAIR = 0,
            .PLLSAIP = RCC_PLLSAIP_DIV4,
        },
    .PLLI2SDivQ = 0,
    .PLLSAIDivQ = 0,
    .PLLSAIDivR = 0,
    .RTCClockSelection = 0,
    .I2sClockSelection = 0,
    .TIMPresSelection = 0,
    .Sai1ClockSelection = 0,
    .Sai2ClockSelection = 0,
    .Usart1ClockSelection = 0,
    .Usart2ClockSelection = 0,
    .Usart3ClockSelection = 0,
    .Uart4ClockSelection = 0,
    .Uart5ClockSelection = 0,
    .Usart6ClockSelection = 0,
    .Uart7ClockSelection = 0,
    .Uart8ClockSelection = 0,
    .I2c1ClockSelection = 0,
    .I2c2ClockSelection = 0,
    .I2c3ClockSelection = 0,
    .I2c4ClockSelection = 0,
    .Lptim1ClockSelection = 0,
    .CecClockSelection = 0,
    .Clk48ClockSelection = RCC_CLK48SOURCE_PLLSAIP,
    .Sdmmc1ClockSelection = 0,
    .Sdmmc2ClockSelection = 0,
    .Dfsdm1ClockSelection = 0,
    .Dfsdm1AudioClockSelection = 0,
};

} // namespace

extern "C" {

// Initializes clock to its max, 180Mhz. Note that this naming follows CubeMX's
// naming out of convention. It's not required that this target provides a
// symbol named SystemClock_Config. This function shares the same purpose as
// the symbol of the same name that is generated by CubeMX.
void SystemClock_Config() {
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  RCC_OscInitTypeDef RCC_OscInitStruct = {
      .OscillatorType = RCC_OSCILLATORTYPE_HSE,
      .HSEState = RCC_HSE_ON,
      .LSEState = RCC_LSE_OFF,
      .HSIState = RCC_HSI_OFF,
      .HSICalibrationValue = 0x0,
      .LSIState = RCC_LSI_OFF,
      .PLL =
          {
              .PLLState = RCC_PLL_ON,
              .PLLSource = RCC_PLLSOURCE_HSE,
              .PLLM = 25,
              .PLLN = 400,
              .PLLP = RCC_PLLP_DIV2,
              .PLLQ = 8,
              .PLLR = 7,
          },
  };

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
    pw_boot_PostMain();
  }

  // OverDrive required for operation > 168Mhz
  if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
    pw_boot_PostMain();
  }

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
    pw_boot_PostMain();
  }

  RCC_ClkInitTypeDef RCC_ClkInitStruct = {
      .ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
                    RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2),
      .SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK,
      .AHBCLKDivider = RCC_SYSCLK_DIV1,
      .APB1CLKDivider = RCC_HCLK_DIV4,
      .APB2CLKDivider = RCC_HCLK_DIV2,
  };

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6) != HAL_OK) {
    pw_boot_PostMain();
  }
}

// Functions needed when configGENERATE_RUN_TIME_STATS is on.
void configureTimerForRunTimeStats(void) {}
unsigned long getRunTimeCounterValue(void) { return uwTick; }

// Required for configCHECK_FOR_STACK_OVERFLOW.
void vApplicationStackOverflowHook(TaskHandle_t, char *pcTaskName) {
  pw::string::Copy(pcTaskName, temp_thread_name_buffer);
  PW_CRASH("Stack OVF for task %s", temp_thread_name_buffer.data());
}

// Required for configUSE_TIMERS.
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                    StackType_t **ppxTimerTaskStackBuffer,
                                    uint32_t *pulTimerTaskStackSize) {
  *ppxTimerTaskTCBBuffer = &freertos_timer_tcb;
  *ppxTimerTaskStackBuffer = freertos_timer_stack.data();
  *pulTimerTaskStackSize = freertos_timer_stack.size();
}

void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
                                   StackType_t **ppxIdleTaskStackBuffer,
                                   uint32_t *pulIdleTaskStackSize) {
  *ppxIdleTaskTCBBuffer = &freertos_idle_tcb;
  *ppxIdleTaskStackBuffer = freertos_idle_stack.data();
  *pulIdleTaskStackSize = freertos_idle_stack.size();
}

void pw_boot_PreStaticMemoryInit() {}

void pw_boot_PreStaticConstructorInit() {
  // Provided by STMicroelectronics SDK. Can be configured to be provided
  // elsewhere by changing pw_third_party_stm32cube_CMSIS_INIT.
  SystemInit();

  // Provided by the STMicroelectronics SDK.
  HAL_Init();

  // Typically provided by CubeMX codegen, SystemClock_Config() is instead
  // provided as part of this target.
  SystemClock_Config();

#if PW_MALLOC_ACTIVE
  pw_MallocInit(&pw_boot_heap_low_addr, &pw_boot_heap_high_addr);
#endif // PW_MALLOC_ACTIVE
  pw_sys_io_Init();
}

// TODO(amontanez): pw_boot_PreMainInit() should get renamed to
// pw_boot_FinalizeBoot or similar when main() is removed.
void pw_boot_PreMainInit() {
  pw::system::Init();
  vTaskStartScheduler();
  PW_UNREACHABLE;
}

// This `main()` stub prevents another main function from being linked since
// this target deliberately doesn't run `main()`.
int main() {}

PW_NO_RETURN void pw_boot_PostMain() {
  // In case main() returns, just sit here until the device is reset.
  while (true) {
  }
  PW_UNREACHABLE;
}

} // extern "C"
