16. STM32. Програмування STM32F103. Flash
Робота із Flash пам`яттю
STM32 не має енергонезалежної EEPROM. EEPROM мають тільки STM32L. Так сталося, що у STMicroelectronics вирішили, ніби EEPROM потрібна тільки для Ultra Low Power серії мікроконтролерів. А що ж нам робити? Нам потрібна енергонезалежна пам`ять. Де нам зберігати наші дані, налаштування, тощо? У Flash! Так, у тій самій пам`яті, де лежить програма мікроконтролера. STM32 може писати у Flash пам`ять.Для того, щоб безпечно щось записати у Flash пам`ять, треба спочатку з`ясувати її структуру. Нас цікавить Main memory. Саме в ній зберігається програма і в цю пам`ять ми будемо писати. Звісно, у не зайняту програмою ділянку пам`яті. Flash пам`ять розбита на сторінки. Кількість і розмір сторінок у різних контролерах різна. Про структуру пам`яті Вашого мікроконтролера читайте у Programming manual.
Ця таблиця наведена для усіх STM32F103 medium-density devices. Наш контролер (STM32F103C8) має 64 Кб Flash пам`яті. Тобто, адреса початку останньої сторінки 0x800FC00.
А тепер "приколи", тобто обмеження при роботі з Flash:
- Писати можна тільки у попередньо витерту пам`ять. У стертої пам`яті усі біти встановлені в "1".
- Витирати можна тільки сторінку цілком. Тобто, ми не можемо витерти 1, 2, чи 10 байтів, тільки цілком сторінку. У нашому випадку - це блок у 1 КБ.
- Писати у Flash треба словами по 32 біта.
Тепер перейдемо до практичної реалізації.
Перед тим, яки починати роботу з Flash треба виконати пару функцій - FLASH_PrefetchBufferCm, FLASH_SetLatency.
void FLASH_Init(void) {
/* Next commands may be used in SysClock initialization function
In this case using of FLASH_Init is not obligatorily */
/* Enable Prefetch Buffer */
FLASH_PrefetchBufferCmd( FLASH_PrefetchBuffer_Enable);
/* Flash 2 wait state */
FLASH_SetLatency( FLASH_Latency_2);
}
Ці функції можуть бути виконані під час налаштування робочої частоти. Дивись статтю "4. STM32. Програмування STM32F103. Тактування"
FLASH Latency рекомендовано встановлювати: FLASH_Latency_0 - 0 < SYSCLK≤ 24 MHz FLASH_Latency_1 - 24 MHz < SYSCLK ≤ 48 MHz FLASH_Latency_2 - 48 MHz < SYSCLK ≤ 72 MHz
Для запису у Flash пам`ять треба її розлочить, стерти сторінку, записати інформацію, залочити Flash:
FLASH_Unlock();
FLASH_ErasePage(MY_FLASH_PAGE_ADDR);
FLASH_ProgramWord((uint32_t)address1, (uint32_t)data1);
FLASH_ProgramWord((uint32_t)address2, (uint32_t)data2);
...
FLASH_ProgramWord((uint32_t)addressn, (uint32_t)datan);
FLASH_Lock();
Читати з флеш:
(*(__IO uint32_t*)address);
Читати 32-бітними словами не завжди зручно і, зазвичай, нам треба зберігати декілька налаштувань різного типу. Для спрощення цього процесу зробимо структуру з параметрами, які нам треба зберігати:
typedef struct
{
char Parameter1; // 1 byte
uint8_t Parameter2; // 1 byte
uint16_t Parameter3; // 2 byte
uint32_t Parameter4; // 4 byte
// 8 byte = 2 * 32 bits words. It`s - OK
// !!! Full size (bytes) must be a multiple of 4 !!!
} tpSettings;
Одна вимога до цієї структури: її довжина має бути кратна 32 бітам, тобто кратна 4 байтам, оскільки ми можемо писати у Flash пам`ять тільки 32 бітними словами. Наприклад, створимо таку структуру, з трьома параметрами:
typedef struct
{
char Parameter1; // 1 byte
uint8_t Parameter2; // 1 byte
unsigned char Parameter3; // 1 byte
// 3 byte = 24 bits. It`s NOT OK!
// !!! Full size (bytes) must be a multiple of 4 !!!
} tpSettings;
Ці параметри займають тільки 3 байти, тобто 24 біти. Треба "дотягнути" розмір до цілого 32-бітного слова. Можна просто добавити додатковий параметр, назвемо його nothing:
typedef struct
{
char Parameter1; // 1 byte
uint8_t Parameter2; // 1 byte
unsigned char Parameter3; // 1 byte
uint8_t nothing; // 1 byte
// 4 byte = 32 bits. It`s - OK
// !!! Full size (bytes) must be a multiple of 4 !!!
} tpSettings;
Тепер нам знадобиться дві функції для зчитування і запису нашої структури:
void FLASH_ReadSettings(void) {
//Read settings
uint32_t *source_addr = (uint32_t *)MY_FLASH_PAGE_ADDR;
uint32_t *dest_addr = (void *)&settings;
for (uint16_t i=0; i<SETTINGS_WORDS; i++) {
*dest_addr = *(__IO uint32_t*)source_addr;
source_addr++;
dest_addr++;
}
}
void FLASH_WriteSettings(void) {
FLASH_Unlock();
FLASH_ErasePage(MY_FLASH_PAGE_ADDR);
// Write settings
uint32_t *source_addr = (void *)&settings;
uint32_t *dest_addr = (uint32_t *) MY_FLASH_PAGE_ADDR;
for (uint16_t i=0; i<SETTINGS_WORDS; i++) {
FLASH_ProgramWord((uint32_t)dest_addr, *source_addr);
source_addr++;
dest_addr++;
}
FLASH_Lock();
}
MY_FLASH_PAGE_ADDR - це адреса сторінки, де ми будемо зберігати наші налаштування. SETTINGS_WORDS - кількість 32-бітних слів, які займає структура.
Повний код програми:
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_flash.h"
// ====================================================
// FLASH Settings struct
// ====================================================
#define MY_FLASH_PAGE_ADDR 0x800FC00
typedef struct
{
char Parameter1; // 1 byte
uint8_t Parameter2; // 1 byte
uint16_t Parameter3; // 2 byte
uint32_t Parameter4; // 4 byte
// 8 byte = 2 32-bits words. It`s - OK
// !!! Full size (bytes) must be a multiple of 4 !!!
} tpSettings;
tpSettings settings;
#define SETTINGS_WORDS sizeof(settings)/4
void FLASH_Init(void) {
/* Next commands may be used in SysClock initialization function
In this case using of FLASH_Init is not obligatorily */
/* Enable Prefetch Buffer */
FLASH_PrefetchBufferCmd( FLASH_PrefetchBuffer_Enable);
/* Flash 2 wait state */
FLASH_SetLatency( FLASH_Latency_2);
}
void FLASH_ReadSettings(void) {
//Read settings
uint32_t *source_addr = (uint32_t *)MY_FLASH_PAGE_ADDR;
uint32_t *dest_addr = (void *)&settings;
for (uint16_t i=0; i<SETTINGS_WORDS; i++) {
*dest_addr = *(__IO uint32_t*)source_addr;
source_addr++;
dest_addr++;
}
}
void FLASH_WriteSettings(void) {
FLASH_Unlock();
FLASH_ErasePage(MY_FLASH_PAGE_ADDR);
// Write settings
uint32_t *source_addr = (void *)&settings;
uint32_t *dest_addr = (uint32_t *) MY_FLASH_PAGE_ADDR;
for (uint16_t i=0; i<SETTINGS_WORDS; i++) {
FLASH_ProgramWord((uint32_t)dest_addr, *source_addr);
source_addr++;
dest_addr++;
}
FLASH_Lock();
}
// ====================================================
int main(void)
{
FLASH_Init();
FLASH_ReadSettings();
settings.Parameter1++;
settings.Parameter2++;
settings.Parameter3++;
settings.Parameter4++;
FLASH_WriteSettings();
while (1)
{
}
}
Пам`ятка
Треба пам`ятати, що Flash пам`ять має ліміт кількості циклів запису. Згідно до документації - мінімум 10000. Це не дуже і багато, якщо досить інтенсивно використовувати Flash пам`ять. Але для зберігання налаштувань цілком достатньо.UPD: Важливо пам'ятати, що для запису у Flash використовуэться HSI - внутрішній тактовий генератор. HSI має бути увімкнений під час запису у Flash.
Бажаю успіхів!
Дивись також:
- 1. STM32. Програмування STM32F103. Тестова плата. Прошивка через UART та через ST-Link
- 2. STM32. Програмування. IDE для STM32
- 3. STM32. Програмування STM32F103. GPIO
- 4. STM32. Програмування STM32F103. Тактування
- 5. STM32. Програмування STM32F103. USART
- 6. STM32. Програмування STM32F103. NVIC
- 7. STM32. Програмування STM32F103. ADC
- 8. STM32. Програмування STM32F103. DMA
- 9. STM32. Програмування STM32F103. TIMER
- 10. STM32. Програмування STM32F103. TIMER. Захоплення сигналу
- 11. STM32. Програмування STM32F103. TIMER. Encoder
- 12. STM32. Програмування STM32F103. TIMER. PWM
- 13. STM32. Програмування STM32F103. EXTI
- 14. STM32. Програмування STM32F103. RTC
- 15. STM32. Програмування STM32F103. BKP
- 16. STM32. Програмування STM32F103. Flash
- 17. STM32. Програмування STM32F103. Watchdog
- 18. STM32. Програмування STM32F103. Remap
- 19. STM32. Програмування STM32F103. I2C Master
- 20. STM32. Програмування STM32F103. I2C Slave
- 21. STM32. Програмування STM32F103. USB
- 22. STM32. Програмування STM32F103. PWR
- 23. STM32. Програмування STM32F103. Option bytes
- 24. STM32. Програмування STM32F103. Bootloader
- STM32. Скачати приклади
- System Workbench for STM32 Інсталяція на Ubuntu
- Keil uVision5 – IDE для STM32
- IAR Workbench – IDE для STM32
- Керування безколекторним двигуном постійного струму (BLDC) за допомогою STM32
- Керування PMSM за допомогою STM32
Ресурс запису можна також збілшити якщо використати принаймні 2 сторінки флеша, заповнюючи кожну по черзі. Цікавий апноут на цю тему від ST з реалізацією для F4: http://www.st.com/content/ccc/resource/technical/document/application_note/ec/dd/8e/a8/39/49/4f/e5/DM00036065.pdf/files/DM00036065.pdf/jcr:content/translations/en.DM00036065.pdf
А точно адреса початку останньої сторінки 0x800FC00 ? Не 0x801FC00 ?
Недавні записи
- Розпізнавання мови (Speech recognition)
- Selenium
- Комп'ютерний зір (Computer Vision)
- Деякі думки про точність вимірювань в електроприводі
- Датчики Холла 120/60 градусів
- Модуль драйверів напівмосту IGBT транзисторів
- Драйвер IGBT транзисторів на A316J
- AS5600. Варіант встановлення на BLDC мотор
- DC-DC для IGBT драйверів ізольований 2 W +15 -8 вольт
- U-FOC - Векторне керування безколекторними моторами
Tags
esp8266 examples adc usart rfid eb-500 soldering lcd stm32 raspberry-pi python mongodb gps mpu-9250 sensors led hih-4000 foc ngnix wifi servo sms ethernet bldc 3d-printer bluetooth mpx4115a web pmsm options remap solar timer bme280 mpu-6050 avr docker flash bkp capture gpio uart meteo i2c usb rtc encoder programmator ssd1306 battery displays java-script barometer watchdog eeprom flask websocket pwm dht11 motor ssd1331 piezo smd brushless atmega books css git st-link dc-dc html nodemcu dma nvic rs-232 exti tim bmp280 max1674
Архіви