Jump to content

    
Sign in to follow this  
Alex_7211

Как убрать атрибут [Compressed] для секции Flash?

Recommended Posts

Отгородил себе флэш для энергонезависимых настроек:

uint16_t ID[256] __attribute__((at(0x00007E00))) = {0, 1, 0x05E0};

Какое-то время всё было хорошо: читалось по имени и стиралось/перезаписывалось по абсолютному адресу. Но в какой-то момент при прошивке там стало появляться такое:

ID[0] = 0x1221 вместо 0
ID[1] = 0x0A01 вместо 1
ID[3] = 0xE0FF вместо 0x05E0

Перезапись из программы по абсолютным адресам работает и дальше всё ОК. Только начальные значения какие-то левые. 

Вот как эта секция выглядит в map-файле:

Load Region LR$$.ARM.__AT_0x00007E00 (Base: 0x00007e00, Size: 0x00000200, Max: 0x00000200, ABSOLUTE, COMPRESSED[0x0000000c])
Execution Region ER$$.ARM.__AT_0x00007E00 (Exec base: 0x00007e00, Load base: 0x00007e00, Size: 0x00000200, Max: 0x00000200, ABSOLUTE, UNINIT, COMPRESSED[0x0000000c])
Exec Addr       Load Addr        Size              Type   Attr          Idx    E Section Name              Object
0x00007e00   COMPRESSED   0x00000200   Data   RW           28    .ARM.__AT_0x00007E00  bvd302main.o

И вот как она выглядела, когда всё работало:

Load Region LR$$.ARM.__AT_0x00007E00 (Base: 0x00007e00, Size: 0x00000200, Max: 0x00000200, ABSOLUTE)
Execution Region ER$$.ARM.__AT_0x00007E00 (Exec base: 0x00007e00, Load base: 0x00007e00, Size: 0x00000200, Max: 0x00000200, ABSOLUTE, UNINIT)
Exec Addr       Load Addr      Size               Type   Attr          Idx    E Section Name             Object
0x00007e00   0x00007e00   0x00000200   Data   RW           26    .ARM.__AT_0x00007E00  bvd302main.o

Что нахрен за COMPRESSED появилось? Я ничо особого не делал, просто добавил немного кода, не относящегося к этой секции. Свободной флэш-памяти - процентов 80. В компиляторе пробовал менять уровни оптимизации - не помогает. Объявление volatile не помогает. Подскажите, как вернуть обратно абсолютный Load Addr и убрать этот COMPRESSED? Кажется, что дело в нем.

Share this post


Link to post
Share on other sites
3 часа назад, VladislavS сказал:

А const  где?

Если я ставлю const, то сектор меняет атрибут RW на RO и перестает стираться/записываться из программы (!) почему-то. Я пробовал. Если это имеет значение, то проц NXP MKE06Z64VLH4 на ядре M0+. Частичная или полная блокировка записи во флэш задается в startXXX.s и там весь флэш открыт для записи. Дальше копать не стал. Работает как переменная и ладно.

3 часа назад, Палыч сказал:

 Вы уверены, что отключение сжатия поможет? Тогда: в опциях линкера указать

--datacompressor off

Перекомпилировал. "Compressed" исчезло. Кажется это оно. Завтра перешью, проверю. Спасибо вам, добрый человек!

Share this post


Link to post
Share on other sites
3 часа назад, Alex_7211 сказал:

Если я ставлю const, то сектор меняет атрибут RW на RO и перестает стираться/записываться из программы (!) почему-то. Я пробовал.

Это вообще не понятно. Такого не должно быть.

Компрессия данных применяется линкером ТОЛЬКО для секций с атрибутом RW. Для RO не применяется. Причем она по-умолчанию включена. Линкер думает, что это ОЗУ и вставляет до main() код декомпрессии и записи туда начальных значений. Т.к. это не ОЗУ, а флеш, то к требуемому результату это не приводит. Но остается вопрос: а почему там не 0хFFFF во всех элементах массива? Значит, перед программированием эта область памяти не стирается, и там остается мусор?

Share this post


Link to post
Share on other sites
13 часов назад, Alex_7211 сказал:

Перекомпилировал. "Compressed" исчезло. Кажется это оно. Завтра перешью, проверю. Спасибо вам, добрый человек!

Спасибо Палычу, изгоняющему бесов! Всё работает.

Share this post


Link to post
Share on other sites
9 часов назад, Darth Vader сказал:

Компрессия данных применяется линкером ТОЛЬКО для секций с атрибутом RW. Для RO не применяется.

Так я же и пишу, что объявляю массив как переменную, которая получает атрибут RW, несмотря на область Flash. При этом всё работало, за исключением компрессии, которая появилась не сразу и стала портить начальные значения. Почему не 0xFFFF - потому что я инициализирую первые 6 байт при объявлении массива. В настройках программатора стоит "erase full chip".

Когда я, как человек воспитанный, объявлял массив const и он получал RO, то не работало стирание из программы - всегда ошибка. Это были мои вторые грабли при работе с Flash. Первые - в модуле MCM установить Enable Stalling Flash Controller, иначе reset сразу при попытке стирания. Возможно, в этом модуле нужно было что-то еще подшаманить, чтобы const заработал, ХЗ.

Share this post


Link to post
Share on other sites
1 час назад, Alex_7211 сказал:

Почему не 0xFFFF - потому что я инициализирую первые 6 байт при объявлении массива. В настройках программатора стоит "erase full chip".

Интересно, а что-же с остальными байтами массива по Вашему мнению?

Я вот к сожалению не знаю способа в си инициализировать только часть массива.  :unknw:

1 час назад, Alex_7211 сказал:

Когда я, как человек воспитанный, объявлял массив const и он получал RO, то не работало стирание из программы - всегда ошибка. Это были мои вторые грабли при работе с Flash.

Я конечно не особо знаком с Keil, но всё-таки не очень понимаю - чего вы пытаетесь добиться этим?:

20 часов назад, Alex_7211 сказал:

Load Region LR$$.ARM.__AT_0x00007E00 (Base: 0x00007e00, Size: 0x00000200, Max: 0x00000200, ABSOLUTE, COMPRESSED[0x0000000c])
Execution Region ER$$.ARM.__AT_0x00007E00 (Exec base: 0x00007e00, Load base: 0x00007e00, Size: 0x00000200, Max: 0x00000200, ABSOLUTE, UNINIT, COMPRESSED[0x0000000c])
Exec Addr       Load Addr        Size              Type   Attr          Idx    E Section Name              Object
0x00007e00   COMPRESSED   0x00000200   Data   RW           28    .ARM.__AT_0x00007E00  bvd302main.o

Чтобы при каждом включении устройства, оно каждый раз стирало и записывало флешь? (ведь как я понимаю - по адресу 0x7E00 находится флешь в вашем МК?).

Это такой тест на количество циклов перезаписи флеша?  :biggrin:   Ну так и тест кривой - надо паттерн-то менять, а то ведь умный загрузчик возьмёт развернёт эту COMPRESSED-секцию инициализации в отдельную память, сравнит с целевой областью памяти и не станет стирать (так как они равны).  :biggrin:

И чем не нравится COMPRESSED? Имхо (если я правильно догадываюсь о его назначении), оно позволяет уменьшить объём секции инициализации переменных, хранящейся во флешь. Ведь у Вас там этот массив инициализируется в основном нулями, и COMPRESSED видимо позволяет линкеру вместо 253 слов нулей записать только пару значение/счётчик_повтора. А убиранием "COMPRESSED" Вы добились только увеличиения секции инициализации данных до полных 256 слов. Тоже не понимаю - зачем???

PS: Советую прислушаться к 

14 часов назад, VladislavS сказал:

Flash как переменная? Барин знает толк в извращениях..

и подумать о том, что поисходит при старте вашей программы в устройстве.

Share this post


Link to post
Share on other sites
55 минут назад, jcxz сказал:

чего вы пытаетесь добиться этим?:

Энергонезависимые настройки, которые можно поменять из программы. И новые настройки снова будут энергонезависимыми. Все же так делают, нет?

56 минут назад, jcxz сказал:

Интересно, а что-же с остальными байтами массива по Вашему мнению?

Keil забивает их нулями. Проверено. Но у меня есть более гуманный к Flash вариант и я забиваю все остальные 253 0xFFFF при объявлении.

58 минут назад, jcxz сказал:

Чтобы при каждом включении устройства, оно каждый раз стирало и записывало флешь?

Нет. Кто "оно"? Всё работает ОК. Все данные сохраняются, не переинициализируются первоначальными данными из прошивки, а сохраняются последние записанные. Вы наверное слабо представляете себе перезапись флэш из программы. Тут хрен можно сломать. Компиллятор уж точно ничего не подставит от себя. Слишком чипо-зависимо.

1 час назад, jcxz сказал:

умный загрузчик

не пользуюсь

1 час назад, jcxz сказал:

И чем не нравится COMPRESSED?

Нельзя уменьшать размер секции. 512 байт - минимальная секция для стирания. 

 

1 час назад, jcxz сказал:

и подумать о том, что поисходит при старте

  Прекрасно отдаю себе отчет. Вообще вот просто по шагам и по тактам.

 

1 час назад, jcxz сказал:

Тоже не понимаю - зачем???

Не понимаете - спросите. Не сочтите за грубость, но чё-то закрадываются сомнения, что вы писали во флэш. В NXP, STM, в PIC везде есть минимальная страница стирания и очень (специально!) мудреный доступ к командам стирания/записи.

В общем, вопрос исчерпан, спасибо всем за внимание.

Share this post


Link to post
Share on other sites
30 минут назад, Alex_7211 сказал:

Энергонезависимые настройки, которые можно поменять из программы. И новые настройки снова будут энергонезависимыми. Все же так делают, нет?

Пытаются записывать настройки во флешь из стартап-кода? Думаю так делаете только Вы.

А большинство делают это из своей программы, собственной функцией записи флешь.

Цитата

Нет. Кто "оно"? Всё работает ОК. Все данные сохраняются, не переинициализируются первоначальными данными из прошивки, а сохраняются последние записанные.

Оно - это сишный стартап код, которому Вы пытаетесь указать записать данные во флешь, разместив RW-секцию данных с начальной инициализацией во флешь. Чтобы проинициализировать такую секцию, стартап коду как раз надо уметь стирать/писать флешь. Может он это и умеет, может и нет - не знаю, но сильно сомневаюсь.

А раз "данные не переинициализируются первоначальными данными из прошивки", то это и говорит как раз о том, что стартап код не умеет писать во флешь. А просто игнорит ваши инициализационные данные. Просто повезло, что в hard fault при этом не падает. :unknw:

Цитата

Вы наверное слабо представляете себе перезапись флэш из программы. Тут хрен можно сломать. Компиллятор уж точно ничего не подставит от себя. Слишком чипо-зависимо.

Я думаю это Вы слабо представляете мои знания о записи флешь. :russian_ru:

Цитата

не пользуюсь

Под таким "загрузчиком" я имел в виду стандартный сишный стартап.

Цитата

  Прекрасно отдаю себе отчет. Вообще вот просто по шагам и по тактам.

Тогда что по вашему должно происходить при старте программы? при наличии в коде такого:

22 часа назад, Alex_7211 сказал:

uint16_t ID[256] __attribute__((at(0x00007E00))) = {0, 1, 0x05E0};

Что и как должен сделать си-стартап код?

 

Цитата

Не понимаете - спросите. Не сочтите за грубость, но чё-то закрадываются сомнения, что вы писали во флэш. В NXP, STM, в PIC везде есть минимальная страница стирания и очень (специально!) мудреный доступ к командам стирания/записи.

Минимальные страницы и записи и стирания есть во всех МК с программной флешью которые я знаю, а не тольков этих.

И из чего Вы делаете выводы о моих знаниях?? Не понимаю... Вот о Ваших "знаниях" прекрасно видно уже из первого поста.

Цитата

В общем, вопрос исчерпан, спасибо всем за внимание.

Проблема успешно заметена под ковёр  :biggrin:

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this