cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H563 and SPI DMA Transfer issue

PFlor.2
Senior

I'm having an issue when using the DMA with SPI.  I'm using the SPI for a 320x240 LCD and want the DMA to help with blocking while transferring large amounts of data with touchGFX.

I'm able to paint the screen one color just using the SPI but when I try to use the hdmatx I can't get it to complete and hangs on waiting for the DMA state to be READY (see below)....

 

void ST7789v_Fill_Color(uint16_t color)
{
  uint16_t i;

  ST7789v_SetWindow(0, 0, ST7789_WIDTH - 1, ST7789_HEIGHT - 1);

  CS_L();

  uint32_t size = ST7789_WIDTH * ST7789_HEIGHT * 2;
  uint16_t chunk_size;
  uint16_t buffer[size/2];
  uint8_t *buf;

  memset(buffer, color, sizeof(buffer));

  if (size > 0) {
    DC_H();

    LCD_WR_REG(ST7789_CMD_RAMWR);

    while (size > 0) {
      buf = (uint8_t *)buffer;
      chunk_size = size > 8192 ? 8192 : size;

      if (DMA_MIN_SIZE <= size) {
        if (HAL_SPI_Transmit_DMA(&hspi3, buf, chunk_size ) != HAL_OK) {
          Error_Handler();
        }
        while (hspi3.hdmatx->State != HAL_DMA_STATE_READY);
      }
      else {
        if (HAL_SPI_Transmit(&hspi3, buf, chunk_size, HAL_MAX_DELAY) != HAL_OK) {
          Error_Handler();
        }
      }
      buf += chunk_size;
      size -= chunk_size;
    }
  }
  CS_H();
}

 

This code hangs at while (hspi3.hdmatx->State != HAL_DMA_STATE_READY); and the state still shows busy.

below is my SPI and DMA configuration.

 

/* SPI3 init function */
void MX_SPI3_Init(void)
{

  /* USER CODE BEGIN SPI3_Init 0 */

  /* USER CODE END SPI3_Init 0 */

  /* USER CODE BEGIN SPI3_Init 1 */

  /* USER CODE END SPI3_Init 1 */
  hspi3.Instance = SPI3;
  hspi3.Init.Mode = SPI_MODE_MASTER;
  hspi3.Init.Direction = SPI_DIRECTION_2LINES_TXONLY;
  hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi3.Init.NSS = SPI_NSS_SOFT;
  hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi3.Init.CRCPolynomial = 0x7;
  hspi3.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  hspi3.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  hspi3.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  hspi3.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
  hspi3.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  hspi3.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  hspi3.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
  hspi3.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  hspi3.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
  hspi3.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
  if (HAL_SPI_Init(&hspi3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI3_Init 2 */

  /* USER CODE END SPI3_Init 2 */
}


    /* SPI3 DMA Init */
    /* GPDMA1_REQUEST_SPI3_TX Init */
    handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
    handle_GPDMA1_Channel0.Init.Request = GPDMA1_REQUEST_SPI3_TX;
    handle_GPDMA1_Channel0.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
    handle_GPDMA1_Channel0.Init.Direction = DMA_MEMORY_TO_PERIPH;
    handle_GPDMA1_Channel0.Init.SrcInc = DMA_SINC_INCREMENTED;
    handle_GPDMA1_Channel0.Init.DestInc = DMA_DINC_FIXED;
    handle_GPDMA1_Channel0.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
    handle_GPDMA1_Channel0.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
    handle_GPDMA1_Channel0.Init.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
    handle_GPDMA1_Channel0.Init.SrcBurstLength = 1;
    handle_GPDMA1_Channel0.Init.DestBurstLength = 1;
    handle_GPDMA1_Channel0.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
    handle_GPDMA1_Channel0.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    handle_GPDMA1_Channel0.Init.Mode = DMA_NORMAL;
    if (HAL_DMA_Init(&handle_GPDMA1_Channel0) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(spiHandle, hdmatx, handle_GPDMA1_Channel0);

    if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV) != HAL_OK)
    {
      Error_Handler();
    }

    /* SPI3 interrupt Init */
    HAL_NVIC_SetPriority(SPI3_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(SPI3_IRQn);
  /* USER CODE BEGIN SPI3_MspInit 1 */

  /* USER CODE END SPI3_MspInit 1 */
  }

 

 Can anyone help me identify what I'm missing??

 

Thanks!

12 REPLIES 12

I noticed that none of my tasks were running and I did have a defaultTask previously running that toggled a pin so I could see a "heartbeat" of the system.

In the debugger when I paused execution I noticed the trace buffer showed it was entering prvTaskExitError after the osKernelStart() was called.  Apparently while I was comparing my TouchGFXHAL.cpp with another application that used TouchGFX and an LTDC interface to the display I was copying over things to see if it would help the problems I has having with the SPI TouchGFX interface and left a few things in there inadvertently...once this was removed the RTOS started running correctly.

PFlor2_0-1733501114939.png

 

Farhad13651
Associate II

Hello

Was your problem solved?

Yes, once I removed the code above and added a task to call the signalVSync() functions at the appropriate interval then the TouchGFX interface worked for single framebuffer.