2024-12-19 04:03 AM
Hi everybody,
I have TIM15, configured to PWM generation, in one shot configuration, using OC1N output. The output is set to 0 and timer disabled..
When I later initialize TIM1, the output of TIM15 goes high at the instant the Update event is generated. I noticed it depend on Fast mode setting - if not set, the output remains low. The Fast mode is required/recommended in One Pulse configuration.
How is it possible to change anything in other timer instance?
Sample code below.
Tomas
//-----------------------------------------------------------------------------
void TIM15_TIM1_Test(void)
//-----------------------------------------------------------------------------
{
// TIM15 init
LL_TIM_InitTypeDef TIM_InitStruct;
TIM_InitStruct.Prescaler = 383; //
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 100;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
TIM_InitStruct.RepetitionCounter = 0;
LL_TIM_Init(TIM15, &TIM_InitStruct);
// output channel setup
LL_TIM_OC_InitTypeDef TIM_OC_InitStruct;
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE;
TIM_OC_InitStruct.CompareValue = 50;
TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_LOW;
TIM_OC_InitStruct.OCNPolarity = LL_TIM_OCPOLARITY_LOW;
TIM_OC_InitStruct.OCIdleState = LL_TIM_OCIDLESTATE_LOW;
TIM_OC_InitStruct.OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
LL_TIM_OC_Init(TIM15, LL_TIM_CHANNEL_CH1, &TIM_OC_InitStruct);
LL_TIM_SetOffStates(TIM15, LL_TIM_OSSI_ENABLE, LL_TIM_OSSR_ENABLE);
// here sits the devil - if I omit the Fast mode, it works fine
LL_TIM_OC_EnableFast(TIM15, LL_TIM_CHANNEL_CH1);
LL_TIM_EnableAllOutputs(TIM15);
LL_TIM_GenerateEvent_UPDATE(TIM15);
LL_TIM_EnableCounter(TIM15); // needed to set the output to 0
// connect pin to timer
LL_GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = BEEPER_PIN;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = BEEPER_AF;
LL_GPIO_Init(BEEPER_PORT, &GPIO_InitStruct);
LL_TIM_DisableCounter(TIM15); // to be started later
// TIM1 init
LL_TIM_InitTypeDef TIM_InitStruct;
TIM_InitStruct.Prescaler = 0;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 959;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
TIM_InitStruct.RepetitionCounter = 0;
// in this call the output TIM15/OC1N goes high
// at the instant of UpdateEvent generation
LL_TIM_Init(TIM1, &TIM_InitStruct);
}
Solved! Go to Solution.
2025-01-06 04:12 PM - edited 2025-01-06 04:12 PM
Interesting. Surprising, but, reconsidering what we see, it's probably to be expected...
TIM1_CR2.MMS = 0 --> Reset - the UG bit from the EGR register is used as trigger output (TRGO). You do set TIM1_EGR.UG, so that generates the TRGO pulse.
---->
TIM15_SMCR.TS = 0 --> ITR0 = TIM1_TRGO is used as trigger (i.e. TRGI pulse did arrive)
--->
TIM15_CCMR1.OC1FE = 1 --> An active edge on the trigger input acts like a compare match on CC1 output.
--->
TIM15_CCMR1.OC1M = 0b110 PWM mode 1 -- Channel 1 is active as long as TIM15_CNT<TIM15_CCR1 else
inactive. (i.e. as CNT = 1 < CCR1 = 0x32, it was active, but due to TRGI->fast mode-> OC forced match, it gets inactive)
--->
TIM15_CC1N pin, but TIM15_CCER.CC1E=0 ---> pin output is NOT inverted version of the compare output, but also TIM15_CCER.CC1NP=1 ---> pin output IS inverted, i.e. the active->inactive transition from above is 0->1 at the pin. And this indeed is what you observe.
The surprising element here is, that the OCxFast mechanism does react to TRGI even if TIMx_SMCR.SMS=0. I was not aware of this.
Remedy may be in avoiding the trigger, e.g. by setting TIM1_CR2.MMS to event which does not occur, or by setting TIM15_SMS.TS to a source which does not exist or is not engaged.
However, I am still not sure why you need the OCxFast mechanism at all. Do you trigger TIM15 from a different timer, or from ETR, or by setting TIMx_EGR.TG? Starting the timer by setting TIM15_CR1.CEN in software IMO does not constitute a trigger which would work through that mechanism.
JW
2024-12-19 10:09 AM
Line 6 and line 47 define the same variable, this cannot compile.
2024-12-19 01:36 PM - edited 2024-12-19 01:38 PM
As @KnarfB pointed out above, there's no point in posting conflicting code fragments. Always copy/paste coherent portions of code. Best, prepare a minimal but complete compilable example exhibiting the problem.
Which pins? Is there a change on TIM1-related pin at the "critical moment"? Check there's no physical short between them.
Read out and check/post content of TIM and relevant GPIO registers just before the "critical moment".
JW
PS.
> The Fast mode is required/recommended in One Pulse configuration.
Do you understand, why?
2024-12-20 10:13 AM
I am sorry, I merged two init functions from two modules into one example code. Since the init structure is fully initilized, it is sufficient to delete the second definition and there is no common data between the two initializations.
Tomas
2024-12-20 10:39 AM
>Always copy/paste coherent portions of code. Best, prepare a minimal but complete compilable example exhibiting the problem.
I did that, but after isolating the problematic code I merged two functions into one, as I have answered to @KnarfB.
So I have posted only one function instead of three (InitTIM15 + InitTIM1 + Call the two above). I hope I will not be crucified for that.
>Which pins? Is there a change on TIM1-related pin at the "critical moment"? Check there's no physical short between them.
TIM1 has no external connection, it is used for ADC timing. I know, there are better timers suitable for this task, but I needed two timers, capable to run i master/slave configuration and connectable to pins, which are not occupied by other non-relocatable devices. And several other requirements. The final choice is TIM1 and TIM3.
TIM15 has separate functionality and has no connection with the two timers above, either internal or external.
>> The Fast mode is required/recommended in One Pulse configuration.
>Do you understand, why?
If I understand RM correctly, it is necessary to minimize delay between start stimulus and generated pulse.
Tomas
2024-12-21 07:11 AM - edited 2024-12-21 07:12 AM
Read out and check/post content of TIM and relevant GPIO registers just before the "critical moment".
You single-step in the through that critical moment (TIM1 Update), don't you. You may also want to compare the registers' content before and after that step.
JW
2025-01-06 02:04 AM
Sorry for delay, factory holiday :)
Attached two files, just before and just after LL_TIM_GenerateEvent_UPDATE(TIM1) .
TIM1, TIM15 and GPIOB register content.
Differences:
- TIM1 SR UIF set (lines 63, 64)
- GPIOB IDR ID13 set (lines 332, 346)
(I have omitted in the post, BEEPER_PORT = GPIOB, BEEPER_PIN = LL_GPIO_PIN_13)
Tomas
2025-01-06 04:12 PM - edited 2025-01-06 04:12 PM
Interesting. Surprising, but, reconsidering what we see, it's probably to be expected...
TIM1_CR2.MMS = 0 --> Reset - the UG bit from the EGR register is used as trigger output (TRGO). You do set TIM1_EGR.UG, so that generates the TRGO pulse.
---->
TIM15_SMCR.TS = 0 --> ITR0 = TIM1_TRGO is used as trigger (i.e. TRGI pulse did arrive)
--->
TIM15_CCMR1.OC1FE = 1 --> An active edge on the trigger input acts like a compare match on CC1 output.
--->
TIM15_CCMR1.OC1M = 0b110 PWM mode 1 -- Channel 1 is active as long as TIM15_CNT<TIM15_CCR1 else
inactive. (i.e. as CNT = 1 < CCR1 = 0x32, it was active, but due to TRGI->fast mode-> OC forced match, it gets inactive)
--->
TIM15_CC1N pin, but TIM15_CCER.CC1E=0 ---> pin output is NOT inverted version of the compare output, but also TIM15_CCER.CC1NP=1 ---> pin output IS inverted, i.e. the active->inactive transition from above is 0->1 at the pin. And this indeed is what you observe.
The surprising element here is, that the OCxFast mechanism does react to TRGI even if TIMx_SMCR.SMS=0. I was not aware of this.
Remedy may be in avoiding the trigger, e.g. by setting TIM1_CR2.MMS to event which does not occur, or by setting TIM15_SMS.TS to a source which does not exist or is not engaged.
However, I am still not sure why you need the OCxFast mechanism at all. Do you trigger TIM15 from a different timer, or from ETR, or by setting TIMx_EGR.TG? Starting the timer by setting TIM15_CR1.CEN in software IMO does not constitute a trigger which would work through that mechanism.
JW
2025-01-07 03:29 AM
Bingo!
That explains how are the two timers connected, although I didn't create any logical connection between them. The fundamental point is that the output reacts to trigger event in OC Fast mode, although the slave mode is disabled. IMHO this should not.
Accepted solution is to not use Fast mode, the generated pulse need not to be of exact delay or duration. And clean up the OC setup, of course.
Thanks very much.
Tomas