2020-10-14 11:54 AM
Dear friends,
I have been using the STM32H743ZI in three phase power supply project and the controller is responsible for the zero crossing detection of the three phases. To do this I use PB0, PB1,PB2 set up as EXTI inputs 0,1,2.
Mains frequency is 50Hz and the controller is running at 480MHz set up in CubeMX of course. For now to verify my hardware I have three LEDs connected to PD7,PD8,PD9. While looking at the LEDs I realized that PD7 is not flashing evenly as the other two are doing. I have then verified this on a scope and it is definitely missing interrupt requests. The the other two are performing as expected without missing a single IRQ.
After spending some time with this I ended up lowering the core clock frequency and low and behold at about 75MHz all interrupts were reported as expected.
Just to clarify the inputs on the GPIOs are 50Hz square waves with slight ringing on the edges. EXTI_LINE_1 and EXTI_LINE_2 perfectly emulates what is happening on PB1 and PB2, but PB0 randomly misses the IRQ about 20% of the time.
Has anyone of you experienced the same and what am I missing?
Here is my test code:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
EXTI0_IRQHandler_Config();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 60;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(PSU_ENABLE_GPIO_Port, PSU_ENABLE_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(L1_GPIO_Port, L1_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : PB0 PB1 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PB2 */
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : L1_Pin */
GPIO_InitStruct.Pin = L1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(L1_GPIO_Port, &GPIO_InitStruct);
}
void EXTI0_IRQHandler_Config(void)
{
/* Enable and set EXTI line 0 Interrupt to the lowest priority */
HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 1);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch( GPIO_Pin )
{
case GPIO_PIN_0: HAL_GPIO_TogglePin( L1_GPIO_Port, L1_Pin ); break;
default:
break;
}
}
void EXTI0_IRQHandler( void )
{
HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_0 );
}
I would appreciate any help with this.
Solved! Go to Solution.
2020-10-15 02:45 AM
For those who want to know.
It is slew rate.
I added logic gate to sharpen the edges of the input signals and it solved the problem.
2020-10-14 01:55 PM
> with slight ringing on the edges.
How do you cope with that?
Instead of toggling outputs, increment a volatile variable in each ISR.
JW
2020-10-15 12:49 AM
Thanks for the response Jan.
At the moment I am not concerned about the ringing. I know how to fix that.
My concern is the missing IRQs on Line 0 and even with a cleaned version of the input signal I still see the same result.
All three lines see exactly the same thing and two of the three are handling it correctly while the first is ignoring some of it.
Last night I thought it might be the rise and fall time of my triggering signals, but again they are all the same.
Just for the sake of completeness, the rise time is 500ns. This is because it is the output of a comparator circuit. LT1011 to be exact. I looked at the data sheet, but cannot find anything on input maximum slew rate. In the end I would need to add some logic to clean up the signals, but for now I need to find the source if my problem.
2020-10-15 02:45 AM
For those who want to know.
It is slew rate.
I added logic gate to sharpen the edges of the input signals and it solved the problem.
2020-10-15 02:56 PM
IMO, the slow slew rate together with some minute noise demonstrated itself as multiple interrupts. Two ISRs would toggle the output so that unless you look very closely at the edge with the scope/LA, you wouldn't notice. The incremented variable would reveal it. Slowing the clock results in the first ISR being slow enough to clear the interrupt flag after the second detected edge.
You may want to consider using timer channels in input capture mode; they have filters at inputs.
2 eurocents
JW
2020-10-15 11:50 PM
Dear Jan,
Thank you for the advice I will definitely consider doing this with the revised board.
Your suggestion regarding the noise on the input is more spot on. I have been looking at it with a scope and there are half mast noise messing up the edge detector. So when the input noise sits at the dead band of the edge detector it somehow blindfolds it for the next very close valid edge.
I am toggling an LED in the ISR of the EXTI and it clearly misses the IRQ when there is a specific type of noise on the inputs.
After adding a SN74LVC32 nor gate to the input pins it made the IRQs more reliable but still not 100%.
Here is my input in yellow to the edge detector.
I will be moving to the timers for a better performance as this is a critical signal required by my system. I am hoping that the edge detector of the timer channels are different to the EXTI.
Thank you again for the help.
2020-10-18 11:51 PM
Dear Jan,
I finally resolved this over the weekend.
First of all the you were right in asking about how I am detecting the problem. The answer is with my scope and it helps but is not good enough for the way the scope signal is presented. In the ISR I toggled a led and of course as in the picture above if the ISR is toggled twice the output pulse woud be very thin. So when I zoomed out it looked very often as if the micro was missing the IRQ, but instead it was not.
I modified my code to trigger the ISR only in a 100 Hz window once in every direction. Now the scope clearly shows that all the IRQs are serviced at full speed.
I love this micro it is a super machine. Thank you for your time that you spent on my request.
Highly appreciated.
Kindest regards
Wynand