Files
proxmark3/common_arm/flash_code/flash_code_hw_at91.c
T

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;
}