[an error occurred while processing this directive]
|
Решил перейти с 3.0 к 3.5 и столкнулся с такими проблемами:
1. При размещении кода данных во внешней памяти ругается
линкёр на объявление:
mem_code { TYPE(PM RAM) START(0x800000) END(0x807fff) WIDTH(16) }
[Error el2011] Invalid memory range and/or width for memory 'mem_code'
После копания обнаружилось что в 3.5 секции программ линкёр пытается
привязать не к физическим, а к логическим адресам. И эти адреса вычисляются
как физ = лог * 2 (для 16 битной внешней памяти), то есть нельзя объявить
сегмент памяти программ выше 0x800000.
При объявлении секции:
mem_code { TYPE(PM RAM) START(0x400000) END(0x407fff) WIDTH(16) }
Линкёр отображает что секция находится по физическому адресу 0x800000-0x80FFFF,
однако код создаётся с обращением не к физическим, а к логическим адресам
то есть в ljump/lcall MSB = 0x40
более того, в файле выходном загрузки (для UART'а) адреса загружаемой секции
в Byte Stream Format Header указывайтся 0x400000
То есть господа представлют физическую память для памяти программ как:
Физ.адрес = Страница * 0x8000 + Лог.адрес * 2
где 0x8000 - логический размер страницы
тогда как по моему представлению и как было ранее:
Физ.адрес = Страница * 0x10000 + Лог.адрес * 2
где 0x10000 - физический размер страницы
То есть ранее было для каждой страницы при использовании програмной памяти
адреса 0x0000-0x7FFF (логические) соответствуют 0x0000-0xFFFF (физические)
То есть в каждой странице использовалась младшая половина.
Щас же (в 3.5) модель памяти для программных сегментов ошибочна.
Добавлю, что всё вышесказанное не проявляется, если весь код размещён в
странице 0.
2. Если объявить секцию и разместить в ней данные data1
...
mem_data1 { TYPE(DM RAM) START(0x810000) END(0x81cfff) WIDTH(16) }
...
data1_dxe { INPUT_SECTIONS( $OBJECTS(data1) $LIBRARIES(data1) ) } > mem_data1
...
и в тексте есть конструкция типа:
...
code = read_rx();
switch (code)
{
case 0x03:
break;
case 0xE0:
break;
case 0xF0:
break;
case 0xF1:
break;
case 0xF2:
break;
case 0xF3:
break;
default:
printf("Unknown command : %02X\n", code);
}
...
[Error li1080] "....." value of ADDR(_L_SW2147483645)-240 (=-0x79) is out of range
Referenced from 0x4001b3
Valid range is [0x0,0xffff]
Как оказалось компилятор создаёт код:
...
AY1 = 224;
AF = AX1 - AY1;
DM(I5 + -3) = AX1;
IF not ac JUMP .P2L8;
AR = AY1 - AX1;
IF eq JUMP .P2L2;
AY1 = 240;
AR = AX1 - AY1;
IF lt JUMP .P2L11;
AY1 = 243;
AR = AX1 - AY1;
IF gt JUMP .P2L11;
I1 = ADDRESS(_L_SW2147483645)-240;
M3 = AX1 ;
IJPG = PAGE ( _analize_packet );
I1 = DM(I1 + M3);
JUMP (I1);
...
.section/data data1;
_L_SW2147483645:
.type _L_SW2147483645,STT_OBJECT;
.var = ADDRESS(.P2L3);
.var = ADDRESS(.P2L4);
.var = ADDRESS(.P2L46);
.var = ADDRESS(.P2L11);
._L_SW2147483645.end:
То есть по части условий переход осуществлятся сравнением, а для блока
case 0xF0:
...
case 0xF1:
...
case 0xF2:
...
case 0xF3:
...
создаёт таблецу меток перехода и усуществлял бы переход, если бы не адрес
размещения _L_SW2147483645 - например 0x810077
и 0x0077 - 0xF0 получается отрицательное число, на что и ругается линкёр
это всё конечно лечится перемещением секции data1 повыше по адресам,
но удручает не это, а факт того что чем старше версия среды (3.5 в данном
случае), тем больше глюков проявляется.
Неужели AD решили таким образом перейти на BlackFin - дискредитируя 219x?
Рассудите, или может я не прав?
С уважением MIR!
E-mail: info@telesys.ru