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

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Как в "незанятой" области FLASH-памяти контроллера сделать определенные значение
RiseOfDeath
сообщение Oct 23 2015, 11:35
Сообщение #16


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 2-10-13
Пользователь №: 78 579



Цитата(Golikov A. @ Oct 21 2015, 12:12) *
Хорошим тоном является проверять
1. пустоту сектора - обычно есть прям такая команда ну или просто смотреть что там FFFFF
2. контрольную сумму настроек, что если вы их изменяли, а вам дернули питание и настройки на половину не верны

3. В особых случаях добавляют признак актуальности, то есть делают 2-3 копии настроек,в начале и конце стоит номер, если он в начале и конце совпадает - значит блок настроек полный, а по номеру определяют последние актуальные. Это позволяет если у вас во время изменения настройки померли, иметь рабочий прошлый вариант. Ну или загрузить прошлые настройки если надо


Спасибо за совет, хотя проверка валидности и актуальности настроек, это отдельный вопрос.

Цитата(stas00n @ Oct 21 2015, 13:23) *
Лично я в подобной ситуации поступил весьма тупо в лоб. Потребуется STSW-LINK004STM32 ST-LINK utility
1. Заливаем .hex с кодом (без пользовательских настроек).
2. Настраиваем прибор, сохраняем настройки.
3. Читаем флеш полностью (вместе с настройками).
4. Сохраняем новый .hex


Тут слишком много "лишних" действий, как мне кажется. Хотя ваш способ имеет право на существование.

Сообщение отредактировал RiseOfDeath - Oct 23 2015, 11:36
Go to the top of the page
 
+Quote Post
Sanya_kv
сообщение Oct 27 2015, 05:34
Сообщение #17


Частый гость
**

Группа: Свой
Сообщений: 185
Регистрация: 25-02-09
Из: Россия
Пользователь №: 45 369



В Keil пользуюсь данным способом:
const char имя_переменной_типа_char [32] __attribute__((at(0x20000))) = { "Определяем её значение" };
0x20000 - адрес, где она будет располагаться.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Oct 27 2015, 14:20
Сообщение #18


Знающий
****

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



Цитата(RiseOfDeath @ Oct 19 2015, 14:00) *
Сосбтвенно что я хочу:
Я использую встроенную нанду для хранения настроек и хочу чтобы при программировании контроллера в него сразу, вместе с программой, зашивались настройки по-умолчанию. (читать и писать программа умеет, но надо чтобы вместо стандартных 0xff в нужной области памяти "изначально" были какие-то определенные значения)
Я предполагаю что мне надо как-то получить на выходе из программы такой hex, чтобы после программирования им контроллера, помимо собственно программы, в жестко заданной области памяти, был тот самый "набор двоичных данных".

Мне кажется, Вашу задачу надо переформулировать так: в программе имеются константы настройки, которые необходимо менять в процессе работы. Эти константы есть часть кода, поэтому говорить о хранении настроек в области "свободной" памяти, как бы вне программы, неверно, т.к. настройки есть часть программного кода в рамках занимаемой памяти.

В принципе, все достаточно просто:
1. Настройка - это есть константа во флэше, объявленная в рамках исходного кода, например:
Код
const float MyCoeff = 5.5;

Очевидно, что 5.5 - это значение по-умолчанию, которое и будет " грузиться" во флэш вместе с программой во время записи/обновления кода. Вот Вам и зашивка настроек по-умолчанию. Также очевидно, что использование настройки в коде есть ни что иное как просто использование имени константы в выражениях.

2. Т.к. предполагается менять значение константы, ее нельзя смешивать с исполняемым кодом, а надо разместить где-то отдельно, чтобы безболезненно переписывать флэш и не завалить код. Это проистекает из принципа работы флэша с постраничными стираниями/записью. Для этого константу для начала надо поместить в известную секцию:
Код
const float MyCoeff __attribute__((section("MYSETTINGS"), used)) = 5.5;

Так нужно поступить со всеми подобными константами-настройками. Компоновщик соберет затем все такие константы в одну секцию.

3. Теперь надо поработать ручками и модифицировать файл скаттера (скрипта компоновщика). Например,
Код
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
;
;   Assume 64Flash
;
LR_IROM1 0x08000000 0x00010000  {  ; load region size_region
  ER_IROM1 0x08000000 0x00010000  {; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 0x00002000  {; RW data
   .ANY (+RW +ZI)
  }
}
;
; In-flash rewritable params, size 1K, must be 1K aligned (page size of used CPU)
;
LR_IROM3 (0x08000000 + (0x00010000-0x400)) 0x400    ; load region size_region
{
   ER_IROM3 (0x08000000 + (0x00010000-0x400)) 0x400 ; load address = execution address
   {
      *(MYSETTINGS)
   }
}

Здесь дано указание компоновщику создать загружаемый регион LR_IROM3 размером в 1К (это размер страницы в STM32F051), а в нем - подрегион ER_IROM3, в котором и соберутся все настройки. Использована последняя страница флэша. Если посмотреть карту памяти готовой программы, можно разместить страницу настроек и непосредственно (но выровненно на страницу!) за "основным" кодом, указав нужные адреса, но лично мне последняя страница нравится больше.

4. Для модификации значений из кода программы надо, очевидно, прочитать всю страницу в буфер, модифицировать значение настройки в буфере по смещению и записать страницу назад по месту.
Смещение будет ((int)&MyCoeff)%0x400. Базовый адрес всей страницы можно вычислить из любой настройки в странице как ((int)&MyCoeff)/0x400*0x400. Это все, конечно, при условии, что все настройки помещаются в одну страницу. Для объемных настроек, пересекающих границы страниц (структуры), нужны соответствующие многостраничные алгоритмы записи во флэш. Или можно выровнять все настройки так, чтобы они никогда не пересекали страницу. Есть еще интересная возможность у компоновщика генерировать константы, доступные в программе. Например, базовый адрес региона можно получить как (void *)&Load$$LR$$LR_IROM3$$Base, а длину региона как (int)&Load$$LR$$LR_IROM3$$Length.

5. Если на образ ELF "натравить" утилиту fromelf.exe как
Код
fromelf.exe --i32 myproject.axf --output myproject.hex

то будет создан ПОДКАТАЛОГ myproject.hex, в котором появятся два файла с именами ER_IROM1 и ER_IROM3 и без расширений. На самом деле это *.HEX файлы. В файле ER_IROM3 собраны все настройки.

6. Внешняя программа, которая хочет модифицировать такой файл, должна, конечно, знать, по какому смещению какая переменная находится. Это нетривиальная задача, особенно по мере развития программы, версий, и т.п. Можно предложить путь дескрипторов или меток. Например, метки всегда четырехбуквенные:
Код
const char myLabel __attribute__((section("MYSETTINGS"), used)) = "MYCO";
const float MyCoeff __attribute__((section("MYSETTINGS"), used)) = 5.5;

Внешняя программа может найти строку MYCO и знать, что после нее идет MyCoeff.

Сообщение отредактировал KnightIgor - Oct 27 2015, 14:27
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 27 2015, 14:33
Сообщение #19


Гуру
******

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



Цитата(KnightIgor @ Oct 27 2015, 17:20) *
1. Настройка - это есть константа во флэше, объявленная в рамках исходного кода, например:
Код
const float MyCoeff = 5.5;

Очевидно, что 5.5 - это значение по-умолчанию, которое и будет " грузиться" во флэш вместе с программой во время записи/обновления кода. Вот Вам и зашивка настроек по-умолчанию. Также очевидно, что использование настройки в коде есть ни что иное как просто использование имени константы в выражениях.

Тогда уж так:
Код
const volatile float MyCoeff = 5.5;

Иначе компилятор не догадается, что эта переменная может меняться.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Oct 27 2015, 15:15
Сообщение #20


Знающий
****

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



Цитата(scifi @ Oct 27 2015, 15:33) *
Тогда уж так:
Код
const volatile float MyCoeff = 5.5;

Иначе компилятор не догадается, что эта переменная может меняться.

Когда и если значение поменяется, компилятор будет уже далеко-далеко.
P.S. Мне просто интересно, а в чем разница в результирующем коде?

Сообщение отредактировал KnightIgor - Oct 27 2015, 15:18
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 27 2015, 17:48
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (KnightIgor @ Oct 27 2015, 18:15) *
Мне просто интересно, а в чем разница в результирующем коде?

Разница или будет, или нет. Если не будет, то как-бы "все хорошо", если будет, то будут глюки. Даже если сейчас "все хорошо", то при изменении исходника все может поменяться. Если Вам глюки НЕ нужны, то объясняйте компилятору все максимально четко используя volatile, если нет абсолютной уверенности в том, что содержимое конфигурации не будет меняться, например, без перезагрузки программы.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 27 2015, 18:21
Сообщение #22


Гуру
******

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



Да и перезагрузка не спасет. gcc очень хорошо умеет подставлять значения констант из константных переменных (и даже из полей структур) прямо в код. И сколько потом ни перегружай программу, некторые части ее могут продолжать рабоать с теми значениями, которые были в момент компиляции. Мы ведь хотели быструю и маленькую программу? Компилятор пошел нам навстречу.


--------------------
На любой вопрос даю любой ответ
"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
KnightIgor
сообщение Oct 28 2015, 10:12
Сообщение #23


Знающий
****

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



Цитата(Сергей Борщ @ Oct 27 2015, 19:21) *
Да и перезагрузка не спасет. gcc очень хорошо умеет подставлять значения констант из константных переменных (и даже из полей структур) прямо в код.

Подтверждаю. И не только gcc, но и armcc KEIL. Ушло, когда такие изменяемые конфигурационные константы собрались в одну кучу в секции. Видимо, поэтому я не стал заморачиваться с volatile, поскольку свод в секцию (в одну область памяти только с данными, которую можно переписывать) изменяемых констант - крутая фразочка вышла cool.gif - с помощью присвоения атрибутов просто неизбежен и необходим при решении поставленно задачи и пресёк одновременно inline-стремление компилятора. Убедил меня scifi, что для строгости, ясности и безопасности стОит объявлять volatile.

ПЫ.СЫ.:
1. Для теста добавил для одной такой "переменной константы" в проекте volatile. Собрал. Загрузил. Вылетел в hard fault из инициализации еще перед main.
2. Есть атрибут __attribute__((noinline)), который предотвращает использование значения константной переменной непосредственно как операнд инструкции ("прямо в коде" в терминах Сергей Борщ). Мой макрос, который размещает константные настройки, выглядит так:
Код
#define ATS(s) __attribute__((section(s), noinline, used))

Так что "забъю" я пока на volatile.

Сообщение отредактировал KnightIgor - Oct 28 2015, 15:55
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 13:21
Рейтинг@Mail.ru


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