EEPROM в STM32L с использованием HAL

До сих пор не использовал внутренний EEPROM в STM32L, только режим эмуляции EEPROM в STM32F, и был очень удивлен отсутствием какой-нибудь внятной статьи с описанием работы с данной периферией, нет вообще ничего. Ну да ладно, разобраться не долго, заодно и накидать по быстрому небольшой туториал для быстрого старта и чтобы самому не забыть через время 🙂

Для начала скажу, что я работаю с микроконтроллером семейства STM32L1 и все функции для работы с EEPROM для него находятся в двух файлах: stm32l1xx_hal_flash_ex.c и stm32l1xx_hal_flash_ex.h

Прежде чем производить запись или чтение из EEPROM необходимо разблокировать доступ к памяти и доступ к регистру FLASH_PECR. В HAL для этого есть функция:

HAL_FLASHEx_DATAEEPROM_Unlock (void);

Описание регистра FLASH_PECR (Program/erase control register) для самых любознательных можно найти на странице 84 референс-мануала RM0038.

Если адрес в памяти используется впервые, то можно сразу писать значение в него, во всех остальных случаях его необходимо почистить перед записью:

HAL_FLASHEx_DATAEEPROM_Erase (uint32_t TypeErase, uint32_t Address);

Здесь параметр TypeErase указывает то, каким образом необходимо стереть данные в памяти EEPROM и может принимать следующие значения:

#define FLASH_TYPEERASEDATA_BYTE         (0x00U)  // Стереть байт
#define FLASH_TYPEERASEDATA_HALFWORD     (0x01U)  // Стереть 2 байта
#define FLASH_TYPEERASEDATA_WORD         (0x02U)  // Стереть 4 байта

Address это адрес в памяти EEPROM. В STM32L151 всего 4096 байт EEPROM в диапазоне адресов от 0x08080000 до 0x08080FFF.

В недрах HAL стирание происходит простой записью нулевого значения по адресу в памяти. Перед стиранием необходимо обязательно сначала вызвать функцию HAL_FLASHEx_DATAEEPROM_Unlock(). Это справедливо и для всех остальных функций для работы с EEPROM.

Для записи значения в EEPROM используется следующая функция HAL:

HAL_FLASHEx_DATAEEPROM_Program (uint32_t TypeProgram, uint32_t Address, uint32_t Data);

Здесь параметр TypeProgram — тип программируемой в EEPROM переменной. Данный параметр может принимать следующие значения:

#define FLASH_TYPEPROGRAMDATA_BYTE         (0x00U)  // Записать 1 байт
#define FLASH_TYPEPROGRAMDATA_HALFWORD     (0x01U)  // Записать 2 байта
#define FLASH_TYPEPROGRAMDATA_WORD         (0x02U)  // Записать 4 байта
#define FLASH_TYPEPROGRAMDATA_FASTBYTE     (0x04U)  // Быстро записать 1 байт
#define FLASH_TYPEPROGRAMDATA_FASTHALFWORD (0x08U)  // Быстро записать 2 байта
#define FLASH_TYPEPROGRAMDATA_FASTWORD     (0x10U)  // Быстро записать 4 байта

Разница между быстрой и обычной записью в строке:

CLEAR_BIT(FLASH->PECR, FLASH_PECR_FTDW);

Бит FTDW регистра FLASH_PECR отвечает за запись данных с фиксированным временем. Если он сброшен, то запись байта, полуслова или слова выполняется без какого-либо предыдущего стирания. Если же он установлен, то перед записью байта, полу слова или слова автоматически выполняется фаза стирания, из чего следует, что время записи будет равно 2xTprog.

Последняя функция для работы с EEPROM:

HAL_FLASHEx_DATAEEPROM_Lock (void);

Эта функция блокирует доступ к памяти и доступ к регистру FLASH_PECR.

Для себя написал две небольшие функции для работы с EEPROM в своих приложениях. Функция записи значения в EEPROM:

void writeToEEPROM (uint32_t address, uint32_t value)
{
	HAL_StatusTypeDef flash_ok = HAL_ERROR;

	while (flash_ok != HAL_OK)
	{
		flash_ok = HAL_FLASHEx_DATAEEPROM_Unlock();
	}

	flash_ok = HAL_ERROR;

	while (flash_ok != HAL_OK)
	{
		flash_ok = HAL_FLASHEx_DATAEEPROM_Erase (FLASH_TYPEERASEDATA_WORD, address);
	}

	flash_ok = HAL_ERROR;

	while (flash_ok != HAL_OK)
	{
		flash_ok = HAL_FLASHEx_DATAEEPROM_Program (FLASH_TYPEPROGRAMDATA_WORD, address, value);
	}

	flash_ok = HAL_ERROR;

	while (flash_ok != HAL_OK)
	{
		flash_ok = HAL_FLASHEx_DATAEEPROM_Lock ();
	}
}

Функция чтения из EEPROM не отличается от любой другой функции чтения из памяти:

uint32_t readFromEEPROM (uint32_t address)
{
	return (*(__IO uint32_t *)address);
}

На этом все.

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

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