STM32 — правильно используем встроенный flash

от автора

Предисловие

Давно ни для кого не секрет, что STMicroelectronics производит замечательные 32-битные ARM микроконтроллеры STM32. В последнее время они набирают всё большую популярность, и на то есть веские причины, которые в рамках этой статьи я повторять не намерен. Кому интересно — раз, два и три.

Однако у резкого повышения популярности есть и неприятные минусы — довольно часто авторы статей повторяют одни и те-же ошибки. А если ещё и в официальном документе производителя нужный момент описан поверхностно — то тут черт ногу сломит, пока найдёт решение проблемы.

Именно о таком моменте я и хочу рассказать. А именно — как правильно использовать возможность записи во встроенный flash нашего МК. Добро пожаловать под кат.

Курим маны, читаем статьи

Подавляющее большинство статей (а если точнее — вообще все, которые я видел) предлагают реализацию алгоритма, рекомендуемого в официальном мануале по программированию флеша. Вот такого:

Кодим, компилим, проверяем — всё работает. Хорошо работает. Ровно до тех пор, пока вы не включите оптимизацию. Я использую gcc и проверял с ключами -O1 и -O2. Без оптимизации — работает. С оптимизацией — не работает. Нервно курим, пьём кофе, и тратим день-два на поиск проблемы и размышления о бренности бытия.

Как правильно

Уж не знаю, почему производитель советует использовать неправильно работающий алгоритм. Возможно где-то это объяснено, но за два дня у меня так и не получилось ничего найти. Решение-же оказалось довольно простым — в регистре FLASH->SR для контроля окончания операции надо использовать не бит BSY (искренне не понимаю, почему даже ST рекомендует использовать его), а бит EOP, выставляющийся при окончании текущей операции стирания/записи.

Причина проста — по тем или иным причинам на момент проверки бит BSY может быть ещё не выставлен. Однако бит EOP выставляется тогда, и только тогда, когда операция завершена. Сбрасывается этот бит вручную, записью в него единицы. Кодим, проверяем, радуемся жизни.

Сырцы

Для полноты картины необходимо найти и почитать другие статьи на эту тему (ссылка на одну из них приведена выше). Здесь-же прилагаю исходники с кратеньким описанием.

Разблокировка работы с flash — эти две строчки необходимо вставить в функцию инициализации МК:

FLASH->KEYR = 0x45670123; FLASH->KEYR = 0xCDEF89AB; 

Стирание страницы flash — перед записью необходимо стереть данные по нужным адресам, это особенность флеша:

//pageAddress - любой адрес, принадлежащий стираемой странице void Internal_Flash_Erase(unsigned int pageAddress) { 	while (FLASH->SR & FLASH_SR_BSY); 	if (FLASH->SR & FLASH_SR_EOP) { 		FLASH->SR = FLASH_SR_EOP; 	}  	FLASH->CR |= FLASH_CR_PER; 	FLASH->AR = pageAddress; 	FLASH->CR |= FLASH_CR_STRT; 	while (!(FLASH->SR & FLASH_SR_EOP)); 	FLASH->SR = FLASH_SR_EOP; 	FLASH->CR &= ~FLASH_CR_PER; } 

Запись:

//data - указатель на записываемые данные //address - адрес во flash //count - количество записываемых байт, должно быть кратно 2 void Internal_Flash_Write(unsigned char* data, unsigned int address, unsigned int count) { 	unsigned int i;  	while (FLASH->SR & FLASH_SR_BSY); 	if (FLASH->SR & FLASH_SR_EOP) { 		FLASH->SR = FLASH_SR_EOP; 	}  	FLASH->CR |= FLASH_CR_PG;  	for (i = 0; i < count; i += 2) { 		*(volatile unsigned short*)(address + i) = (((unsigned short)data[i + 1]) << 8) + data[i]; 		while (!(FLASH->SR & FLASH_SR_EOP)); 		FLASH->SR = FLASH_SR_EOP; 	}  	FLASH->CR &= ~(FLASH_CR_PG); } 

Вот такие пироги. Приятного всем кодинга и поменьше багов.

ссылка на оригинал статьи http://habrahabr.ru/post/213771/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *