|
|
  |
AT91SAM9XE и инициализация FIQ |
|
|
|
Jun 20 2011, 18:30
|
Участник

Группа: Участник
Сообщений: 51
Регистрация: 8-10-09
Пользователь №: 52 809

|
Здравствуйте! Мне нужен файл board_cstartup_iar.s с (IAR 5.xx) с инициализацией обработчика по умолчанию для FIQ и соответствующего стека. Чтобы он функционально был аналогичен файлу Cstartup.s79 из примера AT91SAM7S32-Interrupt-IAR4_11A-1_1-FIQ.zip. Я не настолько хорошо владею предметом, чтобы легко менять .s файлы. Код который я написал в основной программе работает для прерывания IRQ1, но перестает работать когда я меняю IRQ1 на FIQ. Вызывается обработчик FIQ_Handler, который не делает ничего. Спасибо. board_cstartup_iar.s: CODE /* IAR startup file for AT91SAM9XE microcontrollers. */
MODULE ?cstartup
;; Forward declaration of sections. SECTION IRQ_STACK:DATA:NOROOT(2) SECTION CSTACK:DATA:NOROOT(3)
//------------------------------------------------------------------------------ // Headers //------------------------------------------------------------------------------
#define __ASSEMBLY__ #include "board.h"
//------------------------------------------------------------------------------ // Definitions //------------------------------------------------------------------------------
#define ARM_MODE_ABT 0x17 #define ARM_MODE_FIQ 0x11 #define ARM_MODE_IRQ 0x12 #define ARM_MODE_SVC 0x13 #define ARM_MODE_SYS 0x1F
#define I_BIT 0x80 #define F_BIT 0x40
//------------------------------------------------------------------------------ // Startup routine //------------------------------------------------------------------------------
/* Exception vectors */ SECTION .vectors:CODE:NOROOT(2)
PUBLIC resetVector PUBLIC irqHandler
EXTERN Undefined_Handler EXTERN SWI_Handler EXTERN Prefetch_Handler EXTERN Abort_Handler EXTERN FIQ_Handler
ARM
__iar_init$$done: ; The interrupt vector is not needed ; until after copy initialization is done
resetVector: ; All default exception handlers (except reset) are ; defined as weak symbol definitions. ; If a handler is defined by the application it will take precedence. LDR pc, =resetHandler ; Reset LDR pc, Undefined_Addr ; Undefined instructions LDR pc, SWI_Addr ; Software interrupt (SWI/SYS) LDR pc, Prefetch_Addr ; Prefetch abort LDR pc, Abort_Addr ; Data abort B . ; RESERVED LDR pc, =irqHandler ; IRQ LDR pc, FIQ_Addr ; FIQ
Undefined_Addr: DCD Undefined_Handler SWI_Addr: DCD SWI_Handler Prefetch_Addr: DCD Prefetch_Handler Abort_Addr: DCD Abort_Handler FIQ_Addr: DCD FIQ_Handler /* Handles incoming interrupt requests by branching to the corresponding handler, as defined in the AIC. Supports interrupt nesting. */ irqHandler: /* Save interrupt context on the stack to allow nesting */ SUB lr, lr, #4 STMFD sp!, {lr} MRS lr, SPSR STMFD sp!, {r0, lr}
/* Write in the IVR to support Protect Mode */ LDR lr, =AT91C_BASE_AIC LDR r0, [r14, #AIC_IVR] STR lr, [r14, #AIC_IVR]
/* Branch to interrupt handler in Supervisor mode */ MSR CPSR_c, #ARM_MODE_SYS STMFD sp!, {r1-r3, r4, r12, lr} BLX r0 LDMIA sp!, {r1-r3, r4, r12, lr} MSR CPSR_c, #ARM_MODE_IRQ | I_BIT
/* Acknowledge interrupt */ LDR lr, =AT91C_BASE_AIC STR lr, [r14, #AIC_EOICR]
/* Restore interrupt context and branch back to calling code */ LDMIA sp!, {r0, lr} MSR SPSR_cxsf, lr LDMIA sp!, {pc}^
/* After a reset, execution starts here, the mode is ARM, supervisor with interrupts disabled. Initializes the chip and branches to the main() function. */ SECTION .cstartup:CODE:NOROOT(2)
PUBLIC resetHandler EXTERN LowLevelInit EXTERN ?main REQUIRE resetVector ARM
resetHandler:
/* Set pc to actual code location (i.e. not in remap zone) */ LDR pc, =label
/* Perform low-level initialization of the chip using LowLevelInit() */ label: LDR r0, =LowLevelInit LDR r4, =SFE(CSTACK) MOV sp, r4 BLX r0
/* Set up the interrupt stack pointer. */ MSR cpsr_c, #ARM_MODE_IRQ | I_BIT | F_BIT ; Change the mode LDR sp, =SFE(IRQ_STACK)
/* Set up the SYS stack pointer. */ MSR cpsr_c, #ARM_MODE_SYS | F_BIT ; Change the mode LDR sp, =SFE(CSTACK)
/* Branch to main() */ LDR r0, =?main BLX r0
/* Loop indefinitely when program is finished */ loop4: B loop4
END
Cstartup.s79:
;------------------------------------------------------------------------------ ;- ATMEL Microcontroller Software Support - ROUSSET - ;------------------------------------------------------------------------------ ; The software is delivered "AS IS" without warranty or condition of any ; kind, either express, implied or statutory. This includes without ; limitation any warranty or condition with respect to merchantability or ; fitness for any particular purpose, or against the infringements of ; intellectual property rights of others. ;----------------------------------------------------------------------------- ;- File source : Cstartup.s79 ;- Object : Generic CStartup for IAR No Use REMAP ;- Compilation flag : None ;- ;- 1.0 15/Jun/04 JPP : Creation ;- 1.1 01/Apr/05 JPP : save SPSR ;------------------------------------------------------------------------------
#include "AT91SAM7S32_inc.h"
;------------------------------------------------------------------------------ ;- Area Definition ;------------------------------------------------------------------------------
;--------------------------------------------------------------- ; ?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. ;-------------------------------------------------------------
PROGRAM ?RESET RSEG INTRAMSTART_REMAP RSEG INTRAMEND_REMAP
RSEG ICODE:CODE:ROOT(2) CODE32 ; Always ARM mode after reset org 0 reset ;------------------------------------------------------------------------------ ;- Exception vectors ;-------------------- ;- These vectors can be read at address 0 or at RAM address ;- They ABSOLUTELY requires to be in relative addresssing mode in order to ;- guarantee a valid jump. For the moment, all are just looping. ;- If an exception occurs before remap, this would result in an infinite loop. ;- To ensure if a exeption occurs before start application to infinite loop. ;------------------------------------------------------------------------------
B InitReset ; 0x00 Reset handler undefvec: B undefvec ; 0x04 Undefined Instruction swivec: B swivec ; 0x08 Software Interrupt pabtvec: B pabtvec ; 0x0C Prefetch Abort dabtvec: B dabtvec ; 0x10 Data Abort rsvdvec: B rsvdvec ; 0x14 reserved irqvec: B IRQ_Handler_Entry ; 0x18 IRQ fiqvec: ; 0x1c FIQ ;------------------------------------------------------------------------------ ;- Function : FIQ_Handler_Entry ;- Treatments : FIQ Controller Interrupt Handler. ;- Called Functions : AIC_FVR[interrupt] ;------------------------------------------------------------------------------
FIQ_Handler_Entry:
;- Switch in SVC/User Mode to allow User Stack access for C code ; because the FIQ is not yet acknowledged
;- Save and r0 in FIQ_Register mov r9,r0 ldr r0 , [r8, #AIC_FVR] msr CPSR_c,#I_BIT | F_BIT | ARM_MODE_SVC ;- Save scratch/used registers and LR in User Stack stmfd sp!, { r1-r3, r12, lr}
;- Branch to the routine pointed by the AIC_FVR mov r14, pc bx r0
;- Restore scratch/used registers and LR from User Stack ldmia sp!, { r1-r3, r12, lr}
;- Leave Interrupts disabled and switch back in FIQ mode msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ
;- Restore the R0 ARM_MODE_SVC register mov r0,r9
;- Restore the Program Counter using the LR_fiq directly in the PC subs pc,lr,#4
InitReset: ;------------------------------------------------------------------------------ ;- Low level Init (PMC, AIC, ? ....) by C function AT91F_LowLevelInit ;------------------------------------------------------------------------------ EXTERN AT91F_LowLevelInit
#define __iramend SFB(INTRAMEND_REMAP)
;- minumum C initialization ;- call AT91F_LowLevelInit( void)
ldr r13,=__iramend ; temporary stack in internal RAM ;--Call Low level init function in ABSOLUTE through the Interworking ldr r0,=AT91F_LowLevelInit mov lr, pc bx r0 ;------------------------------------------------------------------------------ ;- Stack Sizes Definition ;------------------------ ;- Interrupt Stack requires 2 words x 8 priority level x 4 bytes when using ;- the vectoring. This assume that the IRQ management. ;- The Interrupt Stack must be adjusted depending on the interrupt handlers. ;- Fast Interrupt not requires stack If in your application it required you must ;- be definehere. ;- The System stack size is not defined and is limited by the free internal ;- SRAM. ;------------------------------------------------------------------------------
;------------------------------------------------------------------------------ ;- Top of Stack Definition ;------------------------- ;- Interrupt and Supervisor Stack are located at the top of internal memory in ;- order to speed the exception handling context saving and restoring. ;- ARM_MODE_SVC (Application, C) Stack is located at the top of the external memory. ;------------------------------------------------------------------------------
IRQ_STACK_SIZE EQU (3*8*4) ; 3 words per interrupt priority level
ARM_MODE_FIQ EQU 0x11 ARM_MODE_IRQ EQU 0x12 ARM_MODE_SVC EQU 0x13
I_BIT EQU 0x80 F_BIT EQU 0x40
;------------------------------------------------------------------------------ ;- Setup the stack for each mode ;------------------------------- ldr r0, =__iramend
;- Set up Fast Interrupt Mode and set FIQ Mode Stack msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT ;- Init the FIQ register ldr r8, =AT91C_BASE_AIC
;- Set up Interrupt Mode and set IRQ Mode Stack msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT mov r13, r0 ; Init stack IRQ sub r0, r0, #IRQ_STACK_SIZE
;- Enable interrupt & Set up Supervisor Mode and set Supervisor Mode Stack msr CPSR_c, #ARM_MODE_SVC mov r13, r0
;--------------------------------------------------------------- ; ?CSTARTUP ;--------------------------------------------------------------- EXTERN __segment_init EXTERN main ; Initialize segments. ; __segment_init is assumed to use ; instruction set and to be reachable by BL from the ICODE segment ; (it is safest to link them in segment ICODE). ldr r0,=__segment_init mov lr, pc bx r0
PUBLIC __main ?jump_to_main: ldr lr,=?call_exit ldr r0,=main __main: bx r0
;------------------------------------------------------------------------------ ;- Loop for ever ;--------------- ;- End of application. Normally, never occur. ;- Could jump on Software Reset ( B 0x0 ). ;------------------------------------------------------------------------------ ?call_exit: End b End
;------------------------------------------------------------------------------ ;- Manage exception ;--------------- ;- This module The exception must be ensure in ARM mode ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ ;- Function : IRQ_Handler_Entry ;- Treatments : IRQ Controller Interrupt Handler. ;- Called Functions : AIC_IVR[interrupt] ;------------------------------------------------------------------------------ IRQ_Handler_Entry:
;- Manage Exception Entry ;- Adjust and save LR_irq in IRQ stack sub lr, lr, #4 stmfd sp!, {lr}
;- Save SPSR need to be saved for nested interrupt mrs r14, SPSR stmfd sp!, {r14}
;- Save and r0 in IRQ stack stmfd sp!, {r0}
;- Write in the IVR to support Protect Mode ;- No effect in Normal Mode ;- De-assert the NIRQ and clear the source in Protect Mode ldr r14, =AT91C_BASE_AIC ldr r0 , [r14, #AIC_IVR] str r14, [r14, #AIC_IVR]
;- Enable Interrupt and Switch in Supervisor Mode msr CPSR_c, #ARM_MODE_SVC
;- Save scratch/used registers and LR in User Stack stmfd sp!, { r1-r3, r12, r14}
;- Branch to the routine pointed by the AIC_IVR mov r14, pc bx r0
;- Restore scratch/used registers and LR from User Stack ldmia sp!, { r1-r3, r12, r14}
;- Disable Interrupt and switch back in IRQ mode msr CPSR_c, #I_BIT | ARM_MODE_IRQ
;- Mark the End of Interrupt on the AIC ldr r14, =AT91C_BASE_AIC str r14, [r14, #AIC_EOICR]
;- Restore R0 ldmia sp!, {r0}
;- Restore SPSR_irq and r0 from IRQ stack ldmia sp!, {r14} msr SPSR_cxsf, r14
;- Restore adjusted LR_irq from IRQ stack directly in the PC ldmia sp!, {pc}^ ;--------------------------------------------------------------- ; ?EXEPTION_VECTOR ; This module is only linked if needed for closing files. ;--------------------------------------------------------------- PUBLIC AT91F_Default_FIQ_handler PUBLIC AT91F_Default_IRQ_handler PUBLIC AT91F_Spurious_handler
CODE32 ; Always ARM mode after exeption
AT91F_Default_FIQ_handler b AT91F_Default_FIQ_handler
AT91F_Default_IRQ_handler b AT91F_Default_IRQ_handler
AT91F_Spurious_handler b AT91F_Spurious_handler
ENDMOD
END
Сообщение отредактировал IgorKossak - Jun 26 2011, 15:39
Причина редактирования: научитесь оформлять в [codebox]
|
|
|
|
|
Jun 20 2011, 20:59
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(taoga @ Jun 20 2011, 22:30)  Мне нужен файл board_cstartup_iar.s с (IAR 5.xx) с инициализацией обработчика по умолчанию для FIQ и соответствующего стека. Чтобы он функционально был аналогичен файлу Cstartup.s79 из примера AT91SAM7S32-Interrupt-IAR4_11A-1_1-FIQ.zip. Если хотите получить аналог, просто скопируйте в свой стартап FIQ_Handler_Entry, заменив в нем ARM_MODE_SVC на ARM_MODE_SYS, и добавьте к инициализации стеков Код ;- Set up Fast Interrupt Mode and set FIQ Mode Stack msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT ;- Init the FIQ register ldr r8, =AT91C_BASE_AIC В строке "FIQ_Addr: DCD FIQ_Handler" замените FIQ_Handler на FIQ_Handler_Entry. А вообще, это пример того, как не надо работать с FIQ. Правильно будет добавить инициализацию стека FIQ (в примере используется SVC), дурацкую обертку FIQ_Handler_Entry упразднить как класс, код разместить начиная непосредственно с адреса вектора.
|
|
|
|
|
Jun 21 2011, 07:47
|
Участник

Группа: Участник
Сообщений: 51
Регистрация: 8-10-09
Пользователь №: 52 809

|
добавьте к инициализации стеков Код ;- Set up Fast Interrupt Mode and set FIQ Mode Stack msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT ;- Init the FIQ register ldr r8, =AT91C_BASE_AIC В строке "FIQ_Addr: DCD FIQ_Handler" замените FIQ_Handler на FIQ_Handler_Entry. Добавил этот код к инициализации стека, получил ошибку. Код label: LDR r0, =LowLevelInit LDR r4, =SFE(CSTACK) MOV sp, r4 MOV lr, pc BX r0
/* Set up Fast Interrupt Mode and set FIQ Mode Stack */ msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT /* Init the FIQ register */ ldr r8, =AT91C_BASE_AIC /* Set up the interrupt stack pointer. */ MSR cpsr_c, #ARM_MODE_IRQ | I_BIT | F_BIT ; Change the mode LDR sp, =SFE(IRQ_STACK)
/* Set up the SVC stack pointer. */ MSR cpsr_c, #ARM_MODE_SVC | F_BIT ; Change the mode LDR sp, =SFE(CSTACK)
Building configuration: at91sam9xe-ek - at91sam9xe256_sram Updating build tree... board_cstartup_iar.s Linking Error[Lp002]: relocation failed: out of range or illegal value Kind : R_ARM_LDR_PC_G0[0x4] Location: mem:0x304ff4 "resetHandler" + 0x1c Module: D:\Stas\Atmel\cc2400_arm9_1\at91sam9xe-ek\usb-device-core-project\ewp\at91sam9xe256_sram\Obj\board_cstartup_iar.o Section: 9 (.cstartup) Offset: 0x1c Target : mem:0x300000 "resetVector" Module: D:\Stas\Atmel\cc2400_arm9_1\at91sam9xe-ek\usb-device-core-project\ewp\at91sam9xe256_sram\Obj\board_cstartup_iar.o Section: 8 (.vectors) Offset: 0x0 Error while running Linker В документации и на форуме, написано, что нужно добавить в board_cstartup_iar.s этот код Код ldr PC, [PC,# -0xF20] ;AIC direct Я это сделал, стал вызываться нужный обработчик прерывания, но после него программа уходит на перезагрузку. Как правильно оформить обработчик в этом случае?
|
|
|
|
|
Jun 21 2011, 12:28
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(taoga @ Jun 21 2011, 11:47)  Добавил этот код к инициализации стека, получил ошибку. Надо полагать, он ругается на AT91C_BASE_AIC. Добавьте соответствующий ".inc" Цитата(taoga @ Jun 21 2011, 11:47)  В документации и на форуме, написано, что нужно добавить в board_cstartup_iar.s этот код Код ldr PC, [PC,# -0xF20] ;AIC direct Я это сделал, стал вызываться нужный обработчик прерывания, но после него программа уходит на перезагрузку. Как правильно оформить обработчик в этом случае? Оформление обработчиков прерываний посмотрите в IAR'овской документации. Не помню, правда, "умеет" ли он FIQ, или там общий вариант IRQ/FIQ. В последнем случае часть преимуществ режима FIQ сходит на нет.
|
|
|
|
|
Jun 22 2011, 05:48
|
Участник

Группа: Участник
Сообщений: 51
Регистрация: 8-10-09
Пользователь №: 52 809

|
[quote name='aaarrr' date='Jun 21 2011, 16:28' post='942726'] Надо полагать, он ругается на AT91C_BASE_AIC. Добавьте соответствующий ".inc"
Ругается не на AT91C_BASE_AIC. В irqHandler уже используется данный идентификатор.
|
|
|
|
|
Jun 23 2011, 18:34
|
Участник

Группа: Участник
Сообщений: 51
Регистрация: 8-10-09
Пользователь №: 52 809

|
В 5-м Iar'e у меня возникли проблемы со стандартным драйвером USB. Пример basic-usb... скорость передачи на хост в 4 раза меньше обычной для full speed usb. Поставил iar 6.3, загрузил тот же пример, проблемы со скоростью USB исчезли. Добавил в таблицу векторов стартапа "ldr PC, [PC,# -0xF20] ;AIC direct" для FIQ. Оформил обработчик прерывания макросами __fiq __arm. Прерывание вручную генерируется, от внешнего источника никак. Обработчик прерывания отрабатывает нормально. Плюнул. Переделал схему на IRQ2, прерывание срабатывает от внешнего источника. Только частота срабатывания прерывания 1 МГц оказалась не по зубам этому контроллеру. Поэтому запустил второй SPI для непрерывного приема данных с использованием PDC. Принятые данные дальше передаются по USB. Так вот при начале передачи по USB гробится прием данных по SPI1. Взял исходный код для работы с USB из проекта для ARM7, без использования прерываний, все заработало. Поэтому вопрос: У всех такие грабли с sam9xe или его никто не использует? Нужно сообщать о найденных проблемах в Atmel?
|
|
|
|
|
Jun 24 2011, 18:15
|
Участник

Группа: Участник
Сообщений: 51
Регистрация: 8-10-09
Пользователь №: 52 809

|
Цитата(aaarrr @ Jun 24 2011, 00:55)  А они разве найдены? Формулировка "при начале передачи по USB гробится прием данных по SPI1" их явно не устроит. Ищите источник проблем в своем софте. Может вы подскажите? У меня SPI0 используется для управления приемопередатчиком, по SPI1 с использованием PDC, принимаются данные. Когда я не передаю принятые данные по USB все работает без сбоев. Вставляю код драйвера USB (не знаю чьей разработки Atmel, IAR ...) непрерывный прием прекращается. По USB передается только первый принятый буфер, хотя установлены в PDC два буфера, соответственно срабатывает только одно прерывание ENDRX, и не приходит прерывание RXBUF, хотя если прием прервался, то должно. Убираю код драйвера, вставляю код из старого проекта для IAR 4.x и sam7s, данные непрерывно принимаются и передаются по USB. Код в общем то почти совпадает, за исключением того, что в новом драйвере используются прерывания, и добавлен соответствующий код в обработчик прерываний. И где ошибки в моем коде, когда я никоим образом в своих обработчиках не касаюсь регистров контроллера прерывания (за исключением кода из обработчика в стартапе, который я не менял). Лично мной бы ценились практические советы, подкрепленные соответствующим кодом, а не теоретические изыскания. Если бы в примерах на sam9xe были отображены такие простые вопросы как использование прерывания FIQ, то я бы не задавал дурацкие вопросы вам, службе поддержки Atmel (которая отправила меня на www.at91.com) и at91.com, в котором меня отправили обратно к примерам и документации от Atmel.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|