Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32: как разместить константу только во флеш?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Ivan Kuznetzov
помнится для авр все было очень просто: пишешь перед переменной __flash и все...
как это сделать на STM32 ?
aaarrr
Используйте модификатор const, остальное сделает линкер.
sonycman
Цитата(aaarrr @ Aug 21 2010, 16:30) *
Используйте модификатор const, остальное сделает линкер.

У меня в Кейле был "прецедент", когда простой const не помогал - константа всё равно копировалась в озу.
Выручил static const.
aaarrr
Цитата(sonycman @ Aug 21 2010, 16:40) *
У меня в Кейле был "прецедент", когда простой const не помогал - константа всё равно копировалась в озу.

Очень интересно было бы взглянуть.
sonycman
Цитата(aaarrr @ Aug 21 2010, 21:08) *
Очень интересно было бы взглянуть.

Вот кусок функции:
Код
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"

Константы располагаются вместе с кодом.
Как видно, сначала они считываются из флеш в стёк, и уже затем передаются оттуда указателем.
Совершенно лишние действия и растрата стёка.
А если константа будет весить килобайт? Компилер и в этом случае полностью копирует её на стёк! sad.gif.

Но совсем другой вид, когда добавляем 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.
zltigo
QUOTE (sonycman @ Aug 21 2010, 23:07) *
Вот кусок функции:

Собственно, а чего Вы ожидали приписывая этот квалификатор к ЛОКАЛЬНОЙ переменной? Все совершенно нормально - приказали разместить в RAM, но запретили модифицировать.
sonycman
Цитата(zltigo @ Aug 22 2010, 01:28) *
Собственно, а чего Вы ожидали приписывая этот квалификатор к ЛОКАЛЬНОЙ переменной? Все совершенно нормально - приказали разместить в RAM, но запретили модифицировать.

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

Однако не находите, какая это глупость - переменная инициализирована и является константой - так какого чёрта её засовывать в ОЗУ?
Недоработка компилятора?
rezident
Цитата(sonycman @ Aug 22 2010, 03:52) *
Я лишь показал, что одного квалификатора const недостаточно, чтобы все подряд константы стали размещаться только во флеш smile.gif

Дык это у вас был не "прецедент", а недопонимание в различиях размещения в памяти переменных разных типов. В вашем примере вы создали а) немодицифицируемую б) локальную в) инициализированную г) переменную. А локальные переменные размещаются на стеке или в регистрах, бо время их жизни ограничено необходимостью наличия только внутри функции. Во втором примере тип static дал переменной "неограниченное" время жизни, позволив линкеру разметить ее "на постоянное место жительства" во Flash.
sonycman
Цитата(rezident @ Aug 22 2010, 02:03) *
Дык это у вас был не "прецедент", а недопонимание в различиях размещения в памяти переменных разных типов. В вашем примере вы создали а) немодицифицируемую б) локальную в) инициализированную г) переменную.

Ну и почему эта константа должна быть расположена в ОЗУ? Есть рациональное объяснение?
rezident
Я дописал пояснение. См. выше.
sonycman
Цитата(rezident @ Aug 22 2010, 02:11) *
Я дописал пояснение. См. выше.

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

Но ведь сейчас компиляторы такие продвинутые, highly optimizing. Тогда для чего копировать константу в ОЗУ?
aaarrr
Цитата(sonycman @ Aug 22 2010, 02:05) *
Ну и почему эта константа должна быть расположена в ОЗУ? Есть рациональное объяснение?

Есть, конечно.
Цитата
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.

То есть стандарт в данном случае прямо предписывает создавать новую копию переменной.
sonycman
Цитата(aaarrr @ Aug 22 2010, 02:15) *
То есть стандарт в данном случае прямо предписывает создавать новую копию переменной.

Ну, я и говорю - слепое следование стандарту.
А не рациональное объяснение. Потому что смысла в данном случае - нет.
aaarrr
Цитата(sonycman @ Aug 22 2010, 02:22) *
Ну, я и говорю - слепое следование стандарту.
А не рациональное объяснение.

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

Цитата(sonycman @ Aug 22 2010, 02:22) *
Потому что смысла в данном случае - нет.

Почему же? Мало ли, может я хочу создать массив для ускорения вычислений, но ОЗУ жалко, а стека - нет.
rezident
Цитата(sonycman @ Aug 22 2010, 04:15) *
Тут лишь слепое следование стандартному механизму.

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

Стандарты для того и придумывают, чтобы описать правила общие для всех. Компиляторы сейчас стараются делать как можно ближе к этому стандарту. Диктуется сие необходимостью устранения недопониманий между желанием человека-программиста и реализацией его желания в командах для конкретной железяки. Язык программирования это средство описания желаний программиста. wink.gif
sonycman
Цитата(aaarrr @ Aug 22 2010, 02:43) *
Слепое следование стандарту - это и есть рациональное объяснение.

Которое в данном случае приводит к иррациональным действиям - пустой трате процессорного времени и памяти.
Не в этом ли смысл оптимизации?

Цитата(aaarrr @ Aug 22 2010, 02:43) *
Почему же? Мало ли, может я хочу создать массив для ускорения вычислений, но ОЗУ жалко, а стека - нет.

Тут не понял - стёка нет, но массив то копируется именно на него?

ЗЫ: а, дошло smile.gif
В этом случае, действительно, может быть прок от такого массива.
Но я бы тогда просто убрал const.
aaarrr
Цитата(sonycman @ Aug 22 2010, 02:50) *
Которое в данном случае приводит к иррациональным действиям - пустой трате процессорного времени и памяти.
Не в этом ли смысл оптимизации?

Так ведь вы сами попросили сделать именно так, а не иначе.

Цитата(sonycman @ Aug 22 2010, 02:50) *
Тут не понял - стёка нет, но массив то копируется именно на него?

Имелось в виду, что стека не жалко.
sonycman
Цитата(aaarrr @ Aug 22 2010, 02:53) *
Так ведь вы сами попросили сделать именно так, а не иначе.

Но ведь вы сами сказали, что достаточно одного const - и переменная будет во флеш?
Тогда я именно так и рассуждал.
aaarrr
Цитата(sonycman @ Aug 22 2010, 03:01) *
Но ведь вы сами сказали, что достаточно одного const - и переменная будет во флеш?

Да, каюсь, мне как-то и в голову не пришло, что речь может идти и о локальной переменной.

sonycman
Цитата(aaarrr @ Aug 22 2010, 03:04) *
Да, каюсь, мне как-то и в голову не пришло, что речь может идти и о локальной переменной.

Ну, и мне тогда в голову не могло прийти, что будет такая ахинея благодаря стандарту.

Надеюсь, автор топика, также, как и я, почерпнёт отсюда пригоршню полезной информации biggrin.gif
Ivan Kuznetzov
Это ладно, когда переменные по 1-2 кбайт. Вот у меня OGG/VORBIS плагин для диктофона на vs1053 весит 24 кило!!! Проблему я решил, так: сначала перевел плагин в бинарник, залил на SD карту полученный файл, и считывал с помощью FatFs-ки загружая его в вс-ку по 4 байта, очень удобненько кстати. Теперь запихал этот плагин во внешнюю флешку M25P64. Плагины, которые я нашел на сайте VLSI, очень даже немаленькие, особенно те, что для кодирования ворбиса. Такчто размещать 24 лишних кило в прошивке микроконтроллера - для моего случая не вариант.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.