Главная arrow Программирование arrow AVR arrow IAR EWB AVR: Linking Error[e18]: Range error Sunday, October 22 2017  
ГлавнаяКонтактыАдминистрированиеПрограммированиеСсылки
UK-flag-ico.png English Version
GERMAN-flag-ico.png Die deutsche Version
map.gif карта сайта
нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Поделиться:

IAR EWB AVR: Linking Error[e18]: Range error Версия для печати
Написал microsin   
10.11.2009

 У меня при компиляции проекта, содержавшего смешанный код (асемблер и C - это был проект с использованием библиотеки V-USB. Ассемблер был нужен для кода, критичного к времени выполнения), происходила следующая ошибка:
Error[e18]: Range error
 PC offset out of range. Valid range is -4096 (-0x1000) to 4094 (0x0FFE).
 File: C:\asm\AVR910-protoss\usbdrv\usbdrvasm.S, Line: 54 
 Source:     rjmp    USB_INTR_VECTOR
 
  Where $ = __ATmega128__ + 0x4  [0x4]
            in module "usbdrvasm" (c:\asm\AVR910-protoss\Debug\Obj\usbdrvasm.r90),
            offset 0x4 in segment part 0, segment INTVEC
  What: (usbCrc16 + 0x32) - ($ + 2) [0x1182]
  Allowed range: 0xFFFFF000 - 0xFFF
  Operand: usbCrc16Append [0x1188]
           in module usbdrvasm (c:\asm\AVR910-protoss\Debug\Obj\usbdrvasm.r90),
           Offset 0x32 in segment part 1, segment CODE

Проблема была в том, что команда rjmp USB_INTR_VECTOR в таблице векторов прерываний не доставала до нужной её метки (адрес метки был слишком большой для перехода по rjmp). 

Метода устранения ошибки два:
- заменить команду rjmp на команду jmp - у неё нет тех ограничений, по дальности перехода, как у rjmp, но выполняется jmp на 1 такт дольше. В моем случае это нежелательно - код критичен к времени выполнения прерывания.
- поместить код, который находится по метке USB_INTR_VECTOR, ближе к началу памяти, чтобы достала команда rjmp.

Второй способ можно реализовать, добавив перед кодом с меткой, куда прыгает rjmp, директиву назначения сегмента, который размещается линкером ближе к началу памяти, чем сегмент CODE. Порядок сегментов, которого линкер по умолчению придерживается, следующий (подсмотрел в листинге *.map):
-Z(CODE)INTVEC=0-(_..X_INTVEC_SIZE-1)
-Z(CODE)TINY_F=_..X_FLASH_BASE-FF
-Z(CODE)NEAR_F=_..X_FLASH_BASE-_..X_FLASH_NEND
-Z(CODE)SWITCH=_..X_FLASH_BASE-_..X_FLASH_NEND
-Z(CODE)DIFUNCT=_..X_FLASH_BASE-_..X_FLASH_NEND
-Z(CODE)CODE=_..X_FLASH_BASE-_..X_FLASH_END
-Z(CODE)FAR_F=[_..X_FLASH_BASE-_..X_FLASH_END]/10000
-Z(CODE)INITTAB=_..X_FLASH_BASE-_..X_FLASH_END
-Z(CODE)HUGE_F=_..X_FLASH_BASE-_..X_FLASH_END
-Z(CODE)TINY_ID=_..X_FLASH_BASE-_..X_FLASH_END
-Z(CODE)NEAR_ID=_..X_FLASH_BASE-_..X_FLASH_END
-Z(CODE)CHECKSUM#_..X_FLASH_END

Самый лучший кандидат на нужный сегмент для размещения кода по метке USB_INTR_VECTOR - сегмент NEAR_F. Ошибка пропала, когда я размести перед этим кодом директиву RSEG NEAR_F, вот так (метка USB_INTR_VECTOR как раз та, которая стоит в команде rjmp):
    RSEG    NEAR_F
USB_INTR_VECTOR:
;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt
    push    YL              ;2 [35] push only what is necessary to sync with edge ASAP
    in      YL, SREG        ;1 [37]
    push    YL              ;2 [39]
    ..

Последнее обновление ( 10.11.2009 )
 

Добавить комментарий

:D:lol::-);-)8):-|:-*:oops::sad::cry::o:-?:-x:eek::zzz:P:roll::sigh:

Защитный код
Обновить

< Пред.   След. >

Top of Page
 
microsin © 2017