|
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?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|