diff --git a/boards/arduino-due/Makefile.features b/boards/arduino-due/Makefile.features index 68d5a415c8..7da39abc23 100644 --- a/boards/arduino-due/Makefile.features +++ b/boards/arduino-due/Makefile.features @@ -1,4 +1,5 @@ # Put defined MCU peripherals here (in alphabetical order) +FEATURES_PROVIDED += periph_cpuid FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_pwm FEATURES_PROVIDED += periph_random diff --git a/boards/udoo/Makefile.features b/boards/udoo/Makefile.features index 8ef95166a8..d3484cc750 100644 --- a/boards/udoo/Makefile.features +++ b/boards/udoo/Makefile.features @@ -1,4 +1,5 @@ # Put defined MCU peripherals here (in alphabetical order) +FEATURES_PROVIDED += periph_cpuid FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_random FEATURES_PROVIDED += periph_spi diff --git a/cpu/sam3/include/cpu_conf.h b/cpu/sam3/include/cpu_conf.h index 0debff6c02..276fee53cc 100644 --- a/cpu/sam3/include/cpu_conf.h +++ b/cpu/sam3/include/cpu_conf.h @@ -36,6 +36,11 @@ extern "C" { #define CPU_FLASH_BASE IFLASH0_ADDR /** @} */ +/** + * @brief CPUID_ID_LEN length of cpuid in bytes + */ +#define CPUID_ID_LEN (16) /* 128 bits long, 16 bytes long */ + #ifdef __cplusplus } #endif diff --git a/cpu/sam3/periph/cpuid.c b/cpu/sam3/periph/cpuid.c new file mode 100644 index 0000000000..97bd98c69e --- /dev/null +++ b/cpu/sam3/periph/cpuid.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2015 + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup driver_periph + * @{ + * + * @file cpuid.c + * @brief Low-level CPUID driver implementation + * + * @author Dinh Nguyen + * + * @} + */ + +#include + +#include "cpu_conf.h" +#include "periph/cpuid.h" + +#define EFC_FCMD_STUI 0x0E /* Start unique ID */ +#define EFC_FCMD_SPUI 0x0F /* Stop unique ID */ +#define EFC_KEY 0x5A + +/* During the sequence, the software can not run out of Flash */ + +__attribute__ ((section (".ramfunc"))) +void cpuid_get(void *id) +{ + uint32_t cpuid[4]; /* 128 bits sam3 unique indentifier */ + + /* + Reading SAM3 Unique Identifier process (P 19.3.3.8): + - Send the Start Read unique Identifier command (STUI) by writing the Flash Command Register with the + STUI command. + - When the Unique Identifier is ready to be read, the FRDY bit in the Flash Programming Status Register + (EEFC_FSR) falls + - The Unique Identifier is located in the first 128 bits of the Flash memory mapping. So, at the address + 0x400000-0x40008F. + - To stop the Unique Identifier mode, the user needs to send the Stop Read unique Identifier command (SPUI) + by writing the Flash Command Register with the SPUI command. + - When the Stop read Unique Identifier command (SPUI) has been performed, the FRDY bit in the Flash + Programming Status Register (EEFC_FSR) rises. If an interrupt was enabled by setting the FRDY bit in + EEFC_FMR, the interrupt line of the NVIC is activated. + */ + + /* Send STUI */ + EFC1->EEFC_FCR = EEFC_FCR_FKEY(EFC_KEY) | EFC_FCMD_STUI; + + /* Wait for FRDY bit falls */ + while (EFC1->EEFC_FSR & EEFC_FSR_FRDY); + + /* Read UID */ + cpuid[0] = *(uint32_t *)IFLASH1_ADDR; + cpuid[1] = *(uint32_t *)(IFLASH1_ADDR + 4); + cpuid[2] = *(uint32_t *)(IFLASH1_ADDR + 8); + cpuid[3] = *(uint32_t *)(IFLASH1_ADDR + 12); + + /* Send SPUI */ + EFC1->EEFC_FCR = EEFC_FCR_FKEY(EFC_KEY) | EFC_FCMD_SPUI ; + + /* Wait for FRDY bit rises. */ + while (0 == (EFC1->EEFC_FSR & EEFC_FSR_FRDY)); + + memcpy(id, (void*)cpuid, CPUID_ID_LEN); +}