STM32 H/W CRC 연산

부팅 속도를 개선하기 위해 대시보드 이미지 파일인 PNG를 디코딩하여 플래시에 저장하여 PNG 디코딩 과정에서 발생하는 시간을 없애 부팅 속도를 개선하려고 한다. 외부 플래시에 데이터를 저장하기 때문에 저장된 데이터의 무결성 검사를 해야하며, 일반적으로 MD5, SHA1, SHA256을 많이 사용하지만, STM32F4는 H/W CRC32만 제공하여 CRC로 데이터 무결성을 하려고 한다.

 

STM32F4에서 H/W CRC를 사용하기 위해 아래 이미지와 같이 CubeIDE의 CRC 연산을 활성화 시키도록 한다.

CubeIDE에서 CRC가 활성화되면 아래 코드가 자동으로 생성되며, 아래 생성된 CRC 핸들를 사용하여 H/W CRC 연산을 할 수 있다.

static void MX_CRC_Init(void)
{
    hcrc.Instance = CRC;
    if (HAL_CRC_Init(&hcrc) != HAL_OK)
    {
        Error_Handler();
    }
}

STM32은 두가지의 HW CRC 연산 함수를 제공한다. 하나는 한번에 CRC 연산를 하는 HAL_CRC_Calculate() 함수와 CRC  연산을 누적하는 HAL_CRC_Accumulate() 함수를 제공한다. 두 연산의 CRC 결과는 동일하나 전자의 함수는 메모리가 충분한 환경이라면 간단히 HAL_CRC_Calculate() 함수를 사용하며, 메모리가 충분하지 않다면 HAL_CRC_Accumulate() 함수를 사용하여 데이터를 분할하여 연산하도록 한다.

 

이 두 함수도 지켜야할 규칙이 있는데, 두 함수 모두 H/W 연산을 하기 때문에 데이터 크기는 4바이트의 배수가 되어야 한다. 그래서 데이트 크기를 조정 또는 CRC 연산을 4바이트 배수까지만 연산을 해야 한다. 아래 코드는 4바이트 배수까지만 연산하도록 하였다.

extern CRC_HandleTypeDef hcrc;
uint32_t spinor_crc_calculate(uint8_t *buffer, uint32_t length)
{
    uint32_t crc_length;

    if(length < 4)
        return 0;

    if((length % 4) == 0)
        crc_length = length;
    else
        crc_length = length - (length % 4);

    return HAL_CRC_Calculate(&hcrc, (uint32_t *)buffer, crc_length/4);
}

uint32_t spinor_crc_accumulate(uint8_t *buffer, uint32_t length)
{
    uint32_t crc_length;

    if(length < 4)
        return 0;

    if((length % 4) == 0)
        crc_length = length;
    else
        crc_length = length - (length % 4);

    return HAL_CRC_Accumulate(&hcrc, (uint32_t *)buffer, crc_length/4);
}

그리고 H/W CRC가 CRC32만 지원하기 때문에 데이터를 uint32_t로 형변환하여 연산을 해야 한다. 당연히 데이터 단위가 1바이트에서 4바이트로 변경되었기 때문에 CRC 연산 데이터의 크기도 조정해야 한다.

 

참고로 PNG 디코딩된 데이터의 크기는 약 2.5MB 이며, 이것을 H/W CRC32 연산속도는 40ms 정도의 시간이 소요된다.