cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U575VGT CRC checksum through DMA

Roth.Ian
Associate III

I am working on converting projects from STM32F745VET to STM32U575VGT. Part of the startup routine of the projects is checking for flash errors using the CRC peripheral. The STM32F7 projects initialize a DMA channel in the following way:

void MX_DMA_Init(void)
{

/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();

/* Configure DMA request hdma_memtomem_dma2_stream1 on DMA2_Stream1 */
hdma_memtomem_dma2_stream1.Instance = DMA2_Stream1;
hdma_memtomem_dma2_stream1.Init.Channel = DMA_CHANNEL_0;
hdma_memtomem_dma2_stream1.Init.Direction = DMA_MEMORY_TO_MEMORY;
hdma_memtomem_dma2_stream1.Init.PeriphInc = DMA_PINC_ENABLE;
hdma_memtomem_dma2_stream1.Init.MemInc = DMA_MINC_DISABLE;
hdma_memtomem_dma2_stream1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_memtomem_dma2_stream1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_memtomem_dma2_stream1.Init.Mode = DMA_NORMAL;
hdma_memtomem_dma2_stream1.Init.Priority = DMA_PRIORITY_LOW;
hdma_memtomem_dma2_stream1.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_memtomem_dma2_stream1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_memtomem_dma2_stream1.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_memtomem_dma2_stream1.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Init(&hdma_memtomem_dma2_stream1) != HAL_OK)
{
Error_Handler();
}
}

And then in the code:

__HAL_CRC_DR_RESET(&hcrc);
HAL_DMA_Start_IT(&handle_GPDMA1_Channel12, checkstart, CRC_BASE, checkrange);

where checkstart is defined as 0x08000000 and checkrange is 0x0000FFFC

I tried to use a GPDMA channel on the STM32U5 in the same way, but the calculated checksum does not match. Using the HAL_CRC_Calculate function does result in a checksum match, but this uses the CPU instead of offloading it to DMA.
Is there a way to feed the flash into the CRC peripheral through a DMA channel on the STM32U5?

1 ACCEPTED SOLUTION

Accepted Solutions

@Khaled_DHIF Thank you for this insight, I was not aware of the change in DMA transfer length calculation. Your solution worked for checking flash memory from 0x08000000 to 0x0800FFFB, where 0x0800FFFB is end of word addressing in terms of bytes in 16 bits. I looked at the reference manual for why this was the limit but did not find anything in the memory map. Stepping through the code with the debugger, I realized that although HAL functions passed the transfer length as a 32bit value, it was in fact limited by the size of BNDT in the GPDMA CxBR1 register. To transfer something larger, I would need to use a linked list. I configured in STM32CubeMX a linked list for transferring blocks of 0xFFFC as follows:

/**
  * @brief  DMA Linked-list FlashMemory configuration
  * @param  None
  * @retval None
  */
HAL_StatusTypeDef MX_FlashMemory_Config(void)
{
  HAL_StatusTypeDef ret = HAL_OK;
  /* DMA node configuration declaration */
  DMA_NodeConfTypeDef pNodeConfig;

  /* Set node configuration ################################################*/
  pNodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
  pNodeConfig.Init.Request = DMA_REQUEST_SW;
  pNodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
  pNodeConfig.Init.Direction = DMA_MEMORY_TO_MEMORY;
  pNodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
  pNodeConfig.Init.DestInc = DMA_DINC_FIXED;
  pNodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
  pNodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
  pNodeConfig.Init.SrcBurstLength = 1;
  pNodeConfig.Init.DestBurstLength = 1;
  pNodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1|DMA_DEST_ALLOCATED_PORT0;
  pNodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
  pNodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
  pNodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
  pNodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
  pNodeConfig.SrcAddress = 0x08000000;
  pNodeConfig.DstAddress = CRC_BASE;
  pNodeConfig.DataSize = 0xFFFC;

  /* Build Block1 Node */
  ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &Block1);

  /* Insert Block1 to Queue */
  ret |= HAL_DMAEx_List_InsertNode_Tail(&FlashMemory, &Block1);

  /* Set node configuration ################################################*/
  pNodeConfig.SrcAddress = 0x0800FFFC;

  /* Build Block2 Node */
  ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &Block2);

  /* Insert Block2 to Queue */
  ret |= HAL_DMAEx_List_InsertNode_Tail(&FlashMemory, &Block2);

   return ret;
}

And in the code I started the transfer as follows:

MX_FlashMemory_Config();
HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel12, &FlashMemory);    
__HAL_CRC_DR_RESET(&hcrc);
HAL_DMAEx_List_Start_IT(&handle_GPDMA1_Channel12);

This works if the IAR project calculates a checksum from 0x08000000 to 0x0801FFF7. I hope this helps anyone trying to run a checksum on the STM32U5 line.

View solution in original post

13 REPLIES 13
waclawek.jan
Super User

And does DMA and "manual" checksum match, if you use e.g. checkrange=1?

If not, what are the content of CRC registers for the two cases?

JW

Roth.Ian
Associate III

I set the end address to 0x08000003 in the IAR EWARM linker dialog. If I set checkrange to 1, the HAL_CRC_Calculate method comes up with a match. The DMA version does not match.

Expected value calculated by EWARM: 0x29C17239

Calculated value from CRC with DMA input: 0x6800520C

I meant, comparing all CRC registers' content, and perhaps looking at DMA's registers, too.

What value is at 0x0800'0000?

JW

 

Roth.Ian
Associate III

The DR register is reset to 0xFFFFFFFF before the DMA transfer or HAL_CRC_Calculate command. Changing between the two does not change the value at 0x0800000, which in the memory map of EWARM is listed as 08 53 01 20.

Hello @Roth.Ian 

Could you please provide your DMA configuration?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
Roth.Ian
Associate III

HI @Saket_Om 

Please see the STM32F7 code from above. Here is the STM32U5 configuration where I try to replicate it:

/* GPDMA1 init function */
void MX_GPDMA1_Init(void)
{

  /* USER CODE BEGIN GPDMA1_Init 0 */

  /* USER CODE END GPDMA1_Init 0 */

  /* Peripheral clock enable */
  __HAL_RCC_GPDMA1_CLK_ENABLE();

  /* GPDMA1 interrupt Init */
    HAL_NVIC_SetPriority(GPDMA1_Channel1_IRQn, 8, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel1_IRQn);
    HAL_NVIC_SetPriority(GPDMA1_Channel2_IRQn, 7, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel2_IRQn);
    HAL_NVIC_SetPriority(GPDMA1_Channel3_IRQn, 7, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel3_IRQn);
    HAL_NVIC_SetPriority(GPDMA1_Channel4_IRQn, 7, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel4_IRQn);
    HAL_NVIC_SetPriority(GPDMA1_Channel5_IRQn, 7, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel5_IRQn);
    HAL_NVIC_SetPriority(GPDMA1_Channel7_IRQn, 7, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel7_IRQn);
    HAL_NVIC_SetPriority(GPDMA1_Channel8_IRQn, 8, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel8_IRQn);
    HAL_NVIC_SetPriority(GPDMA1_Channel12_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel12_IRQn);

  /* USER CODE BEGIN GPDMA1_Init 1 */

  /* USER CODE END GPDMA1_Init 1 */
  handle_GPDMA1_Channel12.Instance = GPDMA1_Channel12;
  handle_GPDMA1_Channel12.Init.Request = DMA_REQUEST_SW;
  handle_GPDMA1_Channel12.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
  handle_GPDMA1_Channel12.Init.Direction = DMA_MEMORY_TO_MEMORY;
  handle_GPDMA1_Channel12.Init.SrcInc = DMA_SINC_INCREMENTED;
  handle_GPDMA1_Channel12.Init.DestInc = DMA_DINC_FIXED;
  handle_GPDMA1_Channel12.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
  handle_GPDMA1_Channel12.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
  handle_GPDMA1_Channel12.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
  handle_GPDMA1_Channel12.Init.SrcBurstLength = 1;
  handle_GPDMA1_Channel12.Init.DestBurstLength = 1;
  handle_GPDMA1_Channel12.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1|DMA_DEST_ALLOCATED_PORT0;
  handle_GPDMA1_Channel12.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
  handle_GPDMA1_Channel12.Init.Mode = DMA_NORMAL;
  if (HAL_DMA_Init(&handle_GPDMA1_Channel12) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel12, DMA_CHANNEL_NPRIV) != HAL_OK)
  {
    Error_Handler();
  }
  handle_GPDMA1_Channel7.Instance = GPDMA1_Channel7;
  handle_GPDMA1_Channel7.Init.Request = DMA_REQUEST_SW;
  handle_GPDMA1_Channel7.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
  handle_GPDMA1_Channel7.Init.Direction = DMA_MEMORY_TO_MEMORY;
  handle_GPDMA1_Channel7.Init.SrcInc = DMA_SINC_INCREMENTED;
  handle_GPDMA1_Channel7.Init.DestInc = DMA_DINC_FIXED;
  handle_GPDMA1_Channel7.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
  handle_GPDMA1_Channel7.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
  handle_GPDMA1_Channel7.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
  handle_GPDMA1_Channel7.Init.SrcBurstLength = 1;
  handle_GPDMA1_Channel7.Init.DestBurstLength = 1;
  handle_GPDMA1_Channel7.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1|DMA_DEST_ALLOCATED_PORT0;
  handle_GPDMA1_Channel7.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
  handle_GPDMA1_Channel7.Init.Mode = DMA_NORMAL;
  if (HAL_DMA_Init(&handle_GPDMA1_Channel7) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel7, DMA_CHANNEL_NPRIV) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN GPDMA1_Init 2 */

  /* USER CODE END GPDMA1_Init 2 */

}

I have tried both Channel 7 and 12 to see if there was a difference with a larger FIFO. I have changed the ports around based on my understand of Figure 2 in AN5593. Circular mode for the source did not seem to lead to good results.

 

Hello @Roth.Ian 

Are the DMA HTC and TC interrupt flags triggered correctly?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
waclawek.jan
Super User

Also, what happens if you define an array in memory and in the DMA command change the destination address to that array? Is the first word from FLASH stored there?

JW

Roth.Ian
Associate III

Hello @Saket_Om ,

They are triggered correctly.