drv_crc.c 3.6 KB
Newer Older
W
Wayne Lin 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
/**************************************************************************//**
*
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date            Author           Notes
* 2020-7-4        YCHuang12        First version
*
******************************************************************************/

#include <rtconfig.h>

#if (defined(BSP_USING_CRC) && defined(RT_HWCRYPTO_USING_CRC))

#include <string.h>

#include <rtdevice.h>
#include <rtdbg.h>

#include "NuMicro.h"
#include "drv_pdma.h"

/* Private define ---------------------------------------------------------------*/
#define NU_CRYPTO_CRC_NAME  "nu_CRC"

#define CRC_32_POLY     0x04C11DB7
#define CRC_CCITT_POLY  0x00001021
#define CRC_16_POLY     0x00008005
#define CRC_8_POLY      0x00000007

/* Private variables ------------------------------------------------------------*/

static struct rt_mutex s_CRC_mutex;

static rt_uint32_t nu_crc_run(
    uint32_t u32OpMode,
    uint32_t u32Seed,
    uint32_t u32Attr,
    uint8_t *pu8InData,
    uint32_t u32DataLen
)
{
    uint32_t u32CalChecksum = 0;
    uint32_t i = 0;

    rt_mutex_take(&s_CRC_mutex, RT_WAITING_FOREVER);

    /* Configure CRC controller  */
    CRC_Open(u32OpMode, u32Attr, u32Seed, CRC_CPU_WDATA_8);

    uint8_t *pu8InTempData = pu8InData;

    while (i < u32DataLen)
    {
        if (((((uint32_t)pu8InTempData) % 4) != 0) || (u32DataLen - i < 4))
        {
            CRC->CTL &= ~CRC_CTL_DATLEN_Msk;
            CRC_WRITE_DATA(CRC, (*pu8InTempData) & 0xFF);
            pu8InTempData ++;
            i++;
        }
        else
        {
            CRC->CTL &= ~CRC_CTL_DATLEN_Msk;
            CRC->CTL |= CRC_CPU_WDATA_32;
#if defined (NU_CRC_USE_PDMA)
            int32_t i32PDMATransCnt = (u32DataLen - i) / 4 ;

            i32PDMATransCnt = nu_pdma_mempush((void *)&CRC->DAT, pu8InTempData, 32, i32PDMATransCnt);

            if (i32PDMATransCnt > 0)
            {
                pu8InTempData += (i32PDMATransCnt * 4);
                i += (i32PDMATransCnt * 4);
            }
#else
            CRC_WRITE_DATA(CRC, *(uint32_t *)pu8InTempData);
            pu8InTempData += 4;
            i += 4;
#endif
        }
    }

    /* Get checksum value */
    u32CalChecksum = CRC_GetChecksum();
    rt_mutex_release(&s_CRC_mutex);

    return u32CalChecksum;
}

rt_err_t nu_crc_init(void)
{
    SYS_ResetModule(CRC_RST);

W
Wayne Lin 已提交
97
    rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO);
W
Wayne Lin 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    return RT_EOK;
}

rt_uint32_t nu_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length)
{
    uint32_t u32OpMode;
    uint32_t u32CRCAttr = 0;
    rt_uint32_t crc_result = 0;

    //select CRC operation mode
    switch (ctx->crc_cfg.poly)
    {
    case CRC_32_POLY:
        u32OpMode = CRC_32;
        break;
    case CRC_CCITT_POLY:
        u32OpMode = CRC_CCITT;
        break;
    case CRC_16_POLY:
        u32OpMode = CRC_16;
        break;
    case CRC_8_POLY:
        u32OpMode = CRC_8;
        break;
    default:
        return 0;
    }

    u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFOUT) ? CRC_CHECKSUM_RVS : 0; //CRC Checksum Reverse
    u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFIN) ? CRC_WDATA_RVS : 0;  //CRC Write Data Reverse

    //Calculate CRC checksum, using config's last value as CRC seed
    crc_result = nu_crc_run(u32OpMode, ctx->crc_cfg.last_val, u32CRCAttr, (uint8_t *)in, length);

    //update CRC result to config's last value
    ctx->crc_cfg.last_val = crc_result;
    return crc_result ^ 0x00 ^ ctx->crc_cfg.xorout;
}

#endif //#if (defined(BSP_USING_CRC) && defined(RT_HWCRYPTO_USING_CRC))