/* * Main starting point for STM32F042 boards. * * Copyright (C) 2019 Eug Krashtan * This file may be distributed under the terms of the GNU GPLv3 license. * */ #include "stm32f0xx_hal.h" #include "autoconf.h" #include "command.h" // DECL_CONSTANT #include "board/misc.h" // timer_read_time #include "sched.h" // sched_main #include "internal.h" #include "can.h" #include "log.h" DECL_CONSTANT_STR("MCU","stm32f042"); static IWDG_HandleTypeDef hiwdg; /**************************************************************** * dynamic memory pool ****************************************************************/ static char dynmem_pool[3 * 1024]; // Return the start of memory available for dynamic allocations void * dynmem_start(void) { return dynmem_pool; } // Return the end of memory available for dynamic allocations void * dynmem_end(void) { return &dynmem_pool[sizeof(dynmem_pool)]; } /**************************************************************** * misc functions ****************************************************************/ void command_reset(uint32_t *args) { NVIC_SystemReset(); } DECL_COMMAND_FLAGS(command_reset, HF_IN_SHUTDOWN, "reset"); void clock_config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /**Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI |RCC_OSCILLATORTYPE_HSI14|RCC_OSCILLATORTYPE_HSI48 |RCC_OSCILLATORTYPE_LSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; RCC_OscInitStruct.HSI14State = RCC_HSI14_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.HSI14CalibrationValue = 16; RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; HAL_RCC_OscConfig(&RCC_OscInitStruct); /**Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI48; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1|RCC_PERIPHCLK_RTC; PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI; HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); } // Implement simple early-boot delay mechanism void udelay(uint32_t usecs) { uint32_t end = timer_read_time() + timer_from_us(usecs); while (timer_is_before(timer_read_time(), end)) ; } void watchdog_reset(void) { HAL_IWDG_Refresh(&hiwdg); } DECL_TASK(watchdog_reset); void watchdog_init(void) { hiwdg.Instance = IWDG; hiwdg.Init.Prescaler = IWDG_PRESCALER_16; hiwdg.Init.Window = 4095; hiwdg.Init.Reload = 4095; //HAL_IWDG_Init(&hiwdg); ToDo enable after debug } DECL_INIT(watchdog_init); // Main entry point int main(void) { HAL_Init(); clock_config(); gpio_init(); #if (CONFIG_DEBUG_OUT) LogInit(); #endif sched_main(); return 0; } void __attribute__((weak)) lprint(char *msg) {} void __attribute__((weak)) lnprint(char *msg, size_t len) {} /* * MSP init functions ( __weak replacement ) */ /* * Initializes the Global MSP. */ void HAL_MspInit(void) { __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); __HAL_RCC_WWDG_CLK_ENABLE(); } /**************************************************************** * Debug helper (taken from https://community.arm.com/) * In case of Hard Fault it helps to find fault reason * on Cortex-M0 chips ****************************************************************/ void hard_fault_handler_c(unsigned long *hardfault_args){ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-variable" volatile unsigned long stacked_r0 ; volatile unsigned long stacked_r1 ; volatile unsigned long stacked_r2 ; volatile unsigned long stacked_r3 ; volatile unsigned long stacked_r12 ; volatile unsigned long stacked_lr ; volatile unsigned long stacked_pc ; volatile unsigned long stacked_psr ; volatile unsigned long _CFSR ; volatile unsigned long _HFSR ; volatile unsigned long _DFSR ; volatile unsigned long _AFSR ; volatile unsigned long _BFAR ; volatile unsigned long _MMAR ; stacked_r0 = ((unsigned long)hardfault_args[0]) ; stacked_r1 = ((unsigned long)hardfault_args[1]) ; stacked_r2 = ((unsigned long)hardfault_args[2]) ; stacked_r3 = ((unsigned long)hardfault_args[3]) ; stacked_r12 = ((unsigned long)hardfault_args[4]) ; stacked_lr = ((unsigned long)hardfault_args[5]) ; stacked_pc = ((unsigned long)hardfault_args[6]) ; stacked_psr = ((unsigned long)hardfault_args[7]) ; // Configurable Fault Status Register // Consists of MMSR, BFSR and UFSR _CFSR = (*((volatile unsigned long *)(0xE000ED28))) ; // Hard Fault Status Register _HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ; // Debug Fault Status Register _DFSR = (*((volatile unsigned long *)(0xE000ED30))) ; // Auxiliary Fault Status Register _AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ; // Read the Fault Address Registers. These may not contain valid values. // Check BFARVALID/MMARVALID to see if they are valid values // MemManage Fault Address Register _MMAR = (*((volatile unsigned long *)(0xE000ED34))) ; // Bus Fault Address Register _BFAR = (*((volatile unsigned long *)(0xE000ED38))) ; __asm("BKPT #0\n") ; // Break into the debugger #pragma GCC diagnostic pop }