реклама на сайте
подробности

 
 
> Запись структуры во флэш.
Jenya7
сообщение Nov 25 2014, 08:32
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Я работаю с камнем EFM32TG842. У него есть сектор во флэше для записи данных пользователя - страница 512 байт. Я хочу записать туда свою структуру.
Код
struct sFlashParam
{
    uint16_t customerID;
    uint32_t mainCounter;        
    uint32_t CWcounter;
    uint8_t  mode;                
    uint8_t  channel;             
    uint8_t  meter_type;
       …и так далее.
}

и потом пишу.
Код
      
WriteToFlash(0x0FE00000, (uint32_t*)&flashParam1);

функция выглядит так
Код
void WriteToFlash(uint32_t address, uint32_t *data)
{
    uint32_t *addr = (uint32_t *) address;  //(uint32_t *)0x0FE00000;
    MSC_Init();
    MSC_ErasePage(addr);
    MSC_WriteWord(addr, data, sizeof(data));
    MSC_Deinit();
}

вопрос как структура запишется? каждый член структуры в 32-битный регистр?
и как мне считать структуру из флэша?


Go to the top of the page
 
+Quote Post
3 страниц V  < 1 2 3 >  
Start new topic
Ответов (15 - 29)
Golikov A.
сообщение Nov 25 2014, 12:39
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Код
flashParam1 = *(struct sFlashParam1*)0x0FE00000;


А это по стандарту? Это как-то подменяется на memcpy неявно?
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Nov 25 2014, 12:48
Сообщение #17


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(Golikov A. @ Nov 25 2014, 17:39) *
Код
flashParam1 = *(struct sFlashParam1*)0x0FE00000;


А это по стандарту? Это как-то подменяется на memcpy неявно?

у меня тоже такой вопрос возник. посмотрел в листинг но там ассемблер ничего не понятно.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Nov 25 2014, 13:48
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Мне как-то кажется такое присвоение не корректным, такого рода вещи решается не просмотром листинга а чтением стандарта. Но сейчас нет возможности, потому спросил, может кто из старших товарищей сразу знает ответ. Если не ответят позже надо будет почитать.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Nov 25 2014, 14:25
Сообщение #19


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Jenya7 @ Nov 25 2014, 10:32) *
Я работаю с камнем EFM32TG842. У него есть сектор во флэше для записи данных пользователя - страница 512 байт. Я хочу записать туда свою структуру.

Код
void WriteToFlash(const uint32_t address, void const *data, uint32_t size)
{
    size = 4 * ((size + 3)/4); // always divisable by 4
    MSC_Init();
    MSC_ErasePage((const uint32_t *)address);
    MSC_WriteWord((const uint32_t *)address, data, size);
    MSC_Deinit();
}

Код
WriteToFlash(USERDATA_BASE, &my_struct, sizeof(my_struct));


Не забудьте также разместить функции работы с флэш в ОЗУ (требование процессора). В библиотеке уже все подготовлено, но в среде разработки в скаттер-файле надо указать разместить секцию ram_code в ОЗУ. Для KEIL это будет модификация подсекции загрузки ОЗУ:
Код
  RW_IRAM1 0x20000000 0x00004000  {; RW data
  *(ram_code, +First)             ; flash erase/write functions
   .ANY (+RW +ZI)
  }
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Nov 25 2014, 14:43
Сообщение #20


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(KnightIgor @ Nov 25 2014, 19:25) *
...


спасибо большое за ЦУ. а __attribute__ ((section(".ram"))) не поможет? вроде как это тоже указание на размещение функции в ram.

Сообщение отредактировал IgorKossak - Nov 25 2014, 15:10
Причина редактирования: избыточное цитирование
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Nov 25 2014, 16:47
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



получается копирование структур по указателю выдается на откуп компилятора. Если он умеет копировать каждое поле структуры, то он это может сделать. При этом указатели внутри буду скопированы по значению, то есть будут указывать на ту же область что в исходной структуре, и даже есть шанс что процедура копирования будет оптимизирована под конкретную архитектуру. То есть фактически полный аналог memcpy, интересно....
Go to the top of the page
 
+Quote Post
scifi
сообщение Nov 25 2014, 16:54
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Golikov A. @ Nov 25 2014, 15:39) *
Код
flashParam1 = *(struct sFlashParam1*)0x0FE00000;

А это по стандарту? Это как-то подменяется на memcpy неявно?

В стандарте нет ничего, что это запрещало бы. С точностью до выравнивания, я думаю, но здесь адрес настолько ровный, что не важно. Ну и по крайней мере с одним компилятором видел, что туда тупо подставляется memcpy.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Nov 25 2014, 17:37
Сообщение #23


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Jenya7 @ Nov 25 2014, 16:43) *
спасибо большое за ЦУ. а __attribute__ ((section(".ram"))) не поможет? вроде как это тоже указание на размещение функции в ram.

Функции работы с флэшем в библиотеке для EFM32 уже объявлены и "сложены" в именованную секцию "ram_code", поэтому нужно секцию "ram_code" лишь как-то поместить в ОЗУ. Как написано в помощи к функции WriteWord
Цитата
The flash must be erased prior to writing a new word. This function must be run from RAM. Failure to execute this portion of the code in RAM will result in a hardfault. For IAR, Rowley and Codesourcery this will be achieved automatically. For Keil uVision 4 you must define a section called "ram_code" and place this manually in your project's scatter file.

Кстати, коль мы о секциях заговорили.
Вы можете разместить структуру напрямую в пользовательской странице и работать с ней в коде программы как с нормальной константой во flash:
Код
const MyType MyStruct __attribute__((section("MYDATA"), used)) = {<init fields>};

В скаттере надо указать, чтобы все константы секции были размещены в пользовательской странице, то есть добавить load region
Код
LR_IROM_SETS   (0xFE00000) 0x200  {; User settings in the user    
  ER_IROM_SETS (0x0FE00000) 0x200  {; flash page
    *(MYDATA)
  }
}

В итоге, можно иметь константы, объявленные в разных участках кода, разных файлах проекта, но принадлежащие одной и той же именованной секции, как это показано выше, и пользовать их как обычные константы. А компоновщик кинет все в нужную область флэша согласно указанию из скаттера. Затем можно, например, через коммуникационный протокол модифицировать все эти константы, настраивая таким образом приложение. Например, сменить адрес узла, и т.п. И не надо хранить "копии" настроек из флэш в ОЗУ: в конце концов ОЗУ в контроллерах всегда существенно меньше, чем флэш.

Сообщение отредактировал KnightIgor - Nov 25 2014, 17:40
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Nov 25 2014, 17:58
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



но как я понимаю главное в коде не забыться и не начать обращаться к переменным из флеша на запись? Можно конечно их все объявить константами, но тогда будет не очень удобно обновлять параметры из меню пользователя или через внешний протокол... если это только константы, то да удобно. Я во флэш пихал таблицы остатков при расчете crc16, очень удобно и они прям оттуда и брались при работе
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Nov 25 2014, 22:43
Сообщение #25


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Golikov A. @ Nov 25 2014, 19:58) *
Можно конечно их все объявить константами, но тогда будет не очень удобно обновлять параметры из меню пользователя или через внешний протокол... если это только константы, то да удобно.

Если параметры во флэше, - а я бы назвал это настройками, - обновляются не по 10 раз в секунду, а в какие-либо ключевые моменты жизни приложения, после чего последнее пользуется результатами и делает свою работу, то почему же не удобно обновлять прямо во флэше? Например, коэффициенты коррекций и поправок в системе с ADC, и т.п. Ну, вначале, при калибровке, может и надо будет раз 20 перезаписать настройки, но потом они будут довольно долго неизменны. Или вот пример из нашей практики. Надо управлять светодиодами через ШИМ. Характеристка вход-выход выражается степенной функцией (гамма-коррекция). Если считать на лету каждый раз по формуле для нескольких каналов, можно перегрузить процессор. Можно работать и по таблице, но ее надо качать по каналу. Мы же меняем показатель (гамму) короткой командой, а процессор тут же единожды вычисляет и создает таблицу, которой потом и пользуется постоянно. Все во флэше.
Go to the top of the page
 
+Quote Post
juvf
сообщение Nov 26 2014, 04:40
Сообщение #26


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(scifi @ Nov 25 2014, 17:00) *
Вы будете смеяться, но это то же самое, что и
Код
flashParam1 = *(struct sFlashParam1*)0x0FE00000;

это совершенно разные вещи.

так структуру объявлять не правильно, тем более для 32-х разрядного проца. Нужно выравнивать к 4-ём. Чтоб не париться над выравниванием лучше в структуре сначало объявить 32-х битные переменные ,потом 16-ти, затем 8-ми.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Nov 26 2014, 06:26
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



да вот что-то получается что так наоборот даже более правильно чем через memcpy напрямую.

Цитата
то почему же не удобно обновлять прямо во флэше...

ну то есть у вас в коде это константы и вы их изменить не можете из программы. И есть дополнительные функции которые просто меняют область флеши, фактически не думая что там лежит и тем самым обходят защиту const.
В целом решение, проблему вижу только при изменении структуры настроек во время модификации кода, надо не забыть поправить ее в 2 местах. То есть и саму структуру и функции ее сохранения-модификации во флеше.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Nov 26 2014, 07:02
Сообщение #28


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(juvf @ Nov 26 2014, 09:40) *
это совершенно разные вещи.

так структуру объявлять не правильно, тем более для 32-х разрядного проца. Нужно выравнивать к 4-ём. Чтоб не париться над выравниванием лучше в структуре сначало объявить 32-х битные переменные ,потом 16-ти, затем 8-ми.

как я понял если не указывать явно packed компайлер по дефолту делает padding.

Цитата(KnightIgor @ Nov 25 2014, 22:37) *
Функции работы с флэшем в библиотеке для EFM32 уже объявлены и "сложены" в именованную секцию "ram_code", поэтому нужно секцию "ram_code" лишь как-то поместить в ОЗУ. Как написано в помощи к функции WriteWord

Кстати, коль мы о секциях заговорили.
Вы можете разместить структуру напрямую в пользовательской странице и работать с ней в коде программы как с нормальной константой во flash:
Код
const MyType MyStruct __attribute__((section("MYDATA"), used)) = {<init fields>};

В скаттере надо указать, чтобы все константы секции были размещены в пользовательской странице, то есть добавить load region
Код
LR_IROM_SETS   (0xFE00000) 0x200  {; User settings in the user    
  ER_IROM_SETS (0x0FE00000) 0x200  {; flash page
    *(MYDATA)
  }
}

В итоге, можно иметь константы, объявленные в разных участках кода, разных файлах проекта, но принадлежащие одной и той же именованной секции, как это показано выше, и пользовать их как обычные константы. А компоновщик кинет все в нужную область флэша согласно указанию из скаттера. Затем можно, например, через коммуникационный протокол модифицировать все эти константы, настраивая таким образом приложение. Например, сменить адрес узла, и т.п. И не надо хранить "копии" настроек из флэш в ОЗУ: в конце концов ОЗУ в контроллерах всегда существенно меньше, чем флэш.


Я пишу в Attolic TrueStudio и я честно говоря не нашел там скаттер файл.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 26 2014, 07:05
Сообщение #29


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(juvf @ Nov 26 2014, 06:40) *
так структуру объявлять не правильно
Это было не объявление структуры.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
scifi
сообщение Nov 26 2014, 07:25
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Golikov A. @ Nov 26 2014, 09:26) *
ну то есть у вас в коде это константы и вы их изменить не можете из программы. И есть дополнительные функции которые просто меняют область флеши, фактически не думая что там лежит и тем самым обходят защиту const.

Если структура в флэш-памяти может меняться в процессе работы программы, её следует объявлять как const volatile.

Цитата(Golikov A. @ Nov 26 2014, 09:26) *
В целом решение, проблему вижу только при изменении структуры настроек во время модификации кода, надо не забыть поправить ее в 2 местах. То есть и саму структуру и функции ее сохранения-модификации во флеше.

Эта проблема - вовсе не проблема. Для этого существует X Macro.
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 01:22
Рейтинг@Mail.ru


Страница сгенерированна за 0.01509 секунд с 7
ELECTRONIX ©2004-2016