|
SPI at91sam7s, как правильно выйти из прерывания? |
|
|
|
Jul 8 2010, 04:59
|
Участник

Группа: Участник
Сообщений: 50
Регистрация: 2-12-09
Пользователь №: 54 010

|
есть проблема. SPI на выдачу работает нормально, но как только создаю прерывание по появлению данных в RDR регистре все зависает по окончанию выполнения функции, вектор которой прописан в регистре AIC_SVR для AT91C_ID_SPI c нулевым приоритетом. по идее нужно указать точку окончания команды прерывания записав в AIC_EOICR соответствующий бит и сбросить команды прерывания записью бита в AIC_ICCR. вроде все сделал как описано в мануале, но один фиК после выполнения команды прерывания МК зависает и чегото там ждет, вот только чего??? код инициализации прерывания: Код AIC_ConfigureIT(AT91C_ID_SPI, 0, ISR_SPI); *AT91C_SPI_IER = AT91C_SPI_RDRF; AIC_EnableIT(AT91C_ID_SPI); код вызываемой функции: CODE void ISR_SPI(void) { unsigned int status; // *AT91C_SPI_IDR = AT91C_SPI_RDRF; status = dwSPITemp = (*AT91C_SPI_SR & 0xff);
if (((status & AT91C_SPI_RDRF) != 0)) {
dwSPITemp = *AT91C_SPI_RDR; // dwSPITemp (UINT32)
*AT91C_AIC_EOICR = 0xffffffff; // на всякий случай все регистры обнуляю *AT91C_AIC_ICCR = 0xffffffff; // AIC_ConfigureIT(AT91C_ID_SPI, 0, ISR_SPI); // *AT91C_SPI_IER = AT91C_SPI_RDRF; // AIC_EnableIT(AT91C_ID_SPI); } } как видно, пробовал заново сконфигурировать прерывание и вырубать прерывание на момент выполнения функции. результат один - стопорится и все тут =(. подскажите пожалуйста где ошибка и куда копать. может как новичок гдето делаю "глобальную" ошибку?
|
|
|
|
|
 |
Ответов
(1 - 5)
|
Jul 12 2010, 04:25
|
Участник

Группа: Участник
Сообщений: 50
Регистрация: 2-12-09
Пользователь №: 54 010

|
Цитата(aaarrr @ Jul 8 2010, 12:37)  Что прописано в стартапе (вектор прерывания, "обертки")? там стандартный атмеловский код из примеров: CODE void AIC_ConfigureIT( unsigned int source, unsigned int mode, void (*handler)(void)) { // Disable the interrupt first AT91C_BASE_AIC->AIC_IDCR = 1 << source;
// Configure mode and handler AT91C_BASE_AIC->AIC_SMR[source] = mode; AT91C_BASE_AIC->AIC_SVR[source] = (unsigned int) handler;
// Clear interrupt AT91C_BASE_AIC->AIC_ICCR = 1 << source; } ничего нового я туда не придумывал, да и не вижу особой надобности... может конечно и ошибаюсь. возможно у SPI по умолчанию отключено прерывание на прием при установке режима "Мастер"? но с другой стороны, если мастер не получил данных(т.е. в RDR все нули), то и прерывания не будет. не так-ли? среда: Кейл 4, RTX-либы, атмеловские примеры.
|
|
|
|
|
Jul 12 2010, 11:33
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(SavageForest @ Jul 8 2010, 08:59)  по идее нужно указать точку окончания команды прерывания записав в AIC_EOICR соответствующий бит и сбросить команды прерывания записью бита в AIC_ICCR Для начала нужно установить, не производится ли запись AIC_EOICR в обертке в стартапе. AIC_ICCR в данном случае писать смысла не имеет вообще - прерывание настроено на работу по уровню. Писать Код *AT91C_AIC_ICCR = 0xffffffff; нельзя ни в коем случае - получите "зависшие" прерывания для источников, работающих по фронту. Принудительно сбрасывать работающее по фронту прерывание нет необходимости, AIC делает это автоматически при чтении AIC_IVR. Цитата(SavageForest @ Jul 12 2010, 08:25)  там стандартный атмеловский код из примеров Во-первых, это не стартап. Во-вторых, "стандартного" кода, стартапов и прочего не существует. Нужно знать, что написано именно в том стартапе, что подключен к вашему проекту. Иначе никак нельзя будет выяснить, нужно ли делать запись AIC_EOICR в процедуре обработки прерывания и нужно ли добавлять к этой процедуре модификатор __irq. (Скорее всего, нужно и то и другое).
|
|
|
|
|
Jul 20 2010, 10:59
|
Участник

Группа: Участник
Сообщений: 50
Регистрация: 2-12-09
Пользователь №: 54 010

|
вот. скопипастил целиком. CODE ;/*****************************************************************************/ ;/* SAM7.S: Startup file for Atmel AT91SAM7 device series */ ;/*****************************************************************************/ ;/* <<< Use Configuration Wizard in Context Menu >>> */ ;/*****************************************************************************/ ;/* This file is part of the uVision/ARM development tools. */ ;/* Copyright © 2005-2008 Keil Software. All rights reserved. */ ;/* This software may only be used under the terms of a valid, current, */ ;/* end user licence from KEIL for a compatible version of KEIL software */ ;/* development tools. Nothing else gives you the right to use this software. */ ;/*****************************************************************************/ ; * The SAM7.S code is executed after CPU Reset. This file may be ; * translated with the following SET symbols. In uVision these SET ; * symbols are entered under Options - ASM - Define. ; * ; * REMAP: when set the startup code remaps exception vectors from ; * on-chip RAM to address 0. ; * ; * RAM_INTVEC: when set the startup code copies exception vectors ; * from on-chip Flash to on-chip RAM. ; */
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
Mode_USR EQU 0x10 Mode_FIQ EQU 0x11 Mode_IRQ EQU 0x12 Mode_SVC EQU 0x13 Mode_ABT EQU 0x17 Mode_UND EQU 0x1B Mode_SYS EQU 0x1F
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
; Internal Memory Base Addresses FLASH_BASE EQU 0x00100000 RAM_BASE EQU 0x00200000
;// <h> Stack Configuration (Stack Sizes in Bytes) ;// <o0> Undefined Mode <0x0-0xFFFFFFFF:8> ;// <o1> Supervisor Mode <0x0-0xFFFFFFFF:8> ;// <o2> Abort Mode <0x0-0xFFFFFFFF:8> ;// <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:8> ;// <o4> Interrupt Mode <0x0-0xFFFFFFFF:8> ;// <o5> User/System Mode <0x0-0xFFFFFFFF:8> ;// </h>
UND_Stack_Size EQU 0x00000000 SVC_Stack_Size EQU 0x00000020 ABT_Stack_Size EQU 0x00000000 FIQ_Stack_Size EQU 0x00000000 IRQ_Stack_Size EQU 0x00000040 USR_Stack_Size EQU 0x00000050
ISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ FIQ_Stack_Size + IRQ_Stack_Size)
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE USR_Stack_Size __initial_sp SPACE ISR_Stack_Size
Stack_Top
;// <h> Heap Configuration ;// <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF> ;// </h>
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit
; Reset Controller (RSTC) definitions RSTC_BASE EQU 0xFFFFFD00 ; RSTC Base Address RSTC_MR EQU 0x08 ; RSTC_MR Offset
;/* ;// <e> Reset Controller (RSTC) ;// <o1.0> URSTEN: User Reset Enable ;// <i> Enables NRST Pin to generate Reset ;// <o1.8..11> ERSTL: External Reset Length <0-15> ;// <i> External Reset Time in 2^(ERSTL+1) Slow Clock Cycles ;// </e> ;*/ RSTC_SETUP EQU 1 RSTC_MR_Val EQU 0xA5000401
; Embedded Flash Controller (EFC) definitions EFC_BASE EQU 0xFFFFFF00 ; EFC Base Address EFC0_FMR EQU 0x60 ; EFC0_FMR Offset EFC1_FMR EQU 0x70 ; EFC1_FMR Offset
;// <e> Embedded Flash Controller 0 (EFC0) ;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255> ;// <i> Number of Master Clock Cycles in 1us ;// <o1.8..9> FWS: Flash Wait State ;// <0=> Read: 1 cycle / Write: 2 cycles ;// <1=> Read: 2 cycle / Write: 3 cycles ;// <2=> Read: 3 cycle / Write: 4 cycles ;// <3=> Read: 4 cycle / Write: 4 cycles ;// </e> EFC0_SETUP EQU 1 EFC0_FMR_Val EQU 0x00320100
;// <e> Embedded Flash Controller 1 (EFC1) ;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255> ;// <i> Number of Master Clock Cycles in 1us ;// <o1.8..9> FWS: Flash Wait State ;// <0=> Read: 1 cycle / Write: 2 cycles ;// <1=> Read: 2 cycle / Write: 3 cycles ;// <2=> Read: 3 cycle / Write: 4 cycles ;// <3=> Read: 4 cycle / Write: 4 cycles ;// </e> EFC1_SETUP EQU 0 EFC1_FMR_Val EQU 0x00320100
; Watchdog Timer (WDT) definitions WDT_BASE EQU 0xFFFFFD40 ; WDT Base Address WDT_MR EQU 0x04 ; WDT_MR Offset
;// <e> Watchdog Timer (WDT) ;// <o1.0..11> WDV: Watchdog Counter Value <0-4095> ;// <o1.16..27> WDD: Watchdog Delta Value <0-4095> ;// <o1.12> WDFIEN: Watchdog Fault Interrupt Enable ;// <o1.13> WDRSTEN: Watchdog Reset Enable ;// <o1.14> WDRPROC: Watchdog Reset Processor ;// <o1.28> WDDBGHLT: Watchdog Debug Halt ;// <o1.29> WDIDLEHLT: Watchdog Idle Halt ;// <o1.15> WDDIS: Watchdog Disable ;// </e> WDT_SETUP EQU 1 WDT_MR_Val EQU 0x00008000
; Power Mangement Controller (PMC) definitions PMC_BASE EQU 0xFFFFFC00 ; PMC Base Address PMC_MOR EQU 0x20 ; PMC_MOR Offset PMC_MCFR EQU 0x24 ; PMC_MCFR Offset PMC_PLLR EQU 0x2C ; PMC_PLLR Offset PMC_MCKR EQU 0x30 ; PMC_MCKR Offset PMC_SR EQU 0x68 ; PMC_SR Offset PMC_MOSCEN EQU (1<<0) ; Main Oscillator Enable PMC_OSCBYPASS EQU (1<<1) ; Main Oscillator Bypass PMC_OSCOUNT EQU (0xFF<<8) ; Main OScillator Start-up Time PMC_DIV EQU (0xFF<<0) ; PLL Divider PMC_PLLCOUNT EQU (0x3F<<8) ; PLL Lock Counter PMC_OUT EQU (0x03<<14) ; PLL Clock Frequency Range PMC_MUL EQU (0x7FF<<16) ; PLL Multiplier PMC_USBDIV EQU (0x03<<28) ; USB Clock Divider PMC_CSS EQU (3<<0) ; Clock Source Selection PMC_PRES EQU (7<<2) ; Prescaler Selection PMC_MOSCS EQU (1<<0) ; Main Oscillator Stable PMC_LOCK EQU (1<<2) ; PLL Lock Status PMC_MCKRDY EQU (1<<3) ; Master Clock Status
;// <e> Power Mangement Controller (PMC) ;// <h> Main Oscillator ;// <o1.0> MOSCEN: Main Oscillator Enable ;// <o1.1> OSCBYPASS: Oscillator Bypass ;// <o1.8..15> OSCCOUNT: Main Oscillator Startup Time <0-255> ;// </h> ;// <h> Phase Locked Loop (PLL) ;// <o2.0..7> DIV: PLL Divider <0-255> ;// <o2.16..26> MUL: PLL Multiplier <0-2047> ;// <i> PLL Output is multiplied by MUL+1 ;// <o2.14..15> OUT: PLL Clock Frequency Range ;// <0=> 80..160MHz <1=> Reserved ;// <2=> 150..220MHz <3=> Reserved ;// <o2.8..13> PLLCOUNT: PLL Lock Counter <0-63> ;// <o2.28..29> USBDIV: USB Clock Divider ;// <0=> None <1=> 2 <2=> 4 <3=> Reserved ;// </h> ;// <o3.0..1> CSS: Clock Source Selection ;// <0=> Slow Clock ;// <1=> Main Clock ;// <2=> Reserved ;// <3=> PLL Clock ;// <o3.2..4> PRES: Prescaler ;// <0=> None ;// <1=> Clock / 2 <2=> Clock / 4 ;// <3=> Clock / 8 <4=> Clock / 16 ;// <5=> Clock / 32 <6=> Clock / 64 ;// <7=> Reserved ;// </e> PMC_SETUP EQU 1 PMC_MOR_Val EQU 0x00000601 PMC_PLLR_Val EQU 0x00191C05 PMC_MCKR_Val EQU 0x00000007
PRESERVE8
; Area Definition and Entry Point ; Startup Code must be linked first at Address at which it expects to run.
AREA RESET, CODE, READONLY ARM
; Exception Vectors ; Mapped to Address 0. ; Absolute addressing mode must be used. ; Dummy Handlers are implemented as infinite loops which can be modified.
Vectors LDR PC,Reset_Addr LDR PC,Undef_Addr LDR PC,SWI_Addr LDR PC,PAbt_Addr LDR PC,DAbt_Addr NOP ; Reserved Vector ; LDR PC,IRQ_Addr LDR PC,[PC,#-0xF20] ; Vector From AIC_IVR ; LDR PC,FIQ_Addr LDR PC,[PC,#-0xF20] ; Vector From AIC_FVR
Reset_Addr DCD Reset_Handler Undef_Addr DCD Undef_Handler SWI_Addr DCD SWI_Handler PAbt_Addr DCD PAbt_Handler DAbt_Addr DCD DAbt_Handler DCD 0 ; Reserved Address IRQ_Addr DCD IRQ_Handler FIQ_Addr DCD FIQ_Handler
IMPORT SWI_Handler
Undef_Handler B Undef_Handler ;SWI_Handler B SWI_Handler ; Part of RTL PAbt_Handler B PAbt_Handler DAbt_Handler B DAbt_Handler IRQ_Handler B IRQ_Handler FIQ_Handler B FIQ_Handler
; Reset Handler
EXPORT Reset_Handler Reset_Handler
; Setup RSTC IF RSTC_SETUP != 0 LDR R0, =RSTC_BASE LDR R1, =RSTC_MR_Val STR R1, [R0, #RSTC_MR] ENDIF
; Setup EFC0 IF EFC0_SETUP != 0 LDR R0, =EFC_BASE LDR R1, =EFC0_FMR_Val STR R1, [R0, #EFC0_FMR] ENDIF
; Setup EFC1 IF EFC1_SETUP != 0 LDR R0, =EFC_BASE LDR R1, =EFC1_FMR_Val STR R1, [R0, #EFC1_FMR] ENDIF
; Setup WDT IF WDT_SETUP != 0 LDR R0, =WDT_BASE LDR R1, =WDT_MR_Val STR R1, [R0, #WDT_MR] ENDIF
; Setup PMC IF PMC_SETUP != 0 LDR R0, =PMC_BASE
; Setup Main Oscillator LDR R1, =PMC_MOR_Val STR R1, [R0, #PMC_MOR]
; Wait until Main Oscillator is stablilized IF (PMC_MOR_Val:AND:PMC_MOSCEN) != 0 MOSCS_Loop LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_MOSCS BEQ MOSCS_Loop ENDIF
; Setup the PLL IF (PMC_PLLR_Val:AND:PMC_MUL) != 0 LDR R1, =PMC_PLLR_Val STR R1, [R0, #PMC_PLLR]
; Wait until PLL is stabilized PLL_Loop LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_LOCK BEQ PLL_Loop ENDIF
; Select Clock IF (PMC_MCKR_Val:AND:PMC_CSS) == 1 ; Main Clock Selected LDR R1, =PMC_MCKR_Val AND R1, #PMC_CSS STR R1, [R0, #PMC_MCKR] WAIT_Rdy1 LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_MCKRDY BEQ WAIT_Rdy1 LDR R1, =PMC_MCKR_Val STR R1, [R0, #PMC_MCKR] WAIT_Rdy2 LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_MCKRDY BEQ WAIT_Rdy2 ELIF (PMC_MCKR_Val:AND:PMC_CSS) == 3 ; PLL Clock Selected LDR R1, =PMC_MCKR_Val AND R1, #PMC_PRES STR R1, [R0, #PMC_MCKR] WAIT_Rdy1 LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_MCKRDY BEQ WAIT_Rdy1 LDR R1, =PMC_MCKR_Val STR R1, [R0, #PMC_MCKR] WAIT_Rdy2 LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_MCKRDY BEQ WAIT_Rdy2 ENDIF ; Select Clock ENDIF ; PMC_SETUP
; Copy Exception Vectors to Internal RAM
IF :DEF:RAM_INTVEC ADR R8, Vectors ; Source LDR R9, =RAM_BASE ; Destination LDMIA R8!, {R0-R7} ; Load Vectors STMIA R9!, {R0-R7} ; Store Vectors LDMIA R8!, {R0-R7} ; Load Handler Addresses STMIA R9!, {R0-R7} ; Store Handler Addresses ENDIF
; Remap on-chip RAM to address 0
MC_BASE EQU 0xFFFFFF00 ; MC Base Address MC_RCR EQU 0x00 ; MC_RCR Offset
IF :DEF:REMAP LDR R0, =MC_BASE MOV R1, #1 STR R1, [R0, #MC_RCR] ; Remap ENDIF
; Setup Stack for each mode
LDR R0, =Stack_Top
; Enter Undefined Instruction Mode and set its Stack Pointer MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit MOV SP, R0 SUB R0, R0, #UND_Stack_Size
; Enter Abort Mode and set its Stack Pointer MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit MOV SP, R0 SUB R0, R0, #ABT_Stack_Size
; Enter FIQ Mode and set its Stack Pointer MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit MOV SP, R0 SUB R0, R0, #FIQ_Stack_Size
; Enter IRQ Mode and set its Stack Pointer MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit MOV SP, R0 SUB R0, R0, #IRQ_Stack_Size
; Enter Supervisor Mode and set its Stack Pointer MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit MOV SP, R0 SUB R0, R0, #SVC_Stack_Size
; Enter User Mode and set its Stack Pointer MSR CPSR_c, #Mode_USR IF :DEF:__MICROLIB
EXPORT __initial_sp
ELSE
MOV SP, R0 SUB SL, SP, #USR_Stack_Size
ENDIF
; Enter the C code
IMPORT __main LDR R0, =__main BX R0
IF :DEF:__MICROLIB
EXPORT __heap_base EXPORT __heap_limit
ELSE ; User Initial Stack & Heap AREA |.text|, CODE, READONLY
IMPORT __use_two_region_memory EXPORT __user_initial_stackheap __user_initial_stackheap
LDR R0, = Heap_Mem LDR R1, =(Stack_Mem + USR_Stack_Size) LDR R2, = (Heap_Mem + Heap_Size) LDR R3, = Stack_Mem BX LR ENDIF END
Сообщение отредактировал SavageForest - Jul 20 2010, 11:04
|
|
|
|
|
Jul 20 2010, 12:53
|

Гуру
     
Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515

|
__irq __arm void ISR_SPI(void) Писать в EOICR надо. Код Vectors LDR PC,Reset_Addr LDR PC,Undef_Addr LDR PC,SWI_Addr LDR PC,PAbt_Addr LDR PC,DAbt_Addr NOP ; Reserved Vector ; LDR PC,IRQ_Addr LDR PC,[PC,#-0xF20] ; Vector From AIC_IVR ; LDR PC,FIQ_Addr LDR PC,[PC,#-0xF20] ; Vector From AIC_FVRVectors И не дай бог убирать закомментированное в стартапе.
--------------------
On the road again (Canned Heat)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|