Самый быстрый вариант, который у меня получился: template< typename T >
static void Calculate( CRC_TypeDef* crc, const T* data, const T* end ) noexcept(true)
{
std::size_t unaligned = (reinterpret_cast<std::uintptr_t>(data) & 0b11u) ?
4u - reinterpret_cast<std::uintptr_t>(data) & 0b11u : 0u;
const std::uint8_t* pu8 = reinterpret_cast< const std::uint8_t* >(data);
while ( unaligned-- )
*reinterpret_cast< volatile std::uint8_t* >(&crc->DR) = *pu8++;
const std::uint32_t* pu32 = reinterpret_cast< const std::uint32_t* >(pu8);
const std::uint32_t* pe32 = reinterpret_cast< const std::uint32_t* >( reinterpret_cast<std::uintptr_t>(end) & ~0b11);
while (pu32 < pe32)
crc->DR = __REV(*pu32++);
pu8 = reinterpret_cast< const std::uint8_t* >(pe32);
while (pu8 < reinterpret_cast< const std::uint8_t* >(end))
*reinterpret_cast< volatile std::uint8_t* >(&crc->DR) = *pu8++;
return;
}
Смысл в том, что вначале считается контрольная сумма невыровненного участка побайтно, затем считается контрольная сумма выровненного участка по словам, в конце обрабатывается хвост. На массиве в 4 Кбайта скорость сравнима с тупым копированием в регистр. Результат, разумеется, корректный, проходит тесты как с выровненными, так и невыровненными входными данными на cortex-m0.
Предложенный вами вариант медленнее почти вдвое.