/* 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 */