ADC interrupt handler not retriggered when a flag is set while already executing handler
Hi,
I'm working on a project in which I use both ADC1 and ADC2 in independent mode, with JEOS of both ADCs as interrupt triggers. In the interrupt handler I do some calculations for current controllers. Mockup code below:
void ADC1_2_IRQHandler(void)
{
if (ADC1->ISR & ADC_ISR_JEOS)
{
ADC1->ISR = ADC_ISR_JEOS;
{
<Do something>
}
}
if (ADC2->ISR & ADC_ISR_JEOS)
{
ADC2->ISR = ADC_ISR_JEOS;
{
<Do something>
}
}
}The conversions of ADC1 and ADC2 are triggered by hrtimers (at different frequencies) and therefore JEOS flags of both ADCs can be set while the interrupt handler is still running.
I would expect the interrupt handler to be re-evaluated immediately after it has finished, since there still is a flag set in its ISR. However, this does not seem to happen and the interrupt handler is triggered only after a new flag has been set.
For instance, ADC2 has finished its conversion sequence so it sets JEOS -> Interrupt handler is called -> ADC2 JEOS flag is cleared -> starts work on controller calculations... Now ADC1 is finished so it sets ADC1 JEOS -> Controller calculations are finished -> exit handler and only come back once ADC2 JEOS is triggered again, then it clears ADC1 JEOS as well as it now sees that it is set.
Does anybody know if this is expected behaviour, or am I doing something wrong?
Initialization of ADCs below:
void MX_ADC1_Init(void)
{
ADC_MultiModeTypeDef multimode = {0};
ADC_AnalogWDGConfTypeDef AnalogWDGConfig = {0};
ADC_InjectionConfTypeDef sConfigInjected = {0};
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.GainCompensation = 0;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Analog WatchDog 1
*/
AnalogWDGConfig.WatchdogNumber = ADC_ANALOGWATCHDOG_1;
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_INJEC;
AnalogWDGConfig.Channel = ADC_CHANNEL_3;
AnalogWDGConfig.ITMode = DISABLE;
AnalogWDGConfig.HighThreshold = 2048 + AWD_OCP_SETTING_PFC;
AnalogWDGConfig.LowThreshold = 2048 - AWD_OCP_SETTING_PFC;
AnalogWDGConfig.FilteringConfig = ADC_AWD_FILTERING_NONE;
if (HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Injected Channel
*/
sConfigInjected.InjectedChannel = ADC_CHANNEL_3;
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_12CYCLES_5;
sConfigInjected.InjectedSingleDiff = ADC_DIFFERENTIAL_ENDED;
sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
sConfigInjected.InjectedOffset = 0;
sConfigInjected.InjectedNbrOfConversion = 2;
sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
sConfigInjected.AutoInjectedConv = DISABLE;
sConfigInjected.QueueInjectedContext = DISABLE;
sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJEC_HRTIM_TRG2;
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;
sConfigInjected.InjecOversamplingMode = DISABLE;
if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
/** Configure Injected Channel
*/
sConfigInjected.InjectedChannel = ADC_CHANNEL_6;
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_6CYCLES_5;
sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
}
/* ADC2 init function */
void MX_ADC2_Init(void)
{
ADC_AnalogWDGConfTypeDef AnalogWDGConfig = {0};
ADC_InjectionConfTypeDef sConfigInjected = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/** Common config
*/
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
hadc2.Init.Resolution = ADC_RESOLUTION_12B;
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc2.Init.GainCompensation = 0;
hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc2.Init.LowPowerAutoWait = DISABLE;
hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.NbrOfConversion = 1;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ExternalTrigConv = ADC_EXTERNALTRIG_HRTIM_TRG1;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc2.Init.DMAContinuousRequests = DISABLE;
hadc2.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc2.Init.OversamplingMode = ENABLE;
hadc2.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
hadc2.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_NONE;
hadc2.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
hadc2.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
if (HAL_ADC_Init(&hadc2) != HAL_OK)
{
Error_Handler();
}
/** Configure Analog WatchDog 1
*/
AnalogWDGConfig.WatchdogNumber = ADC_ANALOGWATCHDOG_1;
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_INJEC;
AnalogWDGConfig.Channel = ADC_CHANNEL_1;
AnalogWDGConfig.ITMode = DISABLE;
AnalogWDGConfig.HighThreshold = 2048 + AWD_OCP_SETTING_HB;
AnalogWDGConfig.LowThreshold = 2048 - AWD_OCP_SETTING_HB;
AnalogWDGConfig.FilteringConfig = ADC_AWD_FILTERING_NONE;
if (HAL_ADC_AnalogWDGConfig(&hadc2, &AnalogWDGConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Injected Channel
*/
sConfigInjected.InjectedChannel = ADC_CHANNEL_1;
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_12CYCLES_5;
sConfigInjected.InjectedSingleDiff = ADC_DIFFERENTIAL_ENDED;
sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
sConfigInjected.InjectedOffset = 0;
sConfigInjected.InjectedNbrOfConversion = 3;
sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
sConfigInjected.AutoInjectedConv = DISABLE;
sConfigInjected.QueueInjectedContext = DISABLE;
sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJEC_HRTIM_TRG4;
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;
sConfigInjected.InjecOversamplingMode = DISABLE;
if (HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
/** Configure Injected Channel
*/
sConfigInjected.InjectedChannel = ADC_CHANNEL_3;
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_6CYCLES_5;
sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
if (HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
/** Configure Injected Channel
*/
sConfigInjected.InjectedChannel = ADC_CHANNEL_5;
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;
if (HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
/** Configure the injected channel to be monitored by WatchDog 2 or 3
*/
AnalogWDGConfig.WatchdogNumber = ADC_ANALOGWATCHDOG_3;
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
AnalogWDGConfig.Channel = ADC_CHANNEL_3;
AnalogWDGConfig.HighThreshold = 3441;
AnalogWDGConfig.LowThreshold = 0;
if (HAL_ADC_AnalogWDGConfig(&hadc2, &AnalogWDGConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure the injected channel to be monitored by WatchDog 2 or 3
*/
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
AnalogWDGConfig.Channel = ADC_CHANNEL_5;
if (HAL_ADC_AnalogWDGConfig(&hadc2, &AnalogWDGConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_VOPAMP2;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_24CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
}