繁体   English   中英

神秘的内存写保护

[英]Mysterious memory write protection

我正在 ATSAME51N20A (Cortex-M4) 上实现串行引导加载程序。 我正在通过 UART 读取数据包,并将它们写入内部闪存。 对于某些内存地址,闪存写入工作正常,而对于其他内存地址,它根本不起作用。

是数据表。 我已经检查了我能找到的所有寄存器配置,似乎一切正常。

这是我的初始化代码:

void init(void)
{
     GPIOInit();
     USARTInit();

     NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_AUTOWS | NVMCTRL_CTRLA_WMODE_AP | NVMCTRL_CTRLA_PRM_MANUAL;
     hri_mclk_set_AHBMASK_NVMCTRL_bit(MCLK);
     hri_mclk_set_APBBMASK_NVMCTRL_bit(MCLK);

     PAC->WRCTRL.reg = PAC_WRCTRL_PERID(ID_DSU) | PAC_WRCTRL_KEY_CLR;
     MCLK->AHBMASK.reg |= MCLK_AHBMASK_DSU;
     MCLK->APBBMASK.reg |= MCLK_APBBMASK_DSU;
}

这是我写的闪存代码:


#define APPLICATION_START_ADDRESS 0x8000
#define PAGE_SIZE (512U)

void NVMErasePage(uint32_t pageOffset)
{
    // Set the NVM page address that we want to erase
    NVMCTRL->ADDR.reg = (APPLICATION_START_ADDRESS + (pageOffset * PAGE_SIZE));

    // Wait until the NVM controller is ready
    while (0 == NVMCTRL->STATUS.bit.READY);

    // Lock region size is always bigger than the row size
    NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_UR;

    while (0 == NVMCTRL->STATUS.bit.READY); // Unlocking is a fast operation

    // Erase the page that contains our address
    NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EP;

    // Wait until the NVM controller is ready
    while (0 == NVMCTRL->STATUS.bit.READY);
}

void programApplicationFlashPage(uint32_t pageOffset)
{
    uint32_t *flash_buf = (uint32_t *) (APPLICATION_START_ADDRESS + (pageOffset * PAGE_SIZE));
    for (int i = 0; i < PAGE_SIZE/4; i++)
    {
        flash_buf[i] = *(uint32_t *) (memoryLocation + (i));
    }
    while (0 == NVMCTRL->STATUS.bit.READY);
}

我可以从地址0x1A000x1E080 (偏移量为 145-175)写入闪存页面,但在此之前和之后,应该写入的内存不会改变。

根据数据表RUNLOCK负责 NVM 的写保护,我验证将其设置为解锁所有 NVM 扇区( 0xFFFFFFFF )。

还有什么可能阻止我写入所有 NVM?

编辑

添加了擦除闪存并在闪存/写入操作后等待的代码。 我看到闪存全部被擦除(所有位都设置为高电平),但写操作不起作用。

弄清楚了。 我发出的是擦除页命令而不是擦除块命令。 擦除页仅用于闪存中的 USER 数据页,而不是主闪存库。

这是对我有用的代码:

if((flash_addr % BLOCK_SIZE) == 0)
{
    // Set the NVM block address that we want to erase
    NVMCTRL->ADDR.reg = blockAddress;

    // Unlock the region that contains our address
    NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_UR;

    // Wait until the NVM controller is ready
    while (0 == NVMCTRL->STATUS.bit.READY);

    // Erase the block that contains our address
    NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB;

    // Wait until the NVM controller is ready
    while (0 == NVMCTRL->STATUS.bit.READY);
}

for (int i = 0; i < PAGE_SIZE /4; i++)
{
    flash_buf[i] = *(uint32_t *) (memoryLocation + (i));
}
while (0 == NVMCTRL->STATUS.bit.READY);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM