|
Странная ошибка с __interrupt |
|
|
|
May 31 2013, 18:06
|

Группа: Участник
Сообщений: 12
Регистрация: 10-08-07
Из: Odessa
Пользователь №: 29 704

|
Контроллер : ATMega128 + 64KB внешней памяти Используется внешний xcl файл (настройки линкера) Есть смешанный C/C++ проект, в котором крутится FreeRTOS. Во FreeRTOS используется одно прерывание, которое там описано в ассемблерном исходнике с помощью директивы ORG. Проект компилится и кое-как работает, с прерываниями проблем нет. Теперь я хочу описать еще одно прерывание, пишу: Код // -------------------------------------------------------------------------- // USART1_TXC_vect = 0x80 #pragma vector = USART1_TXC_vect extern "C" __interrupt void interrupt_UART1_TXComplete( void ) // -------------------------------------------------------------------------- { // nop } и тут же получаю ошибку: CODE Building configuration: p45g - Debug Updating build tree... CPTracePrinterStrategy.cpp Linking Error[e16]: Segment INTVEC (size: 0x84 align: 0x1) is too long for segment definition. At least 0x2c more bytes needed. The problem occurred while processing the segment placement command "-Z(CODE)INTVEC=0-(_..X_INTVEC_SIZE-1)", where at the moment of placement the available memory ranges were "CODE:0-2f,CODE:34-8b" Reserved ranges relevant to this placement: CODE:0-2f ?FILL1 CODE:30-33 Absolute code from portmacro CODE:34-8b ?FILL2 Warning[w18]: Segment INTVEC (seg part no 7, symbol "interrupt_UART1_TXComplete::??INTVEC 128" in module "CPTracePrinterStrategy", address [0-83]) overlaps segment ?FILL1 (from module "?FILLER_BYTES", address [0-2f]) Warning[w18]: Segment on the address 30-33 in the module portmacro (F:\PROJECTS\Ð-45\P45G\Firmware\1.00\out\obj\ Debug\portmacro.r90) overlaps segment INTVEC (seg part no 7, symbol "interrupt_UART1_TXComplete::??INTVEC 128" in module "CPTracePrinterStrategy", address [0-83]) Warning[w18]: Segment INTVEC (seg part no 7, symbol "interrupt_UART1_TXComplete::??INTVEC 128" in module "CPTracePrinterStrategy", address [0-83]) overlaps segment ?FILL2 (from module "?FILLER_BYTES", address [34-8b]) Warning[w70]: The segment "?FILL1" on address 0 overlaps previous content in the raw-binary output file. The previously content will be overwritten. Error while running Linker Total number of errors: 1 Total number of warnings: 4 Теперь немного арифметики: размер сегмента INTVEC_SIZE равен 8C (140 байт), а значит сюда поместятся 35 (140 / 4) векторов. В параметре vector указан адрес 0x80, что равно 128 байтам, т.е. адрес находится в пределе сегмента кода прерываний. Так что его тогда не устраивает? Вот XCL с конфигурацией: CODE -ca90
-D_..X_INTVEC_SIZE=8C /* 4 bytes * 35 vectors */ -D_..X_FLASH_TEND=FF /* End of tiny flash memory */ -D_..X_FLASH_NEND=FFFF /* End of near flash memory */ -D_..X_FLASH_END=1FFFF /* End of flash memory */
-D_..X_SRAM_BASE=100 /* Start of ram memory */ -D_..X_SRAM_TEND=100 /* End of tiny ram memory */ -D_..X_SRAM_END=10FF /* End of ram memory */
-D_..X_EEPROM_END=FFF /* End of eeprom memory */
-D_..X_CSTACK_SIZE=400 /* 1024 bytes for auto variables and saved registers. */ -D_..X_RSTACK_SIZE=400 /* 1024 bytes for return addresses */ -D_SVC_STACK_SIZE=0 /* not used */ -D_IRQ_STACK_SIZE=0 /* scmRTOS uses CSTACK for irq */ -D_..X_NEAR_HEAP_SIZE=CAFA /* 0 bytes of heap. */
-D_..X_EXT_SRAM_BASE=1100 -D_..X_EXT_SRAM_END=FFFF
-D_..X_EXT_EPROM_BASE=_..X_SRAM_BASE -D_..X_EXT_EPROM_END=_..X_SRAM_END
-D_..X_EXT_EEPROM_BASE=_..X_SRAM_BASE -D_..X_EXT_EEPROM_END=_..X_SRAM_END
-Z(CODE)INTVEC=0-(_..X_INTVEC_SIZE-1) -H1895 -h(CODE)0-_..X_INTVEC_SIZE /* RETI */ -Z(CODE)TINY_F=_..X_INTVEC_SIZE-_..X_FLASH_TEND -Z(CODE)NEAR_F,SWITCH,DIFUNCT=_..X_INTVEC_SIZE-_..X_FLASH_NEND -Z(CODE)CODE=_..X_INTVEC_SIZE-_..X_FLASH_END -Z(FARCODE)FAR_F=_..X_INTVEC_SIZE-_..X_FLASH_END -Z(CODE)HUGE_F,INITTAB=_..X_INTVEC_SIZE-_..X_FLASH_END -Z(CODE)TINY_ID,NEAR_ID=_..X_INTVEC_SIZE-_..X_FLASH_END -Z(CODE)CHECKSUM#_..X_FLASH_END
-Z(DATA)TINY_I,TINY_Z,TINY_N=_..X_SRAM_BASE-_..X_SRAM_TEND -Z(DATA)NEAR_I,NEAR_Z=_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(DATA)CSTACK+_..X_CSTACK_SIZE=_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(DATA)IOSTREAM_N#_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(XDATA)EEPROM_I,EEPROM_N=0-_..X_EEPROM_END -Z(CONST)NEAR_C=_..X_EXT_EPROM_BASE-_..X_EXT_EPROM_END -Z(DATA)NEAR_N=_..X_EXT_EEPROM_BASE-_..X_EXT_EEPROM_END
-e_PrintfLarge=_Printf -e_medium_write=_formatted_write -e_small_write_P=_formatted_write_P -e_ScanfLarge=_Scanf -e_medium_read=_formatted_read -e_medium_read_P=_formatted_read_P
-w29 А вот и два MAP файла (сегменты) ДО добавления прерывания Код INTVEC CODE 00000000 - 00000003 4 Common 1 ?FILL1 CODE 00000004 - 0000002F 2C Relative 0 ?FILL2 CODE 00000034 - 0000008B 58 Relative 0 NEAR_F CODE 0000008C - 00000275 1EA Relative 0 SWITCH CODE 00000276 - 000002A9 34 Relative 1 CODE CODE 000002AA - 000070D5 6E2C Relative 1 HUGE_F CODE 000070D6 Predefined 0 INITTAB CODE 000070D6 - 000070E3 E Relative 0 TINY_ID CODE 000070E4 Predefined 0 NEAR_ID CODE 000070E4 - 000072ED 20A Relative 0 и ПОСЛЕ: Код ?FILL1 CODE 00000000 - 0000002F 30 Relative 0 INTVEC CODE 00000000 - 00000083 84 Common 1 ?FILL2 CODE 00000034 - 0000008B 58 Relative 0 NEAR_F CODE 0000008C - 00000275 1EA Relative 0 SWITCH CODE 00000276 - 000002A9 34 Relative 1 CODE CODE 000002AA - 000070D7 6E2E Relative 1 HUGE_F CODE 000070D8 Predefined 0 INITTAB CODE 000070D8 - 000070E5 E Relative 0 TINY_ID CODE 000070E6 Predefined 0 NEAR_ID CODE 000070E6 - 000072EF 20A Relative 0
Сообщение отредактировал IgorKossak - May 31 2013, 19:11
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
 |
Ответов
(1 - 12)
|
Jun 1 2013, 06:05
|
Частый гость
 
Группа: Свой
Сообщений: 113
Регистрация: 25-10-07
Из: Краснодар
Пользователь №: 31 725

|
Вам надо вызывать прерывания из ассемблерного кода. В portmacro.s90 добавить Код ... EXTERN interrupt_UART1_TXComplete ... ORG USART1_TX_vect jmp interrupt_UART1_TXComplete в Вашем коде определить функцию прерывания как Код #pragma diag_suppress=Ta006 extern "C" __interrupt void interrupt_UART1_TXComplete( void ) #pragma diag_default=Ta006 { } Еще рекомендую заглушить все неиспользуемые вектора прерываний кодом Код ... ORG INT0_vect reti ORG INT1_vect reti ORG INT2_vect reti ...
Сообщение отредактировал desh - Jun 1 2013, 06:08
|
|
|
|
|
Jun 1 2013, 12:05
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(desh @ Jun 1 2013, 09:05)  Вам надо вызывать прерывания из ассемблерного кода. В portmacro.s90 добавить Код ... EXTERN interrupt_UART1_TXComplete ... ORG USART1_TX_vect jmp interrupt_UART1_TXComplete в Вашем коде определить функцию прерывания как Зачем так делать? Или порт сделан так что по другому не сделать? Цитата(desh @ Jun 1 2013, 09:05)  в Вашем коде определить функцию прерывания как Код #pragma diag_suppress=Ta006 extern "C" __interrupt void interrupt_UART1_TXComplete( void ) #pragma diag_default=Ta006 { } Обычно этого достаточно. Без редактирования ассемблерных файлов. Цитата(desh @ Jun 1 2013, 09:05)  Еще рекомендую заглушить все неиспользуемые вектора прерываний кодом Код ... ORG INT0_vect reti ORG INT1_vect reti ORG INT2_vect reti ... Опять же ИАР сам с этим справлялся. P.S. И лучше заполнить вектора не reti, а сбросом.
|
|
|
|
|
Jun 1 2013, 15:01
|
Частый гость
 
Группа: Свой
Сообщений: 113
Регистрация: 25-10-07
Из: Краснодар
Пользователь №: 31 725

|
Цитата Зачем так делать? Или порт сделан так что по другому не сделать? А чем этот то способ плох? Такой стиль используется в оригинальном примере из FreeRTOS. FreeRTOS поддерживает 2 схемы многозадачности: кооперативную и вытесняющую. При кооперативной многозадачности можно использовать стандартный способ работы с прерываниями, если изменить соответствующим образом порт. При вытесняющей многозадачности работа прерывания от системного таймера отличается от работы остальных прерываний. Поэтому системное прерывание вызывается из ассемблерного кода. Линкеру не нравится, что в одном сегменте необходимо расположить и ассемблерный и сишный код. Цитата Обычно этого достаточно. Без редактирования ассемблерных файлов. Обратите внимание, здесь используется директива подавления предупреждения, а не установки адреса прерывания. Цитата Опять же ИАР сам с этим справлялся. В этом случае не справляется, так как сегмент разбит на несколько частей ассемблерными вызовами. Цитата P.S. И лучше заполнить вектора не reti, а сбросом. А вот тут я с Вами совсем не согласен. Что лучше - надо решать исходя из назначения устройства. Не всех порадует самопроизвольный сброс конечного продукта.
Сообщение отредактировал desh - Jun 1 2013, 15:04
|
|
|
|
|
Jun 1 2013, 15:24
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(desh @ Jun 1 2013, 18:01)  А чем этот то способ плох? Такой стиль используется в оригинальном примере из FreeRTOS. Тем что надо прописывать вектора вручную. То есть приходится брать на себя работу ИАРа. Цитата(desh @ Jun 1 2013, 18:01)  При вытесняющей многозадачности работа прерывания от системного таймера отличается от работы остальных прерываний. Поэтому системное прерывание вызывается из ассемблерного кода. Не вижу, если честно необходимости вызова из ассемблерного файла при вытесняющей многозадачности (может такая необходимость есть, но она неочевидна). Цитата(desh @ Jun 1 2013, 18:01)  Линкеру не нравится, что в одном сегменте необходимо расположить и ассемблерный и сишный код. В этом случае не справляется, так как сегмент разбит на несколько частей ассемблерными вызовами. Ерунда какая-то... Что же по-вашему нельзя объявлять обработчики в *.с и *.asm файлах без каких-то трюков? Не видел такой ситуации когда "Линкеру не нравится". Но создать её на свою голову наверное можно... Цитата(desh @ Jun 1 2013, 18:01)  А вот тут я с Вами совсем не согласен. Что лучше - надо решать исходя из назначения устройства. Не всех порадует самопроизвольный сброс конечного продукта. Случаи бывают разные, это - да...
|
|
|
|
|
Jun 1 2013, 19:56
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(desh @ Jun 1 2013, 18:38)  Эм... Хотелось бы увидеть и обсудить Ваше решение указанной в первом сообщении проблеммы. Для того чтобы увидеть решение проблемы неплохо было бы увидеть проблему. ТС тут выложил нам много букв скрипты линкера, который непонятно что линкует, кучу ошибок вызванных непонятно чем, фреймворки которых никто не видел и тп. Вместо того чтобы выложить проект, в котором проблема возникает. ТС наверное думает что тут форум телепатов... К тому же непонятно как ТС запустил Freertos на M128 - демо-проект с сайта freertos сделан под M323 и для запуска его на M128 требуется некоторая модификация под таргет. Или я не там брал freertos и есть где-то готовый проект под M128 и другие меги? Где такое берут? Цитата(desh @ Jun 1 2013, 18:38)  Ваше решение Скачал с freertos.org демо-проект. Заменил в нём таргет на mega128. Добавил в файл main.c: Код #pragma vector=USART1_UDRE_vect __interrupt void Uart1_UDRE_Handler() { } Получил в ответ такую ругань: Цитата Error[e16]: Segment INTVEC (size: 0x80 align: 0x1) is too long for segment definition. At least 0x44 more bytes needed. The problem occurred while processing the segment placement command "-Z(CODE)INTVEC=0-(_..X_INTVEC_SIZE-1)", where at the moment of placement the available memory ranges were "CODE:0-2f,CODE:34-47,CODE:50-8b" Reserved ranges relevant to this placement: CODE:0-2f ?FILL1 CODE:30-33 Absolute code from portmacro CODE:34-47 ?FILL2 CODE:48-4f Absolute code from portmacro CODE:50-8b ?FILL3 Error while running Linker Total number of errors: 1 Total number of warnings: 1 Убрал в файле portmacro.s90 директиву ASEG (какой-такой ASEG? что они этим сказать хотели?): Код common INTVEC(1)
ORG TIMER1_COMPA_vect ; Vector address jmp SIG_OUTPUT_COMPARE1A ; ISR
ORG USART0_RXC_vect ; Vector address jmp SIG_UART_RECV ; ISR
ORG USART0_UDRE_vect ; Vector address jmp SIG_UART_DATA ; ISR
RSEG CODE Добавил в main.c: CODE volatile char TxData[8]; volatile unsigned char TxIndex, TxSize;
#pragma vector=USART1_UDRE_vect __interrupt void Uart1_UDRE_Handler() { unsigned char tx_index=TxIndex; UDR1=TxData[tx_index++]; if (tx_index==TxSize) UCSR1B&=~(1<<UDRIE1);
TxIndex=tx_index; }
static void vErrorChecks( void *pvParameters ) { static volatile unsigned long ulDummyVariable = 3UL; UCSR1A = 0 | (0<<RXC1) | (1<<TXC1) | (0<<UDRE1) | (0<<FE1) | (0<<DOR1) | (0<<UPE1) | (0<<U2X1) | (0<<MPCM1) ; UCSR1B= 0 | (0<<RXCIE1) | (1<<TXCIE1) | (0<<UDRIE1) | (0<<RXEN1) | (1<<TXEN1) | (0<<UCSZ12) | (0<<RXB81) | (0<<TXB81) ; UCSR1C= 0 | (0<<UMSEL0) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0) ; UBRR1H=0; UBRR1L=5;
/* The parameters are not used. */ ( void ) pvParameters;
/* Cycle for ever, delaying then checking all the other tasks are still operating without error. */ unsigned long counter=0; for( ;; ) { TxSize=sprintf(TxData, "t=%x", counter++); TxIndex=0; UCSR1B|=(1<<UDRIE1); prvCheckOtherTasksAreStillRunning(); vTaskDelay( 3);//mainCHECK_PERIOD ); } }
Цитата IAR Universal Linker V5.2.3.14 Copyright 1987-2011 IAR Systems AB. 12 992 bytes of CODE memory (+ 12 range fill ) 1 928 bytes of DATA memory (+ 21 absolute ) Errors: none Warnings: none Прерывание работает, но не отвалилось что-нибудь в другом месте не знаю... Это решение?
|
|
|
|
|
Jun 1 2013, 20:47
|
Частый гость
 
Группа: Свой
Сообщений: 113
Регистрация: 25-10-07
Из: Краснодар
Пользователь №: 31 725

|
Это решение!  Прошивки совпадают полностью. Вы победили  Цитата К тому же непонятно как ТС запустил Freertos на M128 - демо-проект с сайта freertos сделан под M323 и для запуска его на M128 требуется некоторая модификация под таргет. Или я не там брал freertos и есть где-то готовый проект под M128 и другие меги? Где такое берут? Такое обычно делают сами. Кстати, в соседней ветке автор жалуется, что его система глючит после добавления нового кода. Возможно его проект преодолел рубеж в 64 кб и у него вылезло отличие между таргетами.
Сообщение отредактировал desh - Jun 1 2013, 21:21
|
|
|
|
|
Jun 2 2013, 08:12
|

Группа: Участник
Сообщений: 12
Регистрация: 10-08-07
Из: Odessa
Пользователь №: 29 704

|
_Артём_, часть фреймворка я выложил в этой ветке: http://electronix.ru/forum/index.php?showt...p;#entry1166837Портировал под М128 я сам. На счет RETI или RESET - линкеру указан ключ "-H1895 -h(CODE)0-_..X_INTVEC_SIZE" (см первый пост), где это делается автоматически (0x1895 это опкод reti) desh, у меня размер бинарника всего лишь что-то около 30КБ. А по поводу 64KB - RAMPZ влияет если оперативной памяти больше, а у меня как раз ровно 64КБ. Команды записи во флеш из юзеркода не вызываются, так что RAMPZ по идее никак не должен влиять.
|
|
|
|
|
Jun 2 2013, 12:13
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(desh @ Jun 1 2013, 23:47)  Прошивки совпадают полностью. Прошивки могут и не совпадать - линкер как-нибудь по-другому может всё расположить. Цитата(desh @ Jun 1 2013, 23:47)  Вы победили  "За нашу победу" и выпил, кстати... Цитата(desh @ Jun 1 2013, 23:47)  Такое обычно делают сами. К сожалению. Зря у freertos так сделано - привязали демо проект к какой-то экзотической mega323. Лучше бы проект под mega256 выложили - его проще на других мегах запустить было бы. Цитата(Aeore @ Jun 2 2013, 11:12)  у меня размер бинарника всего лишь что-то около 30КБ. Тогда RAMPZ нипричом. Цитата(Aeore @ Jun 2 2013, 11:12)  А по поводу 64KB - RAMPZ влияет если оперативной памяти больше, а у меня как раз ровно 64КБ. RAPMZ в mega128 используется для доступа к flash за пределами 64 КБ командами ELPM/SPM. То есть не ваш случай, если прошивка меньше 30 КБ.
|
|
|
|
|
Jun 3 2013, 17:57
|

Группа: Участник
Сообщений: 12
Регистрация: 10-08-07
Из: Odessa
Пользователь №: 29 704

|
Цитата(_Артём_ @ Jun 1 2013, 22:56)  Убрал в файле portmacro.s90 директиву ASEG (какой-такой ASEG? что они этим сказать хотели?):
..
Прерывание работает, но не отвалилось что-нибудь в другом месте не знаю... Это решение? Эм.. удалил у себя - все осталось по прежнему O_o
|
|
|
|
|
Jun 3 2013, 18:47
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Aeore @ Jun 3 2013, 20:57)  Эм.. удалил у себя - все осталось по прежнему O_o Это я неточно выразился. Надо было не Цитата Убрал в файле portmacro.s90... , а так: заменил в файле portmacro.s90 директиву ASEG на common INTVEC(1).
|
|
|
|
|
Jun 3 2013, 19:28
|

Группа: Участник
Сообщений: 12
Регистрация: 10-08-07
Из: Odessa
Пользователь №: 29 704

|
И так причину такого поведения я раскрыл, но как ее поправить пока не ясно. Причина: Похоже что линкер видит, что директива org попадает в сегмент прерываний, но он не просто добавляет код инструкции в сегмент начиная с заданного адреса, а усекает весь сегмент на размер org + размер всех инструкций после него (пока не встретится директива смены сегмента). Таким образом Код ORG TIMER1_COMPA_vect ; Vector address jmp SIG_OUTPUT_COMPARE1A; ISR (TIMER1_COMPA_vect = 0x30) и ошибка Код Error[e16]: Segment INTVEC (size: 0x84 align: 0x1) is too long for segment definition. At least 0x2c more bytes needed. для USART1_TXC_vect (= 0x80) связанны таким соотношением: 0x8C - (0x30 + 4) = 0x58 Таким образом он считает, что максимальный размер сегмента равен 0x58 байт. Проверяем так - берем два вектора Код #define ADC_vect (0x54) #define EE_RDY_vect (0x58) и пытаемся их использовать. Первый работает, второй нет. Цитата(_Артём_ @ Jun 3 2013, 21:47)  Это я неточно выразился. Надо было не , а так: заменил в файле portmacro.s90 директиву ASEG на common INTVEC(1). Компилируется, спасибо!
Сообщение отредактировал Aeore - Jun 3 2013, 19:29
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|