Как пользоваться переменными в ld-cкрипте?

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Как пользоваться переменными в ld-cкрипте?

Сообщение Eddy_Em »

Очень неудобно задавать размер блока флеш-памяти в заголовочных файлах, т.к. он все равно должен быть определен в линкере (для выравнивания начала "эмуляции EEPROM во флеш". Конкретно пользуюсь STM32F072CBT6.
В файле stm32f072B.ld задаю:

Код: Выделить всё

MEMORY
{
    rom   (rx) : ORIGIN = 0x08000000, LENGTH = 128K
    ram  (rwx) : ORIGIN = 0x20000000, LENGTH = 16K
}

PROVIDE(_BLOCKSIZE = 2048);

INCLUDE stm32f01234.ld
А в stm32f01234.ld пишу:

Код: Выделить всё

...
  .myvars :
  {
    . = ALIGN(_BLOCKSIZE);
    __varsstart = ABSOLUTE(.);
    KEEP(*(.myvars));
  } > rom
Однако, если я пытаюсь у себя в исходниках обратиться к этой переменной:

Код: Выделить всё

extern const uint32_t _BLOCKSIZE;
то вместо ожидаемого 2048 получаю какое-то непонятное 2953142315.

Вопрос: как мне получить значение переменной _BLOCKSIZE в своем сишном файле?

Добавлено after 5 minutes:
Пытаюсь вот так сделать:

Код: Выделить всё

extern const uint32_t __varsstart, _BLOCKSIZE;
static const uint32_t *blocksize = (uint32_t*)&_BLOCKSIZE;
*blocksize выдает мне 2953142315 вместо 2048!

Добавлено after 20 minutes 40 seconds:
Разобрался. Надо было вот так:

Код: Выделить всё

static const uint32_t blocksize = (uint32_t)&_BLOCKSIZE;
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Реклама
tonyk
Это не хвост, это антенна
Сообщения: 1310
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение tonyk »

Eddy_Em писал(а):Разобрался. Надо было вот так:
Код:
static const uint32_t blocksize = (uint32_t)&_BLOCKSIZE;
Благодарю! Мне это пригодится.
Реклама
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение jcxz »

А зачем создавать какие-то переменные или константы (которые нужно размещать в памяти и обращаться к ним в runtime) если можно объявить всё необходимое при помощи #define?
Я создавал .h-файл, объявлял в нём необходимые константы #define-ами. Затем этот файл включал (#include) и в командный файл линкёра и в .c-файлы.
tonyk
Это не хвост, это антенна
Сообщения: 1310
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение tonyk »

[uquote="jcxz",url="/forum/viewtopic.php?p=4111080#p4111080"]А зачем создавать какие-то переменные или константы (которые нужно размещать в памяти и обращаться к ним в runtime) если можно объявить всё необходимое при помощи #define?[/uquote]
Да хотя бы затем, чтобы, внеся изменения в ld-скрипт, не ползать по h-файлам и быть уверенным в правильности адресов и размеров данных во флэше, к которым ты обращаешься из программы. Эти адреса-размеры вычислит линковщик на этапе редактирования связей, а не ты приколотишь их гвоздями-дефайнами.
Реклама
Эиком - электронные компоненты и радиодетали
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение jcxz »

[uquote="tonyk",url="/forum/viewtopic.php?p=4111096#p4111096"]Да хотя бы затем, чтобы, внеся изменения в ld-скрипт, не ползать по h-файлам и быть уверенным в правильности адресов и размеров данных во флэше, к которым ты обращаешься из программы. Эти адреса-размеры вычислит линковщик на этапе редактирования связей, а не ты приколотишь их гвоздями-дефайнами.[/uquote]Ну так задайте всё нужное в этом самом .h-файле. Едином (если так нужно) и не ползайте.
И кто говорил о каком-то "приколачивании гвоздями"?
Исходный вопрос был в задании: _BLOCKSIZE = 2048
Это "приколачивание гвоздями" или нет? И почему если в .h-файле это "приколачивание гвоздями", то тогда в скрипте линкёра почему это не оно?

Как раз задание в скрипте линкёра это и есть - необходимость ползания по этим скриптам (если например этих скриптов несколько: "отладка во флешь", "отладка в ОЗУ", "отладка в SDRAM", "релиз во флешь с полной оптимизацией" и т.п.). И задание через переменные/const - это невозможность использования этих заданных размеров в выражениях, вычисляемых на этапе компиляции. В то время как через #define в .h-файле - намного гибче и универсальнее.

PS: Да, кстати, определение собственных символьных имён, начинающихся с '_' - плохой стиль и вроде не рекомендуется многими компиляторами, так как зарезервированные внутренние имена (разных констант) компиляторов обычно начинаются с '_'. И возможен конфликт с ними.
Реклама
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение Eddy_Em »

И почему если в .h-файле это "приколачивание гвоздями", то тогда в скрипте линкёра почему это не оно?
Потому что в этом линкер-файле УЖЕ определяется размер флеша и RAM, почему бы туда же не засунуть размер страницы?
А что, можно h-файлы в ld-файлы включать что ли? Тогда почему же так не делают? Может, потому что ld-cкрипту нафиг не нужно знать о 100500 регистрах и функциях?
Задание в скрипте линкера удобней: ты все равно в Makefile указываешь, какой ld-скрипт подключить. А вот заголовочный файл может быть один на целое семейство…
И возможен конфликт с ними.
Это намного менее вероятно, чем конфликт с какой-нибудь одноименной функцией или переменной из моего кода. Где нет подчеркивания.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Реклама
tonyk
Это не хвост, это антенна
Сообщения: 1310
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение tonyk »

Добавлю, что как только ты начнёшь размещать во флэш много переменных, то высока вероятность, что ты ошибёшься с адресами и их размерами. Ситуацию усугубляет то, что в STM32 даже у одного МК на кристалле размер сегментов флэш существенно разный. Как только ты решишь передвинуть данные в другую страницу, тебе придётся пересчитывать все адреса или изначально городить макросы, которые будут пересчитывать все адреса и смещения относительно базы. И да, даже сам факт твоего выхода за границы сегмента флэш линкёр легко обнаружит в отличие от человека. И ОЗУ разбито на области, подключенные к разным шинам, устройствам и доменам питания. Тоже будешь задавать адреса переменных через дефайны?

Поэтому лучше описать линкёру что и куда тебе нужно положить, он разложит и установит правильные значения переменных, содержащих адреса и размеры, которые ты сможешь уверенно и безопасно использовать. Поэтому считаю, что нужно заморочиться скриптом линковщика, дабы избавить себя от ненужной арифметики.
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение jcxz »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4111617#p4111617"]А что, можно h-файлы в ld-файлы включать что ли?[/uquote]

Код: Выделить всё

//!Linker command file.

#define LINKER_CMD
#include "..\memmap.h"

-stack 0x00000000  //!<stack size
-heap  0x00000040  //!<heap size

SECTIONS
{
  .exceptions:            load = 0xFFFF0000
  .bootStart:             load = RAM_SDRAM_ARM_RX_BEGIN
  .sysvecs              > RAM_ARM, type = NOINIT
  .stkSVC               > RAM_ARM, type = NOINIT
  .stkABT               > RAM_ARM, type = NOINIT
  .stkUND               > RAM_ARM, type = NOINIT
  .stkSYS               > RAM_ARM, type = NOINIT
  .stkFIQ               > RAM_ARM, type = NOINIT
  .stkIRQ               > RAM_ARM, type = NOINIT
  .stkIRQnest           > RAM_ARM, type = NOINIT
  .bssTrapData          > RAM_ARM, type = NOINIT
  .bss0: { *(.bssDMA) } > RAM_SHARED_ARM_RW, type = NOINIT
  .bss                  > RAM_SDRAM_ARM_RW, type = NOINIT
  .bssStk               > RAM_SDRAM_ARM_RW, type = NOINIT
  .bssInternal          > RAM_SHARED_ARM_RW
  .noinit               > RAM_SDRAM_ARM_RW, type = NOINIT
...
ку?
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4111617#p4111617"]Тогда почему же так не делают?[/uquote]То что вы этого не_знаете/не_делаете != никто_не_знает/не_делает. Если такая возможность есть в компиляторах/компоновщиках значит кому-то это нужно. И кто-то даже использует.

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4111617#p4111617"]Задание в скрипте линкера удобней: ты все равно в Makefile указываешь, какой ld-скрипт подключить.[/uquote]Разницу между константой заданной через #define и через const int ... понимаете? Похоже нет. Тогда для вас - без разницы. :dont_know:

Добавлено after 4 minutes 1 second:
[uquote="tonyk",url="/forum/viewtopic.php?p=4111663#p4111663"]Добавлю, что как только ты начнёшь размещать во флэш много переменных, то высока вероятность[/uquote]
Вы о чём вообще??? Вроде разговор был о задании константы. Причём тут какие-то "размещения", да ещё переменных? И как вообще во флешь можно размещать переменные?
Что такое в си константа (макрос), определяемая через #define - знаете, нет?
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение Dimon456 »

Господа, а вот такой вопрос: требуется определить остаток свободной RAM.
В avr_gcc определяется так
Спойлер

Код: Выделить всё

int memoryFree()
{
   int freeValue;
	   if((int)__brkval == 0)
	      freeValue = ((int)&freeValue) - ((int)&__bss_end);
	   else
	      freeValue = ((int)&freeValue) - ((int)__brkval);
	   return freeValue;
}
__brkval какая-то системная переменная
как это сделать в arm_gcc?
mallinfo() не предлагать.
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение Eddy_Em »

jcxz, для фантастов, решивших, что можно в линкер-скрипт инклюды сишные добавлять, вот выхлоп:

Код: Выделить всё

make
  LD      mk/steppers.elf
/opt/bin/arm-none-eabi-gcc --static -nostartfiles -L../inc/ld -Tstm32f072B.ld -Wl,-Map=mk/steppers.map -Wl,--gc-sections -mthumb -mcpu=cortex-m0 -march=armv6-m -mtune=cortex-m0 -msoft-float mk/adc.o mk/buttons.o mk/can.o mk/commonproto.o mk/custom_buttons.o mk/flash.o mk/hardware.o mk/main.o mk/proto.o mk/steppers.o mk/strfunct.o mk/usb.o mk/usb_lib.o mk/startup.o -Wl,--start-group -lc -lgcc -Wl,--end-group /opt/bin/../lib/gcc/arm-none-eabi/9.3.1/libgcc.a -o mk/steppers.elf
/opt/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: cannot open linker script file stm32f072xb.h: No such file or directory
collect2: error: ld returned 1 exit status
make: *** [Makefile:128: mk/steppers.elf] Error 1
НЕЛЬЗЯ!
Да и незачем это делать. Потому что переменные линкера - это одно, а дефайны препроцессора gcc — совсем другое!
Команда INCLUDE в ld-скрипте ожидает, что включаться будет кусок линкер-скрипта, а никак не обычный заголовочный файл! Они и лежат-то совершенно в разных местах (сокращу путь к директории до INC): заголовочники — в /INC/Fx/ и /INC/cm, а ld-скрипты — в /INC/ld. Вот так может выглядеть директория /INC/ld:

Код: Выделить всё

stm32f030f.ld  stm32f042x6.ld  stm32f0728.ld  stm32f103x4.ld  stm32f103x8.ld  stm32f103xC.ld  stm32f103xE.ld  stm32f103xG.ld
stm32f01234.ld  stm32f042k.ld  stm32f051x8.ld  stm32f072B.ld  stm32f103x6.ld  stm32f103xB.ld  stm32f103xD.ld  stm32f103xF.ld
Добавлено after 5 minutes 37 seconds:
Dimon456, а как вы можете вообще узнать объем оперативы, если ей навстречу стек растет? Это нужно как-то узнать, где сейчас кончается стек, и из этого адреса вычесть адрес последней объявленной переменной и ее sizeof.

Добавлено after 6 minutes 18 seconds:
Да, полез погуглить сейчас — это невозможно. Можно реализовать ОСРВ, которая сможет сообщать, сколько еще под аллокаторы памяти осталось, но она все равно не жрет всю доступную оперативку: есть еще и для личных нужды место, и для стека.
Я вообще не представляю себе, как можно программно определить предельный размер стека, чтобы наверняка не вбабахаться в него. Можно выхлоп gcc посмотреть, скриптом выдрать оттуда нужные цифры и воткнуть в какой-нибудь заголовочный файл в виде макросов. Т.е. делать make дважды для получения актуальных значений.
Это, наверное, единственный вариант.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
tonyk
Это не хвост, это антенна
Сообщения: 1310
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение tonyk »

Eddy_Em писал(а):Dimon456, а как вы можете вообще узнать объем оперативы, если ей навстречу стек растет?
Адрес последней размещённой переменной тебе линковщик скажет. Зная размер сегмента ОЗУ, можно вычислить размер свободной ОЗУ. Но всё усложняется, когда у тебя несколько сегментов ОЗУ. Тут уже нужно смотреть каждый конкретный случай.

Добавлено after 2 minutes 14 seconds:
Eddy_Em писал(а):Я вообще не представляю себе, как можно программно определить предельный размер стека, чтобы наверняка не вбабахаться в него.
Водяные знаки. Пример реализации есть во FreeRTOS.

Добавлено after 35 minutes 43 seconds:
jcxz писал(а): И как вообще во флешь можно размещать переменные?
Легко! Указываешь секцию, в которой её нужно разместить. Если нужно, можно даже смещение относительно начала секции указать и/или выравнивание. И спокойно работаешь как с обычной переменной. Очень удобно, когда нужно сохранять переменные во флэш. Все адреса и размеры вычисляет при таком подходе линковщик. Кстати, размеры областей памяти для хранения переменных, как известно, зависят от упаковки и выравнивания и могут меняться при смене МК.
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение Eddy_Em »

tonyk, упор был сделан на слове "переменная": во флеше же только константы! Зато их можно сотнями писать. У меня вот 100кБ свободно, а структура конфигурации меньше 50Б занимает. Даже если до 64 округлить, в одну страницу 32 штуки влезет, а суммарно - 160... И лишь на 161-й раз нужно будет стирать флеш и начинать с начала.
Что до свободной оперативки, как я понял, нужно в рантайме узнавать, сколько осталось. А это возможно лишь с точностью до сотни-другой байт.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение DX168B »

Не знаю, как в GCC, но в IAR я делал так:
(тут для куска RAM [CCM], но не суть)
.icf файл линкера:

Код: Выделить всё

define symbol __region_CCM_start__ = 0x10000000;
define symbol __region_CCM_end__   = 0x1000FFFF;
define region CCM_region   = mem:[from __region_CCM_start__   to __region_CCM_end__];
place in CCM_region  { section .ccm };
Далее, в одном заголовочнике:

Код: Выделить всё

#define CCM_RAM _Pragma("location=\".ccm\"")
И уже в исходниках, где нужно объявить переменную/массив/структуру в этой области памяти:

Код: Выделить всё

CCM_RAM int32_t chData[2][AMP_BUFFERS_SIZE/2]; // Многомерный массив
CCM_RAM int32_t leftVol = 1; // Переменная
Компилятор сам уже все распихает. Я обычно использую структуры для хранения настроек и пишу их в память как массив.
I am DX168B and this is my favourite forum on internet!
tonyk
Это не хвост, это антенна
Сообщения: 1310
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение tonyk »

Eddy_Em писал(а):во флеше же только константы!
Ну-у, константы- это вещь условная. Всего лишь замени FLASH на FRAM.
структура конфигурации меньше 50Б занимает
У меня 50К. И большая часть пишется разом. Кстати, в STM32 размер страницы флэш имеет размер от 1К до 256К. Поэтому-то вычисление всех адресов и размеров я отдаю на откуп линкёру.
Что до свободной оперативки, как я понял, нужно в рантайме узнавать, сколько осталось.
Тут подвох в том, что что ОЗУ может быть разбита на несколько областей, подключенных к разным шинам. И переменные ты будешь размещать в разных сегментах. Тогда может получится, что в каждом сегменте осталось по чуть-чуть, а в сумме вполне себе ничего.
А это возможно лишь с точностью до сотни-другой байт.
Даже точнее, до байта. Тут всё зависит от того, сколько ветвей программы и как ты проверишь.
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение Eddy_Em »

[uquote="tonyk",url="/forum/viewtopic.php?p=4112036#p4112036"]Даже точнее, до байта.[/uquote]
А, дошло!
Ведь небольшая переменная скорей всего будет определена на стеке → адрес переменной минус ее sizeof и даст нам конец оперативки. Остается теперь придумать, как определить, где лежит последний элемент самой оперативки...
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение jcxz »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4111933#p4111933"]jcxz, для фантастов, решивших, что можно в линкер-скрипт инклюды сишные добавлять, вот выхлоп:[/uquote]Я вам привёл фрагмент реального командного файла линкёра.

Добавлено after 4 minutes 49 seconds:
[uquote="tonyk",url="/forum/viewtopic.php?p=4111953#p4111953"]Легко! Указываешь секцию, в которой её нужно разместить. Если нужно, можно даже смещение относительно начала секции указать и/или выравнивание. И спокойно работаешь как с обычной переменной. Очень удобно, когда нужно сохранять переменные во флэш. Все адреса и размеры вычисляет при таком подходе линковщик.[/uquote]А теперь покажите как такое можно сделать например на любом XMC4xxx? Или на любом LPC17xx?
А то мануалы их говорят, что это невозможно. :cry:

Добавлено after 15 minutes 16 seconds:
[uquote="Dimon456",url="/forum/viewtopic.php?p=4111897#p4111897"]как это сделать в arm_gcc?[/uquote]Сначала нужно уточнить: Что имеется в виду под "остатком свободной RAM"?
Если речь про объём какого-то региона ОЗУ, не занятый компоновщиком для выходных секций программы (кода/данных), то:
1) Разместить любую переменную/константу в именованной секции (назовём её ".codetailExt").
2) В командном файле компоновщика задать размещение этой секции в конце того региона ОЗУ, незанятый размер которого хотите вычислить.
3) Вычислить незанятый объём как = конец_региона - конец_секции_.codetailExt.
Пример для IAR (фрагмет командного файла компоновщика):

Код: Выделить всё

define region RAM_regionC    = mem:[from 0x20000100 size 0x1FF00]; //DSRAM1 (ro-data)
define block IMAGE_HEAD with fixed order {section .intvec, section .checksum, section .codehead, section .intvecTail, section .codeSignature};
place in RAM_regionC {
  first block IMAGE_HEAD_EXT,
  section .rodata,
  section .text object bsp.o,
  section .text object http.o,
  section .text object json.o,
  section .text object japi.o,
  section .text object dte.o,
  last section .codetailExt
};
Незанятый размер региона RAM_regionC будет = 0x20020000 - (u32)__section_end(".codetailExt") (это уже в си-коде).
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение Eddy_Em »

jcxz, если вычислить таким способом размер, то он будет включать и область, занятую стеком!
Я вам привёл фрагмент реального командного файла линкёра.
ОК, доказываю. Вот файл линкера:

Код: Выделить всё

/* Linker script for STM32F030f4, 16K flash, 4K RAM. */

#include "include.h"

/* Define memory regions. */
MEMORY
{
    rom   (rx) : ORIGIN = 0x08000000, LENGTH = 16K
    ram  (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
}

PROVIDE(_BLOCKSIZE = 1024);

/* Include the common ld script. */
INCLUDE stm32f01234.ld
Вот - включаемый:

Код: Выделить всё

#define FIRSTMACRO      (1)
#define SECOND
extern int testval;
void testfunc();
А вот - выхлоп линкера:

Код: Выделить всё

make
  LD      mk/chiller.elf
/opt/bin/arm-none-eabi-gcc --static -nostartfiles -L../inc/ld -Tstm32f030f.ld -Wl,-Map=mk/chiller.map -Wl,--gc-sections -mthumb -mcpu=cortex-m0 -march=armv6-m -mtune=cortex-m0 -msoft-float mk/adc.o mk/hardware.o mk/main.o mk/mainloop.o mk/protocol.o mk/usart.o mk/startup.o -Wl,--start-group -lc -lgcc -Wl,--end-group /opt/bin/../lib/gcc/arm-none-eabi/9.3.1/libgcc.a -o mk/chiller.elf
/opt/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld:stm32f030f.ld:3: ignoring invalid character `#' in expression
/opt/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld:stm32f030f.ld:3: syntax error
collect2: error: ld returned 1 exit status
make: *** [Makefile:118: mk/chiller.elf] Error 1
Так что, не надо тут байки травить! Нельзя в линкер-скрипт обычный сишный заголовочный файл включить!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение jcxz »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4112467#p4112467"]jcxz, если вычислить таким способом размер, то он будет включать и область, занятую стеком![/uquote]Я не знаю что у вас там за бардак в исходниках, что стек лезет в неиспользуемую область. В нормально построенной программе, стек компонуется в секцию .bss или в .noinit или в специальную секцию стека.

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4112467#p4112467"]Так что, не надо тут байки травить! Нельзя в линкер-скрипт обычный сишный заголовочный файл включить![/uquote]Тут так же как со стеком выше: кто-то умеет, кто-то - нет. Не каждому дано. :dont_know:
tonyk
Это не хвост, это антенна
Сообщения: 1310
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение tonyk »

jcxz писал(а):Или на любом LPC17xx? А то мануалы их говорят, что это невозможно.
UM10360, страница 620 мне говорит, что на LPC17xx всё, о чём я говорил выше применительно к СТМ32, точно также работает для LPC17хх. Разница только в размерах и адресах сегментов. Поэтому читаем мануал на линкёр.
Вот пример описания памяти для STM32F411RE. Обращаю внимание, что некоторые сегменты объединены в одну область, а некоторые используются по отдельности.
Спойлер

Код: Выделить всё

...

/* Memories definition */
MEMORY
{
    RAM                 (xrw)   : ORIGIN = 0x20000000, LENGTH = 128K
    
    SECTOR_0            (rx)    : ORIGIN = 0x08000000, LENGTH = 16K
    SECTOR_1_2          (rx)    : ORIGIN = 0x08004000, LENGTH = 32K
    SECTOR_3            (rx)    : ORIGIN = 0x0800C000, LENGTH = 16K  
    SECTOR_4            (rx)    : ORIGIN = 0x08010000, LENGTH = 64K  
    SECTOR_5_7          (rx)    : ORIGIN = 0x08020000, LENGTH = 384K  
}

/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector_FLASH :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector_FLASH)) /* Startup code */
    . = ALIGN(4);
  } >SECTOR_0

  .plc_params :
  {
    . = ALIGN(2);
    
    KEEP (*(.plc_params))
                    
    /*. = ALIGN(2);*/
  } >SECTOR_1_2
  
  .plc_prog :
  {
    /*. = ALIGN(2);*/
    KEEP (*(.plc_prog))
                    
    . = ALIGN(2);
  } >SECTOR_1_2
     
  .plc_D8xxx :
  {
    . = ALIGN(2);
    
    KEEP (*(.plc_D8xxx))
                    
    . = ALIGN(2);
  } >SECTOR_1_2
        
  .plc_data_regs :
  {
    . = ALIGN(2);
    
    KEEP (*(.plc_data_regs))
                    
    . = ALIGN(2);
  } >SECTOR_3

...

А вот как в эти сегменты размещаются данные:
Спойлер

Код: Выделить всё

...

const uint8 __PLC_params[ SIZE_BYTE_PARAMS ] \
    __attribute__ ( (section( ".plc_params" ), used ) ) =
{
    MAX_STEP / 1000, 0x00,  // 00 0x0000 -- SIZE IN STEP 16000
    0x00, 0x00,             // 02        --
    0x00, 0x00,             // 04        --
    0x00, 0x00,             // 06        --

    0x20, 0x20,             // 08 0x0008 -- PASSWORD 0
    0x20, 0x20,             // 10        -- PASSWORD 1
    0x20, 0x20,             // 12        -- PASSWORD 2
    0x20, 0x20,             // 14        -- PASSWORD 3

    'S', 'K',               // 16 0x0010 -- PLC NAME 0
    '2', 'N',               // 18        -- PLC NAME 1
    '-', 'F',               // 20        -- PLC NAME 2
    '4', '1',               // 22        -- PLC NAME 3
    '1', 'R',               // 24        -- PLC NAME 4
    'E', '-',               // 26        -- PLC NAME 5
    'B', 'o',               // 28        -- PLC NAME 6
    'k', 'r',               // 30        -- PLC NAME 7
    'a',  0,                // 32        -- PLC NAME 8
     0,   0,                // 34        -- PLC NAME 9
     0,   0,                // 36        -- PLC NAME A
     0,   0,                // 38        -- PLC NAME B
     0,   0,                // 40        -- PLC NAME C
     0,   0,                // 42        -- PLC NAME D
     0,   0,                // 44        -- PLC NAME E
     0,   0,                // 46        -- PLC NAME F
    ...
};
const uint16 __PLC_prog[ MAX_STEP ] \
    __attribute__ ( (section( ".plc_prog" ), used ) ) =
{
    0x2800, 0xC801, 0x001C, // -|M0|-(M1)-
    0xFFFF,                 // ----[FEND]-
    0x000F                  // -----[END]-
};

const uint16 __PLC_D8XXX[ 256 ] \
    __attribute__ ( (section( ".plc_D8xxx" ), used ) ) =
{
    0x00C8,             // D8000 - WDT 200ms
   ...
};


const uint16 __PLC_storredRegisters[ STORRED_REGS_NUM ] \
    __attribute__ ( (section( ".plc_data_regs" ), used ) ) =
{
   0
};

...
Если для программирования LPC17xx используется GCC, то достаточно изменить адреса сегментов в соответствии с UM10360, p.620. И, разумеется, прочитать мануал на GNUсный линкёр .
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Как пользоваться переменными в ld-cкрипте?

Сообщение Eddy_Em »

[uquote="jcxz",url="/forum/viewtopic.php?p=4112475#p4112475"]Не каждому дано. :dont_know:[/uquote]
Ну так и надо сразу писать, что вместо компилятора используется какое-нибудь вантузоидное дерьмо типа кайла или яра.

А стек и оперативка растут друг навстречу другу. И обычно размер стека не фиксируют: если слишком мало дашь, может переполниться, если слишком много - часть оперативки попросту не будет использоваться.

Поэтому если оперативка на секции не разбита (что правильно), то никак не узнать размер. Разве что какие-нибудь хитрые МК, у которых несколько типов оперативки - там уже точно можно узнать для всех типов, которые без стека.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Ответить

Вернуться в «Разные вопросы по МК»