summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--linker.html.markdown9
-rw-r--r--ru-ru/linker-ru.html.markdown203
2 files changed, 212 insertions, 0 deletions
diff --git a/linker.html.markdown b/linker.html.markdown
new file mode 100644
index 00000000..ebe6233d
--- /dev/null
+++ b/linker.html.markdown
@@ -0,0 +1,9 @@
+---
+category: tool
+tool: linker
+contributors:
+ - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"]
+---
+
+This article is available in [Russian](http://localhost:4567/docs/ru-ru/linker-ru/).
+
diff --git a/ru-ru/linker-ru.html.markdown b/ru-ru/linker-ru.html.markdown
new file mode 100644
index 00000000..7df29c23
--- /dev/null
+++ b/ru-ru/linker-ru.html.markdown
@@ -0,0 +1,203 @@
+---
+category: tool
+tool: linker
+contributors:
+ - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"]
+translators:
+ - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"]
+lang: ru-ru
+---
+
+# Основные понятия и определения
+**Счетчик позиций** - у компоновщика есть специальная переменная
+"." (точка) всегда содержит текущую позицию вывода.
+
+# Функции
+**ADDR(section)** - возвращает абсолютный адрес указанной секции. Однако
+данная секция должна быть определенна до использования функции ADDR.
+
+**ALIGN(exp)** - возвращает значение счетчика позиций, выравненное на границу
+следующего за exp выражения.
+
+**SIZEOF(section)** - возвращает размер секции в байтах.
+
+**FILL(param)** - определяет образец заполнения для текущей секции. Все
+остальные неуказанные регионы внутри секции заполняются значением указанными
+в аргументе функции.
+
+**KEEP(param)** - используется чтобы помечать param как неустранимый.
+
+**ENTRY(func)** - определяет функцию, которая будет являться точкой входа
+в программу.
+
+```bash
+# Определяем точку входа в программу
+ENTRY(Reset_Handler)
+
+# Определяем перемнную которая содержит адрес вершины стека
+_estack = 0x20020000;
+# Определяем перемнную которая содержит значение размера кучи
+_Min_Heap_Size = 0x200;
+# Определяем перемнную которая содержит значение размера стека
+_Min_Stack_Size = 0x400;
+
+# Описание карты памяти доступной для данного процессора
+# MEMORY
+# {
+# ИМЯ_ОБЛАСТИ_ПАМЯТИ (права доступа) : ORIGIN = АДРЕС_НАЧАЛА, LENGTH = РАЗМЕР
+# }
+# В нашем примере контроллер содержит три области памяти:
+# RAM - начинается с адреса 0x20000000 и занимает 128 Кбайт;
+# CCMRAM - начинается с адреса 0x10000000и занимает 64 Кбайт;
+# FLASH - начинается с адреса 0x8000000 занимает 1024 Кбайт;
+# Причем RAM память доступка для чтения, записи и исполнения.
+# CCMRAM память доступна только на чтение и запись.
+# FLASH память доступна на чтение и исполнение.
+MEMORY
+{
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
+ CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
+ FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
+}
+
+# Описываем выходные секции
+SECTIONS
+{
+ # Первая секция содержит таблицу векторов прерываний
+ .isr_vector :
+ {
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Существует опция --gc-sections, которая позволяет собирать мусор из неиспользуемых
+ # входных разделов. И если есть разделы, которые сборщик муссора не должен трогать,
+ # то их необходимо указать в качестве аргумента функции KEEP() (аналог ключевого слова
+ # volatile).
+ # Запись (*(.isr_vector)) означает разделы .isr_vector во всех объектных файлах. Т.к.
+ # обращение к разделу в общем виде выглядит так: (ИМЯ_ФАЙЛА(ИМЯ_РАЗДЕЛА))
+ KEEP(*(.isr_vector))
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Выражение ">ОБЛАСТЬ_ПАМЯТИ" указывает в какую именно область памяти будет помещенна
+ # данная секция. В нашем слущае секция .isr_vector будет размещена во FLASH памяти.
+ } >FLASH
+
+# ИТОГО: Секция .isr_vector, которая содержит таблицу векторов прерываний выравнивается
+# по границе 4-х байт, помечается как недоступная для сборщика мусора и размещается в начале
+# FLASH памяти микроконтроллера.
+
+ # Вторая секция содержит код программы.
+ .text :
+ {
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Указываем, что в данной секции будут хранится области .text всех
+ # объектных файлов
+ *(.text)
+ *(.text*)
+
+ # Защищаем от сборщика мусора секции .init и .fini
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Определяется переменная _etext, которая хранит в себе адрес конца секции .text и которая
+ # может быть доступна в исходном тексте программы через объявление
+ # volaile unsigned int extern _etext;
+ _etext = .;
+ } >FLASH
+
+# ИТОГО: Секция .text, которая содержит код программы выравнивается по границе 4-х байт,
+# включает в себя: все секции с кодом программы во всех объектных файлах и защищенные
+от сборщика муссора секции .init и .fini во всех объектных файлах, распологается во FLASH
+памяти микроконтроллера сразу за таблицей векторов.
+Секции text, .init и .fini. располагаются в памяти в той последовательности в которой они
+объявлены в скрипте.
+
+ # Третья секция содержит константные данные.
+ .rodata :
+ {
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Указываем, что в данной секции будут хранится области .rodataвсех
+ # объектных файлов
+ *(.rodata)
+ *(.rodata*)
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+ } >FLASH
+
+ # Сохраняем в переменной _sidata абсолютный адрес секции .data
+ _sidata = LOADADDR(.data);
+
+ # Четвертая секция содержит инициализированные переменные.
+ .data :
+ {
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Сохраняем в переменной _sdata адрес текущей позиции (начала секции)
+ _sdata = .;
+
+ # Указываем, что в данной секции будут хранится области .data всех
+ # объектных файлов
+ *(.data)
+ *(.data*)
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Сохраняем в переменной _sdata адрес текущей позиции (конец секции)
+ _edata = .;
+
+ # Функция AT указывает на то, что данный сектор хранится в одной области памяти
+ # (в нашем случае FLASH), а исполняться будет из другой обасти памяти (в нашем случае RAM).
+ # Есть два типа адрессов:
+ # * VMA (Virtual memory address) - это run-time адрес по которому уомпилятор ожидает
+ # видеть данные.
+ # * LMA (Load memory address) - это адрес по которому линкер хранит данные.
+
+ #Startup должен код скопировать секцию .data из адрессов LMA в адресса VMA.
+
+ } >RAM AT> FLASH
+
+ # Пятая секция содержит инициализированные нулем переменные.
+ .bss :
+ {
+ # Сохраняем в переменной _sbss и __bss_start__ адрес текущей позиции (начала секции)
+ _sbss = .;
+ __bss_start__ = _sbss;
+
+ # Указываем, что в данной секции будут хранится области .bss всех
+ # объектных файлов
+ *(.bss)
+ *(.bss*)
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Сохраняем в переменной _ebss и __bss_end__ адрес текущей позиции (начала секции)
+ _ebss = .;
+ __bss_end__ = _ebss;
+ } >RAM
+
+ # Шестая секция содержит кучу и стек. Размещается в самом конце RAM.
+ ._user_heap_stack :
+ {
+ . = ALIGN(4);
+ PROVIDE ( end = . );
+ PROVIDE ( _end = . );
+ . = . + _Min_Heap_Size;
+ . = . + _Min_Stack_Size;
+ . = ALIGN(4);
+ } >RAM
+}
+```
+