eddy_em: (Default)
[personal profile] eddy_em
Работая над более свежей версией хронометра для разнообразных соревнований (пока что все еще на STM32, с ESP32 я немного поковырялся, испугался и забил до поры до времени), опять столкнулся с необходимостью сохранения настроек. Сначала взял свой старый сниппет, немножко подкорректировал (сниппет разрабатывался для STM32F0x2), но потом мне стало как-то неуютно от того, что из более чем 110кБ свободной флеш-памяти я использую лишь 1-2кБ. После поиска решений на разных форумах пришел к такому результату.

Проще всего оказалось определить переменную, пользуясь gcc'шным параметром __attribute__:
__attribute__((section(".myvars"))) static const flash_storage Flash_Storage = {
    .all_stored = USERCONF_INITIALIZER
};

А для того, чтобы эта секция находилась точно после всех остальных данных во флеш-памяти, нужно запихнуть после секции .data в линкер-скрипте вот это:
.myvars :
{
  . = ALIGN(1024);
  KEEP(*(.myvars))
} > rom


Кроме этого улучшения я добавил еще бинарный поиск (потому как искать линейно во флеш-памяти среди десятка тысяч записей — процесс очень долгий, а бинарный поиск позволяет за десяток итераций найти последнюю запись):
static int binarySearch(int l, int r){
    while(r >= l){
        int mid = l + (r - l) / 2;
        uint16_t sz = Flash_Data[mid].userconf_sz;
        if(sz == sizeof(user_conf)){
            if(Flash_Data[mid+1].userconf_sz == 0xffff){
                return mid;
            }else{ // element is to the right
                l = mid + 1;
            }
        }else{ // element is to the left
            r = mid - 1;
        }
    }
    return -1; // not found
}

static int get_gooddata(){
    static uint8_t firstrun = 1;
    if(firstrun){
        firstrun = 0;
        if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
            uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
            flsz -= (uint32_t)Flash_Data - FLASH_BASE;
            uint32_t usz = (sizeof(user_conf) + 1) / 2;
            maxnum = flsz / 2 / usz;
        }
    }
    return binarySearch(0, maxnum-2); // -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
}

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org

May 2025

S M T W T F S
    123
45678910
11121314151617
1819202122 2324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 23rd, 2025 07:42 am
Powered by Dreamwidth Studios