2021-02-20 02:48 AM
Set up TIM4 to generate a hsync pulse of 2us
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_Cmd(TIM4, DISABLE);
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = 0;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = LINEPULSE;
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &timerInitStructure);
TIM_OCInitTypeDef outputChannelInit;
TIM_OCStructInit(&outputChannelInit);
outputChannelInit.TIM_OutputState = TIM_OutputState_Enable;
outputChannelInit.TIM_OutputNState = TIM_OutputNState_Enable;
outputChannelInit.TIM_OCPolarity = TIM_OCPolarity_Low;
outputChannelInit.TIM_OCNPolarity = TIM_OCNPolarity_High;
// channel 1 is hsync (active low)
outputChannelInit.TIM_OCMode = TIM_OCMode_PWM1;
outputChannelInit.TIM_Pulse = HSYNCPULSE;
TIM_OC1Init(TIM4, &outputChannelInit);
Scope trace looks as expected:
Set up TIM3 to be a slave to TIM4 with the same period as TIM4
TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_Update);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);
TIM_SelectInputTrigger(TIM3, TIM_TS_ITR0);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_Cmd(TIM3, DISABLE);
timerInitStructure.TIM_Prescaler = 0;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = LINEPULSE;
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &timerInitStructure);
// channel 1 is hsync backporch shock absorber
outputChannelInit.TIM_OCMode = TIM_OCMode_Inactive;
outputChannelInit.TIM_Pulse = HSYNCPULSE;
TIM_OC1Init(TIM3, &outputChannelInit);
// Interrupt TIM3 for hsync shockabsorber
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
//TIM_ITConfig(TIM3, TIM_IT_Update | TIM_IT_CC1, ENABLE);
TIM3 IRQ handler toggles a GPIO line (magenta trace) on TIM_IT_Update
Q1: Why is there a delay between TIM4 Update and Tim3 Update? I expect TIM3 being a slave would be very close to when TIM4 starts a new period - ie falling edge of hsync pulse.
Now I also enable the TIM3 CC1 IRQ as well as Update IRQ and get this:
You can see the CC1 IRQ gets generated a little before the Update IRQ (as expected)..but..
Q2: TIM3 CC1 has the same Pulse value as TIM4, but the IRQ is much later..I expected TIM3 to be pretty much in phase with TIM4
2021-02-20 07:53 AM
[Answering my own question for anyone reading this later that find its useful]
I noticed that slave pulses were always around 30 CPU cycles later than master. Looked at the code I spotted that TIM3 was ENABLEd about 20 odd instructions before TIM4 was ENABLEd.
Enable them both at the same time and its perfect.
Doh.
2021-02-20 10:38 AM
> TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_Update);
> TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);
This would prevent TIM3 from running most of the time, if not entirely. "Luckily" you do this before enabling TIM3 clock, i.e. TIM3's slave-mode controller is unaffected and TIM3 runs freely.
JW
2021-02-21 12:29 AM
Thanks. However, if I do not ENABLE TIM3 explicitly, setting TIM3 to TIM_SlaveMode_Trigger, I get no TIM3 IRQs at all.
I was expecting TIM4 to trigger TIM3 countup..
2021-02-21 01:32 AM
Read my answer carefully.
Read out the timers' register content and check.
JW
2021-02-21 02:10 AM
Keep getting caught out by the non-orthogonal functionality on these devices!
In this case, TIM4 triggers TIM3 not on ITR0 but only on ITR3. Found this handy map on a website (subsequently found it on p401 of RM0008)