Цитата(Balabes @ Apr 3 2014, 08:52)

Здравствуйте!
Написал небольшую программульку для того что бы используя один жестко настроенный уарт, настраивать второй на нужную скорость.
Собственно вопрос, могу ли я как то сохранить эти настройки что бы в след раз этого не делать?
Думаю, это классический пример для той самой упомянутой эмуляции EEPROM во Flash процессора.
Я бы предложил несколько иной вариант сохранения настроек во flash.
1. Объявляем в тексте программы, где это надо, некую константу, содержащую настройку:
Код
const int baudRate ATS("SETTINGS") = INITIAL_BAUD;
Очевидно, что это константа может использоваться при настройке UART как вполне нормальная "переменная" - по имени. Подобных констант в проекте может быть много, они могут быть разбросаны по всяким файлам проекта. Самое главное, что они при компоновке соберутся рядышком в одну секцию с именем SETTINGS. Кстати, макро ATS() определено где-то общедоступно как:
Код
#define ATS(s) __attribute__((section(s), noinline, used))
2. Очевидно необходимо, чтобы часть flash, которая будет модифицироваться - а это, как уже понятно, будет секция SETTINGS, - была расположена в отдельной странице. Чтобы не смешаться с исполняемым кодом.
Для этого надо использовать scatter файл для компоновщика. Как там у других IDE не знаю, но под KEIL надо взять за основу *.SCT файл, который генерится автоматически, сменить ему имя (чтобы не затерся при очередной перекомпиляции), указать это имя явно в закладке Linker опций проекта, а сам файл дополнить секцией:
Код
;
; In-flash rewritable params, size 2K, must be 2K aligned (page size of used CPU)
;
LR_IROM3 (0x08000000 + (0x00040000-0x800)) 0x800; load region size_region
{
ER_IROM3 (0x08000000 + (0x00040000-0x800)) 0x800; load address = execution address
{
*(SETTINGS)
}
}
Конкретно дополнение выше сделано для STM32F103xC с 256K (0x40000) flash, при этом использована последняя страница flash (0x00040000-0x800) размером 2K (0x800).
3. Теперь надо научить программу модифицировать константы настройки. Для этого написана функции, которые есть обертки функций записи flash из Стандартной Периферийной Библиотеки к STM32F1xx:
CODE
//---------------------------------------------------------------------------
// Flash Support
//---------------------------------------------------------------------------
#include <stm32f10x_flash.h> // ST32F Lib
#include <rtl.h> // for BOOL, U8, U32, etc...
#include <string.h>
//---------------------------------------------------------------------------
//
#ifdef STM32F10X_HD
#define FLASH_PAGE_SIZE 2048
#else
#define FLASH_PAGE_SIZE 1024
#endif
//---------------------------------------------------------------------------
BOOL Do_ProgramFlash (U8 *src, U32 dst_addr, S32 cnt)
{
if (src && cnt > 0)
{
volatile FLASH_Status _f_status = FLASH_COMPLETE;
for (; cnt >= sizeof(U32) && _f_status == FLASH_COMPLETE;
cnt -= sizeof(U32), dst_addr += sizeof(U32), src += sizeof(U32))
{
_f_status = FLASH_ProgramWord (dst_addr, *(U32 *) src);
}
if (cnt && _f_status == FLASH_COMPLETE) // the rest
{
U32 _val = 0;
U8 *_p = (U8 *) &_val;
while (cnt--)
{
*_p++ = *src++;
}
_f_status = FLASH_ProgramWord (dst_addr, _val);
}
return _f_status == FLASH_COMPLETE;
}
return __FALSE;
}
//---------------------------------------------------------------------------
BOOL FlashData (void *src, const void *dst, int len) // "flash_Data"
{
BOOL _ok = dst
&& src
&& len > 0;
U8 *base = (U8*)((U32)dst/FLASH_PAGE_SIZE*FLASH_PAGE_SIZE);
if (_ok && memcmp (src, dst, len) != 0)
{
volatile FLASH_Status _f_status;
U8 _buf [FLASH_PAGE_SIZE]; // buffer for the valid part of the page...
memcpy (_buf, base, FLASH_PAGE_SIZE); // backup the actual in-flash params area
memcpy (_buf + (((U8 *) dst) - base), src, len); // assign new data
__disable_irq(); // CMSIS
FLASH_Unlock();
FLASH_ClearFlag (FLASH_FLAG_BSY |
FLASH_FLAG_EOP |
FLASH_FLAG_PGERR |
FLASH_FLAG_WRPRTERR); // Clear All pending flags
// Erase and reprogram the flash page
_ok = (_f_status = FLASH_ErasePage ((U32)base)) == FLASH_COMPLETE &&
Do_ProgramFlash (_buf, (U32)base, FLASH_PAGE_SIZE);
FLASH_Lock();
__enable_irq(); // CMSIS
}
return _ok;
}
//---------------------------------------------------------------------------
А теперь, когда настанет время модифицировать константу, надо будет записать:
Код
int newBaud;
....
newBaud = 19200;
...
FlashData(&newBaud, &baudRate, sizeof(baudRate));