Jump to content

    
_Desh_

Разместил таблицу векторов и код обработчика в ОЗУ, при прерывании вылетает в HardFault

Recommended Posts

9 часов назад, _Desh_ сказал:

напишу хотя бы для упорядочивания в своей голове

AHTOXA давал вам более простой совет:

9 часов назад, AHTOXA сказал:

попробуйте поместить функцию в .data.

 

То, что вы сделали - фактически повторение действий, которые происходят с переменными секции .data и если вашу секцию .RAM поместить внутрь .data - они будут проделаны и с содержимым вашей секции тоже, при этом вам не потребуется потратить ни одного лишнего байта на CopyCodeRamFunc, LoopCopyCodeRamFunc, _siramfunc, _sramfunc, _eramfunc.

Share this post


Link to post
Share on other sites
30 minutes ago, Сергей Борщ said:

AHTOXA давал вам более простой совет:

Верно, сейчас попробовал сделать как посоветовал АНТОХА, и все получилось.

Просто вчера я свой вариант успел сделать и протестировать раньше, чем увидел его пост.

Спасибо, что обратили мое внимание на это.

Share this post


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

Ну и сами-то функции стирания/записи по-любому придется в ОЗУ размещать.

Зачем? Всё прекрасно работает и из флеша. Там всё для этого предусмотрено - пока идёт запись/стирание, все остальные обращения к флешу просто подвисают.

Share this post


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

После этого осталось только объявить соответствующий атрибут для нужных мне функций. Для целей тестирования я сделал для одной обычной функции (инициализация Systick) и одного обработчика прерывания (того же Systick):

Вижу атрибут размещения кода функции в конкретной секции (section(".RAMFUNC")), но не вижу задания этому коду спец.атрибута "функция в ОЗУ".  :umnik2:

Обычно для этого у компилятора есть спец. зарезервированное слово. Например у IAR - "__ramfunc". И неспроста сделали это спец. слово "__ramfunc".

Если Вы просто разместите какой-то код в отдельной секции, это совсем не означает, что не будет обращений из этого кода за его пределы - в область флешь. Даже если Вы и все функции, вызываемые из своего RAM-ISR тоже аккуратно поместите в ту же самую секцию, то это совсем не гарантирует от того, что после включения оптимизации кода, компилятор может увидеть в коде RAM-ISR и в каком-то другом коде (находящемся во флешь) одинаковый участок. В этом случае оптимизатор (особенно в случае оптимизации "по размеру кода") может оформить эти участки в отдельную функцию и поместить её куда посчитает удобным (например во флешь). И Ваша RAM-ISR начнёт глючить.

То же самое будет, если в коде RAM-ISR и в каком-то другом коде имеются одинаковые массивы констант (или даже - частично одинаковые). Умные оптимизаторы, обнаруживая одинаковые массивы констант, могут объединять их в один экземпляр, адресуя во всех случаях один и тот же экземпляр.

Например объявили Вы в одном месте исходника: char const t1 = "Уникальные данные";

и в совершенно другом: char const t2 = "Уникальные данные";

Компилятор увидит, что они имеют одинаковое содержимое и создаст только единственный экземпляр "Уникальные данные", использовав его адрес и в 1-м и во 2-м месте. Более того - он может даже не целиком равные обнаруживать, а если например: один массив - часть другого.

И тогда у Вас, после очередной компиляции, внезапно окажется, что из RAM-ISR появились обращения во флешь.  :dash2:

 

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

Share this post


Link to post
Share on other sites
9 minutes ago, jcxz said:

Вижу атрибут размещения кода функции в конкретной секции (section(".RAMFUNC")), но не вижу задания этому коду спец.атрибута "функция в ОЗУ".

Я указал секцию, где будет размещена функция, при помощи линкера. В исходнике функции указал, что она размещается именно в этой секции. Затем самостоятельно скопировал код этой функции по соответствующему адресу RAM в стартапе. Что еще я должен сделать, чтобы эта функция разместилась там, где мне нужно?

Share this post


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

Что еще я должен сделать, чтобы эта функция разместилась там, где мне нужно?

Вы прочитали что я написал? Поняли?

Я не знаю какой у Вас компилятор, но например в IAR нужно указать атрибут "__ramfunc".

Share this post


Link to post
Share on other sites

_Desh, еще для экономии флеша можно сделать короткую таблицу прерываний во флеше, экономит приличное количество памяти. Вы собираетесь что затирать весь флешь и бутлоадер тоже?

Edited by MasterElectric

Share this post


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

Что еще я должен сделать, чтобы эта функция разместилась там, где мне нужно?

Всё у вас нормально, не слушайте jcxz, он про IAR вам задвигает.

Share this post


Link to post
Share on other sites
37 minutes ago, jcxz said:

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

Не знаю есть ли подобное в GCC, если бы это позволило бы навязать ramfunc атрибут (сделать копию) всем используемым в функции символам, возможно было бы удобно. Но в любом случае компилятор не сможет гарантировать отсутсвие обращений к flash.

Share this post


Link to post
Share on other sites
19 minutes ago, MasterElectric said:

Вы собираетесь что затирать весь флешь и бутлоадер тоже?

Нет, только страницу с основной программой.

 

8 minutes ago, amaora said:

Но в любом случае компилятор не сможет гарантировать отсутсвие обращений к flash.

Я так и понял, что именно программист должен это гарантировать, вручную разместив все данные и функции, к которым будут обращения, в нужной области памяти.

Edited by _Desh_

Share this post


Link to post
Share on other sites
54 minutes ago, jcxz said:

Например объявили Вы в одном месте исходника: char const t1 = "Уникальные данные";

и в совершенно другом: char const t2 = "Уникальные данные";

Компилятор увидит, что они имеют одинаковое содержимое и создаст только единственный экземпляр "Уникальные данные", использовав его адрес и в 1-м и во 2-м месте. Более того - он может даже не целиком равные обнаруживать, а если например: один массив - часть другого.

Без разницы, компилятор может объединить оба эти массива как раз потому, что они оба во флеше и обращение к нему будет в любом случае. А массивы находящиеся во флеше и RAM компилятор объединять не будет.

Share this post


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

...еще для экономии флеша можно сделать короткую таблицу прерываний во флеше, экономит приличное количество памяти...

На фоне 0,5-1МБ Flash-памяти как-то странно пытаться экономить на таблице векторов... Это во-первых.
Во-вторых. Что Вы имеете ввиду под "сделать короткую таблицу прерываний во флеше"?
Таблица векторов штука статичная по своему размеру. Ну, допустим, в контроллере 20 векторов.
У меня используются 0-й и 19-й векторы. Где экономия? Типа в 1-18-й могу положить любые const-данные?
Ну фиг знает, а надо ли оно такое. Я, например, на таких спичках не экономлю - да и не удобно это.
Если у меня есть какие-то таблицы или структуры неизменяемых данных (заводские настройки, например), я располагаю их в отдельной секции Flash.
А после векторов (ну никак не между ними) кладу размер прошивки и контрольную сумму. И все то же самое относится к случаю расположения таблицы в ОЗУ.

Share this post


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

А для чего вы размещаете сам обработчик в ОЗУ?

Ну, чтобы, например, при операциях с Flash, не потерять на время ее блокировки возникающие прерывания.

9 часов назад, haker_fox сказал:

Мне хватает разместить в ОЗУ только таблицу.

Случаем, не загрузчик под Cortex-M0 пишете?:wink:
А то до боли знакома мысль "разместить в ОЗУ таблицу"... потому что там нет VTOR.
Сам просто относительно недавно этим занимался.

6 часов назад, _Desh_ сказал:

...возможно в конце концов обойдусь простым запретом прерываний на время стирания/записи.

Что-то там запрещать по отношению к операциям стирания/записи Flash - зачем?
Flash итак блокирует выполнение кода при операциях с ней. А если из ОЗУ код выполняется - то снова... зачем запрещать?

6 часов назад, _Desh_ сказал:

Ну и сами-то функции стирания/записи по-любому придется в ОЗУ размещать.

Вроде как, архитектура памяти в 32-х STM-ках еще никого яро не заставляла в ОЗУ обработчики размещать.
В STM8 да, заставляла. В каких-то контроллерах тоже заставляют, но не в STM32, вроде бы...

Share this post


Link to post
Share on other sites
2 minutes ago, Arlleex said:

но не в STM32, вроде бы

Я обязательно разберусь. Просто я на STM32F4 с Миландровского 1986ВЕ1Т пересел. Там обязательно было код записи/стирания флэш-памяти в ОЗУ размещать. Перемещаемой таблицы там не было, потому что Cortex-M0/M1, это я уже сам затеял. Опыта у меня с STM32 мало.

Share this post


Link to post
Share on other sites

короткая таблица это только системные прерывания. т.е. нет смысла создавать таблицу которая будет просто висеть, вектора то в ОЗУ. Ну это не тот случай много все-таки телодвижений еще нужно сделать... плохая идея.

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.