Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
revoxhere
GitHub Repository: revoxhere/duino-coin
Path: blob/master/Arduino_Code/uniqueID.cpp
925 views
1
// Copyright © Luiz Henrique Cassettari. All rights reserved.
2
// Licensed under the MIT license.
3
4
#pragma GCC optimize ("-Ofast")
5
6
#include "uniqueID.h"
7
8
ArduinoUniqueID::ArduinoUniqueID()
9
{
10
#if defined(ARDUINO_ARCH_AVR)
11
for (size_t i = 0; i < UniqueIDsize; i++)
12
{
13
id[i] = boot_signature_byte_get(0x0E + i + (UniqueIDsize == 9 && i > 5 ? 1 : 0));
14
}
15
#elif defined(ARDUINO_ARCH_ESP8266)
16
uint32_t chipid = ESP.getChipId();
17
id[0] = 0;
18
id[1] = 0;
19
id[2] = 0;
20
id[3] = 0;
21
id[4] = chipid >> 24;
22
id[5] = chipid >> 16;
23
id[6] = chipid >> 8;
24
id[7] = chipid;
25
26
#elif defined(ARDUINO_ARCH_ESP32)
27
uint64_t chipid = ESP.getEfuseMac();
28
id[0] = 0;
29
id[1] = 0;
30
id[2] = chipid;
31
id[3] = chipid >> 8;
32
id[4] = chipid >> 16;
33
id[5] = chipid >> 24;
34
id[6] = chipid >> 32;
35
id[7] = chipid >> 40;
36
37
#elif defined(ARDUINO_ARCH_SAM)
38
uint16_t status ;
39
/* Send the Start Read unique Identifier command (STUI) by writing the Flash Command Register with the STUI command.*/
40
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
41
do
42
{
43
status = EFC1->EEFC_FSR ;
44
} while ( (status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY ) ;
45
46
/* The Unique Identifier is located in the first 128 bits of the Flash memory mapping. So, at the address 0x400000-0x400003. */
47
uint32_t pdwUniqueID[4];
48
pdwUniqueID[0] = *(uint32_t *)IFLASH1_ADDR;
49
pdwUniqueID[1] = *(uint32_t *)(IFLASH1_ADDR + 4);
50
pdwUniqueID[2] = *(uint32_t *)(IFLASH1_ADDR + 8);
51
pdwUniqueID[3] = *(uint32_t *)(IFLASH1_ADDR + 12);
52
for (uint8_t i = 0; i < 4; i++)
53
{
54
id[i*4+0] = (uint8_t)(pdwUniqueID[i] >> 24);
55
id[i*4+1] = (uint8_t)(pdwUniqueID[i] >> 16);
56
id[i*4+2] = (uint8_t)(pdwUniqueID[i] >> 8);
57
id[i*4+3] = (uint8_t)(pdwUniqueID[i] >> 0);
58
}
59
60
/* To stop the Unique Identifier mode, the user needs to send the Stop Read unique Identifier
61
command (SPUI) by writing the Flash Command Register with the SPUI command. */
62
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI ;
63
64
/* When the Stop read Unique Unique Identifier command (SPUI) has been performed, the
65
FRDY bit in the Flash Programming Status Register (EEFC_FSR) rises. */
66
do
67
{
68
status = EFC1->EEFC_FSR ;
69
} while ( (status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY );
70
71
#elif defined(ARDUINO_ARCH_SAMD)
72
73
#if defined (__SAMD51__)
74
// SAMD51 from section 9.6 of the datasheet
75
#define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x008061FC)
76
#define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x00806010)
77
#define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x00806014)
78
#define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x00806018)
79
#else
80
//#elif defined (__SAMD21E17A__) || defined(__SAMD21G18A__) || defined(__SAMD21E18A__) || defined(__SAMD21J18A__)
81
// SAMD21 from section 9.3.3 of the datasheet
82
#define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x0080A00C)
83
#define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x0080A040)
84
#define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x0080A044)
85
#define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048)
86
#endif
87
88
uint32_t pdwUniqueID[4];
89
pdwUniqueID[0] = SERIAL_NUMBER_WORD_0;
90
pdwUniqueID[1] = SERIAL_NUMBER_WORD_1;
91
pdwUniqueID[2] = SERIAL_NUMBER_WORD_2;
92
pdwUniqueID[3] = SERIAL_NUMBER_WORD_3;
93
94
for (uint8_t i = 0; i < 4; i++)
95
{
96
id[i*4+0] = (uint8_t)(pdwUniqueID[i] >> 24);
97
id[i*4+1] = (uint8_t)(pdwUniqueID[i] >> 16);
98
id[i*4+2] = (uint8_t)(pdwUniqueID[i] >> 8);
99
id[i*4+3] = (uint8_t)(pdwUniqueID[i] >> 0);
100
}
101
102
#elif defined(ARDUINO_ARCH_STM32)
103
uint32_t pdwUniqueID[3];
104
pdwUniqueID[0] = HAL_GetUIDw0();
105
pdwUniqueID[1] = HAL_GetUIDw1();
106
pdwUniqueID[2] = HAL_GetUIDw2();
107
for (uint8_t i = 0; i < 3; i++)
108
{
109
id[i*4+0] = (uint8_t)(pdwUniqueID[i] >> 24);
110
id[i*4+1] = (uint8_t)(pdwUniqueID[i] >> 16);
111
id[i*4+2] = (uint8_t)(pdwUniqueID[i] >> 8);
112
id[i*4+3] = (uint8_t)(pdwUniqueID[i] >> 0);
113
}
114
#elif defined(ARDUINO_TEENSY40) || defined (ARDUINO_TEENSY41)
115
uint32_t uid0 = HW_OCOTP_CFG0;
116
uint32_t uid1 = HW_OCOTP_CFG1;
117
id[0] = uid0 >> 24;
118
id[1] = uid0 >> 16;
119
id[2] = uid0 >> 8;
120
id[3] = uid0;
121
id[4] = uid1 >> 24;
122
id[5] = uid1 >> 16;
123
id[6] = uid1 >> 8;
124
id[7] = uid1;
125
#elif defined(TEENSYDUINO)
126
uint8_t mac[6];
127
uint8_t sn[4];
128
uint32_t num = 0;
129
__disable_irq();
130
#if defined(HAS_KINETIS_FLASH_FTFA) || defined(HAS_KINETIS_FLASH_FTFL)
131
FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
132
FTFL_FCCOB0 = 0x41;
133
FTFL_FCCOB1 = 15;
134
FTFL_FSTAT = FTFL_FSTAT_CCIF;
135
while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
136
num = *(uint32_t *)&FTFL_FCCOB7;
137
#elif defined(HAS_KINETIS_FLASH_FTFE)
138
kinetis_hsrun_disable();
139
FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
140
*(uint32_t *)&FTFL_FCCOB3 = 0x41070000;
141
FTFL_FSTAT = FTFL_FSTAT_CCIF;
142
while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
143
num = *(uint32_t *)&FTFL_FCCOBB;
144
kinetis_hsrun_enable();
145
#endif
146
__enable_irq();
147
sn[0] = num >> 24;
148
sn[1] = num >> 16;
149
sn[2] = num >> 8;
150
sn[3] = num;
151
mac[0] = 0x04;
152
mac[1] = 0xE9;
153
mac[2] = 0xE5;
154
mac[3] = sn[1];
155
mac[4] = sn[2];
156
mac[5] = sn[3];
157
id[0] = SIM_UIDML >> 24;
158
id[1] = SIM_UIDML >> 16;
159
id[2] = SIM_UIDML >> 8;
160
id[3] = SIM_UIDML;
161
id[4] = SIM_UIDL >> 24;
162
id[5] = SIM_UIDL >> 16;
163
id[6] = 0x40; // marked as version v4, but this uuid is not random based !!!
164
id[7] = SIM_UIDL >> 8;
165
id[8] = 0x80; //variant
166
id[9] = SIM_UIDL;
167
id[10] = mac[0];
168
id[11] = mac[1];
169
id[12] = mac[2];
170
id[13] = mac[3];
171
id[14] = mac[4];
172
id[15] = mac[5];
173
#elif defined(ARDUINO_ARCH_MBED_RP2040)
174
getUniqueSerialNumber(id);
175
#elif defined(ARDUINO_ARCH_MEGAAVR)
176
id[0] = SIGROW.SERNUM0;
177
id[1] = SIGROW.SERNUM1;
178
id[2] = SIGROW.SERNUM2;
179
id[3] = SIGROW.SERNUM3;
180
id[4] = SIGROW.SERNUM4;
181
id[5] = SIGROW.SERNUM5;
182
id[6] = SIGROW.SERNUM6;
183
id[7] = SIGROW.SERNUM7;
184
id[8] = SIGROW.SERNUM8;
185
id[9] = SIGROW.SERNUM9;
186
#endif
187
}
188
189
ArduinoUniqueID _UniqueID;
190
191