diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50e39d81..ce05dc54 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,6 +23,6 @@ jobs: - name: Files are UTF-8 run: ./lint/encoding.sh . - name: Lint Markdown - run: mdl . --ignore-front-matter -r MD003,MD005,MD011,MD019,MD023,MD027,MD028,MD035,MD037,MD038,MD039,MD047 + run: mdl . --ignore-front-matter -r MD003,MD005,MD011,MD019,MD023,MD025,MD027,MD028,MD035,MD037,MD038,MD039,MD047 - name: Lint frontmatter run: ./lint/frontmatter.py . diff --git a/linker.md b/linker.md index e730178f..02aad515 100644 --- a/linker.md +++ b/linker.md @@ -1,34 +1,31 @@ --- category: tool -name: GNU linker (ld) +name: Linker script contributors: - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"] translators: - ["Anuj Shah", "https://github.com/ShahAnuj2610"] +filename: learn.ld --- -## Basic concepts and definitions - **Position counter** - the linker has a special variable -"." (dot) always contains the current output position. +"`.`" (dot) always contains the current output position. -## Functions - -**ADDR (section)** - returns the absolute address of the specified section. However +`ADDR (section)` - returns the absolute address of the specified section. However this section must be defined before using the ADDR function. -**ALIGN (exp)** - returns the value of the position counter aligned to the border +`ALIGN (exp)` - returns the value of the position counter aligned to the border following the exp expression. -**SIZEOF (section)** - returns the size of the section in bytes. +`SIZEOF (section)` - returns the size of the section in bytes. -**FILL (param)** - defines the fill pattern for the current section. All +`FILL (param)` - defines the fill pattern for the current section. All other unspecified regions within the section are filled with the value indicated in function argument. -**KEEP (param)** - used to mark param as fatal. +`KEEP (param)` - used to mark param as fatal. -**ENTRY (func)** - defines the function that will be the entry point +`ENTRY (func)` - defines the function that will be the entry point into the program. ```bash @@ -45,7 +42,7 @@ _Min_Stack_Size = 0x400; # Description of the memory card available for this processor # MEMORY # { -#MEMORY_DOMAIN_NAME (access rights): ORIGIN = START_ADDRESS, LENGTH = SIZE +# MEMORY_DOMAIN_NAME (access rights) : ORIGIN = START_ADDRESS, LENGTH = SIZE # } # In our example, the controller contains three memory areas: # RAM - starts with the address 0x20000000 and takes 128 KB; @@ -56,33 +53,33 @@ _Min_Stack_Size = 0x400; # FLASH memory is available for reading and execution. MEMORY { - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K - CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K - FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K + CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K } # We describe output sections SECTIONS { - # The first section contains a table of interrupt vectors + # The first section contains a table of interrupt vectors .isr_vector : { - # Align the current position to the border of 4 bytes. + # Align the current position to the border of 4 bytes. . = ALIGN(4); - # There is an option --gc-sections, which allows you to collect garbage from unused - # input sections. And if there are sections that the garbage collector should not touch, - # you need to specify them as an argument to the KEEP () function (analogue of the keyword - # volatile). - # The entry (* (. Isr_vector)) means the .isr_vector sections in all object files. Because - # appeal to the section in general terms looks like this: (FILE_NAME (SECTION_NAME)) + # There is an option --gc-sections, which allows you to collect garbage from unused + # input sections. And if there are sections that the garbage collector should not touch, + # you need to specify them as an argument to the KEEP () function (analogue of the keyword + # volatile). + # The entry (* (. Isr_vector)) means the .isr_vector sections in all object files. Because + # appeal to the section in general terms looks like this: (FILE_NAME (SECTION_NAME)) KEEP(*(.isr_vector)) - # Align the current position to the border of 4 bytes. + # Align the current position to the border of 4 bytes. . = ALIGN(4); - # The expression "> MEMORY AREA" indicates which area of ​​memory will be placed - # this section. In our section, the .isr_vector section will be located in FLASH memory. + # The expression "> MEMORY AREA" indicates which area of ​​memory will be placed + # this section. In our section, the .isr_vector section will be located in FLASH memory. } >FLASH # TOTAL: The .isr_vector section that contains the table of interrupt vectors is aligned @@ -92,24 +89,24 @@ SECTIONS # The second section contains the program code. .text : { - # Align the current position to the border of 4 bytes. + # Align the current position to the border of 4 bytes. . = ALIGN(4); # We indicate that in this section the .text areas of all - # object files + # object files *(.text) *(.text*) - # Protect the .init and .fini sections from the garbage collector + # Protect the .init and .fini sections from the garbage collector KEEP (*(.init)) KEEP (*(.fini)) - # Align the current position to the border of 4 bytes. + # Align the current position to the border of 4 bytes. . = ALIGN(4); - # The variable _etext is defined, which stores the address of the end of the .text section and which - # may be available in the source code of the program through the announcement - # volaile unsigned int extern _etext; + # The variable _etext is defined, which stores the address of the end of the .text section and which + # may be available in the source code of the program through the announcement + # volaile unsigned int extern _etext; _etext = .; } >FLASH @@ -123,15 +120,15 @@ SECTIONS # The third section contains constant data. .rodata : { - # Align the current position to the border of 4 bytes. + # Align the current position to the border of 4 bytes. . = ALIGN(4); - # We indicate that in this section areas .rodata will be stored - # object files + # We indicate that in this section areas .rodata will be stored + # object files *(.rodata) *(.rodata*) - # Align the current position to the border of 4 bytes. + # Align the current position to the border of 4 bytes. . = ALIGN(4); } >FLASH @@ -141,47 +138,47 @@ SECTIONS # The fourth section contains initialized variables. .data : { - # Align the current position to the border of 4 bytes. + # Align the current position to the border of 4 bytes. . = ALIGN(4); - # Save the address of the current position (beginning of the section) in the variable _sdata + # Save the address of the current position (beginning of the section) in the variable _sdata _sdata = .; - # We indicate that in this section the .data areas of all - # object files + # We indicate that in this section the .data areas of all + # object files *(.data) *(.data*) - # Align the current position to the border of 4 bytes. + # Align the current position to the border of 4 bytes. . = ALIGN(4); # Save the address of the current position (end of section) in the variable _sdata _edata = .; - # AT function indicates that this sector is stored in one memory area - # (in our case, FLASH), and it will be executed from another area of ​​memory (in our case, RAM). - # There are two types of addresses: - # * VMA (Virtual memory address) - this is the run-time address at which the compiler expects - # see data. - # * LMA (Load memory address) is the address at which the linker stores data. + # AT function indicates that this sector is stored in one memory area + # (in our case, FLASH), and it will be executed from another area of ​​memory (in our case, RAM). + # There are two types of addresses: + # * VMA (Virtual memory address) - this is the run-time address at which the compiler expects + # see data. + # * LMA (Load memory address) is the address at which the linker stores data. - #Startup must code to copy the .data section from the LMA addresses to the VMA addresses. + #Startup must code to copy the .data section from the LMA addresses to the VMA addresses. } >RAM AT> FLASH # The fifth section contains zero-initialized variables. .bss : { - # Save the address of the current position (beginning of the section) in the variable _sbss and __bss_start__ + # Save the address of the current position (beginning of the section) in the variable _sbss and __bss_start__ _sbss = .; __bss_start__ = _sbss; - # We indicate that in this section the .bss areas of all - # object files + # We indicate that in this section the .bss areas of all + # object files *(.bss) *(.bss*) - # Align the current position to the border of 4 bytes. + # Align the current position to the border of 4 bytes. . = ALIGN(4); # Save the address of the current position (beginning of the section) in the variable _ebss and __bss_end__ diff --git a/ru/linker.md b/ru/linker.md index 20f8274e..330ffc2a 100644 --- a/ru/linker.md +++ b/ru/linker.md @@ -1,30 +1,26 @@ --- contributors: - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"] -translators: - - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"] --- -# Основные понятия и определения -**Счетчик позиций** - у компоновщика есть специальная переменная -"." (точка) всегда содержит текущую позицию вывода. +**Счетчик позиций** - у компоновщика есть специальная переменная +"`.`" (точка) всегда содержит текущую позицию вывода. -# Функции -**ADDR(section)** - возвращает абсолютный адрес указанной секции. Однако +`ADDR(section)` - возвращает абсолютный адрес указанной секции. Однако данная секция должна быть определенна до использования функции ADDR. -**ALIGN(exp)** - возвращает значение счетчика позиций, выравненное на границу +`ALIGN(exp)` - возвращает значение счетчика позиций, выравненное на границу следующего за exp выражения. -**SIZEOF(section)** - возвращает размер секции в байтах. +`SIZEOF(section)` - возвращает размер секции в байтах. -**FILL(param)** - определяет образец заполнения для текущей секции. Все -остальные неуказанные регионы внутри секции заполняются значением указанными +`FILL(param)` - определяет образец заполнения для текущей секции. Все +остальные неуказанные регионы внутри секции заполняются значением указанными в аргументе функции. -**KEEP(param)** - используется чтобы помечать param как неустранимый. +`KEEP(param)` - используется чтобы помечать param как неустранимый. -**ENTRY(func)** - определяет функцию, которая будет являться точкой входа +`ENTRY(func)` - определяет функцию, которая будет являться точкой входа в программу. ```bash @@ -32,16 +28,16 @@ translators: ENTRY(Reset_Handler) # Определяем переменную которая содержит адрес вершины стека -_estack = 0x20020000; -# Определяем переменную которая содержит значение размера кучи +_estack = 0x20020000; +# Определяем переменную которая содержит значение размера кучи _Min_Heap_Size = 0x200; # Определяем переменную которая содержит значение размера стека -_Min_Stack_Size = 0x400; +_Min_Stack_Size = 0x400; # Описание карты памяти доступной для данного процессора # MEMORY # { -# ИМЯ_ОБЛАСТИ_ПАМЯТИ (права доступа) : ORIGIN = АДРЕС_НАЧАЛА, LENGTH = РАЗМЕР +# ИМЯ_ОБЛАСТИ_ПАМЯТИ (права доступа) : ORIGIN = АДРЕС_НАЧАЛА, LENGTH = РАЗМЕР # } # В нашем примере контроллер содержит три области памяти: # RAM - начинается с адреса 0x20000000 и занимает 128 Кбайт; @@ -52,136 +48,136 @@ _Min_Stack_Size = 0x400; # FLASH память доступна на чтение и исполнение. MEMORY { - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K - CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K - FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K + CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K } # Описываем выходные секции SECTIONS { - # Первая секция содержит таблицу векторов прерываний + # Первая секция содержит таблицу векторов прерываний .isr_vector : { - # Выравниваем текущую позицию на границу 4-х байт. + # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); - # Существует опция --gc-sections, которая позволяет собирать мусор из неиспользуемых - # входных разделов. И если есть разделы, которые сборщик мусора не должен трогать, - # то их необходимо указать в качестве аргумента функции KEEP() (аналог ключевого слова - # volatile). - # Запись (*(.isr_vector)) означает разделы .isr_vector во всех объектных файлах. Т.к. - # обращение к разделу в общем виде выглядит так: (ИМЯ_ФАЙЛА(ИМЯ_РАЗДЕЛА)) - KEEP(*(.isr_vector)) + # Существует опция --gc-sections, которая позволяет собирать мусор из неиспользуемых + # входных разделов. И если есть разделы, которые сборщик мусора не должен трогать, + # то их необходимо указать в качестве аргумента функции KEEP() (аналог ключевого слова + # volatile). + # Запись (*(.isr_vector)) означает разделы .isr_vector во всех объектных файлах. Т.к. + # обращение к разделу в общем виде выглядит так: (ИМЯ_ФАЙЛА(ИМЯ_РАЗДЕЛА)) + KEEP(*(.isr_vector)) - # Выравниваем текущую позицию на границу 4-х байт. + # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); - - # Выражение ">ОБЛАСТЬ_ПАМЯТИ" указывает в какую именно область памяти будет помещена - # данная секция. В нашем случае секция .isr_vector будет размещена во FLASH памяти. + + # Выражение ">ОБЛАСТЬ_ПАМЯТИ" указывает в какую именно область памяти будет помещена + # данная секция. В нашем случае секция .isr_vector будет размещена во FLASH памяти. } >FLASH -# ИТОГО: Секция .isr_vector, которая содержит таблицу векторов прерываний выравнивается -# по границе 4-х байт, помечается как недоступная для сборщика мусора и размещается в начале +# ИТОГО: Секция .isr_vector, которая содержит таблицу векторов прерываний выравнивается +# по границе 4-х байт, помечается как недоступная для сборщика мусора и размещается в начале # FLASH памяти микроконтроллера. # Вторая секция содержит код программы. .text : { - # Выравниваем текущую позицию на границу 4-х байт. + # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); - - # Указываем, что в данной секции будут хранится области .text всех - # объектных файлов - *(.text) - *(.text*) - # Защищаем от сборщика мусора секции .init и .fini + # Указываем, что в данной секции будут хранится области .text всех + # объектных файлов + *(.text) + *(.text*) + + # Защищаем от сборщика мусора секции .init и .fini KEEP (*(.init)) KEEP (*(.fini)) - # Выравниваем текущую позицию на границу 4-х байт. + # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); - - # Определяется переменная _etext, которая хранит в себе адрес конца секции .text и которая - # может быть доступна в исходном тексте программы через объявление - # volaile unsigned int extern _etext; - _etext = .; + + # Определяется переменная _etext, которая хранит в себе адрес конца секции .text и которая + # может быть доступна в исходном тексте программы через объявление + # volaile unsigned int extern _etext; + _etext = .; } >FLASH - -# ИТОГО: Секция .text, которая содержит код программы выравнивается по границе 4-х байт, -# включает в себя: все секции с кодом программы во всех объектных файлах и защищенные -от сборщика муссора секции .init и .fini во всех объектных файлах, распологается во FLASH -памяти микроконтроллера сразу за таблицей векторов. -Секции text, .init и .fini. располагаются в памяти в той последовательности в которой они -объявлены в скрипте. + +# ИТОГО: Секция .text, которая содержит код программы выравнивается по границе 4-х байт, +# включает в себя: все секции с кодом программы во всех объектных файлах и защищенные +# от сборщика муссора секции .init и .fini во всех объектных файлах, распологается во FLASH +# памяти микроконтроллера сразу за таблицей векторов. +# Секции text, .init и .fini. располагаются в памяти в той последовательности в которой они +# объявлены в скрипте. # Третья секция содержит константные данные. .rodata : { - # Выравниваем текущую позицию на границу 4-х байт. + # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); - # Указываем, что в данной секции будут хранится области .rodata всех - # объектных файлов - *(.rodata) - *(.rodata*) - - # Выравниваем текущую позицию на границу 4-х байт. + # Указываем, что в данной секции будут хранится области .rodata всех + # объектных файлов + *(.rodata) + *(.rodata*) + + # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); } >FLASH - - # Сохраняем в переменной _sidata абсолютный адрес секции .data + + # Сохраняем в переменной _sidata абсолютный адрес секции .data _sidata = LOADADDR(.data); # Четвертая секция содержит инициализированные переменные. - .data : + .data : { - # Выравниваем текущую позицию на границу 4-х байт. + # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); - # Сохраняем в переменной _sdata адрес текущей позиции (начала секции) - _sdata = .; - - # Указываем, что в данной секции будут хранится области .data всех - # объектных файлов - *(.data) - *(.data*) + # Сохраняем в переменной _sdata адрес текущей позиции (начала секции) + _sdata = .; - # Выравниваем текущую позицию на границу 4-х байт. + # Указываем, что в данной секции будут хранится области .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. - + _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 = .; + # Сохраняем в переменной _sbss и __bss_start__ адрес текущей позиции (начала секции) + _sbss = .; __bss_start__ = _sbss; - - # Указываем, что в данной секции будут хранится области .bss всех - # объектных файлов + + # Указываем, что в данной секции будут хранится области .bss всех + # объектных файлов *(.bss) *(.bss*) - # Выравниваем текущую позицию на границу 4-х байт. + # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); - + # Сохраняем в переменной _ebss и __bss_end__ адрес текущей позиции (начала секции) - _ebss = .; + _ebss = .; __bss_end__ = _ebss; } >RAM @@ -197,4 +193,3 @@ SECTIONS } >RAM } ``` -