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. Тестовая плата. Прошивка через последовательный порт и через 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
0x801FC00 наверное так должно быть?)
Додати коментар
Недавні записи
- 🇺🇦 FOC Board STM32F103RB 🧩
- STM32 Motor control SDK - керування оборотами мотора за допомогою потенціометра 📑
- Flask✙Gunicorn✙Nginx➭😎
- STM32 Motor control SDK - програмне керування обертам мотора
- STM32 Motor control SDK - як створити перший проект
- Vue SVG. Приклад побудови живого параметричного креслення
- Вимірювання моменту мотора
- Vue SVG - компонент. Приклад 📑
- Flask + Vue 🏁 Финальный пример 🏁
- Flask, CORS, JSON-файл. Пример#6
Tags
bldc brushless stm32 motor web html css flask atmega foc git java-script pmsm raspberry-pi python websocket mongodb esp8266 nodemcu st-link tim timer docker ngnix programmator ssd1331 ssd1306 wifi uart meteo bme280 bmp280 i2c gps mpu-6050 mpu-9250 sensors 3d-printer options usb barometer remap watchdog flash eeprom rtc bkp encoder pwm servo capture examples dma adc nvic usart gpio books battery dc-dc sms max1674 avr lcd dht11 piezo rs-232 rfid solar exti bluetooth eb-500 displays ethernet led smd soldering mpx4115a hih-4000
Архіви