Я написал приложение загрузчика PIC32MX. Я хотел бы сказать компоновщику, чтобы он помещал его полностью в загрузочную память, чтобы все пространство программы оставалось для конечного приложения.
В настоящее время то, что я считаю соответствующими частями моего .ld
файла, выглядит так:
_RESET_ADDR = 0xBFC00000;
_BEV_EXCPT_ADDR = (0xBFC00000 + 0x380);
_DBG_EXCPT_ADDR = (0xBFC00000 + 0x480);
_DBG_CODE_ADDR = 0xBFC02000;
_DBG_CODE_SIZE = 0xFF0 ;
_GEN_EXCPT_ADDR = _ebase_address + 0x180;
MEMORY
{
kseg0_program_mem (rx) : ORIGIN = 0x9D000000, LENGTH = 0x10000 /* All C Files will be located here */
kseg0_boot_mem : ORIGIN = 0x9FC00000, LENGTH = 0x1000 /* This memory region is dummy */
exception_mem : ORIGIN = 0x9FC01000, LENGTH = 0x200 /* Interrupt vector table */
config3 : ORIGIN = 0xBFC02FF0, LENGTH = 0x4
config2 : ORIGIN = 0xBFC02FF4, LENGTH = 0x4
config1 : ORIGIN = 0xBFC02FF8, LENGTH = 0x4
config0 : ORIGIN = 0xBFC02FFC, LENGTH = 0x4
kseg1_boot_mem : ORIGIN = 0xBFC00000, LENGTH = 0x2FF0 /* C Startup code */
kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x8000
sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000
debug_exec_mem : ORIGIN = 0xBFC02000, LENGTH = 0xFF0
configsfrs : ORIGIN = 0xBFC02FF0, LENGTH = 0x10
}
Это сгенерированный по умолчанию скрипт компоновщика, для PIC32MX695F512H , хотя длина некоторых секций могла измениться — схема памяти чипа есть на странице 61 даташита.
Должен ли я просто изменить ORIGIN
и LENGTH
на kseg0_program_mem
значения kseg0_boot_mem
и указать компоновщику разрешить перекрывающиеся разделы? Это не кажется таким уж чистым. Есть ли способ сказать компоновщику, чтобы он поместил код приложения не в , kseg0_program_mem
а в kseg0_boot_mem
?
Компилятор C поместит код запуска среды выполнения C в файл kseg0_boot_mem
, который устанавливает стек, кучу и общую инициализацию процессора. Количество размещаемого кода kseg0_boot_mem
будет варьироваться между сборкой отладки и сборкой выпуска. Если я правильно помню, когда я работал над загрузчиком для PIC32MX250F, отладочная сборка занимала ~70% kseg0_boot_mem
, чего было недостаточно для моего загрузчика.
Если ваш загрузчик достаточно мал, чтобы поместиться вместе kseg0_boot_mem
с кодом запуска C, уменьшите размер файла kseg0_boot_mem
, а затем переместите kseg0_program_mem
его над новым boot_mem
пространством. Обратите внимание, что вы не можете переместить начальное местоположение пространства kseg0_boot_mem
. Выполнение кода начинается 0xBFC00000
с PIC32, и вы ничего не можете сделать, чтобы изменить это. Если вы хотите переместить весь загрузчик, вам также придется переместить таблицу ISR. Например:
MEMORY
{
kseg0_program_mem (rx) : ORIGIN = 0xBFC01200, LENGTH = 0x1DF0 /* kseg1_boot is 2FF0 long.*/
kseg0_boot_mem : ORIGIN = 0x9FC00000, LENGTH = 0x1000 /* This memory region is dummy */
exception_mem : ORIGIN = 0xBFC01000, LENGTH = 0x200 /* Relocated ISR table. */
config3 : ORIGIN = 0xBFC02FF0, LENGTH = 0x4
config2 : ORIGIN = 0xBFC02FF4, LENGTH = 0x4
config1 : ORIGIN = 0xBFC02FF8, LENGTH = 0x4
config0 : ORIGIN = 0xBFC02FFC, LENGTH = 0x4
kseg1_boot_mem : ORIGIN = 0xBFC00000, LENGTH = 0x1000 /*This has been reduced in size. Was 0x2FF0*/
kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x8000
sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000
debug_exec_mem : ORIGIN = 0xBFC02000, LENGTH = 0xFF0
configsfrs : ORIGIN = 0xBFC02FF0, LENGTH = 0x10
}
ПРИМЕЧАНИЕ: это всего лишь пример сценария загрузчика, и его ни в коем случае нельзя копировать в рабочую среду!
При этом по опыту могу сказать, что пытаться впихнуть нетривиальный загрузчик в boot_mem
пространство программы не получится. Пространства, оставшегося от кода запуска C, обычно недостаточно, особенно если вам нужна тяжелая обработка ошибок и проверка (и да, вы ДЕЙСТВИТЕЛЬНО этого хотите!). Удаление отладочных сборок из очень ограниченного арсенала встроенных инструментов отладки тоже нехорошо. В какой-то момент в будущем вам нужно будет иметь возможность отлаживать аппаратное обеспечение. Я усвоил этот урок трудным путем.
Я рекомендую оставить kseg0_boot_mem
раздел кода в покое и просто работать с kseg0_program_mem
пробелом. Возьмите кусок kseg0_program_mem
сверху или снизу (не имеет значения) и используйте его для кода загрузчика и таблицы ISR. Оставьте себе место для расширения кода загрузчика. Работа с несколькими скриптами компоновщика немного утомительна.
Вместо того, чтобы делать все это в компоновщике, вы также можете сделать это аналогично этому
MEMORY
{
kseg0_program_mem (rx) : ORIGIN = 0x9D000000, LENGTH = 0x5000
bootverify_mem (rx) : ORIGIN = 0x9D03FFAC, LENGTH = 0x50
kseg0_boot_mem : ORIGIN = 0x9FC00490, LENGTH = 0xB70
exception_mem : ORIGIN = 0x9FC01000, LENGTH = 0x300
kseg2_boot_mem : ORIGIN = 0x9FC01380, LENGTH = 0xC80
kseg1_boot_mem : ORIGIN = 0xBFC00000, LENGTH = 0x490
debug_exec_mem : ORIGIN = 0xBFC02000, LENGTH = 0xFF0
config3 : ORIGIN = 0xBFC02FF0, LENGTH = 0x4
config2 : ORIGIN = 0xBFC02FF4, LENGTH = 0x4
config1 : ORIGIN = 0xBFC02FF8, LENGTH = 0x4
config0 : ORIGIN = 0xBFC02FFC, LENGTH = 0x4
kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x10000
sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000
configsfrs : ORIGIN = 0xBFC02FF0, LENGTH = 0x10
}
SECTIONS
{
.config_BFC02FF0 0xBFC02FF0 : {
KEEP(*(.config_BFC02FF0))
} > config3
.config_BFC02FF4 : {
KEEP(*(.config_BFC02FF4))
} > config2
.config_BFC02FF8 : {
KEEP(*(.config_BFC02FF8))
} > config1
.config_BFC02FFC : {
KEEP(*(.config_BFC02FFC))
} > config0
}
PROVIDE(_DBG_CODE_ADDR = 0xBFC02000) ;
PROVIDE(_DBG_CODE_SIZE = 0xFF0) ;
SECTIONS
{
.extra_prgm_mem :
{
*(extra_prgm_mem)
} >kseg0_boot_mem
.extra_prgm_mem2 :
{
KEEP(*(extra_prgm_mem2))
} >kseg2_boot_mem
/*Linker continued*/
Затем в своем коде вы можете поместить каждую функцию туда, куда хотите.
int __attribute__ ((section ("extra_prgm_mem2")))GetVersion(char * Info){
int Result = (Info[4] - '0') * 1000;
Result += ((Info[5] - '0') * 100);
Result += ((Info[6] - '0') * 10);
Result += Info[7] - '0';
}
BOOL __attribute__ ((section ("extra_prgm_mem")))BLMedia_LoadEncryptedFile(char *file_name) {
//Function info
}
Также обратите внимание, что если вы не используете никаких прерываний, вы можете получить еще один 0x1000 в пространстве. Кстати, если это не последовательный загрузчик, я не считаю это подходящим.
Роджер Роуленд
брахи
Эрик Фризен