Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: PM2_Libary PM2_Libary
Diff: Device/FastPWM_STM_TIM.cpp
- Revision:
- 32:e880dcb178f4
- Parent:
- 28:3c8a0d977bc3
- Child:
- 35:d6c2b73d71f5
diff -r 10e2e171f430 -r e880dcb178f4 Device/FastPWM_STM_TIM.cpp
--- a/Device/FastPWM_STM_TIM.cpp Tue Sep 06 20:17:21 2016 +0000
+++ b/Device/FastPWM_STM_TIM.cpp Sun Jan 01 14:37:55 2017 +0000
@@ -6,22 +6,39 @@
typedef __IO uint32_t* CHANNEL_P_T;
-#define PWM_CHANNEL (**(CHANNEL_P_T*)fast_obj)
-#define PWM_TIMER ((TIM_TypeDef*)_pwm.pwm)
+typedef struct {
+ CHANNEL_P_T channel;
+ uint32_t clk_prescaler;
+} fastpwm_struct;
+
+#define PWM_CHANNEL ((((fastpwm_struct*)fast_obj)->channel))
+#define PWM_CLK_PRESCALER ((((fastpwm_struct*)fast_obj)->clk_prescaler))
+#define PWM_TIMER ((TIM_TypeDef*)_pwm.pwm)
#if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1)
extern __IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin);
#endif
void FastPWM::initFastPWM( void ) {
- fast_obj = new (CHANNEL_P_T);
-
+ fast_obj = new fastpwm_struct;
#if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1)
- *(CHANNEL_P_T*)fast_obj = getChannel(PWM_TIMER, _pwm.pin);
+ PWM_CHANNEL = getChannel(PWM_TIMER, _pwm.pin);
#else
- *(CHANNEL_P_T*)fast_obj = &PWM_TIMER->CCR1 + _pwm.channel - 1;
+ PWM_CHANNEL = (&PWM_TIMER->CCR1 + _pwm.channel - 1);
#endif
+ // Depending on the timer and the internal bus it is connected to, each STM timer
+ // can have a fixed prescaler from the clock, especially the faster devices.
+ // In order not to have to hardcode this in, we use knowledge that mbed lib sets
+ // default period to 20ms to reverse engineer the prescaler from this.
+ uint32_t current_hz = SystemCoreClock / (PWM_TIMER->PSC + 1) / (PWM_TIMER->ARR+1);
+ PWM_CLK_PRESCALER = (current_hz + 1) / 50; //50Hz is magic number it should be, +1 is to handle possible rounding errors in mbed setup
+
+ //Sanity check in case a target does something different
+ if ( (PWM_CLK_PRESCALER == 0 ) || (PWM_CLK_PRESCALER > 16)) {
+ PWM_CLK_PRESCALER = 1;
+ }
+
//Enable PWM period syncing for glitch free result
PWM_TIMER->CR1 |= TIM_CR1_ARPE;
@@ -29,7 +46,7 @@
}
void FastPWM::pulsewidth_ticks( uint32_t ticks ) {
- PWM_CHANNEL = ticks;
+ *PWM_CHANNEL = ticks;
}
void FastPWM::period_ticks( uint32_t ticks ) {
@@ -41,15 +58,18 @@
}
uint32_t FastPWM::setPrescaler(uint32_t reqScale) {
- if (reqScale == 0)
+ if (reqScale == 0) {
//Return prescaler
- return PWM_TIMER->PSC + 1;
- if (reqScale > (uint32_t)(1<<16))
- reqScale = 1<<16;
+ return (PWM_TIMER->PSC + 1) * PWM_CLK_PRESCALER;
+ }
+ if (reqScale > (uint32_t)(PWM_CLK_PRESCALER<<16)) {
+ reqScale = PWM_CLK_PRESCALER<<16;
+ }
//Else set prescaler, we have to substract one from reqScale since a 0 in PCVAL is prescaler of 1
- PWM_TIMER->PSC = reqScale - 1;
+ //Take into account PWM_CLK_PRESCALER, we need to make sure reqScale is always rounded up
+ PWM_TIMER->PSC = (reqScale + PWM_CLK_PRESCALER - 1)/PWM_CLK_PRESCALER - 1;
- return reqScale;
+ return setPrescaler(0);
}
#endif
\ No newline at end of file