drv_crc.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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-3-4 CHChen 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_err_t result;
  38. result = rt_mutex_take(&s_CRC_mutex, RT_WAITING_FOREVER);
  39. RT_ASSERT(result == RT_EOK);
  40. /* Configure CRC controller */
  41. CRC_Open(u32OpMode, u32Attr, u32Seed, CRC_CPU_WDATA_8);
  42. uint8_t *pu8InTempData = pu8InData;
  43. while (i < u32DataLen)
  44. {
  45. if (((((uint32_t)pu8InTempData) % 4) != 0) || (u32DataLen - i < 4))
  46. {
  47. CRC->CTL &= ~CRC_CTL_DATLEN_Msk;
  48. CRC_WRITE_DATA((*pu8InTempData) & 0xFF);
  49. pu8InTempData ++;
  50. i++;
  51. }
  52. else
  53. {
  54. CRC->CTL &= ~CRC_CTL_DATLEN_Msk;
  55. CRC->CTL |= CRC_CPU_WDATA_32;
  56. #if defined (NU_CRC_USE_PDMA)
  57. int32_t i32PDMATransCnt = (u32DataLen - i) / 4 ;
  58. i32PDMATransCnt = nu_pdma_mempush((void *)&CRC->DAT, pu8InTempData, 32, i32PDMATransCnt);
  59. if (i32PDMATransCnt > 0)
  60. {
  61. pu8InTempData += (i32PDMATransCnt * 4);
  62. i += (i32PDMATransCnt * 4);
  63. }
  64. #else
  65. CRC_WRITE_DATA(*(uint32_t *)pu8InTempData);
  66. pu8InTempData += 4;
  67. i += 4;
  68. #endif
  69. }
  70. }
  71. /* Get checksum value */
  72. u32CalChecksum = CRC_GetChecksum();
  73. result = rt_mutex_release(&s_CRC_mutex);
  74. RT_ASSERT(result == RT_EOK);
  75. return u32CalChecksum;
  76. }
  77. rt_err_t nu_crc_init(void)
  78. {
  79. SYS_ResetModule(CRC_RST);
  80. return rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO);
  81. }
  82. rt_uint32_t nu_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length)
  83. {
  84. uint32_t u32OpMode;
  85. uint32_t u32CRCAttr = 0;
  86. rt_uint32_t crc_result = 0;
  87. //select CRC operation mode
  88. switch (ctx->crc_cfg.poly)
  89. {
  90. case CRC_32_POLY:
  91. u32OpMode = CRC_32;
  92. break;
  93. case CRC_CCITT_POLY:
  94. u32OpMode = CRC_CCITT;
  95. break;
  96. case CRC_16_POLY:
  97. u32OpMode = CRC_16;
  98. break;
  99. case CRC_8_POLY:
  100. u32OpMode = CRC_8;
  101. break;
  102. default:
  103. return 0;
  104. }
  105. u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFOUT) ? CRC_CHECKSUM_RVS : 0; //CRC Checksum Reverse
  106. u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFIN) ? CRC_WDATA_RVS : 0; //CRC Write Data Reverse
  107. //Calculate CRC checksum, using config's last value as CRC seed
  108. crc_result = nu_crc_run(u32OpMode, ctx->crc_cfg.last_val, u32CRCAttr, (uint8_t *)in, length);
  109. //update CRC result to config's last value
  110. ctx->crc_cfg.last_val = crc_result;
  111. return crc_result ^ 0x00 ^ ctx->crc_cfg.xorout;
  112. }
  113. #endif //#if (defined(BSP_USING_CRC) && defined(RT_HWCRYPTO_USING_CRC))