stm32f1xx how to use DMA to write to TIMx CCR
Turned out I just needed to use TIM_CHANNEL_UPDATE as update source for the DMA and set TIM3 CCR2 as an output. It just works. I used HAL library and I had to create my own HAL_TIM_PWM_Start_DMA and HAL_TIM_PWM_Stop_DMA functions.

Here is the code, it contains hardcoded values for CCR2 and TIM_DMA_ID_UPDATE channel

HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA_HACK(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
{
    /* Set the DMA Period elapsed callback */
    htim-&gt;hdma[TIM_DMA_ID_UPDATE]-&gt;XferCpltCallback = TIM_DMADelayPulseCplt;

    /* Set the DMA error callback */
    htim-&gt;hdma[TIM_DMA_ID_UPDATE]-&gt;XferErrorCallback = TIM_DMAError;

    /* Enable the DMA channel */
    HAL_DMA_Start_IT(htim-&gt;hdma[TIM_DMA_ID_UPDATE], (uint32_t)pData, (uint32_t)&amp;htim-&gt;Instance-&gt;CCR2, Length);

    /* Enable the TIM Capture/Compare 1 DMA request */
    __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_UPDATE);

    /* Enable the Capture compare channel */
    TIM_CCxChannelCmd(htim-&gt;Instance, Channel, TIM_CCx_ENABLE);

    if (IS_TIM_BREAK_INSTANCE(htim-&gt;Instance) != RESET)
    {
        /* Enable the main output */
        __HAL_TIM_MOE_ENABLE(htim);
    }

    /* Enable the Peripheral */
    __HAL_TIM_ENABLE(htim);

    /* Return function status */
    return HAL_OK;
}

HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA_HACK(TIM_HandleTypeDef *htim, uint32_t Channel)
{
    __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_UPDATE);
    /* Disable the Capture compare channel */
    TIM_CCxChannelCmd(htim-&gt;Instance, Channel, TIM_CCx_DISABLE);

    if (IS_TIM_BREAK_INSTANCE(htim-&gt;Instance) != RESET)
    {
        /* Disable the Main Ouput */
        __HAL_TIM_MOE_DISABLE(htim);
    }

    /* Disable the Peripheral */
    __HAL_TIM_DISABLE(htim);

    /* Change the htim state */
    htim-&gt;State = HAL_TIM_STATE_READY;

    /* Return function status */
    return HAL_OK;
}
```