STM32 gotchas
182. TIM channel can't be enabled in TIMx_CCER, if TIMx_CR2.CCPC is set by mistake

In timers which have TIMx_CR2.CCPC bit, setting this bit causes TIMx_CCER.CCxE/CCxNE and TIMx_CCMRx.OCxM to be preloaded. These bits are then loaded to the "working" registers only upon the Commutation event, which is quite unlikely to be generated in most usual timer setups.

If TIMx_CR2.CCPC bit is set inadvertently, by mistake, subsequent changes of TIMx_CCER.CCxE/CCxNE and TIMx_CCMRx.OCxM are ignored (pending no Commutation event). The outward effect of this is, that while changes to TIMx_CCER.CCxE/CCxNE and TIMx_CCMRx.OCxM can be read back, they take no effect, so for example, enabling PWM on a TIM channel has no effect on the pin's state. This can be very confusing.

How could possibly TIMx_CR2.CCPC be set, without user realizing it?

One possibility is, that user calls the LL_TIM_CC_EnablePreload() function, as its name may lead to incorrect conclusion that it enables preload of the Capture-Compare registers (TIMx_CCRx). (In fact this is done by a quite similarly named LL_TIM_OC_EnablePreload() function.)

Another such possibility is to call the LL_TIM_OC_Init() function with not fully initialized LL_TIM_OC_InitTypeDef struct. If the rarely used OCIdleState or OCNIdleState fields are not initialized, they may end up corrupting content of TIMx_CR2 register, including the TIMx_CR2.CCPC bit.