Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[LPC1114][uVision]zapis do portów

marcin026 14 Wrz 2010 10:18 2502 17
  • #1 14 Wrz 2010 10:18
    marcin026
    Poziom 9  

    Witam,
    próbowałem napisać prosty program tylko nie wiem jak pisać do portu. Wcześniej używałem GCC do avrów a tam plik nagłókowy wyglądał inaczej. Ten wygląda tak Link.
    Oto mój prosty program:

    Code:

    #include <LPC11xx.h>

    int main (void)
    {
       LPC_GPIO_TypeDef LPC_GPIO;
       LPC_GPIO.DIR = 0xFFFFFFFF;
       LPC_GPIO.DATA = 0xFFFFFFFF;
       for(;;){}
    }

    Zdebugowałem go w keilu i port się nie zmienił. Wie ktoś jak dobrać się do portów:?:.

    0 17
  • Pomocny post
    #2 14 Wrz 2010 10:33
    tymon_x
    Poziom 30  

    Skorzystaj z mocy jaką daje dokumentacja: User Manual.
    Rozdział System Configuration dużo wyjaśnia. Musisz podciągnąć zegar pod GPIOx, żeby w ogóle zatrybił (; I kilka dodatkowych rzeczy poustawiać, jak PLL (jak wykorzystujesz), zegary (przede wszystkim), Flash Lattency (rejestr FLASHCFG)itp.

    0
  • #3 14 Wrz 2010 13:46
    94075
    Użytkownik usunął konto  
  • #5 03 Lis 2010 20:40
    marcin026
    Poziom 9  

    Witam, mam następujący problem: napisałem dwa proste programy, pierwszy testuje przerwanie od timera a drugi testuje przerwanie SysTick. Problem polega na tym że oba nie działają. W pierwszym przypadku program zamiast skoczyć do funkcji obsługi przerwania, wpada w nieskończoną pętlę.(w pliku startup_LPC11xx.s w linijce 196), a w drugim programie przerwanie nie zostaje zgłoszone.

    Progam1:

    Code:

    #include "LPC11xx.h"

    void Timer16B0_init(void){
       //konfiguracja timera
       LPC_TMR16B0->TCR=0x00000001;    //timer enable
       LPC_TMR16B0->PR =0x00000010;      //prescaler na 4   
       LPC_TMR16B0->MCR=0x00000001;         
          LPC_TMR16B0->MR0=0x0000000F;         
       NVIC_EnableIRQ(TIMER_16_0_IRQn);
    }

    int main(void){
               Timer16B0_init();
               __enable_irq();
       while(1){}   // loop
    }

    __irq void TIMER16_0_IRQHandler (void){
       LPC_TMR16B0->TC=0x00000000;
    }


    program2:
    Code:

    #include "LPC11xx.h"

    volatile uint32_t SysTickCnt;

    __irq void SysTick_Handler (void) {           // SysTick Interrupt Handler (1ms) 
      SysTickCnt++;
    }

    int main(void){
       SystemInit();
       SysTick_Config(50000000/1000 - 1);
       __enable_irq();
       while(1){}      // loop
    }

    Oba programy napisane są w uVision dla procesora LPC1114. Pomocy:!:

    0
  • #6 03 Lis 2010 23:16
    wujcio24
    Poziom 13  

    Pisze programy w asemblerze na mikrokontrolery lpc111x (lpc1114). Ponieważ korzystam z takiej płytki - Link nie posiadam debuggera i także muszę debugować w keilu. Co do uruchomienia systicka/timera mam pewne rozwiązanie które może ci pomóc - możesz wywołać funkcje napisaną w asemblerze która inicjuje systicka/timera. Jeżeli chodzi o inicjacje systicka ta czynność składa się z zaledwie wpisania wartości do trzech rejestrów natomiast jeśli chodzi o timer tutaj jest ich już znacznie więcej. Co do debugowania w keilu muszę cię przestrzec przed jednym. Mam już dość duże doświadczenie w takim debugowaniu i niestety są różnice w działaniu kodu na wirtualnym procesorze a na fizycznym - takie coś obserwowałem w przypadku uarta (w symulatorze działało natomiast na fizycznej płytce już nie).

    Code:
       .syntax unified
    
           .cpu cortex-m0
           .align   2
           .global   systick_init
           .thumb
           .thumb_func
    systick_init:


          //wyzerowanie rejestru SYST_CVR
          movs r1, #0
          ldr r0, =0xE000E018
          str r1, [r0]

          //wpisanie wartosci odliczanej do rejestru SYST_RVR
          movs r1, #1
          lsls r1, #23
          ldr r0, =0xE000E014
          str r1, [r0]

          //ustawienie bitow 0 i 1 w rejestrze SYST_CSR
          movs r1, #3
          ldr   r0, =0xE000E010
          ldr   r0, [r0]
          orrs r0, r1
          ldr   r1, =0xE000E010
          str   r0, [r1]

          pop   {r7, pc}


    Wywołanie takiej funkcji będzie wyglądało tak:

    Code:
    systick_init();


    Trzeba pamiętać też o wcześniejszej deklaracji która u mnie wygląda tak:

    Code:
    extern int systick_init();


    Zaznaczam że pisze kod w Lpcxpresso i u ciebie zapis czegoś takiego może wyglądać inaczej.

    0
  • #7 03 Lis 2010 23:49
    marcin026
    Poziom 9  

    Mój drugi program praktycznie identyczny z przykładowym dołączonym do kompilatora. Przesymulowałem i tam przerwanie jest zgłaszane, natomiast u mnie nie.

    0
  • #8 04 Lis 2010 09:58
    94075
    Użytkownik usunął konto  
  • #9 04 Lis 2010 12:35
    marcin026
    Poziom 9  

    Program kończy w 196 ponieważ jest tam instrukcja B .

    Code:

    Default_Handler PROC

                    EXPORT  WAKEUP_IRQHandler         [WEAK]
                    EXPORT  SSP1_IRQHandler           [WEAK]
                    EXPORT  I2C_IRQHandler            [WEAK]
                    EXPORT  TIMER16_0_IRQHandler      [WEAK]
                    EXPORT  TIMER16_1_IRQHandler      [WEAK]
                    EXPORT  TIMER32_0_IRQHandler      [WEAK]
                    EXPORT  TIMER32_1_IRQHandler      [WEAK]
                    EXPORT  SSP0_IRQHandler           [WEAK]
                    EXPORT  UART_IRQHandler           [WEAK]
                    EXPORT  ADC_IRQHandler            [WEAK]
                    EXPORT  WDT_IRQHandler            [WEAK]
                    EXPORT  BOD_IRQHandler            [WEAK]
                    EXPORT  PIOINT3_IRQHandler        [WEAK]
                    EXPORT  PIOINT2_IRQHandler        [WEAK]
                    EXPORT  PIOINT1_IRQHandler        [WEAK]
                    EXPORT  PIOINT0_IRQHandler        [WEAK]

    WAKEUP_IRQHandler
    SSP1_IRQHandler
    I2C_IRQHandler
    TIMER16_0_IRQHandler
    TIMER16_1_IRQHandler
    TIMER32_0_IRQHandler
    TIMER32_1_IRQHandler
    SSP0_IRQHandler
    UART_IRQHandler
    ADC_IRQHandler
    WDT_IRQHandler
    BOD_IRQHandler
    PIOINT3_IRQHandler
    PIOINT2_IRQHandler
    PIOINT1_IRQHandler
    PIOINT0_IRQHandler

                    B       .     ;ta linia

                    ENDP

    zresztą z przerwaniem od timera0 w programie przykładowym jest podobnie a przerwanie jest obsługiwane czyli program skacze tam do funkcji __irq void SysTick_Handle(void)
    Code:

    SysTick_Handler PROC
                    EXPORT  SysTick_Handler           [WEAK]
                    B       .
                    ENDP

    Chyba że obsługa przerwania w uVision to coś więcej niż napisanie funkcji o takiej samej nazwie jak w pliku startup.

    0
  • #10 04 Lis 2010 12:59
    94075
    Użytkownik usunął konto  
  • Pomocny post
    #11 04 Lis 2010 14:29
    wujcio24
    Poziom 13  

    Najlepszą metodą znalezienia błędu w przypadku jak nic nie pomaga jest analiza kodu w asemblerze jaki został wygenerowany z twojego programu i porównanie go z działającym programem. Pamiętaj że rdzeń cortex-m0 w przeciwieństwie do cortex-m3 jest znacznie prostszy i analiza asemblera nie jest aż tak skomplikowana oczywiście na początku wyda ci się to wręcz nie możliwe do ogarnięcia ale tak naprawdę nie masz tam wielu instrukcji:
    LDR - ładowanie danych z pamięci do rejestru
    STR - ładowanie danych z rejestru do pamięci (rejestr w nawiasach[] na przykład [R1] ma wartość adresu do którego dane mają być załadowane).
    SUB - odejmowanie
    ADD - dodawanie
    LSL - przesunięcie logiczne w lewo
    MOV - wpisanie wartości z rejestru do innego rejestru
    POP - odłożenie na stos
    PUSH - zdjęcie ze stosu
    B - skok do określonego miejsca w pamięci
    BL - skok ze śladem

    Tych instrukcji jest oczywiście więcej ja dałem ci takie niezbędne minimum.

    Co do instrukcji są jeszcze dwie ważne zasady:
    1. Jak chcesz robić operacje nie na rejestrach a wartościach stałych to musisz dopisać do instrukcji literkę S na przykład MOVS R1, #21.
    2. Pewne instrukcje możesz wykonywać tylko na dolnych rejestrach - R0 do R8 chyba.

    Napisz jeszcze czy potrafisz dokonać deasemblacji (chyba tak to się pisze) kodu programu - to także jest przydatna umiejętność. Jeżeli nie potrafisz to ci napisze jak się to robi.

    Napisz także jaką obecnie wiedzę posiadasz żebyśmy wiedzieli gdzie możesz popełniać błędy.

    0
  • #12 04 Lis 2010 14:40
    marcin026
    Poziom 9  

    Programowałem na razie tylko AVRy, w C i troszkę w ASM, w tej chwili próbuje się przesiąść na ARMy, z racji tego że ich nie posiadam (jeszcze) symuluje w Keilu. Deasemblacji dokonałem (włączyłem okienko disassembly w Keilu)

    0
  • #13 04 Lis 2010 16:38
    wujcio24
    Poziom 13  

    Ja bym polecał ci przesiąść się na LPCXpresso według mnie jest znacznie wygodniejsze od Keila dodatkowo pisząc w LPCXpresso możesz dalej debugować w keilu tak jak to robisz do tej pory. Wygląda to dokładnie tak:
    1. Tworzysz nowy fikcyjny projekt w keilu powiedzmy dioda (trzeba wybrać mikrokontroler taki z jakim będziemy pracować)
    2. Piszesz w LPCXpresso i kompilujesz projekt w wyniku czego jest generowany plik AXF.
    3. Ten plik kopiujesz do miejsca gdzie masz projekt w Keilu i zmieniasz nazwę na dioda.axf .
    4. Odpalasz Keila i debugujesz jak do tej pory.

    Polecam LPCXpresso bo:
    1. Według mnie jest prostsze od Keila.
    2. Jest darmowe (chyba).
    3. Jest masa przykładów.
    4. Wyjdzie wersja pod Linuksa (jest już beta).

    Polecam zapoznać się z LPCXpresso - na pewno na tym nie stracisz.

    Co do deasemblacji w Keilu według mnie jest to bardzo dziwnie wyświetlone i polecam jednak użyć narzędzi zawartych w GCC czyli objdumpa.

    A polecenie z konsoli Windowsa wygląda następująco

    Code:

    C:\nxp\lpcxpresso_3.2\Tools\bin\arm-none-eabi-objdump.exe -d C:\lpcxpresso\asm_led_switch\Debug\asm_led_switch.axf > c:\kod_asm.txt

    W miejscu gdzie jest -d zamiast niego może być -D co oznacza żeby zrobić deasemblacje wszystkiego a także masz do wyboru następujące opcje: http://it-pomoc.pl/linux/objdump . najbardziej powinna interesować ciebie opcja zestawienia instrukcji z kodem w C. Nie radzę też tworzyć folderów z nazwą która składa się z dwóch wyrazów a w środku zamiast "_" jest spacja.
    Code:

    C:\lpcxpresso\asm_led_switch\Debug\asm_led_switch.axf - miejsce gdzie jest plik .axf


    Natomiast ten znak ">" oznacza że wynik działania komendy ma zostać zapisana do pliku (możliwe że co innego ale to nie istotne ważne że działa).

    Warto przejrzeć te dokumenty tam masz trochę wiedzy która może ci się przydać:
    http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/index.html
    http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0432c/index.html

    0
  • #14 04 Lis 2010 16:47
    Freddie Chopin
    Specjalista - Mikrokontrolery

    wujcio24 napisał:
    Ja bym polecał ci przesiąść się na LPCXpresso
    [...]
    Polecam LPCXpresso bo:
    1. Według mnie jest prostsze od Keila.
    2. Jest darmowe (chyba).
    3. Jest masa przykładów.
    4. Wyjdzie wersja pod Linuksa (jest już beta).

    Polecam zapoznać się z LPCXpresso - na pewno na tym nie stracisz.

    Na pewno też nie stracisz poznając narzędzia, które naprawdę nie mają żadnych ograniczeń (obsługują wszystko, a nie tylko układy LPC), są darmowe, a nie "darmowe" itd.

    https://www.elektroda.pl/rtvforum/topic1313509.html
    https://www.elektroda.pl/rtvforum/topic1339518-0.html

    4\/3!!

    0
  • #15 04 Lis 2010 17:55
    marcin026
    Poziom 9  

    W działającym przykładzie (po disasembleracji) mam coś takiego:

    Code:

    0x000000E0 E7FE      B        SysTick_Handler (0x000000E0)

    jeśli to jest wektor przerwania to jak ono ma zostać obsłużone jak program sie zatrzymuje? Tylko że chyba nie jest bo jak nadchodzi przerwanie to program wskakuje pod etykietę
    Code:

        25:   SysTickCnt++;
    0x000000F4 4832      LDR      r0,[pc,#200]  ; @0x000001C0

    w takim razie gdzie te wektory są, bo rozumiem że pod wektorem przerwanie musi być skok pod etykietę od której się przerwanie zaczyna.

    0
  • #16 04 Lis 2010 18:25
    wujcio24
    Poziom 13  

    Code:
    0x000000E0 E7FE      B        SysTick_Handler (0x000000E0) 


    To mi wygląda na pętle nieskończoną czyli wygląda to tak program wchodzi w ten adres : 0x000000E0 i wykonuje skok pod adres taki sam do jakiego wszedł a tak być nie może i dlatego widzisz że program "stoi". Teraz włączyłem Keila i przejrzałem tego start up i bym proponował coś takiego (ostrzegam że w Keilu nigdy nie pisałem i mogę się mylić).

    Funkcje która ma wykonywać się zaraz po zgłoszeniu przerwania nazwij powiedzmy dioda i zrób w kodzie (startup) coś takiego:
    Code:

                 SysTick_Handler PROC
                 EXPORT  SysTick_Handler           [WEAK]
                 B       dioda
                 ENDP


    Nie daje gwarancji że zadziała bez sypnięcia jakimiś błędami (na początku chciałem pisać w Keilu w asmie ale uznałem że to jest nie normalne i dlatego pisze w LPCXpresso - miałem masę błędów). Ewentualnie możesz tą całość z startupa wywalić (to co wkleiłem) razem z etykietą, tylko wtedy będzie chyba trzeba jakoś to zadeklarować (może uda się bez deklaracji). Jak już będzie ciężko polecam jeszcze raz przemyśleć to co mówiłem o LPCXpresso.

    0
  • #17 04 Lis 2010 23:10
    marcin026
    Poziom 9  

    LPCXpresso jako kompilatora używa arm-none-eabi czy ja cos pochrzaniłem przy instalacji Eclipse z tutorialu napisanego przez Freddie'go Chopin'a?

    0
  • #18 04 Lis 2010 23:25
    Freddie Chopin
    Specjalista - Mikrokontrolery

    No a jakiego kompilatora ma używać? 99% tych "darmowych" pakietów bazuje na CodeSourcery (czyli arm-none-eabi-...).

    4\/3!

    0