Цитата(InsolentS @ Apr 17 2007, 20:35)

а записать-то можно по-словам? или только внешнаяя епромина?
В отличие от LPC (про STR не знаю, не смотрел еще) у атмела сделана очень удобная вещь: теневой буфер записи имеет размер страницы и отражен на флеш. Т.е. для имитации eeprom (смены значения в одном 32-битном слове) нужно пройтись по странице, прочитать слово из ячейки, фиктивно записать его туда же, потом записать поверх свое новое значение и выполнить команду "запись со стиранием". Вот кусок кода:
Код
#define MCK_CYCLES ((15ULL * MCK + 5000000) / 10000000)
__ramfunc __arm void FlashCommand_RAM(uint32_t command)
{
AT91C_BASE_MC->MC_FCR = command;
while(!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
}
__arm void FlashCommand(uint32_t command, uint32_t mode)
{
__disable_interrupt();
AT91C_BASE_MC->MC_FMR = mode;
FlashCommand_RAM(command);
__enable_interrupt();
}
inline void RewritePage(uint32_t const* addr)
{
FlashCommand( (0x5AULL * AT91C_MC_KEY / 0xFF) | (((uint32_t)addr >> 7) << 8) | AT91C_MC_FCMD_START_PROG,
(0 * AT91C_MC_FRDY) | (0 * AT91C_MC_LOCKE) | ( 0 * AT91C_MC_PROGE) |
(0 * AT91C_MC_NEBP) | (AT91C_MC_FWS_0FWS) | (MCK_CYCLES * AT91C_MC_FMCN / 0xFF));
}
// ----------------------------------------
config_t Config_in_RAM;
config_t const Config_in_Flash
// ----------------------------------------
void UpdateConfig()
{
volatile uint32_t* pTmp = (uint32_t*)((uint32_t)&Config_in_flash & ~0x7F);
uint32_t* pSegmentEnd = (uint32_t*)(((uint32_t)&Config_in_flash & ~0x7F) + 128);
while(pTmp < pSegmentEnd) // copy previous flash contents to shadow buffer
{
uint32_t Data = *pTmp;
*pTmp++ = Data;
}
uint32_t* pSrc = (uint32_t*)&Config_in_RAM;
uint32_t* pDst = (uint32_t*)&Config_in_Flash;
while(pDst < (uint32_t*)((config_t*)&Config_in_Flash + 1))
{
*pDst++ = *pSrc++;
}
RewritePage((uint32_t const*)&Config_in_flash);
}
по желанию, чтобы перестраховаться от затирания прошивки в случае пропадания питания "в тот самый" момент, можно вынести Config_in_Flash в отдельную страницу (только предварительно объявив сегмент в файле линкера):
Код
#pragma segment = "CONFIG_SEG"
#pragma location = "CONFIG_SEG"
config_t const Config_in_Flash