Hello,
I am trying to use the imx8mp's cortex M to create a PWM output for working with the ws2812b LEDs.
The LEDs require a faster clock source than the default, and after checking the clock source possibilities I've found that setting:
pwmConfig.clockSource = kPWM_HighFrequencyClock;
works for the required rates.
I encountered an issue with this clock source that the interrupt no longer triggers when the reload triggers (this is taken from the driver_examples/pwm project).
To be more precise, the interrupt triggers twice at the beginning, then never again, and at the two times that it does, it's not at the expected points where the counter period is complete.
to reproduce this, just take the example and set
pwmConfig.clockSource = kPWM_HighFrequencyClock;
right after getting the default configuration in the main function.
The attempt results in the exact same scenario.
Is there another modification I need to do in order to make this work? or is it just not possible?
Hi
Here are snippets which has been tested by internal team on M4. You can use it as a reference.
PWM_GetDefaultConfig(&pwmConfig);
pwmConfig.clockSource = kPWM_PeripheralClock; // Using 24MHz as clock source
/* Initialize PWM module */
PWM_Init(DEMO_PWM_BASEADDR, &pwmConfig);
/* Enable FIFO empty interrupt */
PWM_EnableInterrupts(DEMO_PWM_BASEADDR, kPWM_FIFOEmptyInterruptEnable);
PWM_SetSampleValue(DEMO_PWM_BASEADDR, LED_0_SAMPLE); // LED_0_SAMPLE = 9
PWM_SetSampleValue(DEMO_PWM_BASEADDR, LED_1_SAMPLE); // LED_1_SAMPLE = 18
PWM_SetSampleValue(DEMO_PWM_BASEADDR, LED_0_SAMPLE);
pwm_pr_cnt += 3;
/* Write the period to the PWM Period Register */
PWM_SetPeriodValue(DEMO_PWM_BASEADDR, PWM_PERIOD_VALUE); // PWM_PERIOD_VALUE = 28
/* Gets interrupt kPWM_FIFOEmptyFlag */
if (PWM_GetStatusFlags(DEMO_PWM_BASEADDR) & kPWM_FIFOEmptyFlag)
{
if (pwm_pr_cnt > PWM_PERIOD + RESET_PERIOD) // PWM_PERIOD = 12 *24, RESET_PERIOD = 64
{
pwm_pr_cnt = 0;
PWM_SetSampleValue(DEMO_PWM_BASEADDR, LED_0_SAMPLE);
}
else if (pwm_pr_cnt > PWM_PERIOD)
{
/* Reset period */
PWM_SetSampleValue(DEMO_PWM_BASEADDR, 0);
}
else
{
/* PWM period */
uint32_t sample_val = (pwm_pr_cnt & 1) ? LED_1_SAMPLE : LED_0_SAMPLE;
PWM_SetSampleValue(DEMO_PWM_BASEADDR, sample_val);
}
pwm_pr_cnt++;
/* Clear kPWM_FIFOEmptyFlag */
PWM_clearStatusFlags(DEMO_PWM_BASEADDR, kPWM_FIFOEmptyFlag);
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
Best Regards
Zhiming
attached is the output, where yellow is the expected PWM output, and the purple is toggled every time the interrupt is triggered (it does not happen again after the 2 toggles that are shown in the picture, and the PWM continues indefinitely without any changes)
Hi
The interrupt process is not suitable for the HighFrequencyClock scenario, you can try kPWM_PeripheralClock using 24MHz as clock source.
Best Regards
Zhiming