2024-09-26 02:19 AM
Hello,
perhaps someone here has an idea what's going wrong:
I wrote a small program with cube ide to calculate a crc32 (standard polynom 0x4c11db7). It took me some time, but now I get the same result when using HAL_CRC_generate and 'manually' feeding the CRC module.
Then I tried to feed the CRC module via DMA (GPDMA, channel 0), and then it becomes a little bit weird:
if the length of data is 1 to 3 bytes, all three methods calculate the same crc.
But if the length is >= 4, the crc generated via dma differs.
Attached is the main.c, but the interesting code of initializing the crc module and the dma channel is listed below...
Thanks,
Gunter
/*
* Method 3: CRC module via DMA
*/
/* init crc module */
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
/* init gpdma channel 0 */
__HAL_RCC_GPDMA1_CLK_ENABLE();
handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
handle_GPDMA1_Channel0.Init.Request = DMA_REQUEST_SW;
handle_GPDMA1_Channel0.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_GPDMA1_Channel0.Init.Direction = DMA_MEMORY_TO_MEMORY;
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_LOW_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();
}
if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}
__HAL_CRC_DR_RESET(&hcrc);
HAL_DMA_Start(&handle_GPDMA1_Channel0, (uint32_t)&testdata[0], (uint32_t)&CRC->DR, crclen);
crc_dma = hcrc.Instance->DR ^ 0xFFFFFFFFu;
if ( (crc_HAL != crc_man) || (crc_HAL != crc_dma) )
{
while (1)
Solved! Go to Solution.
2024-09-26 11:50 PM
Hello TDK,
that was indeed the problem.
After introducing a callback for DMA complete
handle_GPDMA1_Channel0.XferCpltCallback = DmaCompleteCallback;
where a flag is set
volatile uint8_t dmaFinished = 0u;
void DmaCompleteCallback(DMA_HandleTypeDef* hdma)
{
dmaFinished = 1u;
}
and starting the calculation with HAL_DMA_Start_IT(...) (followed by a while loop waiting for flag set...)
handle_GPDMA1_Channel0.XferCpltCallback = DmaCompleteCallback;
dmaFinished = 0u;
HAL_DMA_Start_IT(&handle_GPDMA1_Channel0, (uint32_t)&testdata[0], (uint32_t)&CRC->DR, crclen);
while (!dmaFinished)
{
;
}
crc_dma = hcrc.Instance->DR ^ 0xFFFFFFFFu;
it went smoothly :)
Thanks,
Gunter
(Perhaps this helps others faced the same problem...)
2024-09-26 05:34 AM
This is probably an endian-ness artifact. If your memory looks like 0x01 0x02 0x03 0x04, and you are treating it as a uint32_t word, then it is read as 0x04030201 and the CRC is calculated with that number.
If you transfer one byte at a time, it will calculate the crc with 0x01, then 0x02, etc.
Post exact expected/calculated values you're getting.
> hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
Possibly changing this would fix it.
2024-09-26 06:21 AM
Hello Guru,
thanks for your answer.
To be more precise: the test data used is a simple uint8_t array
static const uint8_t testdata[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
static uint32_t crclen = 3u;
When computing the crc32 over the first 3 value, I get
The crc32 over the first 4 values gives the result
The idea with endianness problem...mhh...I doubt.
All memory access operations are byte wide...
Thanks,
Gunter
2024-09-26 08:13 AM
> HAL_DMA_Start(&handle_GPDMA1_Channel0, (uint32_t)&testdata[0], (uint32_t)&CRC->DR, crclen);
> crc_dma = hcrc.Instance->DR ^ 0xFFFFFFFFu;
Are you waiting long enough for the calculation to complete? HAL_DMA_Start only starts the process. Perhaps insert a delay between those statements. Seems unlikely to be it, but it would explain things.
2024-09-26 08:36 AM
This post has been escalated to the ST Online Support Team for additional assistance. We'll contact you directly.
2024-09-26 11:50 PM
Hello TDK,
that was indeed the problem.
After introducing a callback for DMA complete
handle_GPDMA1_Channel0.XferCpltCallback = DmaCompleteCallback;
where a flag is set
volatile uint8_t dmaFinished = 0u;
void DmaCompleteCallback(DMA_HandleTypeDef* hdma)
{
dmaFinished = 1u;
}
and starting the calculation with HAL_DMA_Start_IT(...) (followed by a while loop waiting for flag set...)
handle_GPDMA1_Channel0.XferCpltCallback = DmaCompleteCallback;
dmaFinished = 0u;
HAL_DMA_Start_IT(&handle_GPDMA1_Channel0, (uint32_t)&testdata[0], (uint32_t)&CRC->DR, crclen);
while (!dmaFinished)
{
;
}
crc_dma = hcrc.Instance->DR ^ 0xFFFFFFFFu;
it went smoothly :)
Thanks,
Gunter
(Perhaps this helps others faced the same problem...)
2024-09-27 01:02 AM
Thanks for coming back with the solution. Please click on "Accept as solution" in that post so that the thread is marked as solved.
The interesting thing in this is, that 0x83DCEFB7 is CRC of only 1 byte, 0x31. So how comes that when the same sequence is used on 3 bytes, the result is correct...
JW