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 ?
Tags
bme280 bmp280 gps mpu-6050 options stm32 ssd1331 ssd1306 eb-500 3d-printer soldering tim mpu-9250 dma watchdog piezo exti web raspberry-pi docker ngnix solar bluetooth foc html css brushless flask dc-dc capture gpio avr rs-232 mpx4115a atmega mongodb st-link barometer pwm nvic git java-script programmator dht11 hih-4000 pmsm encoder max1674 smd sensors rtc adc lcd motor timer meteo examples i2c usb flash sms rfid python esp8266 servo books bldc remap eeprom bkp battery ethernet uart usart displays led websocket nodemcu wifi
Архіви
