Уникальный идентификатор (Unique ID) — уникальный номер устройства, позволяющий отличать его от других устройств.
Примеры:
Токен, где в качестве имени или номера используется уникальный идентификатор. Идентификаторы активно используются практически во всех информационных системах.
Уникальный признак субъекта или объекта доступа.
Хорошим примером будет создание глобальной базы устройств, для обновления и контроля версий прошивок.
1-ое устройство STM32VL-Discovery
Основной документ: “RM0041: STM32F100xx advanced ARM-based 32-bit MCUs”
Регистр “уникальный идентификатор устройства” (96 бит)
Уникальный идентификатор устройства идеально подходит для:
для использования в качестве серийных номеров
для использования в качестве ключей безопасности в целях повышения безопасности кода во флэш-памяти во время
работы и комбинируя этот уникальный идентификатор с криптографических примитивами программного обеспечения и
протоколами для программирования внутренней флэш-памяти
активировать безопасные процессы загрузки и т.д.
96-битный уникальный идентификатор устройства обеспечивает ссылочный номер, который является уникальным для любого
устройства и в любом контексте. Эти биты не могут быть изменены пользователем.
Базовый адрес: 0x1FFFF7E8
Для использования Unique ID, необходимо в программу добавить следующий код:
volatile uint32_t *UniqueID = (uint32_t *)0x1FFFF7E8; volatile uint32_t __UniqueID[3]; __UniqueID[0] = UniqueID[0]; __UniqueID[1] = UniqueID[1]; __UniqueID[2] = UniqueID[2];
2-ое устройство STM32F429I-Discovery
Основной документ RM0090 Reference manual STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439 advanced ARM®-based 32-bit MCUs
Базовый адрес: 0x1FFF7A10
volatile uint32_t *UniqueID = (uint32_t *)0x1FFF7A10; volatile uint32_t __UniqueID[3]; __UniqueID[0] = UniqueID[0]; __UniqueID[1] = UniqueID[1]; __UniqueID[2] = UniqueID[2];
3-ое устройство sam3u4c (128-bit)
Среда для программирования: Atmel Studio 6.2
Основной документ: SAM3U Series Complete Atmel | SMART ARM-based Flash MCU
DATASHEET
Базовый адрес: 0x400E0740
Принципы работы тот же самый, единственное отличие, доступ к ключу не такой простой, как у ST.
uint32_t chipid_read(Chipid *p_chipid, chipid_data_t *p_chipid_data) { if (NULL == p_chipid_data) { return 0xFFFFFFFF; } p_chipid_data->ul_version = (p_chipid->CHIPID_CIDR & CHIPID_CIDR_VERSION_Msk) >> CHIPID_CIDR_VERSION_Pos; p_chipid_data->ul_eproc = (p_chipid->CHIPID_CIDR & CHIPID_CIDR_EPROC_Msk) >> CHIPID_CIDR_EPROC_Pos; p_chipid_data->ul_nvpsiz = (p_chipid->CHIPID_CIDR & CHIPID_CIDR_NVPSIZ_Msk) >> CHIPID_CIDR_NVPSIZ_Pos; p_chipid_data->ul_nvpsiz2 = (p_chipid->CHIPID_CIDR & CHIPID_CIDR_NVPSIZ2_Pos) >> CHIPID_CIDR_NVPSIZ2_Pos; p_chipid_data->ul_sramsiz = (p_chipid->CHIPID_CIDR & CHIPID_CIDR_SRAMSIZ_Msk) >> CHIPID_CIDR_SRAMSIZ_Pos; p_chipid_data->ul_arch = (p_chipid->CHIPID_CIDR & CHIPID_CIDR_ARCH_Msk) >> CHIPID_CIDR_ARCH_Pos; p_chipid_data->ul_nvptyp = (p_chipid->CHIPID_CIDR & CHIPID_CIDR_NVPTYP_Msk) >> CHIPID_CIDR_NVPTYP_Pos; p_chipid_data->ul_extflag = (p_chipid->CHIPID_CIDR & CHIPID_CIDR_EXT) >> 31; if (p_chipid_data->ul_extflag) { p_chipid_data->ul_extid = p_chipid->CHIPID_EXID & CHIPID_EXID_EXID_Msk; } return 0; }
Основная часть программы:
#include <string.h> #include "asf.h" #include "stdio_serial.h" #include "conf_board.h" /// @cond 0 /**INDENT-OFF**/ #ifdef __cplusplus extern "C" { #endif /**INDENT-ON**/ /// @endcond #define STRING_EOL "\r" #define STRING_HEADER "-- CHIPID Example --\r\n" \ "-- "BOARD_NAME" --\r\n" \ "-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL //! Chip ID catalog information: Type ID and its description stream typedef struct chipidtype { /// Identifier uint32_t num; /// Type uint8_t p_str[80]; } chipidtype_t; //! Number of Embedded Processors Supported #define CHIPID_EPROC_SIZE 7 //! Embedded Processors support list const chipidtype_t chipid_eproc[CHIPID_EPROC_SIZE] = { // identifier description {0x1, "ARM946ES"}, {0x2, "ARM7TDMI"}, {0x3, "Cortex-M3"}, {0x4, "ARM920T"}, {0x5, "ARM926EJS"}, {0x6, "Cortex-A5"}, {0x7, "Cortex-M4"} }; //! Number of 1st Non-Volatile Program Memories Supported #define CHIPID_NVPSIZE_SIZE 16 //! 1st Non-Volatile Program Memories support list const chipidtype_t chipid_nvpsize[CHIPID_NVPSIZE_SIZE] = { // identifier description {0x0, "None"}, {0x1, "8K bytes"}, {0x2, "16K bytes"}, {0x3, "32K bytes"}, {0x4, "Reserved"}, {0x5, "64K bytes"}, {0x6, "Reserved"}, {0x7, "128K bytes"}, {0x8, "Reserved"}, {0x9, "256K bytes"}, {0xA, "512K bytes"}, {0xB, "Reserved"}, {0xC, "1024K bytes"}, {0xD, "Reserved"}, {0xE, "2048K bytes"}, {0xF, "Reserved"} }; //! Number of 2nd Non-Volatile Program Memories Supported #define CHIPID_NVPSIZE2_SIZE 16 //! 2nd Non-Volatile Program Memories support list const chipidtype_t chipid_nvpsize2[CHIPID_NVPSIZE2_SIZE] = { // identifier description {0x0, "None"}, {0x1, "8K bytes"}, {0x2, "16K bytes"}, {0x3, "32K bytes"}, {0x4, "Reserved"}, {0x5, "64K bytes"}, {0x6, "Reserved"}, {0x7, "128K bytes"}, {0x8, "Reserved"}, {0x9, "256K bytes"}, {0xA, "512K bytes"}, {0xB, "Reserved"}, {0xC, "1024K bytes"}, {0xD, "Reserved"}, {0xE, "2048K bytes"}, {0xF, "Reserved"} }; //! Number of SRAMs Supported #define CHIPID_SRAMSIZE_SIZE 16 //! SRAMs support list const chipidtype_t chipid_sramsize[CHIPID_SRAMSIZE_SIZE] = { // identifier description {0x0, "48K bytes"}, {0x1, "1K bytes"}, {0x2, "2K bytes"}, {0x3, "6K bytes"}, {0x4, "112K bytes"}, {0x5, "4K bytes"}, {0x6, "80K bytes"}, {0x7, "160K bytes"}, {0x8, "8K bytes"}, {0x9, "16K bytes"}, {0xA, "32K bytes"}, {0xB, "64K bytes"}, {0xC, "128K bytes"}, {0xD, "256K bytes"}, {0xE, "96K bytes"}, {0xF, "512K bytes"} }; //! Number of architectures Supported #define CHIPID_ARCH_SIZE 43 //! Architectures support list const chipidtype_t chipid_archsize[CHIPID_ARCH_SIZE] = { // identifier description {0x19, "AT91SAM9xx Series"}, {0x29, "AT91SAM9XExx Series"}, {0x34, "AT91x34 series"}, {0x37, "CAP7 Series"}, {0x39, "CAP9 Series"}, {0x3B, "CAP11 Series"}, {0x3C, "SAM4E Series"}, {0x40, "AT91x40 Series"}, {0x42, "AT91x42 Series"}, {0x43, "AT91SAMG51 Series"}, {0x44, "AT91SAMG55 Series(49-lead version)"}, {0x45, "AT91SAMG55 Series(64-lead version)"}, {0x46, "AT91SAMG55 Series(100-lead version)"}, {0x47, "AT91SAMG53/SAMG54 Series"}, {0x55, "AT91x55 Series"}, {0x60, "AT91SAM7Axx Series"}, {0x61, "AT91SAM7AQxx Series"}, {0x63, "AT91x63 Series"}, {0x64, "SAM4CxC Series"}, {0x70, "AT91SAM7Sxx Series"}, {0x71, "AT91SAM7XCxx Series"}, {0x72, "AT91SAM7SExx Series"}, {0x73, "AT91SAM7Lxx Series"}, {0x75, "AT91SAM7Xxx Series"}, {0x76, "AT91SAM7SLxx Series"}, {0x80, "ATSAM3UxC Series"}, {0x81, "ATSAM3UxE Series"}, {0x83, "ATSAM3A/SAM4A xC Series"}, {0x84, "ATSAM3X/SAM4X xC Series"}, {0x85, "ATSAM3X/SAM4X xE Series"}, {0x86, "ATSAM3X/SAM4X xG Series"}, {0x88, "ATSAM3S/SAM4S xA Series"}, {0x89, "ATSAM3S/SAM4S xB Series"}, {0x8A, "ATSAM3S/SAM4S xC Series"}, {0x92, "AT91x92 Series"}, {0x93, "ATSAM3NxA/SAM4NxA Series"}, {0x94, "ATSAM3NxB/SAM4NxB Series"}, {0x95, "ATSAM3NxC/SAM4NxC Series"}, {0x98, "ATSAM3SDxA Series"}, {0x99, "ATSAM3SDxB Series"}, {0x9A, "ATSAM3SDxC Series"}, {0xA5, "ATSAM5A Series"}, {0xF0, "AT75Cxx Series"} }; //! Number of ROMs Supported #define CHIPID_NVPTYPE_SIZE 5 //! ROMs support list const chipidtype_t chipid_nvptype[CHIPID_NVPTYPE_SIZE] = { /* identifier description */ {0x0, "ROM"}, {0x1, "ROMless or on-chip Flash"}, {0x4, "SRAM emulating ROM"}, {0x2, "Embedded Flash Memory"}, {0x3, "ROM and Embedded Flash Memory, NVPSIZ is ROM size, NVPSIZ2 is Flash size"} }; //! ChipID data read chipid_data_t g_chipid_data; /** * \brief The function finds chipid from specific list according to ul_id * * \param p_cid_types Pointer to the chipid list. * \param ul_size chipid list size * \param ul_id chipid number * \param p_cid_type pointer to chipid type * \return true if ID is found in list */ static bool chipid_find(const chipidtype_t *p_cid_types, uint32_t ul_size, uint32_t ul_id, chipidtype_t *p_cid_type) { uint32_t ul_counter; for (ul_counter = 0; ul_counter < ul_size; ul_counter++) { if (p_cid_types[ul_counter].num == ul_id) { memcpy(p_cid_type, &p_cid_types[ul_counter], sizeof(chipidtype_t)); return true; } } return false; } /** * \brief The function prints specific chipid data structure. * * \param p_chipid_data Pointer to the chipid data. */ static void chipid_print(chipid_data_t *p_chipid_data) { bool b_found; chipidtype_t cid_type; /* Version */ printf("Version\t0x%lx.\r\n", (unsigned long)p_chipid_data->ul_version); /* Find Embedded Processor */ b_found = chipid_find(chipid_eproc, CHIPID_EPROC_SIZE, p_chipid_data->ul_eproc, &cid_type); if (b_found) { printf("Embedded Processor\t%s.\r\n", cid_type.p_str); } /* Find non-volatile program memory size */ b_found = chipid_find(chipid_nvpsize, CHIPID_NVPSIZE_SIZE, p_chipid_data->ul_nvpsiz, &cid_type); if (b_found) { printf("Nonvolatile program memory size\t%s.\r\n", cid_type.p_str); } /* Find the second non-volatile program memory size */ b_found = chipid_find(chipid_nvpsize2, CHIPID_NVPSIZE2_SIZE, p_chipid_data->ul_nvpsiz2, &cid_type); if (b_found) { printf("Second nonvolatile program memory size\t%s.\r\n", cid_type.p_str); } /* Find internal SRAM size */ b_found = chipid_find(chipid_sramsize, CHIPID_SRAMSIZE_SIZE, p_chipid_data->ul_sramsiz, &cid_type); if (b_found) { printf("Internal SRAM size\t%s.\r\n", cid_type.p_str); } /* Find architecture identifier */ b_found = chipid_find(chipid_archsize, CHIPID_ARCH_SIZE, p_chipid_data->ul_arch, &cid_type); if (b_found) { printf("Architecture identifier\t%s.\r\n", cid_type.p_str); } /* Find non-volatile program memory type */ b_found = chipid_find(chipid_nvptype, CHIPID_NVPTYPE_SIZE, p_chipid_data->ul_nvptyp, &cid_type); if (b_found) { printf("Nonvolatile program memory type\t%s.\r\n", cid_type.p_str); } /* Find extension flag */ if (p_chipid_data->ul_extflag) { printf("Extended chip ID is\t0x%lx. \r\n", (unsigned long)p_chipid_data->ul_extid); } else { puts("Extended chip ID does not exist. \r"); } } /** * \brief Configure UART console. */ static void configure_console(void) { const usart_serial_options_t uart_serial_options = { .baudrate = CONF_UART_BAUDRATE, #ifdef CONF_UART_CHAR_LENGTH .charlength = CONF_UART_CHAR_LENGTH, #endif .paritytype = CONF_UART_PARITY, #ifdef CONF_UART_STOP_BITS .stopbits = CONF_UART_STOP_BITS, #endif }; /* Configure console UART. */ sysclk_enable_peripheral_clock(CONSOLE_UART_ID); stdio_serial_init(CONF_UART, &uart_serial_options); } /** * \brief Application entry point. * * \return Unused (ANSI-C compatibility). */ int main(void) { /* Initialize the system */ sysclk_init(); board_init(); /* Initialize the console uart */ configure_console(); puts(STRING_HEADER); /* Read CHIPID */ chipid_read(CHIPID, &g_chipid_data); /* Dump CHIPID information */ chipid_print(&g_chipid_data); while (1) { } } /// @cond 0 /**INDENT-OFF**/ #ifdef __cplusplus } #endif /**INDENT-ON**/ /// @endcond