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

IAR 9.30.1, как запретить оптимизировать чтение из FLASH?

У меня, правда, в EWAVR компилятор выбрасывает обращение к volatile переменной, размещённой в ОЗУ, на high-оптимизации. Вот этот прикол я тоже не понял...

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


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

Доброго дня. Использую такой подход:

// configData размещается во flash памяти.

#pragma section "FLASH"

#pragma location = "FLASH"

__root const SettingStruct configData = { /*начальные значения элементов структуры SettingStruct*/};

// Объявляю указатель на структуру. Указатель размещается в RAM.

SettingStruct *toConfig;

void main()

{

// Инициализация указателя.

toConfig = (SettingStruct*)&configData;

....

}

Доступ к значению во flash: toConfig->...

Изменение значений: через процедуру перезаписи страницы flash памяти.

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


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

6 minutes ago, KSN said:

Использую такой подход:

А я вот выше показал, что у меня такой подход с включенной оптимизацией balanced или speed не приводит к результату. Даже если указатель на структуру объявлен со словом volatile. Данные из флеши читаются, да. Но не используются. Что не противоречит стандарту.

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


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

Ну тогда пусть линкер считает, что это RW область, а адреса подпихните из нужной области Flash.

Объявите структуру const volatile, и тогда эта банда компилятор с линкером будут бессильны против Вашей воли.

Для этого лучше будет объявить отдельный регион памяти (не знаю насчет IAR), и разместить в root-секции этот массив, чтобы rw_copy() не распространялся на эту область.

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


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

1 minute ago, Arlleex said:

Ну тогда пусть линкер считает, что это RW область, а адреса подпихните из нужной области Flash.

Всё же выходит, что поставленная проблема в топике - нетривиальная?))))

 

Интересно бы ещё услышать, что уважаемый @jcxz скажет)))

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


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

31 минуту назад, haker_fox сказал:

Всё же выходит, что поставленная проблема в топике - нетривиальная?))))

Видите ли в чем штука, тут нужно знать/иметь опыт специфики взаимодействия компилятора и линкера конкретно у IAR. Тут далеко не каждый в курсе каких-то особенностей:smile:

Потому что в силу наворотов для улучшения оптимизации (а ведь смотрите как он наоптимизировал функции, в другом случае это был бы огромный плюс!), будут появляться "дыры", "заплатки", для устранения такой оптимизации.

Однозначно, к Си это не имеет отношения, поэтому где-то в дебрях документации IAR, собранная по кусочкам информация даст картину, которая будет согласована с реальностью, которую Вы наблюдаете))

P.S. А еще можно попробовать поместить эту структуру в отдельную единицу трансляции (сишник), объявить в нужных местах (extern) и отключить LTO, если была включена.

Не забыть только про extern const volatile struct ... {} = {}, а то в плюсах для глобального объекта const имеет внутреннюю связь((

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


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

У меня в icf файле область памяти для размещение констант вынесена из общего объема, который может использовать IAR как ему вздумается.

image.thumb.png.d5f2b1128690a34da826eb44105fbc11.png

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


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

DECLARING OBJECTS VOLATILE AND CONST
If you declare a volatile object const, it will be write-protected but it will still be
stored in RAM memory as the C standard specifies.
To store the object in read-only memory instead, but still make it possible to access it as
a const volatile object, declare it with the __ro_placement attribute. See
__ro_placement, page 371.
To store the object in read-only memory instead, but still make it possible to access it as
a const volatile object, define the variable like this:
const volatile int x @ "FLASH";
The compiler will generate the read/write section FLASH. That section should be placed
in ROM and is used for manually initializing the variables when the application starts
up.
Thereafter, the initializers can be reflashed with other values at any time.

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


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

3 hours ago, haker_fox said:

Всё же выходит, что поставленная проблема в топике - нетривиальная?))))

да как-то не было проблем. Делаю так

 *.icf:
define region sect_region = mem:[from 0x08070000 to 0x08077FFF];
place in sect_region { section sect };

 *.c:
#define fix_rom  _Pragma("location=\"sect\"")

fix_rom const uint8_t arr[] = { .... };

читать uint32_t x = *(volatile uint32_t*) 0x08070000;

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


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

2 часа назад, pyroman сказал:

If you declare a volatile object const, it will be write-protected but it will still be stored in RAM memory as the C standard specifies.

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

9 минут назад, vit496 сказал:

fix_rom const uint8_t arr[] = { .... };

читать uint32_t x = *(volatile uint32_t*) 0x08070000;

Во-первых, у ТС там лежит структура, к которой обращаться всяко приятнее, чем к непонятно что значащим элементам неких uint32_t.
Во-вторых, повторюсь, это потенциально кривой способ, т.к. при банальной смене распределения памяти все уедет и по новой сиди адреса правь.

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


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

4 часа назад, haker_fox сказал:

Всё же выходит, что поставленная проблема в топике - нетривиальная?))))

Да вроде - ничего там сложного.  :wink2:

4 часа назад, haker_fox сказал:

Интересно бы ещё услышать, что уважаемый @jcxz скажет)))

Сорри - весь топик не читал, нет времени, но по проблеме из первого поста, первое что бросается в глаза - я не вижу у Вас в скрипте компоновщика задания способа инициализации для секции ".calInfo".

Я бы сделал примерно так:

__packed struct GeneralCal {
  u16 z0;
  u16 z1;
  u16 z2;
  u16 z3;
  bool calibrated;
};
__packed struct CalInfo {
  GeneralCal general;
  u16 tbl[4096];
};

__root CalInfo volatile const calInfo @ ".calInfo" = {3502, 3318, 369, 184, false};

.icf:

define region FLASHC_regionB = mem:[from 0x08140000 to 0x0817FFFF]; //PMU/FLASH (cached)
...
do not initialize  {section .calInfo};
...
place in FLASHC_regionB {section .calInfo};

результат (.map):

"P2":  place in [from 0x08140000 to 0x0817ffff] { section .calInfo };

...

  Section             Kind        Address     Size  Object           
  -------             ----        -------     ----  ------           
"P2":                                       0x200c                   
  P2-1                         0x08140000   0x200c  <Init block>     
    .calInfo          inited   0x08140000   0x200c  main.o [1]       
                             - 0x0814200c   0x200c                   

...

calInfo                 0x08140000   0x200c  Data  Lc  main.o [1]

.lst:

Спойлер
                              In section .calInfo, align 4, root                                     
00000000   0x0DAE 0x0CF6      DC16 3502, 3318, 369, 184                                              
           0x0171 0x00B8                                                                             
00000008   0x00               DC8 0                                                                  
00000009   0x0000 0x0000      DC16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
00000035   0x0000 0x0000      DC16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
00000061   0x0000 0x0000      DC16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  
           0x0000 0x0000                                                                             
           0x0000 0x0000                                                                             
           0x0000 0x0000              
...

 

Как видно - всё ок.

И никаких ошибок или варнингов при компиляции.

PS: IAR v7.80.4 for ARM.

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


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

PPS: 

код:

if (calInfo.general.calibrated) Pset(PIN_LED1);
else Pclr(PIN_LED1);

его .lst:

 if (calInfo.general.calibrated) Pset(PIN_LED1);             
0x....             LDR.N    R2,??DataTable16_30              
0x....             LDR.N    R0,??DataTable16_4  ;; 0x48028000
0x7A12             LDRB     R2,[R2, #+8]                     
0xF200 0x5004      ADDW     R0,R0,#+1284                     
0xF44F 0x7100      MOV      R1,#+512                         
0x2A00             CMP      R2,#+0                           
0xBF14             ITE      NE                               
0x8001             STRHNE   R1,[R0, #+0]                     
0x8041             STRHEQ   R1,[R0, #+2]                     
 else Pclr(PIN_LED1);
 
...

                   In section .text, align 4, keep-with-next 
       ??DataTable16_30:                                     
0x........         DC32     calInfo

Как видно - и читается и используется в коде calInfo.general.calibrated правильно.

 

Скомпилено это с максимальной оптимизацией (balanced).

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


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

1 hour ago, vit496 said:

читать uint32_t x = *(volatile uint32_t*) 0x08070000

А где красота кода? Оперировать в сишнике адресами - дурной тон, ИМХО. Для этого линкер есть.

1 hour ago, Arlleex said:

т.к. при банальной смене распределения памяти все уедет и по новой сиди адреса правь.

Угу)

45 minutes ago, jcxz said:

я не вижу у Вас в скрипте компоновщика задания способа инициализации для секции ".calInfo".

Ух, спасибо! Я чувствовал, что у Вас будет индивидуальный рецепт, как всегда💗 Завтра буду пробовать на работе)

29 minutes ago, jcxz said:

Как видно - и читается и используется в коде calInfo.general.calibrated правильно.

Это внушает надежду!🤝🙏

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


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

Обычно в подобных случаях меня выручал вариант вида: 

return *((bool*)(&calInfo.general.calibrated));

 

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


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

12 минут назад, jack_avenger сказал:

Обычно в подобных случаях меня выручал вариант вида: 

return *((bool*)(&calInfo.general.calibrated));

Это неверный вариант. Не выручит.

Если конечно не держать оптимизацию всё время выключенной. Но мы же не колхозники - мы так не делаем, правда?  :sarcastic:

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


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

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

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

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

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

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

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

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

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

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