Канал DMA2 (от периферии к памяти) 2 канала прекращает работу после 24 байтов - PullRequest
0 голосов
/ 06 ноября 2019

Я хочу прочитать сообщение UART на выводе GPIO, используя DMA2. Плата является STM32F72ZE. Мне удалось получить один пакет (26 байт), но следующий пакет я получаю с ошибкой. Этот код взят из библиотеки ST для STM32F4.

Эта небольшая программа (раньше я включал CLOCKs для GPIO, DMA2, TIM1):

//Rx DMA configuration
static void UART_Emul_SetConfig_DMARx(void)
{
  hdma_rx.Init.Channel   = DMA_CHANNEL_6;
  hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY
  hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_rx.Init.MemInc    = DMA_MINC_ENABLE;          
  hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  hdma_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
  hdma_rx.Init.Mode                = DMA_NORMAL;
  hdma_rx.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
  hdma_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
  hdma_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
  hdma_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
  hdma_rx.Init.PeriphBurst         = DMA_PBURST_SINGLE;

  hdma_rx.Instance = DMA2_Stream2;

  __HAL_LINKDMA(&TimHandle, hdma[2], hdma_rx);

  HAL_DMA_Init(TimHandle.hdma[2]);

  HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 3, 3);
  HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
}

//Start of DMA before each bytes

static void UART_Emul_ReceiveFrame(UART_Emul_HandleTypeDef *huart, uint32_t *pData)
{
  uint32_t tmp_sr =0;
  uint32_t tmp_ds =0;
  uint32_t tmp_size =0;
  uint32_t tmp_arr =0;

  tmp_arr = TIM1->ARR;
  tmp_ds = (uint32_t)pData;
  tmp_sr = (uint32_t) &(huart->RxPortName->IDR);
  tmp_size =  __HAL_UART_EMUL_FRAME_LENGTH(huart);

  /* Enable the transfer complete interrupt */
  __HAL_DMA_ENABLE_IT(&hdma_rx, DMA_IT_TC);

  /* Enable the transfer Error interrupt */
  __HAL_DMA_ENABLE_IT(&hdma_rx, DMA_IT_TE);

  /* Configure DMA Stream data length */
  hdma_rx.Instance->NDTR = tmp_size;

  /* Configure DMA Stream source address */
  hdma_rx.Instance->PAR = tmp_sr;

  /* Configure DMA Stream destination address */
  hdma_rx.Instance->M0AR = tmp_ds;

  /* Enable the Peripheral */
  __HAL_DMA_ENABLE(&hdma_rx);

   TIM1->CCR2 = ((TIM1->CNT + (tmp_arr / 2)) % tmp_arr);

  /* Enable the TIM Update DMA request */
  __HAL_TIM_ENABLE_DMA(&TimHandle, TIM_DMA_CC2);

  /* Enable Timer */
  __HAL_TIM_ENABLE(&TimHandle);

}
//Configure timer
static void UART_Emul_SetConfig (UART_Emul_HandleTypeDef *huart)
{
  uint32_t bit_time = 0;

  /* Init Bit Time */
  if((HAL_RCC_GetSysClockFreq()/HAL_RCC_GetPCLK2Freq()== 1) | (HAL_RCC_GetSysClockFreq()/HAL_RCC_GetPCLK2Freq()== 2))
  {
      bit_time = ((uint32_t) ((HAL_RCC_GetSysClockFreq()/huart->Init.BaudRate) - 1));
  }
  else
  {
      bit_time = ((uint32_t) (((HAL_RCC_GetPCLK2Freq()*2)/huart->Init.BaudRate) - 1));
  }

  /*##-1- Configure  the Timer peripheral (TIM1) in Bit Delay ##############*/
  /* Initialize TIM1 peripheral as follow:
  + Period = TimerPeriod
  + Prescaler = 0
  + ClockDivision = 0
  + Counter direction = Up
  */
  TimHandle.Instance            = TIM1;
  TimHandle.Init.Period         = bit_time;
  TimHandle.Init.Prescaler      = 0;
  TimHandle.Init.ClockDivision  = 0;
  TimHandle.Init.CounterMode    = TIM_COUNTERMODE_UP;
  HAL_TIM_Base_Init(&TimHandle);

  UART_Emul_SetConfig_DMARx();
}

Я не ставлю здесь прерываниеобработчик EXT1 (где подключена входная линия). Прерывание EXT1 сконфигурировано как Failing.

Объяснение: После сбоя сигнала EXT1 я вызываю функцию UART_Emul_SetConfig_DMARx() для создания прерывания DMA, после чего я делаю байты данных и сохраняю их в глобальный буфер. Это работает нормально, пока я не получу последний байт пакета. Может быть, большая задержка между байтами затрудняет получение следующего байта?

1 Ответ

0 голосов
/ 06 ноября 2019
I found the source of the problem. After analyzing the incorrect data, I determined that all 24 bytes of the second packet have a 1 bit left shift, and all bytes of the third packet have a 2 bit left shift and so on.
The UART_Emul_SetConfig () function, which should calculate the period of one bit, makes it with a large error. So after a long break between packets, the DMA reads correctly, and the TIMER processes it incorrectly.
...