Уникальный ID для устройства. STM32. SAM3.

Уникальный идентификатор (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