Главная arrow Программирование arrow ARM arrow IAR EWB for ARM: работа с внутренней памятью программ (internal flash memory) Thursday, May 25 2017  
ГлавнаяКонтактыАдминистрированиеПрограммированиеСсылки
UK-flag-ico.png English Version
GERMAN-flag-ico.png Die deutsche Version
map.gif карта сайта
нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Поделиться:

IAR EWB for ARM: работа с внутренней памятью программ (internal flash memory) Версия для печати
Написал microsin   
25.06.2010

В статье рассмотрен вопрос перепрошивки flash-памяти контроллеров AT91SAM7X128, AT91SAM7X256, AT91SAM7X512 под управлением программы firmware.

Иногда по разным причинам (bootloader, сохранение настроек, каких-то данных, обновление программы) необходимо иметь возможность модифицировать память программ кристалла непосредственно в выполняемой программе. Быстрый старт в этом вопросе - пример от Atmel c:\Program Files\IAR Systems\Embedded Workbench 5.0 Evaluation\ARM\examples\Atmel\at91sam7x-ek\basic-internalflash-project\. В примере вы найдете все необходимое, он несложен. Но чтобы все заработало, необходимо исправить в нем ошибку.

В регистре MC_FMR (контроллер EFC или EFC0 и EFC1, если используется чип AT91SAM7X512) есть очень важное поле из 8 бит - FMCN. В даташите написано, что туда надо записывать количество циклов тактовой частоты за 1 мкс. В примере basic-internalflash-project все делается в точности, как сказано в даташите - от значения тактовой частоты BOARD_MCK вычисляется 8 бит для поля FMCN и сохраняется в глобальной переменной lMckFMCN (это делается последовательностью вызовов FLASHD_Initialize(BOARD_MCK) -> EFC_SetMasterClock(mck) -> lMckFMCN = FMCN_BITS(lMck)). Потом эта величина используется внутри вызовов EFC_PerformCommand для записи в регистр MC_FMR. Все было бы хорошо, если бы информация в даташите по вычислению поля FMCN была верной.

На самом деле это не так, с чем довелось столкнуться при программировании кристалла AT91SAM7X512. Как известно, у этого кристалла два контроллера flash - EFC0 (обслуживает flash 0x100000..0x13FFFF) и EFC1 (обслуживает flash 0x140000..0x17FFFF). Эти два контроллера ведут себя по-разному по отношению к значению поля FMCN в регистре MC_FMR. Если вычислить поле FMCN как указано в даташите (в примере basic-internalflash-project так все и делается), то контоллер EFC1 программирует свою память совершенно нормально, а программирование памяти контроллером EFC0 сопровождается непредсказуемым поведением ядра микроконтроллера. Опишу условия моего опыта.

Мне было необходимо записать область памяти 0x110000..0x17FFFF кристалла AT91SAM7X512, тактовая частота ядра 48 МГц (кварц на 18.432 МГц, проект заточен для поддержки USB). Почему-то записать могу только в область 0x140000..0x17FFFF, которая обслуживается EFC1, а запись в область 0x110000..0x13FFFF заканчивается глюками и падениями - портятся регистры, программа вылетает то в Abort_Handler, то в Undefined_Handler, то в Reset_Handler, то в Prefetch_Handler. Глюк происходит в FLASHD_Write, при вызове EFC_PerformCommand, и каждый раз случайным образом. Причем если пройти тело EFC_PerformCommand по шагам, то вылета нет.

Константа, записываемая в поле FMCN, у меня равнялась 48 (0x30) - все правильно, ведь за 1 мкс пройдет 48 циклов тактовой частоты. Однако методом подбора значения этого поля мне удалось выяснить, что глюки пропадают начиная с значения поля FMCN, равного 51. Таким образом, для надежной работы следует подобрать значение поля FMCN, либо взять его с запасом, например 64 (0x40) для частоты 48 МГц (и соответственно поправить код макроса FMCN_BITS, вычисляющего значение поля FMCN).

Остальную информацию этой статьи можно почерпнуть из даташита и кода примера basic-internalflash-project.

[Flash AT91SAM7X512]

1. Flash поделена на страницы по 256 (AT91C_IFLASH_PAGE_SIZE) байт, всего 2048 (AT91C_IFLASH_NB_OF_PAGES) страниц. Первые 1024 страницы (0x100000..0x13FFFF) обслуживаются EFC0, следующие 1024 страницы (0x140000..0x17FFFF) обслуживаются EFC1. Память может быть записана только постранично, по 256 байт.

2. Flash также поделена на сектора блокировки по 16384 (AT91C_IFLASH_LOCK_REGION_SIZE) байт, всего 32 сектора (AT91C_IFLASH_NB_OF_LOCK_BITS). В одном секторе 64 страницы по 256 байт. Каждому сектору соответствует бит защиты, который предотвращает запись данных в свой сектор.

3. Для организации собственного bootloader-а (например, с целью обновления firmware) удобно выделить младшие адреса flash (например 0x100000..0x1007FFF) непосредственно под код bootloader, а остальную часть flash (0x108000..0x17FFFFF) - под обновляемую программу.

4. Перед стартом перепрошивки нужно не забыть вызвать FLASHD_Initialize(BOARD_MCK). После этого необходимо защитить код bootloader вызовом FLASHD_Lock (AT91C_IFLASH, 0x107FFF, 0, 0), а перепрошиваемый код разблокировать вызовом FLASHD_Unlock(0x108000, AT91C_IFLASH + AT91C_IFLASH_SIZE - 1, 0, 0).

5. Писать данные можно блоками любого размера, начиная с любого адреса вызовами FLASHD_Write, не заботясь ни о чем (страничная организация памяти и наличие двух регионов, обслуживаемых разными контроллерами, разруливается уже внутри подпрограммы FLASHD_Write), но оптимальнее всего писать блоками, размер которых в байтах делится нацело на 256, и начиная с адреса, младшие 8 бит которого равны 0. В этом случае FLASHD_Write не делает никаких ненужных дополнительных телодвижений.

6. В процессе записи внутренней flash должны быть отключены все прерывания, кроме прерываний, связанных с контроллерами EFC. Кстати, в примере basic-internalflash-project при работе с flash-памятью прерывания не используются, готовность и состояние контроллеров EFC опрашиваются поллингом (периодическими чтениями регистров).

7. Необходимо правильно нестроить количество циклов ожидания при работе с flash-памятью. Это делается в модуле board_lowlevel.c, процедура LowLevelInit (запись регистра EFC_FMR).

[Ссылки]

1. IAR EWB for ARM: учимся управлять сегментами на примере добавления версии по фиксированному адресу.
2IAR EWB for ARM: как поменять абсолютный начальный адрес выполнения программы.
3. IAR EWB for ARM: как из кода C сделать безусловный переход на абсолютный адрес.
4AT91SAM7X: простейший bootloader, читающий firmware с карты SD/MMC (используется EFSL)

Последнее обновление ( 18.05.2011 )
 

Комментарии  

  1. #2 mlecus
    2013-05-0423:50:00 Столкнулся с аналогичной проблемой. Причиной вылета стало то, что память FLASH на время программировани я становится скорее всего недоступной, и если прошивка находится во FLASH - происходит вылет. Поэтому процедура записи во FLASH должна быть с директивой __ramfunc. Дополнительно к этому нужно запрещать прерывания до команды записи в регистр EFC_FCR, и разрешать после считывания подтверждения успешной записи.
  2. #1 maxgrind
    2012-06-0616:24:56 Спасибо за статью. Вот только насчет FMCN в даташите явно говорится про то, что надо писать число циклов за 1.5 мкс, а не за 1 мкс: "When writing the rest of the Flash, this field defines the number of Master Clock cycles in 1.5 microseconds. This number
    must be rounded up".
    У меня тоже вылетал в DataAbort. Только, как потом выяснилось, не из-за настоек EFC, а из за обращения по указателю, который не был выровнен.

    microsin: благодарю за комментарий. Возможно я ошибся - не помню, откуда взялась цифра в 1 мкс. Но то, что пришлось вручную подобрать количество циклов, чтобы самопрошивка flash начала работать нормально - это факт. Код примера, который был от IAR/Atmel, не работал - количество циклов там было неправильное.

Добавить комментарий

:D:lol::-);-)8):-|:-*:oops::sad::cry::o:-?:-x:eek::zzz:P:roll::sigh:

Защитный код
Обновить

< Пред.   След. >

Top of Page
 
microsin © 2017