Информационный портал технической поддержки Центра проектирования интегральных микросхем |
Рисунок 1 - Окно выбора алгоритма программирования FLM в среде Keil
В среде Keil есть шаблонный проект для реализации FLM. Его можно найти в директории, где установлена среда, по пути: Keil_v5\ARM\Flash\_Template. Сама же директория Flash хранит в себе папки с исходниками FLM от популярных производителей микроконтроллеров и их производные – готовые файлы FLM. Шаблонный проект содержит следующие основные файлы:
-FlashDev.c
-FlashPrg.c
-директория Test,
а также файлы проекта среды. Для того, чтобы происходила генерация FLM-файла, в настройках проекта в окне USER, после сборки/компиляции (After Build/Rebuild) указывается следующая команда:
cmd.exe /C copy "Objects\%L" ".\@L.FLM"
В папке Test приведён пример тестирования функций, составляющих алгоритм программирования. К нему обязательно вернёмся, но позже. Сначала реализуем непосредственно алгоритмы.
Приведём список микроконтроллеров Миландр, в которых присутствует внутренняя FLASH-память, поскольку именно для них будем подготавливать новые FLM.
K1901ВЦ1QI;
К1986ВЕ1QI;
К1986ВЕ92QI;
К1986ВК214;
К1986ВК234.
Имеет следующий вид:
struct FlashDevice {
unsigned short Vers; // Version Number and Architecture
char DevName[128]; // Device Name and Description
unsigned short DevType; // Device Type: ONCHIP, EXT8BIT, EXT16BIT, ...
unsigned long DevAdr; // Default Device Start Address
unsigned long szDev; // Total Size of Device
unsigned long szPage; // Programming Page Size
unsigned long Res; // Reserved for future Extension
unsigned char valEmpty; // Content of Erased Memory
unsigned long toProg; // Time Out of Program Page Function
unsigned long toErase; // Time Out of Erase Sector Function
struct FlashSectors sectors[SECTOR_NUM];
};
struct FlashDevice const FlashDevice = {
FLASH_DRV_VERS, // Driver Version, do not modify!
"1986VE1/VE3 IAP 128kB Flash Rev_3", // Device Name
ONCHIP, // Device Type
0x00000000, // Device Start Address
0x00020000, // Device Size in Bytes (128kB)
0x1000, // Programming Page Size
0, // Reserved, must be 0
0xFF, // Initial Content of Erased Memory
5000, // Program Page Timeout 5 Sec
5000, // Erase Sector Timeout 5 Sec
// Specify Size and Address of Sectors
0x00001000, 0x00000000, // Sector Size 4kB (32 Pages)
SECTOR_END
};
FlashPrg.c – это основной файл, где описаны функции для программирования. В шаблоне их представлено 7:
extern int Init (unsigned long adr, // Initialize Flash
unsigned long clk,
unsigned long fnc);
extern int UnInit (unsigned long fnc); // De-initialize Flash
extern int BlankCheck (unsigned long adr, // Blank Check
unsigned long sz,
unsigned char pat);
extern int EraseChip (void); // Erase complete Device
extern int EraseSector (unsigned long adr); // Erase Sector Function
extern int ProgramPage (unsigned long adr, // Program Page Function
unsigned long sz,
unsigned char *buf);
extern unsigned long Verify (unsigned long adr, // Verify Function
unsigned long sz,
unsigned char *buf);
По рекомендациям CMSIS обязательны к реализации 4, а именно:
int EraseSector (unsigned long adr);
int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf);
int Init (unsigned long adr, unsigned long clk, unsigned long fnc);
int UnInit (unsigned long fnc);
А опциональны (не обязательны):
int EraseChip (void);
int BlankCheck (unsigned long adr, unsigned long sz, unsigned char pat);
unsigned long Verify (unsigned long adr, unsigned long sz, unsigned char *buf);
Стоит обратить внимание на обязательность EraseSector (…) и необязательность EraseChip (…). К сожалению, в текущих официальных FLM для микроконтроллеров «Миландр» всегда был реализован EraseChip, а при выборе Erase Sectors сыпались ошибки, потому что данная функция просто не содержала какого-либо описания, хотя и обязательна (ранее функция просто сразу возвращала нужное значение).
Рисунок 2 - Алгоритм операции стирания
FLM загружается в RAM-память. Далее исполняется функция Init() – процедура инициализации. Она необходима для отключения прерываний и настройки тактирования. Важно отметить, что программирование внутренней памяти выполняется при тактировании ядра от внутреннего HSI-генератора. Это позволяет всегда программировать микросхему независимо от того, установлен ли внешний источник частоты на плате или нет. Для микросхем К1986ВК214/234 у данной функции есть дополнительный функционал. Его рассмотрим отдельно. В зависимости от того, что выбрано в окне отладчика - Рисунок 1, поле Download Function (выбрать можно одну из 3-х опций: Erase Chip, Erase Sectors, Do not Erase) происходит стирание полное или по секторам.
При выполнении полного стирания вызывается функция EraseChip (), внутри которой происходит вызов библиотечной EEPROM_EraseAllPages() (драйвер MDR32F9Qx_eeprom.c официальной библиотеки), которая сотрет весь чип. Аппаратно микросхемы К1901ВЦ1QI, К1986ВЕ1QI, К1986ВЕ92QI поддерживают полное стирание всей памяти или стирание страницы. (К1986ВК214/234 вновь отличается – вернёмся к нему отдельно)
При процессе стирания по секторам, как видно из диаграммы рисунка 2, для начала вызывается функция BlankCheck (), которая выполняет роль проверки стертой страницы, сравнивая данные памяти по каждому адресу сектора со значением стертой ячейки. Если ячейка не пуста, то тогда уже вызывается функционал EraseSector(), внутри которого реализована библиотечная функция EEPROM_ErasePage(), потом проверяется следующая страница. Условимся, что в терминах документации на микроконтроллеры, стереть можно страницу, а в терминах функций FLM стирается сектор, поэтому пускай это будет одно и тоже. Если BlankCheck () сразу дает информацию о том, что страница пуста, то понятно, что EraseSector() не вызывается, что позволяет лишний раз не стирать микросхему, тем самым продлевая ресурс FLASH-памяти, который ограничен определенным количеством циклов перезаписи.
После следует вызов UnInit (), в которой происходит процедура деинициализации: возвращение настроек частоты, разрешение прерываний.
Рисунок 3 - Алгоритм операции программирования
По сути, они являются сопутствующими для всех операций с памятью. В зависимости от того, в связке с какой процедурой - стиранием или программированием – вызываются, они могу давать разный функционал. Для этого на их вход и подается третий аргумент:
/*
* Initialize Flash Programming Functions
* Parameter: adr: Device Base Address
* clk: Clock Frequency (Hz)
* fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
* Return Value: 0 - OK, 1 - Failed
*/
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {…}
Далее на рисунке 4 приведён алгоритм верификации, как он реализован и какие функции вызываются.
Рисунок 4 - Алгоритм операции верификации
1. Контроллер FLASH-памяти, в отличие от микроконтроллеров К1901ВЦ1QI, К1986ВЕ1QI, К1986ВЕ92QI, не умеет стирать всю память, а только блок размером 32 Кбайта или страницу (которую принимаем за сектор) размером 512 байт. Поэтому для стирания всей памяти организован цикл последовательного стирания всех блоков:
for (i = 0; i < BLOCK_SIZE * CNT_BLOCK; i += BLOCK_SIZE)
EEPROM_EraseBlock(i, EEPROM_Main_Bank_Select);
Каждый блок имеет размер по 32 КБ. У контроллера К1986ВК234 4 блока, у К1986ВК214 всего 2.
2. Второе важное примечание заключается в том, что загрузчик всех 2-х номиналов микросхем расположен в информационной FLASH-памяти и его можно «затереть», работая с микросхемой. В связи с тем, что таблица векторов непереносима и всегда расположена с адреса 0x0, то с данного адреса может отображаться две области внутренней FLASH-памяти:
Область памяти, которая отображается с адреса 0х0, определяется значением бита FPOR регистра BKP_REG_0E. А именно:
FPOR = 0 - EEPROM_Info_Bank
FPOR = 1 - EEPROM_Main_Bank.
Таким образом, при старте по питанию микросхемы всегда начинают выполнять программу с информационной памяти, где располагается загрузчик. Загрузчик считывает комбинацию на выводах MODE и, если она равна b’00, то устанавливается бит FPOR=1, происходит сброс и переключение памяти на основную. Подробнее об этом можно прочитать в статье про старт микроконтроллеров.
В связи с этими особенностями функционал FLM функции Init (…) при процедуре стирания памяти для микроконтроллеров К1986ВК234/214 расширен:
if (fnc == 1)
{
if ((MDR_BKP->REG_0E & BKP_REG_0E_FPOR) == 0x00000000)
{
for (i = 0; i < PAGE_SIZE * PAGES_TO_BOOT; i += PAGE_SIZE)
EEPROM_ErasePage(i, EEPROM_Info_Bank_Select);
for (i = 0; i < BOOT_SIZE; i++)
EEPROM_ProgramWord (i*4, EEPROM_Info_Bank_Select, BOOT_LOADER[i]);
}
}
Тут происходит проверка, установлен ли бит FPOR, и если нет, то стирается информационная память и в неё записывается стандартный бутлоадер, режимы которого указаны спецификации.
#define READ_BY_EEPROM
uint32_t ReadWord(uint32_t Address)
{
#ifndef READ_BY_EEPROM
return *((volatile uint32_t *)(Address));
#else
return EEPROM_ReadWord(Address, BANK_SELECTOR);
#endif
Каждый из тестовых примеров нужно запускать из ОЗУ-памяти микроконтроллера, контролируя в режиме отладки корректность выполнения реализованных алгоритмов.
Сайт: | https://support.milandr.ru |
E-mail: | support@milandr.ru |
Телефон: | +7 495 221-13-55 |