не могу заставить работать эту операционку с FIQ. С IRQ у меня все работает, но мне покоя не дает этот простаивающий ресурс, тем более, что большого запаса по производительности у меня нет.
Линковщик:
Код
-D_CSTACK_SIZE=4
-D_IRQ_STACK_SIZE=100
-D_FIR_STACK_SIZE=100
-D_SVC_STACK_SIZE=100
-D_ABT_STACK_SIZE=4
-D_UND_STACK_SIZE=4
-D_HEAP_SIZE=0
-Z(DATA)CSTACK+_CSTACK_SIZE=RAMSTART-RAMEND
-Z(DATA)IRQ_STACK+_IRQ_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)FIR_STACK+_FIR_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)SVC_STACK+_SVC_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)ABT_STACK+_ABT_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)UND_STACK+_UND_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)HEAP+_HEAP_SIZE=RAMSTART-RAMEND
-D_IRQ_STACK_SIZE=100
-D_FIR_STACK_SIZE=100
-D_SVC_STACK_SIZE=100
-D_ABT_STACK_SIZE=4
-D_UND_STACK_SIZE=4
-D_HEAP_SIZE=0
-Z(DATA)CSTACK+_CSTACK_SIZE=RAMSTART-RAMEND
-Z(DATA)IRQ_STACK+_IRQ_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)FIR_STACK+_FIR_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)SVC_STACK+_SVC_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)ABT_STACK+_ABT_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)UND_STACK+_UND_STACK_SIZE=RAMSTART-RAMEND
-Z(DATA)HEAP+_HEAP_SIZE=RAMSTART-RAMEND
Настройка стека:
Код
mrs r0,cpsr ; Original PSR value
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#IRQ_MODE ; Set IRQ mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(IRQ_STACK) & 0xFFFFFFF8 ; End of IRQ_STACK
mrs r0,cpsr ; Original PSR value
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#FIQ_MODE ; Set FIQ mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(FIR_STACK) & 0xFFFFFFF8 ; End of FIR_STACK
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(CSTACK) & 0xFFFFFFF8 ; End of CSTACK
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SVC_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(SVC_STACK) & 0xFFFFFFF8 ; End of SVCSTACK
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#IRQ_MODE ; Set IRQ mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(IRQ_STACK) & 0xFFFFFFF8 ; End of IRQ_STACK
mrs r0,cpsr ; Original PSR value
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#FIQ_MODE ; Set FIQ mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(FIR_STACK) & 0xFFFFFFF8 ; End of FIR_STACK
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(CSTACK) & 0xFFFFFFF8 ; End of CSTACK
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SVC_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(SVC_STACK) & 0xFFFFFFF8 ; End of SVCSTACK
Вот так настраивается с IRQ (так работает):
Код
void init_interrupts()
{
MEMMAP = 1;
VICSoftIntClear = ~0;
VICIntEnClear = ~0;
VICIntSelect = 0;
set_VICVectCntls(1, hw::VIC_CHANNEL_TIMER1, &irq_timer1_handler_asm);
set_VICVectCntls(2, hw::VIC_CHANNEL_UART0, &irq_uart0_handler_asm);
set_VICVectCntls(3, hw::VIC_CHANNEL_UART1, &irq_uart1_handler_asm);
VICDefVectAddr = reinterpret_cast<unsigned long>(&non_vectored_handler_asm);
VICIntEnable =
BIT_(hw::VIC_CHANNEL_TIMER1) +
BIT_(hw::VIC_CHANNEL_UART0) +
BIT_(hw::VIC_CHANNEL_UART1);
VICProtection = 1;
VICVectAddr = 0;
}
{
MEMMAP = 1;
VICSoftIntClear = ~0;
VICIntEnClear = ~0;
VICIntSelect = 0;
set_VICVectCntls(1, hw::VIC_CHANNEL_TIMER1, &irq_timer1_handler_asm);
set_VICVectCntls(2, hw::VIC_CHANNEL_UART0, &irq_uart0_handler_asm);
set_VICVectCntls(3, hw::VIC_CHANNEL_UART1, &irq_uart1_handler_asm);
VICDefVectAddr = reinterpret_cast<unsigned long>(&non_vectored_handler_asm);
VICIntEnable =
BIT_(hw::VIC_CHANNEL_TIMER1) +
BIT_(hw::VIC_CHANNEL_UART0) +
BIT_(hw::VIC_CHANNEL_UART1);
VICProtection = 1;
VICVectAddr = 0;
}
Вот так с FIQ (иногда работает, но очень редко, потом зависает в prefetch interrupt):
Код
void init_interrupts()
{
MEMMAP = 1;
VICSoftIntClear = ~0;
VICIntEnClear = ~0;
VICIntSelect = 0;
set_VICVectCntls(2, hw::VIC_CHANNEL_UART0, &irq_uart0_handler_asm);
set_VICVectCntls(3, hw::VIC_CHANNEL_UART1, &irq_uart1_handler_asm);
VICDefVectAddr = reinterpret_cast<unsigned long>(&non_vectored_handler_asm);
VICIntSelect = BIT_(hw::VIC_CHANNEL_TIMER1);
VICIntEnable =
BIT_(hw::VIC_CHANNEL_TIMER1) +
BIT_(hw::VIC_CHANNEL_UART0) +
BIT_(hw::VIC_CHANNEL_UART1);
VICProtection = 1;
VICVectAddr = 0;
}
{
MEMMAP = 1;
VICSoftIntClear = ~0;
VICIntEnClear = ~0;
VICIntSelect = 0;
set_VICVectCntls(2, hw::VIC_CHANNEL_UART0, &irq_uart0_handler_asm);
set_VICVectCntls(3, hw::VIC_CHANNEL_UART1, &irq_uart1_handler_asm);
VICDefVectAddr = reinterpret_cast<unsigned long>(&non_vectored_handler_asm);
VICIntSelect = BIT_(hw::VIC_CHANNEL_TIMER1);
VICIntEnable =
BIT_(hw::VIC_CHANNEL_TIMER1) +
BIT_(hw::VIC_CHANNEL_UART0) +
BIT_(hw::VIC_CHANNEL_UART1);
VICProtection = 1;
VICVectAddr = 0;
}
Таблица прерываний:
Код
org 0x00
__program_start: B ?cstartup
undefvec: B undef_handler_proxy
swivec: B swi_handler_proxy
pabtvec: B prefetch_handler_proxy
dabtvec: B data_handler_proxy
org 0x18
irqvec: LDR PC, [PC, #-0xFF0]
fiqvec: B fiq_handler_proxy
__program_start: B ?cstartup
undefvec: B undef_handler_proxy
swivec: B swi_handler_proxy
pabtvec: B prefetch_handler_proxy
dabtvec: B data_handler_proxy
org 0x18
irqvec: LDR PC, [PC, #-0xFF0]
fiqvec: B fiq_handler_proxy
Прокси:
Код
undef_handler_proxy B undef_handler;
swi_handler_proxy B vPortYieldProcessor;
prefetch_handler_proxy B prefetch_handler;
data_handler_proxy B data_handler;
fiq_handler_proxy B fiq_handler_asm;
swi_handler_proxy B vPortYieldProcessor;
prefetch_handler_proxy B prefetch_handler;
data_handler_proxy B data_handler;
fiq_handler_proxy B fiq_handler_asm;
Обработчики прерываний (ASM)
Код
fiq_handler_asm:
portSAVE_CONTEXT
BL fiq_handler_impl;
portRESTORE_CONTEXT
irq_timer1_handler_asm:
portSAVE_CONTEXT
BL irq_timer1_handler_impl;
portRESTORE_CONTEXT
portSAVE_CONTEXT
BL fiq_handler_impl;
portRESTORE_CONTEXT
irq_timer1_handler_asm:
portSAVE_CONTEXT
BL irq_timer1_handler_impl;
portRESTORE_CONTEXT
Обработчики прерываний (C++)
Код
extern "C" __arm void fiq_handler_impl(void)
{
timer1_uart_isr_impl();
}
extern "C" __arm void irq_timer1_handler_impl(void)
{
timer1_uart_isr_impl();
}
{
timer1_uart_isr_impl();
}
extern "C" __arm void irq_timer1_handler_impl(void)
{
timer1_uart_isr_impl();
}
Спасибо.