Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Запись во FLASH
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Jenya7
Я пишу во флеш полусловами (uint16_t), как и положено
Код
FLASH_Status WriteFlash(void* src, void* dst, int len)
{
    uint16_t* srcw = (uint16_t*)src;
    volatile uint16_t* dstw = (uint16_t*)dst;

    FLASH_Status status = FLASH_COMPLETE;
    
    FLASH->CR |= FLASH_CR_PG; /* Programm the flash */
    
    while (len)
    {
    *dstw = *srcw;
    while ((FLASH->SR & FLASH_SR_BSY) != 0 )
        
        
    if (*dstw != *srcw )
    {
             status = FLASH_ERROR_PROGRAM;
             break;
    }
    dstw++;
    srcw++;
    //len = len - sizeof(uint16_t);
        len--;
    }
    
    FLASH->CR &= ~FLASH_CR_PG; /* Reset the flag back !!!! */
    
    return status;
}


допустим пишу структуру
Код
typedef struct G_MOTOR_DATA_S
{
    uint8_t debug;
    uint8_t service;
    uint8_t current_mot_num;
    uint8_t storage;
    
    uint32_t max_pos_diff;
    uint32_t max_pos_diff_count;
    uint32_t pwm_min;
    uint32_t pwm_max;
    uint32_t pwm_delta;
    uint32_t max_stabdel;
    
    //run_time
    uint32_t pos_diff_count;
    uint32_t stabdel_count;
    
} GLOB_MOTOR_DATA;

#define GLOB_MOTOR_DATA_HALF_WORD_CNT  18

соответственно размер в uint16_t - 18.
тестирую
Код
glob_mot_data.debug = 0x01;
    glob_mot_data.service = 0x01;
    glob_mot_data.current_mot_num = 0x02;
    glob_mot_data.storage = 0x02;
    
    glob_mot_data.max_pos_diff = 0xAA;
    glob_mot_data.max_pos_diff_count = 0xAA;
    glob_mot_data.pwm_min = 0xBB;
    glob_mot_data.pwm_max = 0xBB;
    glob_mot_data.pwm_delta = 0xCC;
    glob_mot_data.max_stabdel = 0xCC;
    
    size = GLOB_MOTOR_DATA_HALF_WORD_CNT;
    addr = (uint32_t *)(flash_page + offset);
    status = WriteFlash(&glob_mot_data, addr, size);

смотрим в память и что мы видим (на картинке)? растояние между полями не uint32_t а два uint32_t. как так?

категорически извиняюсь. моя ошибка. неправильно посчитал.
arhiv6
Где вы тут два uint32_t увидели? 0x00 0x00 0x00 0xCC - это 4 байта, 4 байта*8 бит=32 бита. Что не так?

И ещё, если вы дефайном GLOB_MOTOR_DATA_HALF_WORD_CNT задаёте размер структуры, то это неправильно, компилятор может при желании выделить всем полям по 4 байта, в том числе и для uint8_t. Вот подробнее.
Jenya7
Цитата(arhiv6 @ Feb 19 2018, 14:44) *
Где вы тут два uint32_t увидели? 0x00 0x00 0x00 0xCC - это 4 байта, 4 байта*8 бит=32 бита. Что не так?

И ещё, если вы дефайном GLOB_MOTOR_DATA_HALF_WORD_CNT задаёте размер структуры, то это неправильно, компилятор может при желании выделить всем полям по 4 байта, в том числе и для uint8_t. Вот подробнее.

глаз замылился. долго тупил в экран, стал считать лишние байты.
я бы с удовольствием сделал без привязки к размеру - вместо while (len) сделать while (*srcw) но так нельзя. если только последним членом в структуре вставить какой нибудь терминатор '\0'.

я слежу чтоб все структуры были /4.
arhiv6
Цитата(Jenya7 @ Feb 19 2018, 17:01) *
я бы с удовольствием сделал без привязки к размеру - вместо while (len) сделать while (*srcw) но так нельзя. если только последним членом в структуре вставить какой нибудь терминатор '\0'.

Или используйте #pragma pack, чтобы компилятор паковал структуру без "пробелов", или, что ещё лучше в вашем случае - избавьтесь от магической константы 18, пусть компилятор сам этот размер высчитывает: вместо
Код
#define GLOB_MOTOR_DATA_HALF_WORD_CNT  18
пишите
Код
#define GLOB_MOTOR_DATA_HALF_WORD_CNT (sizeof(G_MOTOR_DATA_S))
Jenya7
Цитата(arhiv6 @ Feb 19 2018, 15:21) *
Или используйте #pragma pack, чтобы компилятор паковал структуру без "пробелов", или, что ещё лучше в вашем случае - избавьтесь от магической константы 18, пусть компилятор сам этот размер высчитывает: вместо
Код
#define GLOB_MOTOR_DATA_HALF_WORD_CNT  18
пишите
Код
#define GLOB_MOTOR_DATA_HALF_WORD_CNT (sizeof(G_MOTOR_DATA_S))

sizeof высчитывается в uint8_t а я записываю во флеш в uint16_t. при подстановке в WriteFlash(&glob_mot_data, addr, size); я передаю размер в uint16_t, так это определено - писать не байтами а uint16_t.

ааа. если я верну len = len - sizeof(uint16_t); я могу передать передать размер в байтах в качестве аргумента?
arhiv6
Так Вы в функцию FLASH_Status WriteFlash(void* src, void* dst, int len) передавайте размер в байтах, а внутри неё на флешку пишите по два байта.
Jenya7
Цитата(arhiv6 @ Feb 19 2018, 15:44) *
Так Вы в функцию FLASH_Status WriteFlash(void* src, void* dst, int len) передавайте размер в байтах, а внутри неё на флешку пишите по два байта.

так я так и делаю - привожу к (uint16_t*) - но тогда соответственно нужно и размер уменьшать пропорционально len -= sizeof(uint16_t); у меня сейчас len--;

да. точно. спасибо. наконец устаканилось в голове.

раз пошла такая пьянка может мы решим проблему переполнения страницы? одним топиком двух зайчиков чпокнем.
x893
Боже мой.
Это же офигенная проблема.
Как же мы будем её решать ?
Только коллективным разумом будем сравнивать длину с размером страницы и записывать минимальное из этих чисел и передвигать указать на записанное количество и потом её же вычитать из длины и сравнивать её с нулем.
Хотя нет - это путь простой и не подходит гуру программирования.
Будем дисскутировать и делать череж ж...

Вот такой план есть - пойдет ?
Jenya7
Цитата
Только коллективным разумом будем сравнивать длину с размером страницы и записывать минимальное из этих чисел и передвигать указать на записанное количество и потом её же вычитать из длины и сравнивать её с нулем.

я хочу обойтись минимальным количеством аргументов. только текущий адрес.

как бы можно и так
Код
uint32_t SpaceLeft(uint32_t page, uint32_t addr, uint32_t size, uint32_t *overflow)
{
    *overflow = 0;
    uint32_t end_of_page = (page + FLASH_PAGE_SIZE) - 1;
    
    if ((addr + size) > end_of_page)
        *overflow = 1;
    
    return  end_of_page - addr;
}

но мне не нравиться. куча аргументов.
x893
Сложно мне сказать, так не понимаю всё глубину полёта мысли.
По мне так сделать функцию с параметрами

указатель на данные
кол-во байт для записи
адрес куда писать

И возвращать false если нет ошибки и true если жизнь не удалась и сохранить не удалось.

А в ней уже проявлять мастерство программирования.
картошка
Думаю что в тему. Чтоб не парится с прагмапаками, прагмапушами и прагмапопами или аналогичными вещами - нужно усвоить архизнаниё ! wink.gif .

Все базовые (интежер) типы данных компиляторы размещают по адресам кратным их размерности (это для 16 битных и 32 битных компиляторов). При создании структур желательно не микшировать подряд и в праполую char, short и long.
Настоятельно рекомендую сортировать в типовом порядке от 4 байтных - до 1 байтных, Причём при переходе типов самостоятельно дополнять нужными полями нужной размерности.
Пример создания структуры состоящей из фиксированного набора параметров, например три 4 байтных, два 2 байтных и одного однобайтного:

Хорошо:------------------Не хорошо------------------------------------Не хорошо
long------------------------char------------------------------------------- short
long------------------------short (впереди выравнивание + 1)-------- long (впереди выравнивание + 2)
long------------------------long------------------------------------------- short
short-----------------------long-------------------------------------------- long (впереди выравнивание + 2)
short-----------------------long-------------------------------------------- char
char------------------------short------------------------------------------- long (впереди выравнивание + 3)
-----------------------------------------------------------------------------------------------------------------------------
17 байт--------------------18 байт-----------------------------------------24 байт

В случае примеров "не хорошо" - дополнять руками какими нибудь типовыми полями по нужной размерности sm.gif, чтоб компилятор не делал это за вас.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.