|
BootLoader - странные команды, Команды в неиспользуемой области Flash |
|
|
|
May 12 2011, 08:29
|
Частый гость
 
Группа: Свой
Сообщений: 168
Регистрация: 8-10-08
Из: РФ Смоленск
Пользователь №: 40 764

|
Пишу загрузчик дял AVR (Mega328) в IAR EWAVR 5.1. Отредактировал файл настроек линкера: Код /* - lnkm324s.xcl - * * XLINK command file for the ICCAVR C-compiler using the --cpu=m324, -ms * options. * * Usage: xlink your_file(s) -f lnkm324s * * File version: $Revision: 1.1 $ */
/*=================== CONSTANTS =============================*/ /* Constants used in the ranges down below, * Do not change these lines, * if it is not stated otherwise */
/* ÏÅÐÅÄÅËÀÍÎ ÏÎÄ ÇÀÃÐÓÇ×ÈÊ Ñ ÐÀÇÌÅÐÎÌ 2048 ñëîâ (4096 áàéò). Íà÷èíàåòñÿ ñ àäðåñà 7000 (â áàéòàõ) */ /* ÂÍÈÌÀÍÈÅ! Ëåíêåð ðàáîòàåò ñ áàéòîâîé àäðåñàöèåé (íå ñìîòðÿ íà òî, ÷òî Flash ïàìÿòü AVR ñîñòîèò èç ñëîâ 2 áàéòà) */
/* Code (flash) segments */ -D_..X_INTVEC_SIZE=7C /* 31 Interrupt vectors * 4 bytes each */ -D_..X_FLASH_TEND=FF /* End of tiny flash memory */ -D_..X_FLASH_NEND=7FFF /* End of near flash memory */ -D_..X_FLASH_END=7FFF /* End of flash memory */ /* Internal data memory */ -D_..X_SRAM_BASE=100 /* Start of ram memory */ -D_..X_SRAM_TEND=100 /* End of tiny ram memory */
-D_..X_SRAM_END=8FF /* End of ram memory */ /* Internal EEPROM */ -D_..X_EEPROM_END=3FF /* End of eeprom memory */ /*==================== END OF CONSTANTS =====================*/
/* * Modify the lines below to alter the size of the RSTACK, CSTACK and HEAP * segments. These need to be fine tuned to suit your specific application. * The '_..X_' prefix is used by C-SPY as an indication that the label should * not be displayed in the dissassembly window. */ -D_..X_CSTACK_SIZE=100 /* 256 bytes for auto variables and saved registers. */ -D_..X_RSTACK_SIZE=40 /* 64 bytes for return addresses, equivalent to 32 */ /* levels of calls, including interrupts. */ -D_..X_HEAP_SIZE=80 /* 128 bytes of heap. */ -D_..X_NEAR_HEAP_SIZE=80 /* 128 bytes of heap. */
/* Define CPU */ -ca90
/* * The following segments are located in the internal memory of * the ATmega324. Do not change these lines. */
/* Code memory */ -Z(CODE)INTVEC=7000-(7000+_..X_INTVEC_SIZE-1) /*-Z(CODE)INTVEC=0-(_..X_INTVEC_SIZE-1)*/
/* Fill unused interrupt vector's with RETI */ -H1895 -h(CODE)7000-(7000+_..X_INTVEC_SIZE) /*-h(CODE)0-_..X_INTVEC_SIZE*/
-Z(CODE)TINY_F=_..X_INTVEC_SIZE-_..X_FLASH_TEND -Z(CODE)NEAR_F,SWITCH,INITTAB,DIFUNCT=_..X_INTVEC_SIZE-_..X_FLASH_END -Z(CODE)CODE=(7000+_..X_INTVEC_SIZE)-_..X_FLASH_END /*-Z(CODE)CODE=_..X_INTVEC_SIZE-_..X_FLASH_END*/ -Z(CODE)TINY_ID,NEAR_ID=(7000+_..X_INTVEC_SIZE)-_..X_FLASH_END /*-Z(CODE)TINY_ID,NEAR_ID=_..X_INTVEC_SIZE-_..X_FLASH_END*/ -Z(CODE)CHECKSUM#_..X_FLASH_END
/* Internal data memory */ -Z(DATA)TINY_I,TINY_Z,TINY_N=_..X_SRAM_BASE-_..X_SRAM_TEND -Z(DATA)NEAR_I,NEAR_Z,NEAR_N=_..X_SRAM_BASE-_..X_SRAM_END
/* * If external SRAM is available it is possible to place the stacks there. * However, the external memory is slower than the internal so moving the * stacks to the external memory will degrade the system performance. */ -Z(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_SRAM_BASE-_..X_SRAM_END -Z(DATA)CSTACK+_..X_CSTACK_SIZE=_..X_SRAM_BASE-_..X_SRAM_END
/* * If external SRAM is available it might be a good idea to move the * heap segment there, i.e. remove the _..X_SRAM_BASE-_..X_SRAM_END range. */ -Z(DATA)HEAP+_..X_HEAP_SIZE=_..X_SRAM_BASE-_..X_SRAM_END -Z(DATA)IOSTREAM_N#_..X_SRAM_BASE-_..X_SRAM_END -Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=_..X_SRAM_BASE-_..X_SRAM_END
/* Internal eeprom memory */ -Z(XDATA)EEPROM_I,EEPROM_N=0-_..X_EEPROM_END
/* Select reduced "printf" support to reduce library size. See configuration section in manual concerning printf/sprintf. */
/*Dlib*/ -e_PrintfSmall=_Printf
/*Clib*/ -e_small_write=_formatted_write
/*Dlib and Clib*/ -e_small_write_P=_formatted_write_P
/* Disable floating-point support in "scanf" to reduce library size. See configuration section in manual concerning scanf/sscanf */
/*Dlib*/ -e_ScanfSmall=_Scanf
/*Clib*/ -e_medium_read=_formatted_read
/*Dlib and Clib*/ -e_medium_read_P=_formatted_read_P
/* Suppress one warning which is not relevant for this processor */ -w29
/* Code will now reside in file aout.a90 or aout.d90, unless -o is specified */ /* .d90 is the default if debug system is linked (option -r) */ /* .a90 is the default without debugging. Default format is -Fmotorola */ Код, как и указано, размещается с адреса 0x7000, работает без ошибок (включая прерывания). Но... Начиная с адреса 0x7C (неиспользуемый сегмент памяти области приложения) появляется цепочка команд. Дамп памяти:  Дизассемблер: Код ......
+0000003B: FFFF ??? Data or unknown opcode +0000003C: FFFF ??? Data or unknown opcode +0000003D: FFFF ??? Data or unknown opcode @0000003E: _..X_INTVEC_SIZE +0000003E: 0013 ??? Data or unknown opcode +0000003F: 011A MOVW R2,R20 Copy register pair @00000040: _..X_RSTACK_SIZE +00000040: 0000 NOP No operation @00000041: ?<Segment init: NEAR_I> +00000041: 001A ??? Data or unknown opcode +00000042: 0100 MOVW R0,R0 Copy register pair +00000043: 7DDA ANDI R29,0xDA Logical AND with immediate +00000044: FFFF ??? Data or unknown opcode +00000045: FFFF ??? Data or unknown opcode ...... Вопрос. Что это за инициализация, откуда она берётся (в настройках линкера эти адреса нигде не фигурируют). И главное, что произоёдёт, когда в эту область памяти вместо этих команд будет загружена основная программа.
|
|
|
|
|
 |
Ответов
(1 - 5)
|
May 12 2011, 08:54
|
Частый гость
 
Группа: Свой
Сообщений: 168
Регистрация: 8-10-08
Из: РФ Смоленск
Пользователь №: 40 764

|
В этом файле чёрт ногу сломит. Наёшл 2 записи Цитата INITTAB Relative segment CODE 0000007C - 00000081 Segment part 12. и Цитата INITTAB Relative segment CODE 00000082 - 00000087 Segment part 18. Вот так память бьётся на сегменты  Прикрепил файл к посту.
Сообщение отредактировал Sergey_Aleksandrovi4 - May 12 2011, 08:59
|
|
|
|
|
May 12 2011, 09:43
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Sergey_Aleksandrovi4 @ May 12 2011, 11:54)  Нашёл 2 записи Сегмент INITTAB содержит таблицы, по которым startup-код обнуляет и присваивает начальные значения глобальным и статическим переменным. Почему именно этот сегмент линкер вынес - сложно сказать, но в строке -Z(CODE)NEAR_F,SWITCH,INITTAB,DIFUNCT=_..X_INTVEC_SIZE-_..X_FLASH_END вы разрешили ему положить этот сегмент в свободное место в диапазоне адресов 7C...7FFF, что он и сделал. Полагаю, тут надо использовать не _..X_INTVEC_SIZE, а 7000+_..X_INTVEC_SIZE. Причем "магическое число" 7000 удобнее также объявить константой через -D_..X_FLASH_START=7000 и дальше уже оперировать с ней.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 12 2011, 10:32
|
Частый гость
 
Группа: Свой
Сообщений: 168
Регистрация: 8-10-08
Из: РФ Смоленск
Пользователь №: 40 764

|
Спасибо за совет, помогло. Область приложений теперь девственно чиста (0xFF). Запись Код (CODE)NEAR_F,SWITCH,INITTAB,DIFUNCT=_..X_INTVEC_SIZE-_..X_FLASH_END у самого подозрения вызывала, но боялся вносить правки в файл конфигурации (все изменения делал по мотивам предыдущих тем форума, посвящённым построению загрузчиков AVR). То же и с "магическим" 0x7000. Прикрепляю файл конфигураци, вдруг кому ещё пригодится (не смог загрузить файл с расширением *.xcl, поэтому заменил на *.txt). Вопрос вдогонку. После того, как в файле настроек линкера объявил константу -D_..X_FLASH_START=7000, можно ли как-нибудь использовать её при вычислениях в тексте программы? Или она доступна только линкеру?
Сообщение отредактировал Sergey_Aleksandrovi4 - May 12 2011, 10:41
|
|
|
|
|
May 12 2011, 11:55
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Sergey_Aleksandrovi4 @ May 12 2011, 13:32)  боялся вносить правки в файл конфигурации Так он-то писан был в расчете на приложение, которое начинается с 0. QUOTE (Sergey_Aleksandrovi4 @ May 12 2011, 13:32)  После того, как в файле настроек линкера объявил константу -D_..X_FLASH_START=7000, можно ли как-нибудь использовать её при вычислениях в тексте программы? Или она доступна только линкеру? Если объявить ее без начальных "_..", то можно, хоть и "с вывертом". Выверт заключается в следующем: фактически, все константы линкера для компилятора - адреса (переменных либо функций), а не собственно значения переменных. Поэтому вы можете объявить extern uint8_t const X_FLASH_START, но значение 0x7000 будет иметь адрес этой "переменной", т.е. использовать надо будет uintptr_t FLASH_START = (uintptr_t)&X_FLASH_START; и дальше работайте FLASH_START на здоровье. Но помните, что поскольку этот адрес не известен на этапе компиляции - компилятор скорее всего не сможет заранее просчитать константные арифметические выражения с этой переменной и будет вынужден вычислять их на этапе выполнения. "_.." в начале константы говорит о том, что эта константа локальная для скрипта и она не будет фигурировать ни в объектном файле, ни в дизассемблированном коде.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|