mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
ЛР14. Обновление скрипта компоновщика и стартап-файла
This commit is contained in:
@@ -103,17 +103,6 @@ _Таблица 1. Ассемблерные мнемоники для целоч
|
|||||||
Все это с подробными комментариями описано в файле `linker_script.ld`.
|
Все это с подробными комментариями описано в файле `linker_script.ld`.
|
||||||
|
|
||||||
```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") /* Указываем порядок следования байт */
|
OUTPUT_FORMAT("elf32-littleriscv") /* Указываем порядок следования байт */
|
||||||
|
|
||||||
ENTRY(_start) /* мы сообщаем компоновщику, что первая
|
ENTRY(_start) /* мы сообщаем компоновщику, что первая
|
||||||
@@ -144,8 +133,8 @@ _trap_stack_size = 640; /* Размер стека обработ
|
|||||||
|
|
||||||
_stack_size = 640; /* Размер программного стека.
|
_stack_size = 640; /* Размер программного стека.
|
||||||
Данный размер позволяет выполнить
|
Данный размер позволяет выполнить
|
||||||
до 8 вложенных вызовов.
|
от 8 вложенных вызовов.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
В данном разделе описывается размещение программы в памяти.
|
В данном разделе описывается размещение программы в памяти.
|
||||||
@@ -188,11 +177,22 @@ SECTIONS
|
|||||||
*(.text*)
|
*(.text*)
|
||||||
} > instr_mem
|
} > instr_mem
|
||||||
|
|
||||||
В скобках после оператора AT указывается Load Memory Address (LMA). Чтобы
|
|
||||||
адреса памяти инструкций и памяти данных при компоновке не пересекались, мы
|
/*
|
||||||
будем использовать заведомо несуществующий LMA, который в последствии будем
|
Секция данных размещается аналогично секции инструкций за исключением
|
||||||
игнорировать.
|
адреса загрузки в памяти (Load Memory Address, LMA). Поскольку память
|
||||||
.data : AT (0x80000000) {
|
инструкций и данных физически разделены, у них есть пересекающееся адресное
|
||||||
|
пространство, которое мы бы хотели использовать (поэтому в разделе MEMORY мы
|
||||||
|
указали что стартовые адреса обоих памятей равны нулю). Однако компоновщику
|
||||||
|
это не нравится, ведь как он будет размещать две разные секции в одно и то же
|
||||||
|
место. Поэтому мы ему сообщаем, с помощью оператора "AT", что загружать секцию
|
||||||
|
данных нужно на самом деле не по нулевому адресу, а по какому-то другому,
|
||||||
|
заведомо большему чем размер памяти инструкций, но процессор будет
|
||||||
|
использовать адреса, начинающиеся с нуля. Такой вариант компоновщика
|
||||||
|
устраивает и он собирает исполняемый файл без ошибок. Наша же задача,
|
||||||
|
загрузить итоговую секцию данных по нулевым адресам памяти данных.
|
||||||
|
*/
|
||||||
|
.data : AT (0x00800000) {
|
||||||
/*
|
/*
|
||||||
Общепринято присваивать GP значение равное началу секции данных, смещенное
|
Общепринято присваивать GP значение равное началу секции данных, смещенное
|
||||||
на 2048 байт вперед.
|
на 2048 байт вперед.
|
||||||
@@ -206,6 +206,7 @@ SECTIONS
|
|||||||
*/
|
*/
|
||||||
_gbl_ptr = . + 2048;
|
_gbl_ptr = . + 2048;
|
||||||
*(.*data*)
|
*(.*data*)
|
||||||
|
*(.sdata*)
|
||||||
} > data_mem
|
} > data_mem
|
||||||
|
|
||||||
|
|
||||||
@@ -242,12 +243,12 @@ SECTIONS
|
|||||||
Дополнительно мы указываем, что данная секция должна быть размещена в
|
Дополнительно мы указываем, что данная секция должна быть размещена в
|
||||||
регионе "data_mem".
|
регионе "data_mem".
|
||||||
*/
|
*/
|
||||||
|
_bss_start = .;
|
||||||
.bss : {
|
.bss : {
|
||||||
_bss_start = .;
|
*(.bss*)
|
||||||
*bss*
|
*(.sbss*)
|
||||||
*(COMMON)
|
|
||||||
_bss_end = .;
|
|
||||||
} > data_mem
|
} > data_mem
|
||||||
|
_bss_end = .;
|
||||||
|
|
||||||
|
|
||||||
/*=================================
|
/*=================================
|
||||||
|
@@ -39,8 +39,8 @@ _trap_stack_size = 640; /* Размер стека обработ
|
|||||||
|
|
||||||
_stack_size = 640; /* Размер программного стека.
|
_stack_size = 640; /* Размер программного стека.
|
||||||
Данный размер позволяет выполнить
|
Данный размер позволяет выполнить
|
||||||
до 8 вложенных вызовов.
|
от 8 вложенных вызовов.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
В данном разделе описывается размещение программы в памяти.
|
В данном разделе описывается размещение программы в памяти.
|
||||||
@@ -83,11 +83,22 @@ SECTIONS
|
|||||||
*(.text*)
|
*(.text*)
|
||||||
} > instr_mem
|
} > instr_mem
|
||||||
|
|
||||||
В скобках после оператора AT указывается Load Memory Address (LMA). Чтобы
|
|
||||||
адреса памяти инструкций и памяти данных при компоновке не пересекались, мы
|
/*
|
||||||
будем использовать заведомо несуществующий LMA, который в последствии будем
|
Секция данных размещается аналогично секции инструкций за исключением
|
||||||
игнорировать.
|
адреса загрузки в памяти (Load Memory Address, LMA). Поскольку память
|
||||||
.data : AT (0x80000000) {
|
инструкций и данных физически разделены, у них есть пересекающееся адресное
|
||||||
|
пространство, которое мы бы хотели использовать (поэтому в разделе MEMORY мы
|
||||||
|
указали что стартовые адреса обоих памятей равны нулю). Однако компоновщику
|
||||||
|
это не нравится, ведь как он будет размещать две разные секции в одно и то же
|
||||||
|
место. Поэтому мы ему сообщаем, с помощью оператора "AT", что загружать секцию
|
||||||
|
данных нужно на самом деле не по нулевому адресу, а по какому-то другому,
|
||||||
|
заведомо большему чем размер памяти инструкций, но процессор будет
|
||||||
|
использовать адреса, начинающиеся с нуля. Такой вариант компоновщика
|
||||||
|
устраивает и он собирает исполняемый файл без ошибок. Наша же задача,
|
||||||
|
загрузить итоговую секцию данных по нулевым адресам памяти данных.
|
||||||
|
*/
|
||||||
|
.data : AT (0x00800000) {
|
||||||
/*
|
/*
|
||||||
Общепринято присваивать GP значение равное началу секции данных, смещенное
|
Общепринято присваивать GP значение равное началу секции данных, смещенное
|
||||||
на 2048 байт вперед.
|
на 2048 байт вперед.
|
||||||
@@ -101,6 +112,7 @@ SECTIONS
|
|||||||
*/
|
*/
|
||||||
_gbl_ptr = . + 2048;
|
_gbl_ptr = . + 2048;
|
||||||
*(.*data*)
|
*(.*data*)
|
||||||
|
*(.sdata*)
|
||||||
} > data_mem
|
} > data_mem
|
||||||
|
|
||||||
|
|
||||||
@@ -137,12 +149,12 @@ SECTIONS
|
|||||||
Дополнительно мы указываем, что данная секция должна быть размещена в
|
Дополнительно мы указываем, что данная секция должна быть размещена в
|
||||||
регионе "data_mem".
|
регионе "data_mem".
|
||||||
*/
|
*/
|
||||||
|
_bss_start = .;
|
||||||
.bss : {
|
.bss : {
|
||||||
_bss_start = .;
|
*(.bss*)
|
||||||
*bss*
|
*(.sbss*)
|
||||||
*(COMMON)
|
|
||||||
_bss_end = .;
|
|
||||||
} > data_mem
|
} > data_mem
|
||||||
|
_bss_end = .;
|
||||||
|
|
||||||
|
|
||||||
/*=================================
|
/*=================================
|
||||||
|
@@ -31,8 +31,8 @@ _irq_config:
|
|||||||
li t1, -1 # -1 (все биты равны 1) означает, что разрешены все прерывания
|
li t1, -1 # -1 (все биты равны 1) означает, что разрешены все прерывания
|
||||||
la t2, _trap_stack_ptr
|
la t2, _trap_stack_ptr
|
||||||
csrw mtvec, t0
|
csrw mtvec, t0
|
||||||
csrw mie, t1
|
|
||||||
csrw mscratch, t2
|
csrw mscratch, t2
|
||||||
|
csrw mie, t1
|
||||||
|
|
||||||
# Вызов функции main
|
# Вызов функции main
|
||||||
_main_call:
|
_main_call:
|
||||||
|
Reference in New Issue
Block a user