in STM32_HAL_CRC there is a function, that calculates CRC for data, that is passed byte by byte.
and if data length is npt a multiple of 4, it calculates CRC of tail:
if ((BufferLength % 4U) != 0U)
{
if ((BufferLength % 4U) == 1U)
{
*(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[4U * i]; /* Derogation MisraC2012 R.11.5 */
}
if ((BufferLength % 4U) == 2U)
{
data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) 1U];
pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
*pReg = data;
}
if ((BufferLength % 4U) == 3U)
{
data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) 1U];
pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
*pReg = data;
*(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[(4U * i) 2U]; /* Derogation MisraC2012 R.11.5 */
}
pBuffer
is pointer to uint8_t array;
CRC Data Register is 32bit width and
Each write operation to the data register creates a combination of the previous CRC value (stored in CRC_DR) and the new one. CRC computation is done on the whole 32-bit data word or byte by byte depending on the format of the data being written.
so, FE,
*(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[4U * i];
writes tail data to MSB(assuming CRC_DR is big endian) of CRC_DR and crc computation with InitialValue = previousCrcResult
and income = previousCrcResult & (pBuffer[4U * i] << 24)
is performed;
after this operation 0x651F2550
in DR is changed on 0x340BC6D9
but when I try this:
_hcrc.Instance->DR = ncrc & ((((uint32_t)pBuffer[4U * i]) << 24) | 0x00FFFFFF);
0x651F2550
in DR is changed on 0x1D87D8BB
also I proposed that CRC_DR is little endian, and tried this:
_hcrc.Instance->DR = ncrc & (0xFFFFFF00 | ((uint32_t)pBuffer[4U * i]));
0x651F2550
in DR is changed on 0xEBCF331F
As for me, the last one looks clearly the same to this
So I don't understand where am I wrong.
And also don't understand what is happening there.
CodePudding user response:
Both of your code suggestions that start _hcrc.Instance->DR =
are writing 32-bit words to the peripheral. This is a different operation from writing a byte to either end of that register. The peripheral knows what type you write and performs more or less CRC cycles depending on the size.
The manual says that byte writes should be right aligned, so you need to do:
*(__IO uint8_t *)(&hcrc->Instance->DR) =
Note that the intermediate cast to void pointer in the HAL is unnecessary.
If you don't want to include the HAL headers then replace __IO
with volatile
.