问题描述
我一直在尝试从 Atmel SAM3U MCU 读取唯一标识符 (UID),但事实证明它比实现它所需要的更困难。有没有人有任何例子或可以建议如何正确阅读它?每当我这样做时,我都会在 do while
循环(如文档状态)中等待 EEFC(闪存 ROM)状态寄存器更改状态,但它从未这样做,因此 MCU 会陷入循环。
这是我正在使用的代码
// must run this from SRAM
__attribute__((section(".ARM.__at_0x20080000"))) void Get_Unique_ID(unsigned int *pdwUniqueID)
{
Efc *p_efc;
unsigned int status;
// clear the array
pdwUniqueID[0] = 0;
pdwUniqueID[1] = 0;
pdwUniqueID[2] = 0;
pdwUniqueID[3] = 0;
// send the Start Read Unique Identifier command (STUI) by writing the Flash Command Register with the STUI command
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;
// wait for the Flash Programming Status Register (EEFC_FSR) to fall
do { status = p_efc->EEFC_FSR; }
while ((status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY);
// the Unique Identifier is located in the first 128 bits of the Flash memory mapping
pdwUniqueID[0] = *(unsigned int *)IFLASH0_ADDR;
pdwUniqueID[1] = *(unsigned int *)(IFLASH0_ADDR + 4);
pdwUniqueID[2] = *(unsigned int *)(IFLASH0_ADDR + 8);
pdwUniqueID[3] = *(unsigned int *)(IFLASH0_ADDR + 12);
// 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
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SPUI;
// when the Stop Read Unique Unique Identifier command (SPUI) has been performed
// the FRDY bit in the Flash Programming Status Register (EEFC_FSR) rises
do { status = p_efc->EEFC_FSR; }
while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
}
请注意,__attribute__((section(".ARM.__at_0x20080000")))
不是通过链接器将此函数动态分配给 SRAM 的最佳方法,我们将不胜感激任何有关如何使其更具动态性的建议。
已解决 问题是我拥有的芯片是假的,所以 SAM-BA 会返回它指定的 SRAM 缓冲区地址中的任何内容。这是 SAM-BA 中的一个错误,因为如果它收到 0x00000000,它应该给出错误或警告消息,然后停止读取。 不要从中国购买假芯片!
谢谢。
解决方法
我认为 p_efc
没有正确初始化。
您创建了一个指向 Efc
数据结构的指针,该数据结构因此指向某物。
然后您将某事写到某处并期望它起作用。
Efc *p_efc;
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;
我的猜测是您需要将其初始化为正确的 EEFC 基址。 datasheet 有以下内容:
SAM3U4(256 KB 内部闪存 版本)嵌入了两个 EEFC(EEFC0 用于 Flash0,EEFC1 用于 Flash1) 而 SAM3U2/1 嵌入了一个 EEFC。
因此,根据您的 MCU 版本,您需要解决 EEFC0 或 EEFC1。我假设您使用 libopencm3 但这适用于任何其他库。寻找 EEFC location define。按照定义/文件/链接我们到达 this page,它告诉我们将 Efc
指针指向 EEFC0_BASE
或 EEFC1_BASE
。我建议您使用 EEFC0
和 EEFC1
定义,因为它使您的代码更便携。
因此,如果您的 Efc 位于 EEFC0
,那么您的代码应该可以工作:
Efc *p_efc = EEFC0;