diff --git a/Labs/14. Programming/README.md b/Labs/14. Programming/README.md index 79e7668..8306b4e 100644 --- a/Labs/14. Programming/README.md +++ b/Labs/14. Programming/README.md @@ -103,17 +103,6 @@ _Таблица 1. Ассемблерные мнемоники для целоч Все это с подробными комментариями описано в файле `linker_script.ld`. ```ld -/* ----------------------------------------------------------------------------- -* Project Name : Architectures of Processor Systems (APS) lab work -* Organization : National Research University of Electronic Technology (MIET) -* Department : Institute of Microdevices and Control Systems -* Author(s) : Andrei Solodovnikov -* Email(s) : hepoh@org.miet.ru - -See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. -* ------------------------------------------------------------------------------ -*/ - OUTPUT_FORMAT("elf32-littleriscv") /* Указываем порядок следования байт */ ENTRY(_start) /* мы сообщаем компоновщику, что первая @@ -144,8 +133,8 @@ _trap_stack_size = 640; /* Размер стека обработ _stack_size = 640; /* Размер программного стека. Данный размер позволяет выполнить - до 8 вложенных вызовов. - */ + от 8 вложенных вызовов. + */ /* В данном разделе описывается размещение программы в памяти. @@ -188,11 +177,22 @@ SECTIONS *(.text*) } > instr_mem - В скобках после оператора AT указывается Load Memory Address (LMA). Чтобы - адреса памяти инструкций и памяти данных при компоновке не пересекались, мы - будем использовать заведомо несуществующий LMA, который в последствии будем - игнорировать. - .data : AT (0x80000000) { + + /* + Секция данных размещается аналогично секции инструкций за исключением + адреса загрузки в памяти (Load Memory Address, LMA). Поскольку память + инструкций и данных физически разделены, у них есть пересекающееся адресное + пространство, которое мы бы хотели использовать (поэтому в разделе MEMORY мы + указали что стартовые адреса обоих памятей равны нулю). Однако компоновщику + это не нравится, ведь как он будет размещать две разные секции в одно и то же + место. Поэтому мы ему сообщаем, с помощью оператора "AT", что загружать секцию + данных нужно на самом деле не по нулевому адресу, а по какому-то другому, + заведомо большему чем размер памяти инструкций, но процессор будет + использовать адреса, начинающиеся с нуля. Такой вариант компоновщика + устраивает и он собирает исполняемый файл без ошибок. Наша же задача, + загрузить итоговую секцию данных по нулевым адресам памяти данных. + */ + .data : AT (0x00800000) { /* Общепринято присваивать GP значение равное началу секции данных, смещенное на 2048 байт вперед. @@ -206,6 +206,7 @@ SECTIONS */ _gbl_ptr = . + 2048; *(.*data*) + *(.sdata*) } > data_mem @@ -242,12 +243,12 @@ SECTIONS Дополнительно мы указываем, что данная секция должна быть размещена в регионе "data_mem". */ + _bss_start = .; .bss : { - _bss_start = .; - *bss* - *(COMMON) - _bss_end = .; + *(.bss*) + *(.sbss*) } > data_mem + _bss_end = .; /*================================= diff --git a/Labs/14. Programming/linker_script.ld b/Labs/14. Programming/linker_script.ld index fde5c46..7ad170f 100644 --- a/Labs/14. Programming/linker_script.ld +++ b/Labs/14. Programming/linker_script.ld @@ -39,8 +39,8 @@ _trap_stack_size = 640; /* Размер стека обработ _stack_size = 640; /* Размер программного стека. Данный размер позволяет выполнить - до 8 вложенных вызовов. - */ + от 8 вложенных вызовов. + */ /* В данном разделе описывается размещение программы в памяти. @@ -83,11 +83,22 @@ SECTIONS *(.text*) } > instr_mem - В скобках после оператора AT указывается Load Memory Address (LMA). Чтобы - адреса памяти инструкций и памяти данных при компоновке не пересекались, мы - будем использовать заведомо несуществующий LMA, который в последствии будем - игнорировать. - .data : AT (0x80000000) { + + /* + Секция данных размещается аналогично секции инструкций за исключением + адреса загрузки в памяти (Load Memory Address, LMA). Поскольку память + инструкций и данных физически разделены, у них есть пересекающееся адресное + пространство, которое мы бы хотели использовать (поэтому в разделе MEMORY мы + указали что стартовые адреса обоих памятей равны нулю). Однако компоновщику + это не нравится, ведь как он будет размещать две разные секции в одно и то же + место. Поэтому мы ему сообщаем, с помощью оператора "AT", что загружать секцию + данных нужно на самом деле не по нулевому адресу, а по какому-то другому, + заведомо большему чем размер памяти инструкций, но процессор будет + использовать адреса, начинающиеся с нуля. Такой вариант компоновщика + устраивает и он собирает исполняемый файл без ошибок. Наша же задача, + загрузить итоговую секцию данных по нулевым адресам памяти данных. + */ + .data : AT (0x00800000) { /* Общепринято присваивать GP значение равное началу секции данных, смещенное на 2048 байт вперед. @@ -101,6 +112,7 @@ SECTIONS */ _gbl_ptr = . + 2048; *(.*data*) + *(.sdata*) } > data_mem @@ -137,12 +149,12 @@ SECTIONS Дополнительно мы указываем, что данная секция должна быть размещена в регионе "data_mem". */ + _bss_start = .; .bss : { - _bss_start = .; - *bss* - *(COMMON) - _bss_end = .; + *(.bss*) + *(.sbss*) } > data_mem + _bss_end = .; /*================================= diff --git a/Labs/14. Programming/startup.S b/Labs/14. Programming/startup.S index 2c88bd9..6d54e7d 100644 --- a/Labs/14. Programming/startup.S +++ b/Labs/14. Programming/startup.S @@ -31,8 +31,8 @@ _irq_config: li t1, -1 # -1 (все биты равны 1) означает, что разрешены все прерывания la t2, _trap_stack_ptr csrw mtvec, t0 - csrw mie, t1 csrw mscratch, t2 + csrw mie, t1 # Вызов функции main _main_call: