【问题标题】:Keil uVision - Atmel SAM3U Read Unique IdentifierKeil uVision - Atmel SAM3U 读取唯一标识符
【发布时间】:2021-05-01 05:20:58
【问题描述】:

我一直在尝试从 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,它应该给出错误或警告消息,然后停止读取。 不要从中国购买假芯片!

谢谢。

【问题讨论】:

  • 有什么理由不写循环,例如while((p_efc->EEFC_FSR & EEFC_FSR_FRDY)==0){}
  • 我问的原因是因为 SAM 部件在一些寄存器中往往具有神秘的未记录副作用。有时您必须在不屏蔽位域的情况下读取整个寄存器,否则会出现未记录的硅奥秘。
  • 循环代码不是我认为的问题。问题是 MCU 没有触发那些 Flash ROM (EEFC) 寄存器位,因此它实际上卡在了那个循环中。
  • 在调用函数之前是否禁用了所有中断(“IRQ 禁用”)?
  • 是的,中断被禁用。

标签: arm embedded microcontroller keil atmel


【解决方案1】:

我不相信 p_efc 已正确初始化。 您创建一个指向 Efc 数据结构的指针,从而指向 something

然后您将 something 写入 somewhere 并期望它能够工作。

Efc *p_efc;
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;

我的猜测是您需要将其初始化为正确的 EEFC 基地址。 datasheet 有以下说法:

SAM3U4(256 KB 内部闪存 版本)嵌入两个 EEFC(Flash0 为 EEFC0,Flash1 为 EEFC1) 而 SAM3U2/1 嵌入了一个 EEFC。

因此,根据您的 MCU 版本,您需要寻址 EEFC0 或 EEFC1。我假设您使用 libopencm3 但这适用于任何其他库。寻找EEFC location define。在我们到达this page 的定义/文件/链接之后,它告诉我们将Efc 指针指向EEFC0_BASEEEFC1_BASE。我建议您使用 EEFC0EEFC1 定义,因为它使您的代码更便携。

因此,如果您的 Efc 位于 EEFC0,那么您的代码应该可以工作:

Efc *p_efc = EEFC0;

【讨论】:

  • 感谢您的建议。我已将其全部更改为放弃指向Efc 数据结构的指针,而是使用EEFC0。此外,我已经在 SRAM 区域中编译了这两个文件(即:MAIN.C 和 UID.C,其中包含上面的代码示例)。代码现在可以工作并且不会冻结,但我得到的值与 SAM-BA 完全不同。任何想法为什么会这样?如果您想查看,我可以上传我的整个简单 Keil 示例项目。
  • 另外,我没有使用 libopencm3。我正在使用 Keil uVision 库并包含 3U1C。 ARM MCU 的这种变体只有一个 EEFC,实际上定义为 EFC0。根据我上面的评论,指针现在已完全删除,并且如前所述,我直接使用定义(IE:EFC0->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;)。所以澄清一下,所有对p_efc-> 的引用现在都只是EFC0->。但是,我没有得到正确的位。我使用上面的代码得到第一个地址0x44203120,根据SAM-BA,它实际上应该是0x574A73F8
猜你喜欢
  • 1970-01-01
  • 2020-11-10
  • 2012-03-25
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多