drv_crc.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-7-4 YCHuang12 First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if (defined(BSP_USING_CRC) && defined(RT_HWCRYPTO_USING_CRC))
  14. #include <string.h>
  15. #include <rtdevice.h>
  16. #include <rtdbg.h>
  17. #include "NuMicro.h"
  18. #include "drv_pdma.h"
  19. /* Private define ---------------------------------------------------------------*/
  20. #define NU_CRYPTO_CRC_NAME "nu_CRC"
  21. #define CRC_32_POLY 0x04C11DB7
  22. #define CRC_CCITT_POLY 0x00001021
  23. #define CRC_16_POLY 0x00008005
  24. #define CRC_8_POLY 0x00000007
  25. /* Private variables ------------------------------------------------------------*/
  26. static struct rt_mutex s_CRC_mutex;
  27. static rt_uint32_t nu_crc_run(
  28. uint32_t u32OpMode,
  29. uint32_t u32Seed,
  30. uint32_t u32Attr,
  31. uint8_t *pu8InData,
  32. uint32_t u32DataLen
  33. )
  34. {
  35. uint32_t u32CalChecksum = 0;
  36. uint32_t i = 0;
  37. rt_mutex_take(&s_CRC_mutex, RT_WAITING_FOREVER);
  38. /* Configure CRC controller */
  39. CRC_Open(u32OpMode, u32Attr, u32Seed, CRC_CPU_WDATA_8);
  40. uint8_t *pu8InTempData = pu8InData;
  41. while (i < u32DataLen)
  42. {
  43. if (((((uint32_t)pu8InTempData) % 4) != 0) || (u32DataLen - i < 4))
  44. {
  45. CRC->CTL &= ~CRC_CTL_DATLEN_Msk;
  46. CRC_WRITE_DATA(CRC, (*pu8InTempData) & 0xFF);
  47. pu8InTempData ++;
  48. i++;
  49. }
  50. else
  51. {
  52. CRC->CTL &= ~CRC_CTL_DATLEN_Msk;
  53. CRC->CTL |= CRC_CPU_WDATA_32;
  54. #if defined (NU_CRC_USE_PDMA)
  55. int32_t i32PDMATransCnt = (u32DataLen - i) / 4 ;
  56. i32PDMATransCnt = nu_pdma_mempush((void *)&CRC->DAT, pu8InTempData, 32, i32PDMATransCnt);
  57. if (i32PDMATransCnt > 0)
  58. {
  59. pu8InTempData += (i32PDMATransCnt * 4);
  60. i += (i32PDMATransCnt * 4);
  61. }
  62. #else
  63. CRC_WRITE_DATA(CRC, *(uint32_t *)pu8InTempData);
  64. pu8InTempData += 4;
  65. i += 4;
  66. #endif
  67. }
  68. }
  69. /* Get checksum value */
  70. u32CalChecksum = CRC_GetChecksum();
  71. rt_mutex_release(&s_CRC_mutex);
  72. return u32CalChecksum;
  73. }
  74. rt_err_t nu_crc_init(void)
  75. {
  76. SYS_ResetModule(CRC_RST);
  77. rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO);
  78. return RT_EOK;
  79. }
  80. rt_uint32_t nu_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length)
  81. {
  82. uint32_t u32OpMode;
  83. uint32_t u32CRCAttr = 0;
  84. rt_uint32_t crc_result = 0;
  85. //select CRC operation mode
  86. switch (ctx->crc_cfg.poly)
  87. {
  88. case CRC_32_POLY:
  89. u32OpMode = CRC_32;
  90. break;
  91. case CRC_CCITT_POLY:
  92. u32OpMode = CRC_CCITT;
  93. break;
  94. case CRC_16_POLY:
  95. u32OpMode = CRC_16;
  96. break;
  97. case CRC_8_POLY:
  98. u32OpMode = CRC_8;
  99. break;
  100. default:
  101. return 0;
  102. }
  103. u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFOUT) ? CRC_CHECKSUM_RVS : 0; //CRC Checksum Reverse
  104. u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFIN) ? CRC_WDATA_RVS : 0; //CRC Write Data Reverse
  105. //Calculate CRC checksum, using config's last value as CRC seed
  106. crc_result = nu_crc_run(u32OpMode, ctx->crc_cfg.last_val, u32CRCAttr, (uint8_t *)in, length);
  107. //update CRC result to config's last value
  108. ctx->crc_cfg.last_val = crc_result;
  109. return crc_result ^ 0x00 ^ ctx->crc_cfg.xorout;
  110. }
  111. #endif //#if (defined(BSP_USING_CRC) && defined(RT_HWCRYPTO_USING_CRC))