Skip to main content
Associate II
June 27, 2024
Question

PWM Frequency Issue in STM32WB55CGU6TR with RTOS

  • June 27, 2024
  • 2 replies
  • 3213 views

Hello,

I am currently working with the STM32WB55CGU6TR MCU and using an RTOS. I've created two threads:

  1. PWM Thread: This thread generates PWM signals using the GPIO toggle method at frequencies of 60Hz and 600Hz.
  2. Read FIFO Thread: This thread reads data from the IMU FIFO. The IMU triggers an interrupt when data is ready, and the MCU waits for this interrupt via the EXTI_CALLBACK function to read the data.

Issue:

The PWM thread is producing signals at 50Hz and 500Hz instead of the intended 60Hz and 600Hz. Additionally, the duty cycle is not constant. Here are the steps I have tried:

Case 1: Both threads have the same priority, resulting in the PWM thread giving 50Hz and 500Hz.

Case 2: Increasing the PWM thread priority by 1 causes the Read FIFO thread to stop working entirely.

I would appreciate any insights or suggestions on how to resolve these issues.

Thank you!

 

 

 

/* USER CODE BEGIN Header_Startpwm_imuTask */
/**
 * @brief Function implementing the pwm_imuTask thread.
 * @PAram argument: Not used
 * @retval None
 */
/* USER CODE END Header_Startpwm_imuTask */
void StartPWM_Task(void *argument)
{
	int time=INTIAL_VALUE;
	uint16_t time_delay=INTIAL_VALUE;
	/* USER CODE BEGIN 5 */
	/* Infinite loop */
 for(;;)
	{
 GPIO_SET_PIN(GPIOA, GPIO_PIN_0);//CAM_TRIG
		 for(time=1;time<=5;time++)
		 {
			 GPIO_SET_PIN(GPIOA, GPIO_PIN_8);//INS_TRIG
			 GPIO_SET_PIN(GPIOA, GPIO_PIN_9);//IMU1_TRIG

			 delay_us(833);
			 GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_8);//INS_TRIG
			 GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_9);
			 delay_us(833);
		 }
		 GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_0);//CAM_TRIG
		 for(time=1;time<=5;time++)
		 {
			 GPIO_SET_PIN(GPIOA, GPIO_PIN_8);//INS_TRIG
			 GPIO_SET_PIN(GPIOA, GPIO_PIN_9);//IMU1_TRIG
			 delay_us(833);
			 GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_8);//INS_TRIG
			 GPIO_CLEAR_PIN(GPIOA, GPIO_PIN_9);//IMU1_TRIG
			 delay_us(833);
		 }
	 }

}

 


 

 

/* USER CODE BEGIN Header_StartDefaultTask */
/**
 * @brief Function implementing the defaultTask thread.
 * @PAram argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartDefaultTask */
void StartReadFIFOTask(void *argument)
{
uint32_t flagsWaiter=0;
uint32_t waitFlags = 0x01; // Wait for flag 0 to be set
uint8_t rawdata1[16]={0};
 /* USER CODE BEGIN 5 */
 /* Infinite loop */
#if 1
reset();
ICM42688_enableFifo();
ICM42688_enableLN_mode();
delay_ms(3);
ICM42688_enableDataReadyInterrupt();
delay_ms(3);
whoAmI();
#endif

while(1)
{
#if 1
	//printf("while\n\r");
	if(data_1_ready == 1)
	{
		data_1_ready = 0;
		printf("Data ready interrupt 1... \n\r");
		multi_i2c_read((0x69<<1),0x30,rawdata1,16);

		for (size_t i=0; i<16; i++) {
		 	 printf("FIFO Data %#x.. \n\r", rawdata1[i]);
		 }
	}
#endif
}
}

 

 

2 replies

Bob S
Super User
June 27, 2024

What does your delay_us() function do?  If it does not yield then lower priority tasks will never run because your PWM task is always running.

Using software to generate PWM signals like that will never work with any guaranteed precision.  You need to use hardware timers.  Either to generate the PWM directly (that is what they are made for), or to generate interrupts that then trigger the PWM task to do something (via RTOS events/mutex/etc.).

Associate II
July 1, 2024

Hi @Bob S  ,

1 .delay_us() function wiil generate the delay using hardware timer2 . If i used this timer without rtos i can get precisely 60hz and 600hz !.

/*Microsecond delay function definition*/
void delay_us(uint16_t time)
{

/* change your code here for the delay in microseconds */

__HAL_TIM_SET_COUNTER(&htim2, 0);

while ((__HAL_TIM_GET_COUNTER(&htim2))<time);

}

 2.I used the hardware timers directly to generate the PWM signal But there is phase shift after two or three pulses

Below is the configuration for PWM using slave trigger concept.

pippalla_chakravarthi_0-1719843314095.png

pippalla_chakravarthi_1-1719843417112.png

 

 

pippalla_chakravarthi_2-1719843575470.png

 

 

Bob S
Super User
July 8, 2024

There is a phase shift when using the timer hardware?  Is this between the 3 signals from TIM1 or between the TIM1 signals and the TIM2 signal?  Either way, if the timers are free running I would not expect any change in phase relationship.  Are you starting or stopping the timers to toggle your "CAM_TRIG" signal?

Tesla DeLorean
Guru
July 10, 2024

That delay is not thread safe, read the starting count and subtract that from the current, and compare that with the delay time desired. Don't zero the count.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..