ser_num.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * Copyright (c) 2021 ARM Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * ----------------------------------------------------------------------
  19. *
  20. * $Date: 27. May 2021
  21. * $Revision: V1.0.0
  22. *
  23. * Project: CMSIS-DAP Examples LPC-Link2
  24. * Title: ser_num.c CMSIS-DAP Serial Number module for LPC-Link2
  25. *
  26. *---------------------------------------------------------------------------*/
  27. #include <stdint.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include "ser_num.h"
  31. // Serial Number
  32. #define SER_NUM_PREFIX "00A1"
  33. static char SerialNum[32];
  34. #define IAP_LOCATION *(volatile unsigned int *)(0x10400100)
  35. #define IAP_READ_DEVICE_SERIAL_NUMBER 58U
  36. typedef void (*IAP)(unsigned int [],unsigned int[]);
  37. /**
  38. \brief Calculate 32-bit CRC (polynom: 0x04C11DB7, init value: 0xFFFFFFFF)
  39. \param[in] data pointer to data
  40. \param[in] len data length (in bytes)
  41. \return CRC32 value
  42. */
  43. static uint32_t crc32 (const uint8_t *data, uint32_t len) {
  44. uint32_t crc32;
  45. uint32_t n;
  46. crc32 = 0xFFFFFFFFU;
  47. while (len != 0U) {
  48. crc32 ^= ((uint32_t)*data++) << 24U;
  49. for (n = 8U; n; n--) {
  50. if (crc32 & 0x80000000U) {
  51. crc32 <<= 1U;
  52. crc32 ^= 0x04C11DB7U;
  53. } else {
  54. crc32 <<= 1U;
  55. }
  56. }
  57. len--;
  58. }
  59. return (crc32);
  60. }
  61. /**
  62. \brief Get serial number string. First characters are fixed. Last eight
  63. characters are Unique (calculated from devices's unique ID)
  64. \return Serial number string or NULL (callculation of unique ID failed)
  65. */
  66. char *GetSerialNum (void) {
  67. uint32_t command_param[5];
  68. uint32_t status_result[5];
  69. uint32_t uid;
  70. char *str;
  71. IAP iap_entry;
  72. memset(command_param, 0, sizeof(command_param));
  73. memset(status_result, 0, sizeof(status_result));
  74. iap_entry = (IAP)IAP_LOCATION;
  75. command_param[0] = IAP_READ_DEVICE_SERIAL_NUMBER;
  76. iap_entry(command_param, status_result);
  77. str = NULL;
  78. if (status_result[0] == 0U) {
  79. uid = crc32 ((uint8_t *)&status_result[1], 16U);
  80. snprintf(SerialNum, sizeof(SerialNum), "%s%08X", SER_NUM_PREFIX, uid);
  81. str = SerialNum;
  82. }
  83. return (str);
  84. }