|
|
  |
Проблема с IRQ прерыванием |
|
|
|
Oct 30 2007, 11:06
|
Участник

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739

|
Проект под IAR 4.41 Язык С/С++
Программа сделана для работы с внешнего ОЗУ 0х21000000 Вектора прописываются там же 0х21000000 Появиласть проблема с IRQ прерыванием... так как нужно послать PC по адресу 0хfffff100 где расположен AIC_SVR. Но при срабатывании прерывания попадаем по адрессу 0х00000018.
Как мне быть есть два пути: 1 - разместить вектора по адр 0х00000018 2 - добится того чтобы ldr pc, [pc,#-0xF20] посылала на 0xfffff100, но тогда необходимо прибавить к PC,#0xdefff0e8 , синтаксис не позволяет мне этого сделать.
Может есть еще какие решения? from startup code ;--------------------------------------------------------------- ; ?RESET ; Reset Vector. ; Normally, segment INTVEC is linked at address 0. ; For debugging purposes, INTVEC may be placed at other ; addresses. ; A debugger that honors the entry point will start the ; program in a normal way even if INTVEC is not at address 0. ;--------------------------------------------------------------- MODULE ?RESET ; COMMON INTVEC:CODE:NOROOT(2); RSEG ICODE:CODE:NOROOT(2) PUBLIC __program_start EXTERN ?cstartup ; EXTERN undef_handler, swi_handler, prefetch_handler ; EXTERN data_handler, irq_handler, fiq_handler CODE32; Always ARM mode after reset ADRSTART: org 0x00+ADRSTART __program_start ldr pc,=?cstartup; Absolute jump org 0x04+ADRSTART undef_handler: ldr pc,=undef_handler org 0x08+ADRSTART swi_handler: ldr pc,=swi_handler org 0x0c+ADRSTART prefetch_handler: ldr pc,=prefetch_handler org 0x10+ADRSTART data_handler: ldr pc,=data_handler org 0x18+ADRSTART ldr pc, [pc,#-0xF20] ; IRQ : read the AIC org 0x1c+ADRSTART fiq_handler: ldr pc,=fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20 org 0x20+ADRSTART LTORG ; ENDMOD __program_start ENDMOD
Сообщение отредактировал Daermon - Oct 30 2007, 11:20
|
|
|
|
|
Oct 30 2007, 12:29
|

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

|
Цитата(Daermon @ Oct 30 2007, 14:06)  Программа сделана для работы с внешнего ОЗУ 0х21000000 Вектора прописываются там же 0х21000000 Вы можете разместить вектора где угодно, но процессор, несмотря на это, все равно будет при исключениях переходить в фиксированные адреса 00-1С. Поэтому, при размещении векторов в ОЗУ надо сделать remap, тогда начальная область ОЗУ (или все ОЗУ) окажется также отражено на нулевые адреса и процессор при исключении попадет на ваши вектора. Только надо помпить, что несмотря на то, что вектора физически расположены в верхних адресах, их содержимое должно быть таким, как будто они находятся в нулевых. В вашем случае надо написть в .xcl что-то вроде Код -DRAMSTART=21000000 -DRAMEND=21003FFF
// vectors always linked to 0x00-0x3F -Z(CODE)INTVEC=00000000-0000003F
// Mirrored vectors placed in RAM -Z(CODE)INTVEC_I=RAMSTART-RAMEND -QINTVEC=INTVEC_I
-Z(CODE)ICODE,CODE,DIFUNCT,SWITAB=RAMSTART-RAMEND А при старте отладчика (в .mac) сделать ремап : Код execUserReset() { Remap_RAM(); __writeMemory32(0xD3,0x98,"Register"); // CPSR = SVC mode, ARM, IRQ, FIQ disabled __writeMemory32(0x00000000,0xB4,"Register"); }
Remap_RAM() { __var tmp; tmp = __readMemory32(0x00200000, "Memory"); // read from RAM area __writeMemory32(~tmp, 0x00200000, "Memory"); // alter RAM area if( ~tmp != __readMemory32(0x00000000, "Memory") ) // check if altering mirrored to remap area { __writeMemory32(0x00000001, 0xFFFFFF00,"Memory"); // otherwice remap } __writeMemory32(tmp, 0x00200000 ,"Memory"); // restore RAM data __message " remapped to RAM"; } Цитата(alexander55 @ Oct 30 2007, 14:12)  Рекомендую указать компилятор и uC для определенности. Компилятор был указан, а насчет uC - прекрасный повод потренироваться в телепатии. Раз упомятут AIC_SVR - это атмел. Раз ОЗУ живет начиная с 0x21000000 - это что-нибудь с внешней памятью. Интуитивно предполагаем RM9200.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 30 2007, 13:38
|
Участник

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739

|
Спасибо большое! Но у меня пара вопросов появилась.
Исправления в .xlc Добавил: -DRAMSTART=21000000 -DRAMEND=22000000 вместо: //-DRAMSTART=(MEMSTART+40) //-DRAMEND=MEMEND //******************************************
//************************************************ // Address range for reset and exception // vectors (INTVEC). // The vector area is 32 bytes, // an additional 32 bytes is allocated for the // constant table used by ldr PC in cstartup.s79. //************************************************ Добавил: // vectors always linked to 0x00-0x3F -Z(CODE)INTVEC=00000000-0000003F // Mirrored vectors placed in RAM -Z(CODE)INTVEC_I=RAMSTART-RAMEND -QINTVEC=INTVEC_I Было: //-Z(CODE)INTVEC=MEMSTART:+40
//*************************************************** Тоже добавил: -Z(CODE)ICODE,CODE,DIFUNCT,SWITAB=RAMSTART-RAMEND
//////////////////////////////////////////////////////////////////////////////////
Remap_RAM() { __var tmp; tmp = __readMemory32(0x00200000, "Memory"); // read from RAM area
__writeMemory32(~tmp, 0x00200000, "Memory"); // alter RAM area if( ~tmp != __readMemory32(0x00000000, "Memory") ) // check if altering mirrored to remap area { __writeMemory32(0x00000001, 0xFFFFFF00,"Memory"); // otherwice remap } __writeMemory32(tmp, 0x00200000 ,"Memory"); // restore RAM data __message " remapped to RAM"; } Это все тоже добавил, но не совсем понятно что именно происходит тут?
Вот что добавил в *.mac
execUserPreload() { init_PLL_180(); //__writeMemory32(0xAAAAAAAA,0x00000000,"Memory"); // if(__readMemory32(0x00000000,"Memory") != 0xAAAAAAAA) // { // __writeMemory32(0x01,0xFFFFFF00,"Memory"); // MC_RCR: toggle remap bit // } init_SDRAM (); Remap_RAM(); // __writeMemory32(0xD3,0x98,"Register"); // CPSR = SVC mode, ARM, IRQ, FIQ disabled // __writeMemory32(0x00000000,0xB4,"Register");
__message("Target init macro complete");
Где то что то не так, потому что копирование векторов не происходит.[size=4]
}
|
|
|
|
|
Oct 30 2007, 15:06
|

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

|
Цитата(Daermon @ Oct 30 2007, 16:38)  Это все тоже добавил, но не совсем понятно что именно происходит тут? Упс, виноват - это был ремап на внутреннее ОЗУ для SAM7S. Поскольку вы так и не уточнили, что у вас за контроллер, будет трудновато подсказать. Но идея Remap_RAM() все та же: считываем из ОЗУ из области, где лежат вектора значение, запоминаем его, изменяем эту ячейку в ОЗУ, смотрим, отразилось ли это изменение на области векторов. Если отразилось - ремап уже сделан, если не отразилось - делаем ремап. После чего восстанавливаем считанное в начале значение. Если у вас RM9200, то он не умеет ремапить SDRAM на нулевые адреса. Вам придется скопировать вектора в начало внутреннего ОЗУ и после этого сделать Remap на внутреннее ОЗУ: Код execUserPreload() { __var i; init_PLL_180(); init_SDRAM (); } execUserReset() { for( i = 0; i < 0x40; i += 4 ) // copy vectors from app to internal RAM { tmp = __readMemory32(0x21000000 + i, "Memory"); __writeMemory32(tmp,0x00200000 + i, "Memory"); }
Remap_RAM();
__writeMemory32(0xD3,0x98,"Register"); // CPSR = SVC mode, ARM, IRQ, FIQ disabled __writeMemory32(0x00000000,0xB4,"Register"); } Причем копирование надо делать в execUserReset() или execUserSetup(), потому что в момент исполнения execUserPreload() ваша программа еще не загружена и копировать нечего. Или можно обойтись без копирования, если сразу слинковать вектора во внутреннее ОЗУ: Код -DINTRAMSTART=00200000 -DINTRAMEND=00203FFF
// vectors always linked to 0x00-0x3F -Z(CODE)INTVEC=00000000-0000003F
// Mirrored vectors placed in internal RAM -Z(CODE)INTVEC_I=INTRAMSTART-INTRAMEND -QINTVEC=INTVEC_I
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 31 2007, 05:53
|
Участник

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739

|
Каша в голове  Попробую по порядку: 1. sturtup код настраивает вектора прерывания на адрес 0х21000000 2. мне необходимо сделать зеркало с адреса 0х21000000 на 0х00000000 // vectors always linked to 0x00-0x3F -Z(CODE)INTVEC=00000000-0000003F // Mirrored vectors placed in RAM -Z(CODE)INTVEC_I=RAMSTART-RAMEND -QINTVEC=INTVEC_I // Вот тут буква Q обязательна?3. В файл *.mac добавить execUserReset() { for( i = 0; i < 0x40; i += 4 ) // copy vectors from app to internal RAM { tmp = __readMemory32(0x21000000 + i, "Memory"); __writeMemory32(tmp,0x00200000 + i, "Memory"); // Здесь точно 0x00200000? и почему он? а не например 0x00000000. } // делаем ремап __var tmp; tmp = __readMemory32(0x00200000, "Memory"); // read from RAM area __writeMemory32(~tmp, 0x00200000, "Memory"); // alter RAM area if( ~tmp != __readMemory32(0x00000000, "Memory") ) // check if altering mirrored to remap area { __writeMemory32(0x00000001, 0xFFFFFF00,"Memory"); // otherwice remap } __writeMemory32(tmp, 0x00200000 ,"Memory"); // restore RAM data __message " remapped to RAM"; __writeMemory32(0xD3,0x98,"Register"); // CPSR = SVC mode, ARM, IRQ, FIQ disabled __writeMemory32(0x00000000,0xB4,"Register"); } 4. Хотел узнать когда именно исполняется execUserReset() и execUserPreload() до стартапа или после него? Почему то после всего что сделал полностью затирается облатсть 0х00000000 - 0х001ffffc
Сообщение отредактировал Daermon - Oct 31 2007, 05:59
|
|
|
|
|
Oct 31 2007, 07:17
|
Участник

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739

|
Все... из внутреннего ОЗУ (0x00200000) все ремапится в 0х00000000
Но вот из внешнего ОЗУ 0x21000000 не копируются данные во внутреннее ОЗУ.
execUserSetup() { __var tmp; for( i = 0; i < 0x40; i += 4 ) // copy vectors from app to internal RAM { tmp = __readMemory32(0x21000000 + i, "Memory"); // НЕ РАБОТАЕТ!!! __writeMemory32(tmp,0x00200000+ i, "Memory"); } Remap_RAM();
//__writeMemory32(0xD3,0x98,"Register"); // CPSR = SVC mode, ARM, IRQ, FIQ disabled //__writeMemory32(0x00000000,0xB4,"Register"); }
|
|
|
|
|
Oct 31 2007, 10:25
|
Участник

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739

|
Вроде бы в этом разобрался, но появилась другая проблема. Теперь программа начала стартовать с адресса 0х00000000, что не есть ГУД.
Помагает программный Reset, после которого прогрмма стартует с адресса 0x21000000 и прерывания срабатывают нормально.
execUserPreload() { init_PLL_180(); init_SDRAM (); __message("Target init macro complete"); } execUserSetup() { __var tmp,i; Remap_RAM(); for( i = 0; i < 0x40; i += 4 ) // copy vectors from app to internal RAM { tmp = __readMemory32(0x21000000 + i, "Memory"); __writeMemory32(tmp,0x00200000+ i, "Memory"); } __writeMemory32(0xD3,0x98,"Register"); // CPSR = SVC mode, ARM, IRQ, FIQ disabled __writeMemory32(0x00000000,0xB4,"Register"); }
в .xlc
//************************************************ // Address range for reset and exception // vectors (INTVEC). // The vector area is 32 bytes, // an additional 32 bytes is allocated for the // constant table used by ldr PC in cstartup.s79. //************************************************ -Z(CODE)INTVEC=0x00000000-0x0000003F -Z(CODE)INTVEC_I=0x21000000-0x2100003f -QINTVEC_I=INTVEC
Что сделать чтобы программа стартовала с адресса 0х21000000???
|
|
|
|
|
Oct 31 2007, 10:45
|

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

|
Цитата(Daermon @ Oct 31 2007, 13:25)  Теперь программа начала стартовать с адресса 0х00000000, что не есть ГУД. Что сделать чтобы программа стартовала с адресса 0х21000000??? Почему не есть гуд? Ведь именно с этого адреса программа стартует в железе без отладчика. По адресу 0х21000000 располагается вектор ресета, который вы скопировали во внутреннее ОЗУ и отмапировали на адрес 0. Т.е. старт с адреса 0 должен приводить к тому же результату. Но если хотите - в execUserReset в конец допишите Код __writeMemory32(0xD3,0x98,"Register"); // CPSR = SVC mode, ARM, IRQ, FIQ disabled __writeMemory32(0x21000000,0xB4,"Register"); Цитата(Daermon @ Oct 31 2007, 08:53)  -QINTVEC=INTVEC_I // Вот тут буква Q обязательна? Help->Linker and library tools user guide. Цитата(Daermon @ Oct 31 2007, 08:53)  4. Хотел узнать когда именно исполняется execUserReset() и execUserPreload() до стартапа или после него? Посмотрите Help->ARM Embedded Workbench User guide. Поищите по ключевому слову execUserPreload - там все довольно подробно описано. Мне тут пришел в голову еще один вариант, как обойтись без копирования - сделать ремап в execUserPreload(), а вектора расположить по адресу 0. Тогда при загрузке по адресу 0 будет внутреннее ОЗУ и вектора сразу лягут куда надо.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 31 2007, 11:40
|
Участник

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739

|
Спасибо. Наконец прерывания заработали....но только при работе через SAM-ICE. После того как заливаю во внешнюю ОЗУ, при возникновении прерывания программа зависает.
Запускаю плату: U-Boot 1.1.4 (Aug 20 2006 - 21:33:18)
DRAM: 32 MB Parallel flash ignored Flash: 0 kB DataFlash:AT45DB642 Nb pages: 8192 Page Size: 1056 Size= 8650752 bytes Logical address: 0xC0000000 Area 0: C0000000 to C00083FF (RO) Bootstrap Area 1: C0008400 to C003DDFF (RO) U-Boot Area 3: C003FF00 to C0041FFF Environment Area 4: C0042000 to C018BFFF OS Area 5: C018C000 to C083FFFF FS In: serial Out: serial Err: serial Hit any key to stop autoboot: 0 U-Boot>
Закачиваю через DBGU файл - формат raw-binary: U-Boot> loadb ## Ready for binary (kermit) download to 0x21000000 at 115200 bps... ## Total Size = 0x0000316c = 12652 Bytes ## Start Addr = 0x21000000 U-Boot>go 0x21000000
И вот тут при появлении прерывания программа зависает...
Что тут может быть?
|
|
|
|
|
Oct 31 2007, 11:59
|

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

|
Цитата(Daermon @ Oct 31 2007, 14:40)  U-Boot>go 0x21000000 И вот тут при появлении прерывания программа зависает... Видимо все то же - никто не скопировал вектора, никто не сделал Remap.Могу предложить добавить в программу функцию Код #include <stdint.h> _C_LIB_DECL #pragma language=extended #pragma location="ICODE" int __low_level_init(void) { // copy vectors uint32_t const *pSrc = (uint32_t *)0x21000000; uint32_t *pDst = (uint32_t *)0x00200000; //RAMSTART uint_fast8_t Size = 0x40 / sizeof *Dst; do { *pDst++ = *pSrc++; } while (--Size);
// remap uint32_t *pVectors = (uint32_t *)0x00200014; //reserved vector in mirrored RAM uint32_t Tmp = *pVectors; *pVectors = ~Tmp; if( (uint32_t *)0x00000014 != ~Tmp ) AT91C_BASE_MC->MC_RCR = AT91C_MC_RCB; // REMAP *pVectors = Tmp;
return 1; // init RAM. } #pragma language=default _END_C_LIB_DECL
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 31 2007, 12:35
|
Участник

Группа: Новичок
Сообщений: 36
Регистрация: 26-10-07
Пользователь №: 31 739

|
Чуть подправил if( *((uint32_t *)0x00000014) != ~Tmp )
И все !!! Работает!! Огромное СПАСИБА!!!
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|