Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как и куда можно записать пользовательские данные в SAM7x?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
InsolentS
собственно, сабж. В АВРах я для этого юзал епром, а тут видимо надо писать во флеш, но не пойму как, там ведь надо целыми страницами жонглировать?
KRS
Это на всех ARMах с флешой проблема
можно только страницами стерать (у некоторых еще и писать только блоками напимер LPC)
у ST был аппликейшен ноте как из флеша eeprom имитировать
InsolentS
Цитата(KRS @ Apr 18 2007, 00:16) *
Это на всех ARMах с флешой проблема
можно только страницами стерать (у некоторых еще и писать только блоками напимер LPC)
у ST был аппликейшен ноте как из флеша eeprom имитировать


а записать-то можно по-словам? или только внешнаяя епромина?
Сергей Борщ
Цитата(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
InsolentS
Цитата(Сергей Борщ @ Apr 18 2007, 03:20) *

Большое спасибо!!!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.