logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

ARM - przerwanie timera, problem z migającą diodą LED

gn000 19 Wrz 2007 00:48 3098 13
REKLAMA
  • #1 4298066
    gn000
    Poziom 12  
    Posty: 93
    Ocena: 19
    Mam pewien problem.
    Problem ten dotyka mnie praktycznie od początku pracy
    z ARMami, wygląda to tak pisze sobie procedure obsługi przerwania dokonuję jakiejś drobnej zmiany i wszystko przestaje działać, i właśnie dziś udało mi się przyłapać ten problem troche dokładniej i conajmniej ciekawie.
    Wiec :

    //***************** PROBLEMATYCZNE LINIE KODU *************************
    //
    if (IO0PIN & LED0)
    {
    IO0CLR = LED0;
    }
    else
    {
    IO0SET = LED0;
    }
    //***********************************************************************************

    jest to fragment który bada stan lini wyjściowej procesora i jeśli 1 to daje 0, jak 0 to daje 1
    do tego pinu jest podpięta dioda led celem sygnalizacji wszelkich pomysłów (taki debugger) pierwotnie był on używany do obserwacji
    czy wystąpiło przerwanie timera, tak czy inaczej działanie kodu objawia się miganiem diody.
    Program i był testowany i w przerwaniu i w main i nigdy nie było problemu z tym fragmentem.
    Problem jest gdy wywale ten "debuger", program bez niego nie działa !!!
    Nawet jeśli zmienie procedure tak:
    //***************** PROBLEMATYCZNE LINIE KODU *************************
    //
    if (IO0PIN & LED0)
    {
    IO0CLR = LED0;
    }
    else
    {
    // IO0SET = LED0;
    }
    //***********************************************************************************
    to przestaje działać, i nie chodzi tu o samego leda bo jak go odłącze kabelkiem a zostawie kod to też działa, coś jest w samym zapisie
    czy jak ? albo znowu ślepy jestem ?

    Niżej jest zamieszczone całe przerwanie, tak sobie pisałem pisałem i napisałem działa ale tylko z tym debugerem na diodie led !!!
    Na koniec dodam że już kilka razy miałem taki problem z przerwaniami, i za diabła nie wiem co jest !!! Dopiero siadam i przepisuje program inaczej, ostatnio zrobiłem tak że w przerwaniu ustawiłem flage "wystapiłoPrzerwanie" a w main sprawdzałem tą flagę i brałem się za obsługe, musiałem tak zrobić bo termin gonił, ale dalej tak niedam rady. help !




    static void timer0ISR(void) __attribute__ ((interrupt ("IRQ")));
    static void timer0ISR(void)
    {

    TimeOutRS0 --;
    if (TimeOutRS0 == 0)
    {
    uart0_rx_insert_idx = 0; //Zerujemy wskaznik
    TimeOutRS0 = CzasTimeOutRS0;
    if (OdebranoStartRS0 == 1)
    {
    OdebranoStartRS0 = 0;
    OdebranoPakietRS0 = 1;
    }
    }
    //
    TimeOutRS1 --;
    if (TimeOutRS1 == 0)
    {
    uart1_rx_insert_idx = 0; //Zerujemy wskaznik
    TimeOutRS1 = CzasTimeOutRS1;
    if (OdebranoStartRS1 == 1)
    {
    OdebranoStartRS1 = 0;
    if (uart1_rx_buffer[0] == 0xAC)
    {
    OdebranoPakietRS1 = 1;
    //Stop = 1;
    }
    }
    }
    timer0Count++;



    //***************** PROBLEMATYCZNE LINIE KODU *************************
    //
    if (IO0PIN & LED0)
    {
    IO0CLR = LED0;
    }
    else
    {
    IO0SET = LED0;
    }
    //***********************************************************************************


    T0IR = 0xFF; // Clear the timer 0 interrupt
    VICVectAddr = 0; // Update VIC priorities
    }
  • REKLAMA
  • #2 4298195
    Konto nie istnieje
    Konto nie istnieje  
  • #3 4298363
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    if (IO0PIN & LED0) 
    { 
    IO0CLR = LED0; 
    } 
    else 
    { 
    IO0SET = LED0; 
    }


    To w końcu ten pin "LED0" jest wejściem czy wyjściem? Ja rejestr IOPIN używam tylko jak sprawdzam stan wejścia, natomiast do sprawdzania czy dioda LED świeci czy nie służy mi zwykła zmienna.
  • REKLAMA
  • #4 4298465
    gn000
    Poziom 12  
    Posty: 93
    Ocena: 19
    Faktycznie zapomniałem procek to LPC2138, kompilator WINARM wersji teraz nie pamiętam. LED0 jest wyjściem ale chyba można jednocześnie testować stan na IOPIN bo normalnie to działa.

    "Obniż zegar i ustaw tryb MAM 0 lub 1" oczywiście wieczorem sprawdze, może coś więcej na temat "syndrom MAM"
  • REKLAMA
  • #5 4298609
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #6 4298712
    gn000
    Poziom 12  
    Posty: 93
    Ocena: 19
    "obsługa zagnieżdżonych przerwań jest skopana" - czy jest jakaś możliwość obejścia tego problemu jeśli mam włączone kilka przerwań jednocześnie i mogą się wzajemnie nakładać w czasie ?
  • #7 4298961
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    Cytat:
    Aha, w gcc obsługa zagnieżdżonych przerwań jest skopana, jeśli takowe używasz.


    Niby dlaczego? Ja uzywam WinARMa z SAM7S256 i zagniezdzone przerwania bardzo dobrze dzialaja. Mozna ustawiac priorytety dla konkretnych przerwan i przerwanie o wyzszym przerwie przerwanie o nizszym priorytecie.
    Wszystko zalezy od tego jakiej rozbiegowki uzywasz.
  • #8 4299186
    Konto nie istnieje
    Konto nie istnieje  
  • #9 4300038
    _Matik_
    Poziom 19  
    Posty: 390
    Pomógł: 25
    Ocena: 7
    wklejam moj fragment rozbiegowki dla LPC2101/2/3 dotyczacy wstawki od handlera, zastepujacej kod dodawany przez kompilator GCC dla funkcji z atrybutem interrupt
    
    // Runtime Interrupt Vectors
    // -------------------------
    
    		.equ	VICVectAddr, 0xfffff030
    Vectors:
            b     _start                    // reset - _start
            ldr   pc,_undf                  // undefined - _undf
            ldr   pc,_swi                   // SWI - _swi
            ldr   pc,_pabt                  // program abort - _pabt
            ldr   pc,_dabt                  // data abort - _dabt
            nop                             // reserved
    //        ldr   pc,[pc,#-0xFF0]           // IRQ - read the VIC
            ldr   pc,_irq		            // IRQ - _irq
            ldr   pc,_fiq                   // FIQ - _fiq
    
    // Use this group for development
    _undf:  .word __undf                    // undefined
    _swi:   .word __swi                     // SWI
    _pabt:  .word __pabt                    // program abort
    _dabt:  .word __dabt                    // data abort
    _irq:   .word __irq                     // IRQ
    _fiq:   .word __fiq                     // FIQ
    
    __undf: b     .                         // undefined
    __swi:  b     .                         // SWI
    __pabt: b     .                         // program abort
    __dabt: b     .                         // data abort
    // __irq:  b     .                         // IRQ
    
    // Hadler IRQ, zastepuje ten generowany przez gcc
    
    __irq:
    		stmfd sp!, { lr } /* save return address on IRQ stack */
    		mrs lr, spsr /* use lr to save spsr_irq */
    		stmfd sp!, { r4-r5, lr } /* save work regs & spsr on stack */
    
    		ldr r4, =VICVectAddr /* get the ISR address from VIC */
    		ldr r5, [r4]
    
    		msr cpsr_c, #0x13 /* supervisor mode, interrupts ON */
    //		msr cpsr_c, #0x93 /* supervisor mode, interrupts OFF */
    
    		stmfd sp!, { r0-r3, r12, lr } /* save work regs & lr_svc on stack */
    		mov lr, pc /* set return to common exit of ISR */
    		mov pc, r5 /* go handle the interrupt */
    		ldmfd sp!, { r0-r3, r12, lr } /* restore regs & lr_svc */
    
    		msr cpsr_c, #0x92 /* IRQ mode, interrupts OFF */
    
    		str lr, [r4] /* update VICVectAddr */
    
    		ldmfd sp!, { r4-r5, lr } /* restore work regs and spsr_irq */
    		msr spsr_cxsf, lr /* put back spsr_irq */
    		ldmfd sp!, { lr } /* restore return address */
    
    		subs pc, lr, #0x4 /* return, restoring CPSR from SPSR */
    
    __fiq:  b     .                         // FIQ
    


    Jak widac, nie uzywam FIQ, zreszta innych wektorow oprocz IRQ tez nie. Ten kod powstal na bazie kodu z ktoregos forum LPC2000.
  • #10 4465166
    gn000
    Poziom 12  
    Posty: 93
    Ocena: 19
    Witam, po małej przerwie, niestety mój problem jest nadal aktualny, wkleiłem podany kod i to całkowicie wywaliło program.

    to mój plik startowy, prosze o jakąś rade



    .global _etext // -> .data initial values in ROM
    .global _data // -> .data area in RAM
    .global _edata // end of .data area
    .global __bss_start // -> .bss area in RAM
    .global __bss_end__ // end of .bss area
    .global _stack // top of stack

    // Stack Sizes
    .set UND_STACK_SIZE, 0x00000004
    .set ABT_STACK_SIZE, 0x00000004
    .set FIQ_STACK_SIZE, 0x00000004
    .set IRQ_STACK_SIZE, 0X00000200
    .set SVC_STACK_SIZE, 0x00000a00

    // Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
    .set MODE_USR, 0x10 // User Mode
    .set MODE_FIQ, 0x11 // FIQ Mode
    .set MODE_IRQ, 0x12 // IRQ Mode
    .set MODE_SVC, 0x13 // Supervisor Mode
    .set MODE_ABT, 0x17 // Abort Mode
    .set MODE_UND, 0x1B // Undefined Mode
    .set MODE_SYS, 0x1F // System Mode

    .equ I_BIT, 0x80 // when I bit is set, IRQ is disabled
    .equ F_BIT, 0x40 // when F bit is set, FIQ is disabled

    .text
    .arm
    .section .init, "ax"

    .code 32
    .align 2

    .global _boot
    .func _boot
    _boot:








    ///////

    ///////








    //----------------------------------------------------------------
    // Runtime Interrupt Vectors
    //----------------------------------------------------------------

    .equ VICVectAddr, 0xfffff030
    Vectors:
    b _start // reset - _start
    ldr pc,_undf // undefined - _undf
    ldr pc,_swi // SWI - _swi
    ldr pc,_pabt // program abort - _pabt
    ldr pc,_dabt // data abort - _dabt
    nop // reserved
    // ldr pc,[pc,#-0xFF0] // IRQ - read the VIC
    ldr pc,_irq // IRQ - _irq
    ldr pc,_fiq // FIQ - _fiq

    // Use this group for development
    _undf: .word __undf // undefined
    _swi: .word __swi // SWI
    _pabt: .word __pabt // program abort
    _dabt: .word __dabt // data abort
    _irq: .word __irq // IRQ
    _fiq: .word __fiq // FIQ

    __undf: b . // undefined
    __swi: b . // SWI
    __pabt: b . // program abort
    __dabt: b . // data abort
    // __irq: b . // IRQ

    // Hadler IRQ, zastepuje ten generowany przez gcc

    __irq:
    stmfd sp!, { lr } /* save return address on IRQ stack */
    mrs lr, spsr /* use lr to save spsr_irq */
    stmfd sp!, { r4-r5, lr } /* save work regs & spsr on stack */

    ldr r4, =VICVectAddr /* get the ISR address from VIC */
    ldr r5, [r4]

    msr cpsr_c, #0x13 /* supervisor mode, interrupts ON */
    // msr cpsr_c, #0x93 /* supervisor mode, interrupts OFF */

    stmfd sp!, { r0-r3, r12, lr } /* save work regs & lr_svc on stack */
    mov lr, pc /* set return to common exit of ISR */
    mov pc, r5 /* go handle the interrupt */
    ldmfd sp!, { r0-r3, r12, lr } /* restore regs & lr_svc */

    msr cpsr_c, #0x92 /* IRQ mode, interrupts OFF */

    str lr, [r4] /* update VICVectAddr */

    ldmfd sp!, { r4-r5, lr } /* restore work regs and spsr_irq */
    msr spsr_cxsf, lr /* put back spsr_irq */
    ldmfd sp!, { lr } /* restore return address */

    subs pc, lr, #0x4 /* return, restoring CPSR from SPSR */

    __fiq: b . // FIQ
    ////----------------------------------------------------------------





    .endfunc






    // Setup the operating mode & stack.
    // ---------------------------------
    .global _start, start, _mainCRTStartup
    .func _start

    _start:
    start:
    _mainCRTStartup:

    // Initialize Interrupt System
    // - Set stack location for each mode
    // - Leave in System Mode with Interrupts Disabled
    // -----------------------------------------------

    .equ TopStack, 0x40008000
    ldr r0,=TopStack

    // ldr r0,=_stack
    msr CPSR_c,#MODE_UND|I_BIT|F_BIT // Undefined Instruction Mode
    mov sp,r0
    sub r0,r0,#UND_STACK_SIZE
    msr CPSR_c,#MODE_ABT|I_BIT|F_BIT // Abort Mode
    mov sp,r0
    sub r0,r0,#ABT_STACK_SIZE
    msr CPSR_c,#MODE_FIQ|I_BIT|F_BIT // FIQ Mode
    mov sp,r0
    sub r0,r0,#FIQ_STACK_SIZE
    msr CPSR_c,#MODE_IRQ|I_BIT|F_BIT // IRQ Mode
    mov sp,r0
    sub r0,r0,#IRQ_STACK_SIZE
    msr CPSR_c,#MODE_SVC|I_BIT|F_BIT // Supervisor Mode
    mov sp,r0
    sub r0,r0,#SVC_STACK_SIZE
    msr CPSR_c,#MODE_SYS|I_BIT|F_BIT // System Mode
    mov sp,r0

    // Copy initialized data to its execution address in RAM
    // -----------------------------------------------------
    #ifdef ROM_RUN
    ldr r1,=_etext // -> ROM data start
    ldr r2,=_data // -> data start
    ldr r3,=_edata // -> end of data
    1: cmp r2,r3 // check if data to move
    ldrlo r0,[r1],#4 // copy it
    strlo r0,[r2],#4
    blo 1b // loop until done
    #endif
    // Clear .bss
    // ----------
    mov r0,#0 // get a zero
    ldr r1,=__bss_start // -> bss start
    ldr r2,=__bss_end__ // -> bss end
    2: cmp r1,r2 // check if data to clear
    strlo r0,[r1],#4 // clear 4 bytes
    blo 2b // loop until done

    /*
    Call C++ constructors (for objects in "global scope")
    ctor loop added by Martin Thomas 4/2005
    based on a Anglia Design example-application for ST ARM
    */

    LDR r0, =__ctors_start__
    LDR r1, =__ctors_end__
    ctor_loop:
    CMP r0, r1
    BEQ ctor_end
    LDR r2, [r0], #4
    STMFD sp!, {r0-r1}
    MOV lr, pc
    MOV pc, r2
    LDMFD sp!, {r0-r1}
    B ctor_loop
    ctor_end:

    // Call main program: main(0)
    // --------------------------
    mov r0,#0 // no arguments (argc = 0)
    mov r1,r0
    mov r2,r0
    mov fp,r0 // null frame pointer
    mov r7,r0 // null frame pointer for thumb
    ldr r10,=main
    mov lr,pc

    /* Enter the C code, use BX instruction so as to never return */
    /* use BLX (?) main if you want to use c++ destructors below */

    bx r10 // enter main()

    /* "global object"-dtors are never called and it should not be
    needed since there is no OS to exit to. */
    /* Call destructors */
    # LDR r0, =__dtors_start__
    # LDR r1, =__dtors_end__
    dtor_loop:
    # CMP r0, r1
    # BEQ dtor_end
    # LDR r2, [r0], #4
    # STMFD sp!, {r0-r1}
    # MOV lr, pc
    # MOV pc, r2
    # LDMFD sp!, {r0-r1}
    # B dtor_loop
    dtor_end:

    .size _start, . - _start
    .endfunc

    .global _reset, reset, exit, abort
    .func _reset



    _reset:
    reset:
    exit:
    abort:
    #if 0
    // Disable interrupts, then force a hardware reset by driving P23 low
    // -------------------------------------------------------------------
    mrs r0,cpsr // get PSR
    orr r0,r0,#I_BIT|F_BIT // disable IRQ and FIQ
    msr cpsr,r0 // set up status register

    ldr r1,=(PS_BASE) // PS Base Address
    ldr r0,=(PS_PIO) // PIO Module
    str r0,[r1,#PS_PCER_OFF] // enable its clock

    ldr r1,=(PIO_BASE) // PIO Base Address
    ldr r0,=(1<<23) // P23
    str r0,[r1,#PIO_PER_OFF] // make sure pin is contolled by PIO
    str r0,[r1,#PIO_CODR_OFF] // set the pin low
    str r0,[r1,#PIO_OER_OFF] // make it an output
    #endif
    b . // loop until reset

    .size _reset, . - _reset
    .endfunc

    .end
  • #11 4467317
    Konto nie istnieje
    Konto nie istnieje  
  • #12 4480044
    gn000
    Poziom 12  
    Posty: 93
    Ocena: 19
    Witam,
    Cytat:
    wywaliłeś oczywiście ze swojego programu deklaracje z atrybutem interrupt?
    raczej tego nie zrobiłem, bo nie wiem o co chodzi, czy mam usunąć deklaracje procedur tych do których program wchodzi w czasie przerwania ?
  • #13 4482760
    Konto nie istnieje
    Konto nie istnieje  
  • #14 4609921
    gn000
    Poziom 12  
    Posty: 93
    Ocena: 19
    Dziękuje _Matik_ i albertb znowu walczyłem z tematem dodatkowo doszło jeszcze kilka problemów, ale kod _Matik_a rozwiązał problem. Zmieniłem tylko linie:
    msr cpsr_c, #0x13 /* supervisor mode, interrupts ON */
    // msr cpsr_c, #0x93 /* supervisor mode, interrupts OFF */

    na
    // msr cpsr_c, #0x13 /* supervisor mode, interrupts ON */
    msr cpsr_c, #0x93 /* supervisor mode, interrupts OFF */

    napiszcie coś jakie miało znaczenie wyłączenie tych przerwań.
    Mam włączone przerwania timer *2, uart *2, RTC

Podsumowanie tematu

✨ Problem dotyczy migającej diody LED podłączonej do pinu wyjściowego LPC2138, sygnalizującej przerwanie timera. Fragment kodu sprawdza stan pinu przez rejestr IO0PIN i na jego podstawie zmienia stan pinu LED0, co działało poprawnie w main i w przerwaniu. Jednak po drobnych zmianach w procedurze obsługi przerwania kod przestaje działać. Dyskusja wskazuje na możliwe problemy związane z konfiguracją MAM (Memory Accelerator Module) w LPC2138, które mogą powodować błędy w działaniu przerwań. Zalecane jest obniżenie zegara i ustawienie trybu MAM na 0 lub 1. Ponadto poruszono temat obsługi zagnieżdżonych przerwań w kompilatorze GCC, która może być wadliwa, co wymaga stosowania własnej rozbiegówki (handlera przerwań) zamiast atrybutu interrupt. Przykładowy kod rozbiegówki dla LPC210x został udostępniony i po jego zastosowaniu problem został rozwiązany. Wskazano również, że wyłączanie przerwań (msr cpsr_c, #0x93) w odpowiednim momencie ma znaczenie dla stabilności działania systemu z wieloma aktywnymi przerwaniami (timer, UART, RTC).
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA