神秘的内存写保护
Mysterious memory write protection
我正在 ATSAME51N20A (Cortex-M4) 上实现串行引导加载程序。我正在通过 UART 读取数据包,并将它们写入内部闪存。对于某些内存地址,闪存写入工作正常,而对于其他地址则根本不起作用。
Here 是数据表。我已经检查了我能找到的所有寄存器配置,一切似乎都没有问题。
这是我的初始化代码:
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;
}
这是我写的flash代码:
#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);
}
我可以从地址 0x1A00
到 0x1E080
(偏移量 145-175)写入闪存页面,但在此之前和之后,应该写入的内存不会改变。
根据数据表,RUNLOCK
负责 NVM 的写保护,我验证了它被设置为解锁所有 NVM 扇区 (0xFFFFFFFF
)。
还有什么可以阻止我写入所有 NVM?
编辑
添加了擦除闪存并在 flash/write 操作后等待的代码。我看到闪存全部被擦除(所有位都设置为高),但写操作不起作用。
想通了。我发出的是擦除页面命令而不是擦除块命令。擦除页仅适用于闪存中的用户数据页,而不适用于主闪存组。
这是对我有用的代码:
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);
我正在 ATSAME51N20A (Cortex-M4) 上实现串行引导加载程序。我正在通过 UART 读取数据包,并将它们写入内部闪存。对于某些内存地址,闪存写入工作正常,而对于其他地址则根本不起作用。
Here 是数据表。我已经检查了我能找到的所有寄存器配置,一切似乎都没有问题。
这是我的初始化代码:
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;
}
这是我写的flash代码:
#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);
}
我可以从地址 0x1A00
到 0x1E080
(偏移量 145-175)写入闪存页面,但在此之前和之后,应该写入的内存不会改变。
根据数据表,RUNLOCK
负责 NVM 的写保护,我验证了它被设置为解锁所有 NVM 扇区 (0xFFFFFFFF
)。
还有什么可以阻止我写入所有 NVM?
编辑
添加了擦除闪存并在 flash/write 操作后等待的代码。我看到闪存全部被擦除(所有位都设置为高),但写操作不起作用。
想通了。我发出的是擦除页面命令而不是擦除块命令。擦除页仅适用于闪存中的用户数据页,而不适用于主闪存组。
这是对我有用的代码:
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);