/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file stm32g0xx_it.c * @brief Interrupt Service Routines. ****************************************************************************** * @attention * *

© Copyright (c) 2020 STMicroelectronics. * All rights reserved.

* * This software component is licensed by ST 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 * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "stm32g0xx_it.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "modbus.h" #include "SEGGER_RTT.h" #include "dac.h" #include "log.h" #include "precharge.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN TD */ /* USER CODE END TD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define TAG "ISR " /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ extern DMA_HandleTypeDef hdma_adc1; extern ADC_HandleTypeDef hadc1; extern DAC_HandleTypeDef hdac1; extern TIM_HandleTypeDef htim6; extern TIM_HandleTypeDef htim7; extern TIM_HandleTypeDef htim14; extern TIM_HandleTypeDef htim15; extern TIM_HandleTypeDef htim16; extern TIM_HandleTypeDef htim17; extern UART_HandleTypeDef huart1; /* USER CODE BEGIN EV */ extern uint16_t ADC_values[ADC_CHANNELS]; extern uint16_t rawMOSFETsVoltageDrop; extern int32_t rawContactVoltageDropPlus; extern int32_t rawContactVoltageDropMinus; extern int command_parser_is_enabled; extern void DoNothing(void); extern void OpenBothMOSFETSVeryFast(void); extern void (*MOSFETS_Management)(void); // function pointer extern void (*ExternalGreenLED_Management)(void); extern sys_data_t sys_data; extern void ADC_Open_Both_MOSFETs(void); extern void ADC_Close_Both_MOSFETs(void); extern void TurnExternalGreenLEDOff(void); extern void TurnExternalGreenLEDOn(void); extern void (*AUTO_Mode)(uint32_t, int); // Function pointer that contains function that is executed when gSwitch is in AUTO mode (depends on DIP switches) extern void EnterPowerSavingMode(void); extern void ExternalGreenLEDShortBlinking(void); extern int overcurrent_shutdown_is_active; extern int overload_shutdown_is_active; extern uint32_t overcurrent_shutdown_time; //extern uint32_t overload_shutdown_time; extern void (*InrushCurrentManagement)(void); extern int low_bat_shutdown_is_active; //extern uint16_t i_samples[I_RMS_SAMPLES_COUNT]; //extern uint16_t d_samples[I_RMS_SAMPLES_COUNT]; //extern uint16_t u_samples[I_RMS_SAMPLES_COUNT]; //extern volatile int32_t i_samples_counter; extern int statDataChanged; extern volatile uint32_t maxIntegral; /* USER CODE END EV */ /******************************************************************************/ /* Cortex-M0+ Processor Interruption and Exception Handlers */ /******************************************************************************/ /** * @brief This function handles Non maskable interrupt. */ void NMI_Handler(void) { /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ /* USER CODE END NonMaskableInt_IRQn 0 */ HAL_RCC_NMI_IRQHandler(); /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ while (1) { //OpenBothMOSFETS(); HAL_GPIO_TogglePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin); SEGGER_RTT_WriteString(0, "NMI ERROR!!!\n"); } /* USER CODE END NonMaskableInt_IRQn 1 */ } /** * @brief This function handles Hard fault interrupt. */ void HardFault_Handler(void) { /* USER CODE BEGIN HardFault_IRQn 0 */ SEGGER_RTT_WriteString(0, RTT_CTRL_TEXT_BRIGHT_RED); SEGGER_RTT_WriteString(0, "Hardfault ERROR!!!\n"); /* USER CODE END HardFault_IRQn 0 */ while (1) { /* USER CODE BEGIN W1_HardFault_IRQn 0 */ HAL_GPIO_TogglePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin); //OpenBothMOSFETS(); /* USER CODE END W1_HardFault_IRQn 0 */ } } /** * @brief This function handles System service call via SWI instruction. */ void SVC_Handler(void) { /* USER CODE BEGIN SVC_IRQn 0 */ /* USER CODE END SVC_IRQn 0 */ /* USER CODE BEGIN SVC_IRQn 1 */ /* USER CODE END SVC_IRQn 1 */ } /** * @brief This function handles Pendable request for system service. */ void PendSV_Handler(void) { /* USER CODE BEGIN PendSV_IRQn 0 */ /* USER CODE END PendSV_IRQn 0 */ /* USER CODE BEGIN PendSV_IRQn 1 */ /* USER CODE END PendSV_IRQn 1 */ } /** * @brief This function handles System tick timer. */ #ifdef USE_RAM_FUNC __RAM_FUNC void SysTick_Handler(void) #else void SysTick_Handler(void) #endif { /* USER CODE BEGIN SysTick_IRQn 0 */ //LED_ERROR_GPIO_Port->BSRR = LED_ERROR_Pin; /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick(); /* USER CODE BEGIN SysTick_IRQn 1 */ //LED_ERROR_GPIO_Port->BRR = LED_ERROR_Pin; /* USER CODE END SysTick_IRQn 1 */ } /******************************************************************************/ /* STM32G0xx Peripheral Interrupt Handlers */ /* Add here the Interrupt Handlers for the used peripherals. */ /* For the available peripheral interrupt handler names, */ /* please refer to the startup file (startup_stm32g0xx.s). */ /******************************************************************************/ /** * @brief This function handles DMA1 channel 1 interrupt. */ #ifdef USE_RAM_FUNC __RAM_FUNC void DMA1_Channel1_IRQHandler(void) #else void DMA1_Channel1_IRQHandler(void) #endif { /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */ TP2_GPIO_Port->BSRR = TP2_Pin; static uint32_t current_integral = 0; rawMOSFETsVoltageDrop = ADC_values[MOSFETS_VDROP_CHANNEL]; /*if (ADC_values[U_BAT_CHANNEL] < ADC_BAT_CRITICAL_VOLTAGE) { MOSFETS_Management = &OpenBothMOSFETSVeryFast; if (low_bat_shutdown_is_active == 0) { sys_data.s.ubsenseb_voltage = 0; low_bat_shutdown_is_active = 1; sys_data.s.device_status |= (1 << LOWBAT_ERROR); sys_data.s.lowbat_error_cnt++; statDataChanged = 1; } }*/ MOSFETS_Management(); rawContactVoltageDropPlus = ADC_values[I_PLUS_CHANNEL]; // Charge current sensor raw value rawContactVoltageDropMinus = ADC_values[I_MINUS_CHANNEL]; // Discharge current sensor raw value DMA1->IFCR |= DMA_FLAG_TC1; uint32_t current_adc_value = (rawContactVoltageDropPlus >= rawContactVoltageDropMinus)? rawContactVoltageDropPlus: rawContactVoltageDropMinus; if (current_adc_value >= sys_data.s.copper_v_drop_adc_limit) { current_integral += current_adc_value; if (current_integral > maxIntegral) // maxIntegral updated in main loop { InrushCurrentManagement(); current_integral = 0; } } else current_integral = 0; TP2_GPIO_Port->BRR = TP2_Pin; return; /* USER CODE END DMA1_Channel1_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_adc1); /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */ /* USER CODE END DMA1_Channel1_IRQn 1 */ } /** * @brief This function handles ADC1, COMP1 and COMP2 interrupts (COMP interrupts through EXTI lines 17 and 18). */ #ifdef USE_RAM_FUNC __RAM_FUNC void ADC1_COMP_IRQHandler(void) #else void ADC1_COMP_IRQHandler(void) #endif { /* USER CODE BEGIN ADC1_COMP_IRQn 0 */ //LED_STATE_GPIO_Port->BSRR = LED_STATE_Pin; // DO NOT BREAKPOINT THIS !!! MOSFETs DIES!!! // We open both MOSFETs arrays no matter which way overcurrent happened OpenBothMOSFETSVeryFast(); HAL_NVIC_DisableIRQ(ADC1_COMP_IRQn); //__HAL_ADC_CLEAR_FLAG(&hadc1, (ADC_FLAG_AWD3 | ADC_FLAG_AWD2)); MOSFETS_Management = &DoNothing; if (overload_shutdown_is_active == 0) { overcurrent_shutdown_is_active = 1; overcurrent_shutdown_time = uwTick; sys_data.s.overcurrent_error_cnt++; statDataChanged = 1; } //LED_STATE_GPIO_Port->BRR = LED_STATE_Pin; return; /* USER CODE END ADC1_COMP_IRQn 0 */ HAL_ADC_IRQHandler(&hadc1); /* USER CODE BEGIN ADC1_COMP_IRQn 1 */ /* USER CODE END ADC1_COMP_IRQn 1 */ } /** * @brief This function handles TIM6, DAC1 and LPTIM1 interrupts (LPTIM1 interrupt through EXTI line 29). */ void TIM6_DAC_LPTIM1_IRQHandler(void) { /* USER CODE BEGIN TIM6_DAC_LPTIM1_IRQn 0 */ HAL_TIM_IRQHandler(&htim6); // We dont't use DAC ISR return; /* USER CODE END TIM6_DAC_LPTIM1_IRQn 0 */ HAL_TIM_IRQHandler(&htim6); HAL_DAC_IRQHandler(&hdac1); /* USER CODE BEGIN TIM6_DAC_LPTIM1_IRQn 1 */ /* USER CODE END TIM6_DAC_LPTIM1_IRQn 1 */ } /** * @brief This function handles TIM7 and LPTIM2 interrupts (LPTIM2 interrupt through EXTI line 30). */ void TIM7_LPTIM2_IRQHandler(void) { /* USER CODE BEGIN TIM7_LPTIM2_IRQn 0 */ /* USER CODE END TIM7_LPTIM2_IRQn 0 */ HAL_TIM_IRQHandler(&htim7); /* USER CODE BEGIN TIM7_LPTIM2_IRQn 1 */ /* USER CODE END TIM7_LPTIM2_IRQn 1 */ } /** * @brief This function handles TIM14 global interrupt. */ void TIM14_IRQHandler(void) { /* USER CODE BEGIN TIM14_IRQn 0 */ /* USER CODE END TIM14_IRQn 0 */ HAL_TIM_IRQHandler(&htim14); /* USER CODE BEGIN TIM14_IRQn 1 */ /* USER CODE END TIM14_IRQn 1 */ } /** * @brief This function handles TIM15 global interrupt. */ void TIM15_IRQHandler(void) { /* USER CODE BEGIN TIM15_IRQn 0 */ /* USER CODE END TIM15_IRQn 0 */ HAL_TIM_IRQHandler(&htim15); /* USER CODE BEGIN TIM15_IRQn 1 */ /* USER CODE END TIM15_IRQn 1 */ } /** * @brief This function handles TIM16 global interrupt. */ void TIM16_IRQHandler(void) { /* USER CODE BEGIN TIM16_IRQn 0 */ /* USER CODE END TIM16_IRQn 0 */ HAL_TIM_IRQHandler(&htim16); /* USER CODE BEGIN TIM16_IRQn 1 */ /* USER CODE END TIM16_IRQn 1 */ } /** * @brief This function handles TIM17 global interrupt. */ void TIM17_IRQHandler(void) { /* USER CODE BEGIN TIM17_IRQn 0 */ /* USER CODE END TIM17_IRQn 0 */ HAL_TIM_IRQHandler(&htim17); /* USER CODE BEGIN TIM17_IRQn 1 */ /* USER CODE END TIM17_IRQn 1 */ } /** * @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25. */ #ifdef USE_RAM_FUNC __RAM_FUNC void USART1_IRQHandler(void) #else void USART1_IRQHandler(void) #endif { /* USER CODE BEGIN USART1_IRQn 0 */ //LED_ERROR_GPIO_Port->BSRR = LED_ERROR_Pin; MODBUS_UART_IRQHandler(&huart1); //LED_ERROR_GPIO_Port->BRR = LED_ERROR_Pin; return; /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ } /* USER CODE BEGIN 1 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef * htim) { // We don't have periodic timer interrupts, so we can disable any timer, which generated interrupt HAL_TIM_Base_Stop_IT(htim); if (htim->Instance == TIM6) { // This timer is used to start MOSFETs ON mode only after 250ms delay after turn on of VBOOST voltage sys_data.s.user_button_mode = SWITCH_ON; #ifdef INVERTER_CAP_PRECHARGE SetReturnFunction(&ADC_Close_Both_MOSFETs); MOSFETS_Management = &PreChargeStage; #else MOSFETS_Management = &ADC_Close_Both_MOSFETs; #endif //MOSFETS_Management = &ADC_Close_Both_MOSFETs; sys_data.s.relay_status = RELAY_IS_CLOSED; ExternalGreenLED_Management = &TurnExternalGreenLEDOn; } else if (htim->Instance == VBOOST_ON_TIMER.Instance) { // This timer is used to start MOSFETs regulation only after 250ms delay after VBOOST voltage activation in AUTO mode sys_data.s.user_button_mode = SWITCH_AUTO; AUTO_Mode(0, 1); // Reinitializing AUTO mode } else if (htim->Instance == VBOOST_OFF_TIMER.Instance) { // This timer is used to turn off VBOOST voltage after 100ms after entering into OFF mode //HAL_GPIO_WritePin(DISABLE_VBOOST_GPIO_Port, DISABLE_VBOOST_Pin, VBOOST_DISABLE); } else if (htim->Instance == TIM15) { #ifdef DISABLE_SHORTCUT_DETECTION_DURING_SWITCH_OFF EnableShortCutDetection(); HAL_TIM_Base_Stop_IT(htim); #endif } else if (htim->Instance == TIM16) { #ifdef DISABLE_SHORTCUT_DETECTION_DURING_SWITCH_OFF DisableShortCutDetection(); #endif // This timer is used to turn off switch after 60sec after entering into ON mode sys_data.s.user_button_mode = SWITCH_OFF; MOSFETS_Management = &ADC_Open_Both_MOSFETs; sys_data.s.relay_status = RELAY_IS_OPENED; ExternalGreenLED_Management = &TurnExternalGreenLEDOff; // After 100ms we turn off VBOOST voltage for power saving HAL_TIM_Base_Stop_IT(&VBOOST_OFF_TIMER); __HAL_TIM_CLEAR_FLAG(&VBOOST_OFF_TIMER, TIM_FLAG_UPDATE); __HAL_TIM_SET_COUNTER(&VBOOST_OFF_TIMER, 0); HAL_TIM_Base_Start_IT(&VBOOST_OFF_TIMER); } else if (htim->Instance == TIM17) { // This timer is used to stop parsing Modbus commands for 10sec after illegal command is recieved command_parser_is_enabled = 1; } } //------------------------------------------------------------------------------ /* USER CODE END 1 */