mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-09-04 08:24:45 +00:00
48 lines
2.3 KiB
C
48 lines
2.3 KiB
C
//
|
|
// Created by dxl on 2026/5/27.
|
|
//
|
|
#include "flash_code_apis.h"
|
|
|
|
|
|
RAMFUNC
|
|
bool FlashCodeEWriteMinUnit(uint32_t flash_address, const uint32_t *data, uint32_t *flash_start, uint32_t *status) {
|
|
*status = 0x00;
|
|
// The default is AT91C_BASE_EFC0. If the current write address exceeds AT91C_BASE_EFC0,
|
|
// it will automatically switch to AT91C_BASE_EFC1.
|
|
AT91PS_EFC efc_bank = AT91C_BASE_EFC0;
|
|
// If bank1 is currently being writing, we need to calculate the offset to get the starting position of bank1 in flash.
|
|
int offset = 0;
|
|
// Calculate how many pages have been written in total.
|
|
uint32_t page_n = (flash_address - (uint32_t) flash_start) / AT91C_IFLASH_PAGE_SIZE;
|
|
if (page_n >= AT91C_IFLASH_NB_OF_PAGES / 2) {
|
|
// When writing to bank2, we need to recalculate the page from 0 to 1023.
|
|
page_n -= AT91C_IFLASH_NB_OF_PAGES / 2;
|
|
// Switch to AT91C_BASE_EFC1
|
|
efc_bank = AT91C_BASE_EFC1;
|
|
// We need to offset the writes or it will not fill the correct bank write buffer.
|
|
// offset = 65535, 65535 * 4(u32) = 262,140, for write bank1 not bank0.
|
|
offset = (AT91C_IFLASH_NB_OF_PAGES / 2) * AT91C_IFLASH_PAGE_SIZE / sizeof(uint32_t);
|
|
}
|
|
// The Flash of the SAM7S512/256/128 contains a 256-byte write buffer, accessible through a 32-bit interface.
|
|
// The Flash of the SAM7S64/321/32/161/16 contains a 128-byte write buffer, accessible through a 32-bit interface.
|
|
// The writing is not directly written to the flash, but committed to the latch buffer,
|
|
// and then to write the EFC register triggers the erase and write.
|
|
// In addition, the write operation only considers the address of the lower eight bits,
|
|
// so actually only needs to write data to flash_start,
|
|
// and the chip will automatically copy the data to the latch buffer and increase count.
|
|
for (int i = 0; i < FlashCodeGetEWMinUnit() / sizeof(uint32_t); i++) {
|
|
flash_start[offset + i] = data[i];
|
|
}
|
|
efc_bank->EFC_FCR = MC_FLASH_COMMAND_KEY |
|
|
MC_FLASH_COMMAND_PAGEN(page_n) |
|
|
AT91C_MC_FCMD_START_PROG;
|
|
// Wait until flashing of page finishes
|
|
uint32_t sr;
|
|
while (!((sr = efc_bank->EFC_FSR) & AT91C_MC_FRDY));
|
|
if (sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) {
|
|
*status = sr;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|