Перейти к содержанию
    

Запись во FLASH

Я пишу во флеш полусловами (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. как так?

 

категорически извиняюсь. моя ошибка. неправильно посчитал.

post-71075-1519031333_thumb.png

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Где вы тут два uint32_t увидели? 0x00 0x00 0x00 0xCC - это 4 байта, 4 байта*8 бит=32 бита. Что не так?

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Где вы тут два 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.

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я бы с удовольствием сделал без привязки к размеру - вместо 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))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Или используйте #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); я могу передать передать размер в байтах в качестве аргумента?

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так Вы в функцию FLASH_Status WriteFlash(void* src, void* dst, int len) передавайте размер в байтах, а внутри неё на флешку пишите по два байта.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так Вы в функцию FLASH_Status WriteFlash(void* src, void* dst, int len) передавайте размер в байтах, а внутри неё на флешку пишите по два байта.

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

 

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

 

раз пошла такая пьянка может мы решим проблему переполнения страницы? одним топиком двух зайчиков чпокнем.

Изменено пользователем 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;
}

но мне не нравиться. куча аргументов.

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сложно мне сказать, так не понимаю всё глубину полёта мысли.

По мне так сделать функцию с параметрами

 

указатель на данные

кол-во байт для записи

адрес куда писать

 

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

 

А в ней уже проявлять мастерство программирования.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Все базовые (интежер) типы данных компиляторы размещают по адресам кратным их размерности (это для 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 байт

 

В случае примеров "не хорошо" - дополнять руками какими нибудь типовыми полями по нужной размерности :), чтоб компилятор не делал это за вас.

Изменено пользователем картошка

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...