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

STM32: как разместить константу только во флеш?

помнится для авр все было очень просто: пишешь перед переменной __flash и все...

как это сделать на STM32 ?

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


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

Используйте модификатор const, остальное сделает линкер.

У меня в Кейле был "прецедент", когда простой const не помогал - константа всё равно копировалась в озу.

Выручил static const.

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


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

У меня в Кейле был "прецедент", когда простой const не помогал - константа всё равно копировалась в озу.

Очень интересно было бы взглянуть.

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


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

Очень интересно было бы взглянуть.

Вот кусок функции:

void    TagReader::LoadTags(TAG_FILESLOT * sl)
{
    const char tag_v1[] = {'T', 'A', 'G'};
    const char tag_v2[] = {'I', 'D', '3'};
    const char title[] = {'T', 'I', 'T', '2'};
    const char artist[] = {'T', 'P', 'E', '1'};
    ...
    if (!memcmp(buf, tag_v2, sizeof(tag_v2)) ...

генерится такой код:

;;;282    void    TagReader::LoadTags(TAG_FILESLOT * sl)
000000  e92d4ff3          PUSH     {r0,r1,r4-r11,lr}
;;;283    {
000004  4604              MOV      r4,r0
;;;285        
;;;286        const char tag_v1[] = {'T', 'A', 'G'};
000006  a0d1              ADR      r0,|L11.844|
000008  f5ad7d37          SUB      sp,sp,#0x2dc        ;283
00000c  6800              LDR      r0,[r0,#0]
;;;287        const char tag_v2[] = {'I', 'D', '3'};
00000e  90b0              STR      r0,[sp,#0x2c0]
000010  a0cf              ADR      r0,|L11.848|
;;;288        const char title[] = {'T', 'I', 'T', '2'};
;;;289        const char artist[] = {'T', 'P', 'E', '1'};
000012  2140              MOVS     r1,#0x40
000014  6800              LDR      r0,[r0,#0]          ;287
000016  90b1              STR      r0,[sp,#0x2c4]      ;288
000018  a0ce              ADR      r0,|L11.852|
00001a  6800              LDR      r0,[r0,#0]          ;288
00001c  90b2              STR      r0,[sp,#0x2c8]      ;289
00001e  a0ce              ADR      r0,|L11.856|
000020  6800              LDR      r0,[r0,#0]          ;289
000022  90b3              STR      r0,[sp,#0x2cc]      ;290
        ...
;;;330        if (!memcmp(buf, tag_v2, sizeof(tag_v2))
000098  2203              MOVS     r2,#3
00009a  a9b1              ADD      r1,sp,#0x2c4
00009c  68e0              LDR      r0,[r4,#0xc]
00009e  f7fffffe          BL       memcmp
        ...
000346  e8bd8ff0          POP      {r4-r11,pc}
;;;558    
                          ENDP

00034a  0000              DCW      0x0000
                  |L11.844|
00034c  54414700          DCB      "TAG",0
                  |L11.848|
000350  49443300          DCB      "ID3",0
                  |L11.852|
000354  54495432          DCB      "TIT2"
                  |L11.856|
000358  54504531          DCB      "TPE1"

Константы располагаются вместе с кодом.

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

Совершенно лишние действия и растрата стёка.

А если константа будет весить килобайт? Компилер и в этом случае полностью копирует её на стёк! :(.

 

Но совсем другой вид, когда добавляем static:

;;;282    void    TagReader::LoadTags(TAG_FILESLOT * sl)
000000  e92d4ff3          PUSH     {r0,r1,r4-r11,lr}
;;;283    {
000004  4604              MOV      r4,r0
;;;285        
;;;286        static const char tag_v1[] = {'T', 'A', 'G'};
;;;287        static const char tag_v2[] = {'I', 'D', '3'};
;;;288        static const char title[] = {'T', 'I', 'T', '2'};
;;;289        static const char artist[] = {'T', 'P', 'E', '1'};
000006  2000              MOVS     r0,#0
000008  f5ad7d33          SUB      sp,sp,#0x2cc        ;283
        ...
;;;330        if (!memcmp(buf, tag_v2, sizeof(tag_v2))
000080  2203              MOVS     r2,#3
000082  49bf              LDR      r1,|L11.896|
000084  68e0              LDR      r0,[r4,#0xc]
000086  f7fffffe          BL       memcmp
        ...
000330  f50d7d35          ADD      sp,sp,#0x2d4
000334  e8bd8ff0          POP      {r4-r11,pc}
;;;558    
                          ENDP
                  |L11.896|
                          DCD      ||.constdata||+0x3

                          AREA ||.constdata||, DATA, READONLY, ALIGN=0

                  tag_v1
000000  544147            DCB      0x54,0x41,0x47
                  tag_v2
000003  49                DCB      0x49
000004  4433              DCB      0x44,0x33
                  title
000006  5449              DCB      0x54,0x49
000008  5432              DCB      0x54,0x32
                  artist
00000a  5450              DCB      0x54,0x50
00000c  4531              DCB      0x45,0x31

Вот теперь константы хранятся в своей секции и выбираются прямым указателем без копирования на стёк.

 

Компилятор RealView 4.1 из uVision 4.10, оптимизация О2.

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


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

Вот кусок функции:

Собственно, а чего Вы ожидали приписывая этот квалификатор к ЛОКАЛЬНОЙ переменной? Все совершенно нормально - приказали разместить в RAM, но запретили модифицировать.

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


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

Собственно, а чего Вы ожидали приписывая этот квалификатор к ЛОКАЛЬНОЙ переменной? Все совершенно нормально - приказали разместить в RAM, но запретили модифицировать.

Я лишь показал, что одного квалификатора const недостаточно, чтобы все подряд константы стали размещаться только во флеш :)

 

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

Недоработка компилятора?

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


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

Я лишь показал, что одного квалификатора const недостаточно, чтобы все подряд константы стали размещаться только во флеш :)

Дык это у вас был не "прецедент", а недопонимание в различиях размещения в памяти переменных разных типов. В вашем примере вы создали а) немодицифицируемую б) локальную в) инициализированную г) переменную. А локальные переменные размещаются на стеке или в регистрах, бо время их жизни ограничено необходимостью наличия только внутри функции. Во втором примере тип static дал переменной "неограниченное" время жизни, позволив линкеру разметить ее "на постоянное место жительства" во Flash.

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


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

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

Ну и почему эта константа должна быть расположена в ОЗУ? Есть рациональное объяснение?

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


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

Я дописал пояснение. См. выше.

Тут лишь слепое следование стандартному механизму.

 

Но ведь сейчас компиляторы такие продвинутые, highly optimizing. Тогда для чего копировать константу в ОЗУ?

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


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

Ну и почему эта константа должна быть расположена в ОЗУ? Есть рациональное объяснение?

Есть, конечно.

6.2.4 Storage durations of objects

...

4 An object whose identifier is declared with no linkage and without the storage-class

specifier static has automatic storage duration.

5 For such an object that does not have a variable length array type, its lifetime extends

from entry into the block with which it is associated until execution of that block ends in

any way. (Entering an enclosed block or calling a function suspends, but does not end,

execution of the current block.) If the block is entered recursively, a new instance of the

object is created each time. The initial value of the object is indeterminate. If an

initialization is specified for the object, it is performed each time the declaration is

reached in the execution of the block; otherwise, the value becomes indeterminate each

time the declaration is reached.

То есть стандарт в данном случае прямо предписывает создавать новую копию переменной.

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


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

То есть стандарт в данном случае прямо предписывает создавать новую копию переменной.

Ну, я и говорю - слепое следование стандарту.

А не рациональное объяснение. Потому что смысла в данном случае - нет.

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


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

Ну, я и говорю - слепое следование стандарту.

А не рациональное объяснение.

Слепое следование стандарту - это и есть рациональное объяснение. Не должен компилятор заниматься самодеятельностью ни при каких условиях.

 

Потому что смысла в данном случае - нет.

Почему же? Мало ли, может я хочу создать массив для ускорения вычислений, но ОЗУ жалко, а стека - нет.

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


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

Тут лишь слепое следование стандартному механизму.

 

Но ведь сейчас компиляторы такие продвинутые, highly optimizing. Тогда для чего копировать константу в ОЗУ?

Стандарты для того и придумывают, чтобы описать правила общие для всех. Компиляторы сейчас стараются делать как можно ближе к этому стандарту. Диктуется сие необходимостью устранения недопониманий между желанием человека-программиста и реализацией его желания в командах для конкретной железяки. Язык программирования это средство описания желаний программиста. ;)

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


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

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

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

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

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

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

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

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

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

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