реклама на сайте
подробности

 
 
> Вложенные прерывания, GCC и ARM7
Novichok1
сообщение Mar 1 2010, 05:08
Сообщение #1


Участник
*

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



Доброго времени суток!
Работаю с платой LPC2478, требуется реализовать вложенные (nested) прерывания.
Нарыл несколько статей на эту тему, но пока ни один метод не запахал.
Тестирую прерывания таким образом:

Код
void TestInterrupts::TestTimers()
{
    myPrintf("\nSTART TestTimers()\n");

    Timer0VICInit(Timer0ISR);
    Timer1VICInit(Timer1ISR);
    Timer1StartWithInt(1000);

    myPrintf("\nEND TestTimers()\n");
}

void TestInterrupts::Timer0ISR()
{
    T0IR  = TIR_MR0_INT; // reset interrrupt flags
    myPrintf("\nTimer0ISR()\n");
    // Dummy write to VIC to signal end of interrupt
    VICVectAddr = 0x00000000;
}

void TestInterrupts::Timer1ISR()
{
    IENABLE;

    T1IR  = TIR_MR0_INT; // reset interrrupt flags
    myPrintf("\nSTART Timer1ISR()\n");
        Timer0StartWithInt(5000);
    volatile tU8 dummy = 0;
    while(1)
    {
        dummy = 0;
    }
    myPrintf("\nEND Timer1ISR()\n");
    IDISABLE;
    // Dummy write to VIC to signal end of interrupt
    VICVectAddr = 0x00000000;
}


Где в качестве IENABLE пробовал разные последовательности ассемблерных команд, вычитанных с разных статей:
Код
// FROM Nesting of interrupts in the LPC2000 (AN10381)
#define IENABLE /* Nested Interrupts Entry */ \
        __asm__ ("MRS LR, SPSR"); /* Copy SPSR_irq to LR */ \
        __asm__ ("STMFD SP!, {LR}"); /* Save SPSR_irq */ \
        __asm__ ("MSR CPSR_c, #0x1F"); /* Enable IRQ (Sys Mode) */ \
        __asm__ ("STMFD SP!, {LR}"); /* Save LR */ \

Код
// FROM Real-time processing with the Philips LPC ARM microcontroller; using GCC and the MicroC/OS-II RTOS.
#define IENABLE /* Nested Interrupts Entry */ \
        __asm__ ("sub lr, lr, #4"); /* (1) Save IRQ context, including the APCS registers, and r4-6 */ \
        __asm__ ("stmfd sp!, {r0-r6, ip, lr}"); \
        __asm__ ("mrs r4, spsr"); /* (2) Save the SPSR_irq register */ \
        __asm__ ("ldr r5, =0xFFFFFF00"); /* (3) Read the VICVectAddr */ \
        __asm__ ("ldr r6, [r5]"); \
        __asm__ ("msr cpsr_c, 0x1F"); /* (4) Change to SYS mode and enable IRQ */ \
        __asm__ ("stmfd sp!, {lr}"); /* (5) Save the banked SYS mode link register */ \


То есть, на консоли должно появиться
Цитата
START TestTimers()
END TestTimers()
START Timer1ISR()
START Timer0ISR()


А на самом деле последняя строка не выводиться, что говорит о невхождении в обработчик вложенного прерывания Timer0.
Так вот, первый мой вопрос, какая же все таки последовательной команд должна быть в прологе и эпилоге обработчика для LPC2478?

И еще, во втором случае IENABLE полное описание вхождения и вывода их вложенных прерываний выглядит так:
Цитата
nested_irq_isr:
/* (1) Save IRQ context, including the APCS registers, and r4-6 */
sub lr, lr, #4
stmfd sp!, {r0-r6, ip, lr}
/* (2) Save the SPSR_irq register */
mrs r4, spsr
/* (3) Read the VICVectAddr */
ldr r5, VICVECTADDR
ldr r6, [r5]
/* (4) Change to SYS mode and enable IRQ */
msr cpsr_c, #SYS_MODE
/* (5) Save the banked SYS mode link register */
stmfd sp!, {lr}
/* (6) Call the C-coded handler */
mov lr, pc
ldr pc, r6
/* (7) Restore SYS mode link register */
ldmfd sp!, {lr}
36
AR1803 May 10, 2006
/* (8) Change to IRQ mode and disable IRQ */
msr cpsr_c, #IRQ_MODE|IRQ_DISABLE
/* (9) Restore the SPSR */
msr spsr, r4
/* (10) Acknowledge the VIC */
mov r0, #0
str r0, [r5]
/* (11) Restore IRQ context and return from interrupt */
ldmfd sp!, {r0-r6, ip, pc}^


И это описание натолкнуло меня на дополнительный вопрос, а можно ли в GCC переопределять последовательность операций для вызова функций, например путем создания собственных атрибутов для функций. И дальнейшим их использованием в примерно таком виде:
Код
static void Timer0ISR()  __attribute__ ((my_nested_interrupt))


Сообщение отредактировал Novichok1 - Mar 1 2010, 05:14
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Novichok1
сообщение Mar 1 2010, 09:12
Сообщение #2


Участник
*

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



Может и правда, дело в стартапе, выложу его на всякий случай, может кто и увидит несостыковку.
CODE
#
# *** Startup Code (executed after Reset) ***
#

#include "config.h"

# Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs

.equ Mode_USR, 0x10
.equ Mode_FIQ, 0x11
.equ Mode_IRQ, 0x12
.equ Mode_SVC, 0x13
.equ Mode_ABT, 0x17
.equ Mode_UND, 0x1B
.equ Mode_SYS, 0x1F

.equ I_Bit, 0x80 /* when I bit is set, IRQ is disabled */
.equ F_Bit, 0x40 /* when F bit is set, FIQ is disabled */

.equ sram_bottom, SRAM_SADDR
.equ sram_top, SRAM_TOP
.equ stackTop, SRAM_TOP

#define VAL_PLLCFG_MSEL ((PLL_MUL - 1) << 0)
#if (PLL_DIV == 1)
#define PLL_DIV_VALUE 0x00
#elif (PLL_DIV == 2)
#define PLL_DIV_VALUE 0x01
#elif (PLL_DIV == 4)
#define PLL_DIV_VALUE 0x10
#elif (PLL_DIV == 8)
#define PLL_DIV_VALUE 0x11
#endif
#define VAL_PLLCFG_PSEL (PLL_DIV_VALUE << 5)
#define VAL_PLLCFG (VAL_PLLCFG_MSEL | VAL_PLLCFG_PSEL)

# Phase Locked Loop (PLL) definitions
.equ PLL_BASE, 0xE01FC080 /* PLL Base Address */
.equ PLLCON_OFS, 0x00 /* PLL Control Offset*/
.equ PLLCFG_OFS, 0x04 /* PLL Configuration Offset */
.equ PLLSTAT_OFS, 0x08 /* PLL Status Offset */
.equ PLLFEED_OFS, 0x0C /* PLL Feed Offset */
.equ PLLCON_PLLE, (1<<0) /* PLL Enable */
.equ PLLCON_PLLC, (1<<1) /* PLL Connect */
.equ PLLSTAT_PLOCK, (1<<10) /* PLL Lock Status */

#define HANDLER(HandlerLabel,HandleLabel) \
HandlerLabel: ;\
sub sp, sp, #4 ;\
stmfd sp!, {r0};\
ldr r0, =HandleLabel;\
ldr r0, [r0] ;\
str r0, [sp,#4] ;\
ldmfd sp!, {r0,pc}

# Starupt Code must be linked first at Address at which it expects to run.

.text
.arm
# ******************************************************************************
# Declare external function
# ******************************************************************************
.extern lowLevelInit
.extern exceptionHandlerInit

.global _startup
.func _startup
_startup:

# Exception Vectors
# Mapped to Address 0.

Vectors:
_vectors:
# If vectors are in FLASH, starting at 0x00000000
#if (MAM_MAP == 1)
B handleReset /* jump to reset code */
B HandlerUndef /* handlerUndef */
B HandlerSWI /* SWI interrupt handler */
B HandlerPabort /* handlerPAbort */
B HandlerDabort /* handlerDAbort */
NOP /* Reserved Vector */
#if (IRQ_HANDLER == 0)
B HandlerIRQ /* handlerIRQ */
#else
LDR PC,[PC,#-0x120] /* jump to address supplied by VIC */
#endif
B HandlerFIQ /* handlerFIQ */

# Create handlers
HANDLER(HandlerUndef, HandleUndef)
HANDLER(HandlerSWI, HandleSWI)
HANDLER(HandlerPabort, HandlePabort)
HANDLER(HandlerDabort, HandleDabort)
#if (IRQ_HANDLER == 0)
HANDLER(HandlerIRQ, HandleIRQ)
#endif
HANDLER(HandlerFIQ, HandleFIQ)

# If vectors are in RAM, starting at 0x40000000
#else
LDR PC,[PC,#resetHandlerAddress - . - 8] /* handle reset */
LDR PC,[PC,#undefHandlerAddress - . - 8] /* handlerUndef */
LDR PC,[PC,#swiHandlerAddress - . - 8] /* SWI interrupt handler */
LDR PC,[PC,#pabortHandlerAddress - . - 8] /* handlerPAbort */
LDR PC,[PC,#dabortHandlerAddress - . - 8] /* handlerDAbort */
NOP /* Reserved Vector */
#if (IRQ_HANDLER == 0)
LDR PC,[PC,#irqHandlerAddress - . - 8] /* jump to common irq handler */
#else
LDR PC,[PC,#-0x120] /* jump to address supplied from VIC */
#endif
LDR PC,[PC,#fiqHandlerAddress - . - 8] /* handlerFIQ */

resetHandlerAddress:
.word handleReset

undefHandlerAddress:
.word 0

swiHandlerAddress:
.word 0

pabortHandlerAddress:
.word 0

dabortHandlerAddress:
.word 0

irqHandlerAddress:
.word 0

fiqHandlerAddress:
.word 0

#endif

# Reset Handler
handleReset:

# Call pll initialization
# BL pllInit

# Setup Stack for each mode
LDR R0, =stackTop

# Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #stackSize_UND

# Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #stackSize_ABT

# Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #stackSize_FIQ

# Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #stackSize_IRQ

# Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC|I_Bit|F_Bit
MOV SP, R0
SUB R0, R0, #stackSize_SVC

# Enter System Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SYS|I_Bit|F_Bit
MOV SP, R0

# Setup a default Stack Limit (when compiled with "-mapcs-stack-check")
SUB SL, SP, #stackSize_SYS

#if (MAM_MAP == 2)
# Copy exception vectors into SRAM
MOV R8, #SRAM_SADDR
LDR R9, =Vectors
# Move exception vectors (7 vectors + 1 reserved)
LDMIA R9!, {R0-R7}
STMIA R8!, {R0-R7}
# Move addresses belonging to exception vectors (7 addresses)
LDMIA R9!, {R0-R6}
STMIA R8!, {R0-R6}
#endif

# Call low-level initialization
# BL lowLevelInit

# Relocate .data section (Copy from ROM to RAM)
LDR R1, =_etext
LDR R2, =_data
LDR R3, =_edata
LoopRel: CMP R2, R3
LDRLO R0, [R1], #4
STRLO R0, [R2], #4
BLO LoopRel

# Clear .bss section (Zero init)
MOV R0, #0
LDR R1, =__bss_start__
LDR R2, =__bss_end__
LoopZI: CMP R1, R2
STRLO R0, [R1], #4
BLO LoopZI

# Initialize exception vectors
# BL exceptionHandlerInit

# Enter the C code
Jump_To_Main:
ADR LR, __Return_from_Main
MOV R0, #0
MOV R1, #0
LDR R2, =main
BX R2

__Return_from_Main:
B __Return_from_Main

.size _startup, . - _startup
.endfunc


#
# Reserve memory for exception handlers
#
.struct SRAM_SADDR + 0x20
HandleReset:

.struct SRAM_SADDR + 0x24
HandleUndef:

.struct SRAM_SADDR + 0x28
HandleSWI:

.struct SRAM_SADDR + 0x2c
HandlePabort:

.struct SRAM_SADDR + 0x30
HandleDabort:

.struct SRAM_SADDR + 0x34
HandleIRQ:

.struct SRAM_SADDR + 0x38
HandleFIQ:

#
# Reserve memory for stack areas
#
.struct STK_SADDR
UserStack: /* User stack not used (size = 0) */

.struct UserStack + stackSize_SYS
SYSStack:

.struct SYSStack + stackSize_SVC
SVCStack:

.struct SVCStack + stackSize_UND
UndefStack:

.struct UndefStack + stackSize_ABT
AbortStack:

.struct AbortStack + stackSize_IRQ
IRQStack:

.struct IRQStack + stackSize_FIQ
FIQStack: /* this position equals top of SRAM */

.end



Кстати, если следовать советам "Real-time processing with the Philips LPC ARM microcontroller; using GCC and the MicroC/OS-II RTOS." то я подозреваю этот код загрузки обработчика
Код
nested_irq_isr:
/* (1) Save IRQ context, including the APCS registers, and r4-6 */
sub lr, lr, #4
stmfd sp!, {r0-r6, ip, lr}
/* (2) Save the SPSR_irq register */
mrs r4, spsr
/* (3) Read the VICVectAddr */
ldr r5, VICVECTADDR
ldr r6, [r5]
/* (4) Change to SYS mode and enable IRQ */
msr cpsr_c, #SYS_MODE
/* (5) Save the banked SYS mode link register */
stmfd sp!, {lr}
/* (6) Call the C-coded handler */
mov lr, pc
ldr pc, r6
/* (7) Restore SYS mode link register */
ldmfd sp!, {lr}
/* (8) Change to IRQ mode and disable IRQ */
msr cpsr_c, #IRQ_MODE|IRQ_DISABLE
/* (9) Restore the SPSR */
msr spsr, r4
/* (10) Acknowledge the VIC */
mov r0, #0
str r0, [r5]
/* (11) Restore IRQ context and return from interrupt */
ldmfd sp!, {r0-r6, ip, pc}^
нужно поместить в макрос HANDLER(HandlerLabel,HandleLabel)? Но тогда возникает вопрос, что такое VICVECTADDR, просто адрес 0xFFFFFF00, или нечто иное?

Сообщение отредактировал rezident - Mar 4 2010, 13:33
Причина редактирования: Редактирование оформления цитаты исходника.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Novichok1   Вложенные прерывания, GCC и ARM7   Mar 1 2010, 05:08
- - sergeeff   Про прерывания а форуме для ARM столько уже понапи...   Mar 1 2010, 06:57
- - Novichok1   Цитата1. Заставить VIC вызывать по прерыванию С++ ...   Mar 1 2010, 08:07
- - Novichok1   Хорошо, частично разобрался, для вызовов всех прер...   Mar 4 2010, 05:44
- - Novichok1   И благодаря такому подходу исчезли глюки, которые ...   Mar 4 2010, 07:06
- - GetSmart   театр одного актёра   Mar 4 2010, 23:26
- - aaarrr   Цитата(GetSmart @ Mar 5 2010, 02:26) теат...   Mar 4 2010, 23:57
|- - Novichok1   Цитата(aaarrr @ Mar 5 2010, 02:57) Перед ...   Mar 5 2010, 04:59
|- - aaarrr   Цитата(Novichok1 @ Mar 5 2010, 07:59) Бол...   Mar 5 2010, 10:04
|- - GetSmart   Цитата(aaarrr @ Mar 5 2010, 15:04) Вложен...   Mar 5 2010, 12:14
||- - Novichok1   Цитата(GetSmart @ Mar 5 2010, 15:14) Это ...   Mar 5 2010, 12:43
||- - GetSmart   Цитата(Novichok1 @ Mar 5 2010, 17:43) То ...   Mar 5 2010, 12:54
||- - Novichok1   Цитата(GetSmart @ Mar 5 2010, 15:54) То б...   Mar 5 2010, 13:12
|- - Novichok1   Цитата(aaarrr @ Mar 5 2010, 13:04) Вложен...   Mar 5 2010, 12:23
- - GetSmart   Цитата(Novichok1)Вот и складывается впечатление, ч...   Mar 5 2010, 06:44
- - Novichok1   Ну точнее, там используется два источника прерыван...   Mar 5 2010, 07:22
- - GetSmart   Если после команды ldmfd в эпилоге второго ничего ...   Mar 5 2010, 07:43
|- - Novichok1   Цитата(GetSmart @ Mar 5 2010, 10:43) Если...   Mar 5 2010, 07:47
- - GetSmart   ЦитатаВсе-таки кажется странным, что некорректный ...   Mar 5 2010, 12:35
|- - Novichok1   Цитата(GetSmart @ Mar 5 2010, 15:35) Со с...   Mar 5 2010, 12:55
- - aaarrr   Цитата(Novichok1 @ Mar 5 2010, 15:23) А н...   Mar 5 2010, 12:41
- - GetSmart   Это не свой атрибут, а стандартный. Используется т...   Mar 5 2010, 13:03
- - GetSmart   Цитата(Novichok1)Спасибо, а не в курсе, Не, не в к...   Mar 5 2010, 14:03
- - GetSmart   Novichok1, хотел ещё спросить, зачем было делать о...   Mar 11 2010, 12:21
- - Novichok1   А разве к статическим членам нет доступа? Ведь обр...   Mar 11 2010, 15:07
- - GetSmart   Я бы всё таки выделил прерывания из класса. ИМХО э...   Mar 11 2010, 16:35
|- - Novichok1   Цитата(GetSmart @ Mar 11 2010, 20:35) Зна...   Mar 11 2010, 18:22
- - GetSmart   Вообще, излишняя универсальность, которая не понад...   Mar 11 2010, 19:02
|- - Novichok1   Цитата(GetSmart @ Mar 11 2010, 22:02) А ч...   Mar 12 2010, 04:49
- - GetSmart   Цитата(Novichok1)Но в любом случае, мне не совсем ...   Mar 12 2010, 05:50
- - Aurochs   Цитата(GetSmart @ Mar 12 2010, 07:50) Так...   Mar 13 2010, 18:30


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 08:22
Рейтинг@Mail.ru


Страница сгенерированна за 0.01425 секунд с 7
ELECTRONIX ©2004-2016