From 26b0f592f57780cade8ea6e75c4b5e30c2ec8fdc Mon Sep 17 00:00:00 2001 From: Andrei Solodovnikov Date: Mon, 11 Dec 2023 16:45:48 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=A013.=20=D0=98=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BA=D1=80?= =?UTF-8?q?=D0=B8=D0=BF=D1=82=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D1=89=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Labs/13. Programming/README.md | 70 ++++++++++++++++++++------- Labs/13. Programming/linker_script.ld | 55 ++++++++++++++++++--- 2 files changed, 100 insertions(+), 25 deletions(-) diff --git a/Labs/13. Programming/README.md b/Labs/13. Programming/README.md index 4b26624..c991270 100644 --- a/Labs/13. Programming/README.md +++ b/Labs/13. Programming/README.md @@ -95,25 +95,48 @@ ENTRY(_start) /* мы сообщаем компоно находится у метки "start" */ -/* - Объявляем вспомогательные глобальные переменные -*/ -_text_size = 0x4000; /* Размер памяти инстр.: 16KiB */ -_data_base_addr = 0x8000; /* Стартовый адрес секции данных */ -_data_size = 0x4000; /* Размер памяти данных: 16KiB */ +_text_size = 0x4000; /* Размер памяти инстр.: 16KiB */ +_data_base_addr = 0x4000; /* Стартовый адрес секции данных */ +_data_size = 0x4000; /* Размер памяти данных: 16KiB */ _data_end = _data_base_addr + _data_size; -_trap_stack_size = 2560; /* Размер стека обработчика перехватов. +_trap_stack_size = 2560; /* Размер стека обработчика перехватов. Данный размер позволяет выполнить до 32 вложенных вызовов при обработке перехватов. - */ + */ -_stack_size = 1280; /* Размер программного стека. +_stack_size = 1280; /* Размер программного стека. Данный размер позволяет выполнить до 16 вложенных вызовов. - */ + */ + +/* + В данном разделе указывается структура памяти: + Сперва идет регион "rom", являющийся read-only памятью с исполняемым кодом + (об этом говорят атрибуты 'r' и 'x' соответственно). Этот регион начинается + с адреса 0x00000000 и занимает _text_size байт. + Далее идет регион "ram", начинающийся с адреса _data_base_addr и занимающий + _data_size байт. Этот регион является памятью, противоположной региону "ram" + (в том смысле, что это не read-only память с исполняемым кодом). +*/ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = _text_size + ram (!rx) : ORIGIN = _data_base_addr, LENGTH = _data_size +} + + +/* + В данном разделе описывается размещение программы в памяти. + Программа разделяется на различные секции: + - секции исполняемого кода программа; + - секции статических переменных и массивов, значение которых должно быть + "вшито" в программу; + и т.п. +*/ + SECTIONS { PROVIDE( _start = 0x00000000 ); /* Позиция start в памяти @@ -137,23 +160,31 @@ SECTIONS секция .text итогового файла, которая состоит из секций .boot, а также всех секций, начинающихся на .text во всех переданных компоновщику двоичных файлах. + Дополнительно мы указываем, что данная секция должна быть размещена в + регионе "rom". */ - .text : {*(.boot) *(.text*)} + .text : {*(.boot) *(.text*)} >rom /* Поскольку мы не знаем суммарного размера получившейся секции, мы проверяем - что не вышли за границы памяти инструкций и переносим счетчик адресов за пределы. Памяти инструкций в область памяти данных + что не вышли за границы памяти инструкций и переносим счетчик адресов за + пределы памяти инструкций в область памяти данных. + Дополнительно мы указываем, что данная секция должна быть размещена в + регионе "ram". */ ASSERT(. < _text_size, ".text section exceeds instruction memory size") . = _data_base_addr; /* Следующая команда сообщает, что начиная с адреса, которому в данных момент - равен счетчик адресов (_data_base_addr) будет находиться секция .data итогового файла, которая состоит из секций всех секций, начинающихся + равен счетчик адресов (_data_base_addr) будет находиться секция .data + итогового файла, которая состоит из секций всех секций, начинающихся на .data во всех переданных компоновщику двоичных файлах. + Дополнительно мы указываем, что данная секция должна быть размещена в + регионе "ram". */ - .data : {*(.data*)} + .data : {*(.data*)} >ram /* Общепринято присваивать GP значение равное началу секции данных, смещенное @@ -171,7 +202,8 @@ SECTIONS /* Поскольку мы не знаем суммарный размер всех используемых секций данных, - перед размещением других секций, необходимо выравнять счетчик адресов по 4х-байтной границе. + перед размещением других секций, необходимо выравнять счетчик адресов по + 4х-байтной границе. */ . = ALIGN(4); @@ -197,9 +229,12 @@ SECTIONS указывающие на начало и конец bss-секции посредством счетчика адресов. Подробнее: https://en.wikipedia.org/wiki/.bss + + Дополнительно мы указываем, что данная секция должна быть размещена в + регионе "ram". */ _bss_start = .; - .bss : {*(.bss*)} + .bss : {*(.bss*)} >ram _bss_end = .; @@ -213,7 +248,8 @@ SECTIONS стека от наложения на него стека прерываний. Однако перед этим, мы должны убедиться, что под программный стек останется хотя бы 1280 байт (ничем не обоснованное число, взятое с потолка). - Такое значение обеспечивает до 16 вложенных вызовов (если сохранять только необерегаемые регистры). + Такое значение обеспечивает до 16 вложенных вызовов (если сохранять только + необерегаемые регистры). ================================= */ diff --git a/Labs/13. Programming/linker_script.ld b/Labs/13. Programming/linker_script.ld index f783a2d..0f7ec52 100644 --- a/Labs/13. Programming/linker_script.ld +++ b/Labs/13. Programming/linker_script.ld @@ -6,7 +6,7 @@ ENTRY(_start) /* мы сообщаем компоно */ _text_size = 0x4000; /* Размер памяти инстр.: 16KiB */ -_data_base_addr = 0x8000; /* Стартовый адрес секции данных */ +_data_base_addr = 0x4000; /* Стартовый адрес секции данных */ _data_size = 0x4000; /* Размер памяти данных: 16KiB */ _data_end = _data_base_addr + _data_size; @@ -21,6 +21,32 @@ _stack_size = 1280; /* Размер программного Данный размер позволяет выполнить до 16 вложенных вызовов. */ + +/* + В данном разделе указывается структура памяти: + Сперва идет регион "rom", являющийся read-only памятью с исполняемым кодом + (об этом говорят атрибуты 'r' и 'x' соответственно). Этот регион начинается + с адреса 0x00000000 и занимает _text_size байт. + Далее идет регион "ram", начинающийся с адреса _data_base_addr и занимающий + _data_size байт. Этот регион является памятью, противоположной региону "ram" + (в том смысле, что это не read-only память с исполняемым кодом). +*/ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = _text_size + ram (!rx) : ORIGIN = _data_base_addr, LENGTH = _data_size +} + + +/* + В данном разделе описывается размещение программы в памяти. + Программа разделяется на различные секции: + - секции исполняемого кода программа; + - секции статических переменных и массивов, значение которых должно быть + "вшито" в программу; + и т.п. +*/ + SECTIONS { PROVIDE( _start = 0x00000000 ); /* Позиция start в памяти @@ -44,23 +70,31 @@ SECTIONS секция .text итогового файла, которая состоит из секций .boot, а также всех секций, начинающихся на .text во всех переданных компоновщику двоичных файлах. + Дополнительно мы указываем, что данная секция должна быть размещена в + регионе "rom". */ - .text : {*(.boot) *(.text*)} + .text : {*(.boot) *(.text*)} >rom /* Поскольку мы не знаем суммарного размера получившейся секции, мы проверяем - что не вышли за границы памяти инструкций и переносим счетчик адресов за пределы. Памяти инструкций в область памяти данных + что не вышли за границы памяти инструкций и переносим счетчик адресов за + пределы памяти инструкций в область памяти данных. + Дополнительно мы указываем, что данная секция должна быть размещена в + регионе "ram". */ ASSERT(. < _text_size, ".text section exceeds instruction memory size") . = _data_base_addr; /* Следующая команда сообщает, что начиная с адреса, которому в данных момент - равен счетчик адресов (_data_base_addr) будет находиться секция .data итогового файла, которая состоит из секций всех секций, начинающихся + равен счетчик адресов (_data_base_addr) будет находиться секция .data + итогового файла, которая состоит из секций всех секций, начинающихся на .data во всех переданных компоновщику двоичных файлах. + Дополнительно мы указываем, что данная секция должна быть размещена в + регионе "ram". */ - .data : {*(.data*)} + .data : {*(.data*)} >ram /* Общепринято присваивать GP значение равное началу секции данных, смещенное @@ -78,7 +112,8 @@ SECTIONS /* Поскольку мы не знаем суммарный размер всех используемых секций данных, - перед размещением других секций, необходимо выравнять счетчик адресов по 4х-байтной границе. + перед размещением других секций, необходимо выравнять счетчик адресов по + 4х-байтной границе. */ . = ALIGN(4); @@ -104,9 +139,12 @@ SECTIONS указывающие на начало и конец bss-секции посредством счетчика адресов. Подробнее: https://en.wikipedia.org/wiki/.bss + + Дополнительно мы указываем, что данная секция должна быть размещена в + регионе "ram". */ _bss_start = .; - .bss : {*(.bss*)} + .bss : {*(.bss*)} >ram _bss_end = .; @@ -120,7 +158,8 @@ SECTIONS стека от наложения на него стека прерываний. Однако перед этим, мы должны убедиться, что под программный стек останется хотя бы 1280 байт (ничем не обоснованное число, взятое с потолка). - Такое значение обеспечивает до 16 вложенных вызовов (если сохранять только необерегаемые регистры). + Такое значение обеспечивает до 16 вложенных вызовов (если сохранять только + необерегаемые регистры). ================================= */