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

 
 
 
Reply to this topicStart new topic
> FIQ+FreeRTOS на LPC2146
meister
сообщение Jan 23 2008, 07:09
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 219
Регистрация: 20-11-07
Пользователь №: 32 484



Здравствуйте,

не могу заставить работать эту операционку с 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


Настройка стека:
Код
    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


Вот так настраивается с 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;
    }


Вот так с 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;
    }


Таблица прерываний:
Код
    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


Прокси:
Код
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;


Обработчики прерываний (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


Обработчики прерываний (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();
}


Спасибо.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 23 2008, 08:38
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Я все это не читал, поскольку сразу понял, что не смогу понять за конечное количество времени, что Вы хотите сделать с бедным FIQ sad.gif. Но с FIQ никаких специальных проблем нет - при работающем от IRQ ядре системы отдельные обработчики прерываний могут висеть на FIQ. Следует иметь ввиду только следующие моменты:
- по умолчанию в критических секциях запрещается и IRQ и FIQ - надо доработать при необходимости;
- из FIQ нельзя осуществлять системные вызовы требующие переключения контекста. В принципе это не смертельно, ибо FIQ оно на то и FIQ дабы чего-то (а не все подряд! где его эффективность к нулю приблизится )быстро обслуживать. Если очень ну очень и в исключительных случаях надо, то вполне правильным рещением следует признать эмуляцию обычного прерывания из FIQ для переключения контекста.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
meister
сообщение Jan 25 2008, 09:15
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 219
Регистрация: 20-11-07
Пользователь №: 32 484



Сорри. Симулятор в IAR меня обманул, на железе - работает.

Ниже уже не актуально.
===

Цитата(zltigo @ Jan 23 2008, 11:38) *
Если очень ну очень и в исключительных случаях надо, то вполне правильным рещением следует признать эмуляцию обычного прерывания из FIQ для переключения контекста.


Я попробую этот вариант потрясти - там контекст нужно переключать далеко не каждый раз. А как генерировать софтварное прерывание? Так не получается sad.gif

Код
namespace
{
    unsigned const my_sw_irq_channel = 31;
}

__arm __irq void irq_sw_test(void)
{
    VICVectAddr = 0;
}

__arm __irq void non_vectored_handler(void)
{
    VICVectAddr = 0;
}

int main()
{
    MEMMAP = 1;
    
    VICSoftIntClear = ~0;
    VICIntEnClear = ~0;
    VICIntSelect = 0;
    
    VICVectAddr0 = reinterpret_cast<unsigned long>(&irq_sw_test);
    VICVectCntl0 = 0x20 | my_sw_irq_channel;

    VICDefVectAddr = reinterpret_cast<unsigned long>(&non_vectored_handler);

    VICIntEnable = BIT_(my_sw_irq_channel);

    VICProtection = 1;
    VICVectAddr = 0;
    
    __enable_interrupt();

    VICSoftInt = BIT_(my_sw_irq_channel);
    
    assert(0 && "here");
}


Сообщение отредактировал meister - Jan 25 2008, 09:25
Go to the top of the page
 
+Quote Post

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

 


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


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