summaryrefslogtreecommitdiff
path: root/bsp/nuvoton/libraries/m031/rtt_port/drv_crc.c
blob: 6081e52f89cda68cbe5f5c3ee726ffc225ee4022 (plain)
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
97
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
138
139
140
/**************************************************************************//**
*
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date            Author           Notes
* 2021-02-01      klcheng          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_crc.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_err_t result;

    result = rt_mutex_take(&s_CRC_mutex, RT_WAITING_FOREVER);
    RT_ASSERT(result == RT_EOK);

    /* Configure CRC controller  */
    CRC_Open(u32OpMode, u32Attr, u32Seed, CRC_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((*pu8InTempData) & 0xFF);
            pu8InTempData ++;
            i++;
        }
        else
        {
            CRC->CTL &= ~CRC_CTL_DATLEN_Msk;
            CRC->CTL |= CRC_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(*(uint32_t *)pu8InTempData);
            pu8InTempData += 4;
            i += 4;
#endif
        }
    }

    /* Get checksum value */
    u32CalChecksum = CRC_GetChecksum();

    result = rt_mutex_release(&s_CRC_mutex);
    RT_ASSERT(result == RT_EOK);

    return u32CalChecksum;
}

rt_err_t nu_crc_init(void)
{
    SYS_ResetModule(CRC_RST);
    return rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO);
}

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))