Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

STM32 DMA timer triggered at specific period with external trigger

I'm trying to interface a CPU that has a parallel bus, and trying to connect it to STM32. The CPU bus is connected to PORTD, I mean by that CS1, CS2, A1, and it's data bus D0 to D7. The CPU has IOWR signal and IORD signal too, I connected them to PA1,PC6. I've tried to use Timer8, in STM32F429I, with external trigger which is PC6, and start a DMA transfer. The DMA is configured as circular buffer, and I'm trying to capture a lot of data, like 5Kbytes from PORTD that is connected to (DMA peripheral to memory). The transfer is slow, DMA hangs, The triggering from timer (IOWR) happens so fast, I don't get complete buffers, (The CPU actually sends LCD data), I'm receiving part of it sometimes, and sometimes complete picture.

I would like to know a way or an approach to solve that problem.

I'm using HAL, and that's my current code:

Timer Init:

Bash:
static void MX_TIM8_Init(void)
{

    /* USER CODE BEGIN TIM8_Init 0 */

    /* USER CODE END TIM8_Init 0 */

    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_SlaveConfigTypeDef sSlaveConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};

    /* USER CODE BEGIN TIM8_Init 1 */

    /* USER CODE END TIM8_Init 1 */
    htim8.Instance = TIM8;
    htim8.Init.Prescaler = 0;
    htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim8.Init.Period = 65535;
    htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim8.Init.RepetitionCounter = 0;
    htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
    {
        Error_Handler();
    }
    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
    {
        Error_Handler();
    }
    sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
    sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
    sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_FALLING;
    sSlaveConfig.TriggerFilter = 0;
    if (HAL_TIM_SlaveConfigSynchro(&htim8, &sSlaveConfig) != HAL_OK)
    {
        Error_Handler();
    }
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
    {
        Error_Handler();
    }

}

DMA, Timer Configuration:

Code:
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(htim_base->Instance==TIM8)
  {
  /* USER CODE BEGIN TIM8_MspInit 0 */

  /* USER CODE END TIM8_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_TIM8_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**TIM8 GPIO Configuration
    PC6     ------> TIM8_CH1
*/
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* TIM8 DMA Init */
    /* TIM8_CH4_TRIG_COM Init */
    hdma_tim8_ch4_trig_com.Instance = DMA2_Stream7;
    hdma_tim8_ch4_trig_com.Init.Channel = DMA_CHANNEL_7;
    hdma_tim8_ch4_trig_com.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_tim8_ch4_trig_com.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_tim8_ch4_trig_com.Init.MemInc = DMA_MINC_ENABLE;
    hdma_tim8_ch4_trig_com.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_tim8_ch4_trig_com.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_tim8_ch4_trig_com.Init.Mode = DMA_CIRCULAR;
    hdma_tim8_ch4_trig_com.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    hdma_tim8_ch4_trig_com.Init.FIFOMode  = DMA_FIFOMODE_DISABLE;


    if (HAL_DMA_Init(&hdma_tim8_ch4_trig_com) != HAL_OK)
    {
      Error_Handler();
    }

    /* Several peripheral DMA handle pointers point to the same DMA handle.
     Be aware that there is only one stream to perform all the requested DMAs. */
   //__HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_CC4],hdma_tim8_ch4_trig_com);
    __HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_TRIGGER],hdma_tim8_ch4_trig_com);
    //__HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_COMMUTATION],hdma_tim8_ch4_trig_com);
    HAL_DMA_RegisterCallback(&hdma_tim8_ch4_trig_com,HAL_DMA_XFER_CPLT_CB_ID,HAL_DMA_TransferComplete);
    HAL_DMA_RegisterCallback(&hdma_tim8_ch4_trig_com,HAL_DMA_XFER_HALFCPLT_CB_ID,HAL_DMA_HalfTransferComplete);

    /* TIM8 interrupt Init */
   // HAL_NVIC_SetPriority(TIM8_TRG_COM_TIM14_IRQn, 2, 0);
   // HAL_NVIC_EnableIRQ(TIM8_TRG_COM_TIM14_IRQn);
  /* USER CODE BEGIN TIM8_MspInit 1 */

  /* USER CODE END TIM8_MspInit 1 */
  }


Processing the two buffers:

Code:
// Process data from the circular buffer
    if(half_transfer)
    {
        half_transfer=0;

        // Process data from the first half of the buffer
        for (uint32_t i = 0; i < DMA_BUFFER_SIZE / 2; ++i) {
            processData(buffer[i]);
        }
    }
    if(full_transfer)
    {
        full_transfer=0;


        for (uint32_t i = DMA_BUFFER_SIZE / 2; i < DMA_BUFFER_SIZE; ++i) {
            processData(buffer[i]);
        }
    }



Enabling and Starting DMA Transfer:

Code:
__HAL_TIM_ENABLE_IT(&htim8, TIM_IT_TRIGGER);
/* Enable the TIMX OC channel */

__HAL_TIM_ENABLE_DMA(&htim8, TIM_DMA_TRIGGER);
HAL_DMA_Start_IT(&hdma_tim8_ch4_trig_com,(uint32_t)&(GPIOD->IDR),(uint32_t)buffer,sizeof(buffer));



1715525711113.png
 
The trigger signal should be synchronized properly with the CPU's bus activity. If the CPU's signals (IOWR) are too fast for the DMA to keep up, you may need to introduce synchronization logic or adjust the triggering mechanism.
 

Latest threads

New Articles From Microcontroller Tips

Back
Top