Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Kategoria: Kamery IP / Alarmy / Automatyka Bram
Montersi
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Wszystko o ARM (LPCxxxx) i programowaniu w asm i C.

atom1477 08 Lis 2009 17:51 15217 141
  • Pomocny post
    #91 08 Lis 2009 17:51
    94075
    Usunięty  
  • Pomocny post
    #92 08 Lis 2009 18:58
    arrevalk
    Poziom 25  

    Można też poczytać o szczegółach implementacji FreeRTOS: Link .
    Jeżeli nie wyświetli się po lewej stronie menu, to wchodzimy na www.freertos.org
    More Advanced...->How FreeRTOS works.
    Co prawda omawiana tam jest implementacja na AVR, ale po takiej lekturze można zajrzeć do źródeł samego systemu.

  • #93 08 Lis 2009 21:12
    atom1477
    Poziom 43  

    albertb napisał:
    Bo wyjście z wątku jest normalną instrukcją return z funkcji (ukrytej w makrach), więc kompilator załatwia sprawy zwiazane ze stosem za Ciebie.

    No ale to oznacza że wątek kończy się wtedy kiedy kończy się funkcja.
    Czyli inaczej mówiąc kiedy kończy się blok, bo mówiąc blok właśnie miałem na myśli taką jedną nierozbijaną na mniejsze kawałki funkcję.

    A mi chodzi o to żeby można było opuścić blok (funkcję) w środku jej wykonywania. I później do niej powrócić oczywiście.
    Bo właśnie mam funkcję która się wykonuje kilka sekund.


    albertb napisał:
    Natomiast powoduje to pewne ograniczenia kodu tych "wątkowych" funkcji i raczej trzeba używać zmiennych statycznych,
    bo wartości lokalnych nie są zachowywane. Ale wszystko jest na stronie i moim zdaniem warto przez to przebrnąć, bo i przydaje się, i poszerza zrozumienie języka.

    Albert

    To akurat była by dla mnie mała wada, ale z poprzedniego powodu prawdopodobnie to odpada.


    arrevalk napisał:
    Można też poczytać o szczegółach implementacji FreeRTOS: Link .
    Jeżeli nie wyświetli się po lewej stronie menu, to wchodzimy na www.freertos.org
    More Advanced...->How FreeRTOS works.
    Co prawda omawiana tam jest implementacja na AVR, ale po takiej lekturze można zajrzeć do źródeł samego systemu.


    Rzecz w tym że podstawy znam. Tym bardziej dla AVR. Po prostu na razie nie mam czasu i potrzeby robić tego na ARMie. Moim zdaniem sposób w jaki ja chcę to zrobić jest wcale nie najgorszy. Generowanie przebiegu o dużej szybkości na FIQ. Odbieranie danych z UARTów na IRQ. Też normalka.
    Zostaje LCD i to jest jedyna wątpliwa rzecz. Ale dla Was, bo na pewnio nie dla mnie :D

    Jutro to przetestuję.

    Zresztą to nie pierwsza i nie ostatnia rzecz do której nikt mnie nie przekona.
    Do C też nikt mnie nie przekonał. Musiałem przekonać się sam.
    Tak samo i tutaj. Może i robię źle, ale sam muszę do tego dojść.
    Więc daremny jest Wasz trud przekonywania mnie :D
    W każdym razie dzięki za tkwienie w temacie.

  • Pomocny post
    #94 09 Lis 2009 09:00
    94075
    Usunięty  
  • #95 19 Lis 2009 16:55
    atom1477
    Poziom 43  

    Znowu problemy :D
    1. BootLoader.
    Przeczytałem sobie notę AN10835_1 od NXP i chciałem się zabrać za zapis do pamięci FLASH.

    Code:

    #define Fcclk 72000000

    #define IAP_CLK Fcclk
    #define IAP_LOCATION 0x7FFFFFF1
    #define iap_entry(a, b) ((void (*)())(IAP_LOCATION))(a, b)
    unsigned long command[5] = {0,0,0,0,0};
    unsigned long result[3]= {0,0,0};

    #define IAP_CMD_PrepareSec     50
    #define IAP_CMD_EraseSec       52
    #define IAP_CMD_CopyRAMToFlash 51

    volatile uint32_t VICIntEnable_backup;

    ...
    ...

                       VICIntEnable_backup = VICIntEnable;
                       VICIntEnable = 0;

                       command[0] = IAP_CMD_PrepareSec;
                       command[1] = 24;    // StartSecNum
                       command[2] = 25;    // EndSecNum
                       iap_entry(command, result);


                       command[0] = IAP_CMD_EraseSec;
                       command[1] = 24;
                       command[2] = 25;
                       command[3] = IAP_CLK / 1000;
                       iap_entry(command, result);


                       VICIntEnable = VICIntEnable_backup;


                       sprintf(Text, "Juz");
                       Text_ptr = Text;
                       Pisz_16x16(Text_ptr, 380, 380);


    No i po pierwsze nie wiem jaką mam zadeklarować częstotliwość Fcclk. W nocie katalogowej nie raczyli tego napisać. U mnie Fcclk to 432MHz ale trochę trudno mi uwierzyć że o tą częstotliwość chodzi. No ale nic, podstawiłem. No i nie działa.
    Powstawiałem w MHz, kHz i Hz. Potem 72MHz tak samo.
    Też nic. Program zawiesza się gdzieś na wywołaniu procedury kasowania sektorów.
    To znaczy nie wypisuje mi textu „Juz” a przerwania nie są przywracane do działania.
    Samo zaznaczanie sektorów (IAP_CMD_PrepareSec) działa.

    Napisali coś takiego:
    Code:

    command[4] = IAP_CLK / 1000;// Fcclk in KHz

    ale to też nic nie mówi bo nie wiadomo czy to Fcclk czy może command[4] ma być w kHz. Oczywiście wyraźnie napisali że Fcclk, ale cholera ich tam wie bo wspomnieli o tym tylko raz, w tym miejscu gdzie jest dzielenie przez 1000.

    Więc pytanie: co robię źle?

    2. Wrapper przerwań.
    Wszystkie przerwania ustawiłem jako IRQ (to znaczy to co było FIQ zamieniłem na IRQ).
    Skompilowałem. Zaprogramowałam. Przetestowałem. Działa.
    Oczywiście zagnieżdżania przerwań nie było, ale przerwania i program główny się wykonywały/wykonywał i robiły/robił to co trzeba.
    No to teraz wstawiłem takie coś do pliku vectors:
    Code:

    /******************************************************************************
    * author: Freddie Chopin
    * file: vectors.s
    * last change: 2009-06-01
    *
    * chip: LPC2478
    * compiler: arm-none-eabi-gcc 4.3.3
    *
    * description:
    * vector table for ARM7TDMI-S / LPC2478
    ******************************************************************************/

    .arm
    .section .vectors
    _vectors:

       ldr      PC,Reset_vector               // Reset exception
       ldr      PC,Undefined_vector            // Undefined Instruction exception
       ldr      PC,SWI_vector               // Software Interrupt exception
       ldr      PC,Prefetch_Abort_vector      // Prefetch Abort exception
       ldr      PC,Data_Abort_vector         // Data Abort exception
       nop                              // reserved for code signature
       ldr      PC,IRQ_Wrapper
       ldr      PC,FIQ_vector               // Fast Interrupt exception

    Reset_vector:         .word   Reset_Handler
    Undefined_vector:      .word   Undefined_Handler
    SWI_vector:            .word   SWI_Handler
    Prefetch_Abort_vector:   .word   Prefetch_Abort_Handler
    Data_Abort_vector:      .word   Data_Abort_Handler
    FIQ_vector:            .word   FIQ_Handler

    //******************************************************************************
        .equ    NO_IRQ,         0x80                     /* mask to disable IRQ */
        .equ    NO_FIQ,         0x40                     /* mask to disable FIQ */
        .equ    NO_INT,         (NO_IRQ | NO_FIQ) /*mask to disable IRQ and FIQ */
        .equ    FIQ_MODE,       0x11
        .equ    IRQ_MODE,       0x12
        .equ    SYS_MODE,       0x1F

    IRQ_Wrapper:
        MOV     r13,r0              /* save r0 in r13_IRQ */
        SUB     r0,lr,#4            /* put return address in r0_SYS */
        MOV     lr,r1               /* save r1 in r14_IRQ (lr) */
        MRS     r1,spsr             /* put the SPSR in r1_SYS */

        MSR     cpsr_c,#(SYS_MODE | NO_IRQ) /* SYSTEM, no IRQ, but FIQ enabled! */
        STMFD   sp!,{r0,r1}         /* save SPSR and PC on SYS stack */
        STMFD   sp!,{r2-r3,r12,lr}  /* save APCS-clobbered regs on SYS stack */
        MOV     r0,sp               /* make the sp_SYS visible to IRQ mode */
        SUB     sp,sp,#(2*4)        /* make room for stacking (r0_SYS, r1_SYS) */

        MSR     cpsr_c,#(IRQ_MODE | NO_IRQ) /* IRQ mode, IRQ/FIQ disabled */
        STMFD   r0!,{r13,r14}       /* finish saving the context (r0_SYS,r1_SYS)*/

        MSR     cpsr_c,#(SYS_MODE | NO_IRQ) /* SYSTEM mode, IRQ disabled */

        //LDR     r12,=BSP_irq
        ldr      R12,[PC,#-0x120]      //VICVectAddr
        MOV     lr,pc               /* copy the return address to link register */
        BX      r12                 /* call the C IRQ-handler (ARM/THUMB) */


        MSR     cpsr_c,#(SYS_MODE | NO_INT) /* SYSTEM mode, IRQ/FIQ disabled */
        MOV     r0,sp               /* make sp_SYS visible to IRQ mode */
        ADD     sp,sp,#(8*4)        /* fake unstacking 8 registers from sp_SYS */

        MSR     cpsr_c,#(IRQ_MODE | NO_INT) /* IRQ mode, both IRQ/FIQ disabled */
        MOV     sp,r0               /* copy sp_SYS to sp_IRQ */
        LDR     r0,[sp,#(7*4)]      /* load the saved SPSR from the stack */
        MSR     spsr_cxsf,r0        /* copy it into spsr_IRQ */

        LDMFD   sp,{r0-r3,r12,lr}^  /* unstack all saved USER/SYSTEM registers */
        NOP                         /* can't access banked reg immediately */
        LDR     lr,[sp,#(6*4)]      /* load return address from the SYS stack */
        MOVS    pc,lr               /* return restoring CPSR from SPSR */

    /******************************************************************************
    * END OF FILE
    ******************************************************************************/


    No więc od razu pytanie: Co jest źle? Bo oczywiście nie działa. Wszystko ulega zawieszeniu. Pewnie generowany jest jakiś wyjątek, ale oczywiście debugowanie mi nie działa więc nie mam jak sprawdzić.
    Przykład to to coś podane przez Freddiego Chopina dla procesorów ATMELa.
    Jedyne co zrobiłem to linijkę:
    LDR r12,=BSP_irq
    zamieniłem na:
    ldr R12,[PC,#-0x120] //VICVectAddr

  • Pomocny post
    #96 19 Lis 2009 17:26
    94075
    Usunięty  
  • #97 19 Lis 2009 18:22
    atom1477
    Poziom 43  

    albertb napisał:
    1. Fcclk to częstotliwość taktowania procesora w Hz.

    Ok.

    albertb napisał:
    2. Spróbuj z pojedynczym sektorem

    No właśnie nie wiedziałem jak to się liczy i myślałem że sektor końcowy musi być większy od początkowego więc tak to ustawiłem dlatego (Myślałem że sektor końcowy to sektor który ma już nie być obsługiwany). Ale sprawdzę.

    albertb napisał:
    3. Wyłącz przerwania ustawiając CPSR, a nie VIC

    Jak doczytam jak to zrobić to tak zrobię :D

    albertb napisał:
    4. Mam nadzieję, że przerwań nie deklarujesz w kodzie z atrybutem interrupt?

    A tutaj chodzi Ci o zapis do FLASHa czy o Wrappera przerwań? Jak by jednak nie było przerwania mają atrybut "IRQ". Dlaczego miały by nie mieć? Żeby kompilator nie dorzucał ich obsługi bo Wrapper sam ją załatwia?

  • Pomocny post
    #98 19 Lis 2009 18:32
    Freddie Chopin
    Specjalista - Mikrokontrolery

    atom1477 napisał:
    albertb napisał:
    3. Wyłącz przerwania ustawiając CPSR, a nie VIC

    Jak doczytam jak to zrobić to tak zrobię :D

    W startupie jest to przecież zrobione 6x - zobacz po prostu jak.

    Cytat:
    albertb napisał:
    4. Mam nadzieję, że przerwań nie deklarujesz w kodzie z atrybutem interrupt?

    A tutaj chodzi Ci o zapis do FLASHa czy o Wrappera przerwań? Jak by jednak nie było przerwania mają atrybut "IRQ". Dlaczego miały by nie mieć? Żeby kompilator nie dorzucał ich obsługi bo Wrapper sam ją załatwia?

    Skoro masz odpowiedni sposób powrotu we wrapperze, a przerwania wywołujesz z niego jak zwyczajne funkcje, to nie mogą być one z atrybutem, bo inaczej wygląda sekwencja powrotu z przerwania, a inaczej z funkcji. Tutaj twój Wrapper zajmuje się powrotem z przerwania.

    4\/3!!

  • #99 19 Lis 2009 19:54
    atom1477
    Poziom 43  

    Freddie Chopin napisał:
    atom1477 napisał:
    albertb napisał:
    3. Wyłącz przerwania ustawiając CPSR, a nie VIC

    Jak doczytam jak to zrobić to tak zrobię :D

    W startupie jest to przecież zrobione 6x - zobacz po prostu jak.

    Właśnie o to mi chodziło bo wiem że to tam jest :D
    Doczytanie właśnie miało polegać na zajrzeniu do startupa :D


    Freddie Chopin napisał:
    Cytat:
    albertb napisał:
    4. Mam nadzieję, że przerwań nie deklarujesz w kodzie z atrybutem interrupt?

    A tutaj chodzi Ci o zapis do FLASHa czy o Wrappera przerwań? Jak by jednak nie było przerwania mają atrybut "IRQ". Dlaczego miały by nie mieć? Żeby kompilator nie dorzucał ich obsługi bo Wrapper sam ją załatwia?

    Skoro masz odpowiedni sposób powrotu we wrapperze, a przerwania wywołujesz z niego jak zwyczajne funkcje, to nie mogą być one z atrybutem, bo inaczej wygląda sekwencja powrotu z przerwania, a inaczej z funkcji. Tutaj twój Wrapper zajmuje się powrotem z przerwania.

    4\/3!!


    I to mnie trochę cieszy bo trochę się martwiłem że Wrapper mocno obciąży procesor. Ale skoro Wrapper przejmuje trochę tej roboty która wcześniej i tak była robiona to tym lepiej.
    A co z zapisem do rejestru VICVectAddr pod koniec obsługi przerwań? Ma być czy nie? Obstawiam że nie bo w takim razie zapis do tego rejestru następował by za wcześnie.

  • Pomocny post
    #100 19 Lis 2009 20:17
    94075
    Usunięty  
  • #101 19 Lis 2009 21:06
    atom1477
    Poziom 43  

    O! Aż tak? No ale dobra :D
    Niestety Eclipse nie łyka stałych USER_MODE czy CPSR_I (plik hdr/hdr_cpsr.h oczywiście dołączyłem) więc musiałem się podratować wpisaniem konkretnych liczb. Mam nadzieję że zadziała :D
    Idę testować.

    Dodano po 26 [minuty]:

    Niestety nic nie działa.
    Fcclk = 72000000
    Jeden sektor (24)
    Wyłączanie i włączanie przerwań za pomocą CPSR.
    Nie działa.

    Przerwania bez atrybutu „IRQ”.
    Też nie działa.

    Program wchodzi do Wrappera albo przynamniej próbuje wejść. Widzę bo program główny trochę się wykonuje (umieściłem trochę rzeczy przed włączeniem kontrolera VIC) i nagle przestaje.
    Ale przerwanie już się nie wykonuje (w przerwaniu mam zmianę stanu pinu (diody) i dioda się nie zaświeca/nie zaczyna migać).

  • Pomocny post
    #102 20 Lis 2009 08:55
    94075
    Usunięty  
  • #103 20 Lis 2009 11:48
    atom1477
    Poziom 43  

    Dobra, Chyba rozumiem. Czyli ten fragment będzie dobry tylko wtedy gdy będzie umieszczony na siódmej pozycji po etykiecie "_vectors:", tak?

    Czyli może być:

    Code:

    ldr R12, VICVectAddr_data
    ldr R12, [R12]      //VICVectAddr
    ...
    ...
    VICVectAddr_data:   .word   0xFFFFFF00

    ?

    Bo chyba takie coś nie przejdzie:
    Code:

    Label_1:
    ldr      R12,[PC,#(-0x100 - Label1)]      //VICVectAddr

    ?

  • Pomocny post
    #104 20 Lis 2009 12:16
    Freddie Chopin
    Specjalista - Mikrokontrolery

    atom1477 napisał:
    Czyli może być:
    Code:

    ldr R12, VICVectAddr_data
    ldr R12, [R12]      //VICVectAddr
    ...
    ...
    VICVectAddr_data:   .word   0xFFFFFF00

    ?

    Możesz zrobić tak:

    ldr R12, =0xFFFFFF00

    4\/3!!

  • #105 20 Lis 2009 12:26
    atom1477
    Poziom 43  

    Wiem, ale dla pewności dałem po swojemu bo nie wiadomo gdzie kompilator wstawi ten adres. Nie jest głupi ale w tak krytycznym miejscu może nie skumać o co chodzi.

  • Pomocny post
    #106 20 Lis 2009 12:29
    Freddie Chopin
    Specjalista - Mikrokontrolery
  • #107 20 Lis 2009 19:56
    atom1477
    Poziom 43  

    Jeżeli tutaj:

    Code:

        MSR     cpsr_c,#(IRQ_MODE | NO_INT) /* IRQ mode, both IRQ/FIQ disabled */
        MOV     sp,r0               /* copy sp_SYS to sp_IRQ */
        0xFFFFFF00
        LDR     r0,[sp,#(7*4)]      /* load the saved SPSR from the stack */
        MSR     spsr_cxsf,r0        /* copy it into spsr_IRQ */

    to trochę będzie różnica ;p
    Ale kompilator na pewno nie jest taki głupi.
    Niestety zła wiadomość jest taka że po poprawieniu tego adresu Wrapper nadal nie działa.


    EDIT1. A czy ten kod na pewno będzie pasował też do rdzenia ARMv4?

    EDIT2. A może mi ktoś wyjaśnić jak rozpocząć debugowanie?
    Na razie doszedłem do tego że trzeba wejść do Debug Configurations.
    Potem New_configuration tylko nie wiem gdzie. Na razie bezmyślnie biorę C/C++ Attach to Local Application.
    W Project wybieram mój projekt i dalej już nie wiem co mam zrobić.


    EDIT3. Dobra. Częściowo rozwiązałem problem.
    Problemem było to:
    Code:

       ldr      PC,Data_Abort_vector         // Data Abort exception
       nop                              // reserved for code signature
       //ldr      PC,[PC,#-0x120]               // Interrupt exception -> VIC
       ldr      PC,IRQ_Wrapper                       //<-------------------------------------
       ldr      PC,FIQ_vector               // Fast Interrupt exception

    Reset_vector:         .word   Reset_Handler
    Undefined_vector:      .word   Undefined_Handler
    SWI_vector:            .word   SWI_Handler
    Prefetch_Abort_vector:   .word   Prefetch_Abort_Handler
    Data_Abort_vector:      .word   Data_Abort_Handler
    FIQ_vector:            .word   FIQ_Handler

    //******************************************************************************
        .equ    NO_IRQ,         0x80                     /* mask to disable IRQ */
        .equ    NO_FIQ,         0x40                     /* mask to disable FIQ */
        .equ    NO_INT,         (NO_IRQ | NO_FIQ) /*mask to disable IRQ and FIQ */
        .equ    FIQ_MODE,       0x11
        .equ    IRQ_MODE,       0x12
        .equ    SYS_MODE,       0x1F

    IRQ_Wrapper:                       //<-------------------------------------
        MOV     r13,r0              /* save r0 in r13_IRQ */


    Zamieniłem to na:
    Code:

       ldr      PC,Data_Abort_vector         // Data Abort exception
       nop                              // reserved for code signature
       //ldr      PC,[PC,#-0x120]               // Interrupt exception -> VIC
       ldr      PC,Wrapper_vector                       //<-------------------------------------
       ldr      PC,FIQ_vector               // Fast Interrupt exception

    Reset_vector:         .word   Reset_Handler
    Undefined_vector:      .word   Undefined_Handler
    SWI_vector:            .word   SWI_Handler
    Prefetch_Abort_vector:   .word   Prefetch_Abort_Handler
    Data_Abort_vector:      .word   Data_Abort_Handler
    Wrapper_vector:         .word   Wrapper_Handler                       //<-------------------------------------
    FIQ_vector:            .word   FIQ_Handler

    //******************************************************************************
        .equ    NO_IRQ,         0x80                     /* mask to disable IRQ */
        .equ    NO_FIQ,         0x40                     /* mask to disable FIQ */
        .equ    NO_INT,         (NO_IRQ | NO_FIQ) /*mask to disable IRQ and FIQ */
        .equ    FIQ_MODE,       0x11
        .equ    IRQ_MODE,       0x12
        .equ    SYS_MODE,       0x1F

    Wrapper_Handler:                       //<-------------------------------------
        MOV     r13,r0              /* save r0 in r13_IRQ */


    I działa. A jakim sposobem do tego doszedłem! Umieszczałem sobie z różnych miejscach kodu kod zapalający diodę :D

    Ale żadnego zagnieżdżania przerwań nie ma. Jak bym nie ustawił priorytetów to gdy wyskoczy mi dłuższe przerwanie to to krótsze a częściej wywoływane przerwanie nie chce się wbijać w to pierwsze przerwanie.


    EDIT4. Nie bardzo rozumiem to:
    Code:

        MSR     cpsr_c,#(IRQ_MODE | NO_IRQ) /* IRQ mode, IRQ/FIQ disabled */
        STMFD   r0!,{r13,r14}       /* finish saving the context (r0_SYS,r1_SYS)*/

        MSR     cpsr_c,#(SYS_MODE | NO_IRQ) /* SYSTEM mode, IRQ disabled */    //<---- To ----

        //LDR     r12,=BSP_irq
        ldr R12, =0xFFFFFF00
        ldr R12, [R12]      //VICVectAddr
        MOV     lr,pc               /* copy the return address to link register */
        BX      r12                 /* call the C IRQ-handler (ARM/THUMB) */


    Ja bym raczej przed wykonaniem skoku do procedury obsługi przerwania spowrotem włączył przerwania IRQ.
    Może dlatego zagnieżdżanie nie działa, mimo że samo wywoływanie procedur obsługi przerwań działa?

    EDIT5 :D. Chyba tak, bo znalazłem to:
    Cytat:
    NOTE: The BSP_irq() function is entered with IRQ disabled (and FIQ enabled), but it can internally unlock IRQs, if the MCU is equipped with an interrupt controller that performs prioritization of IRQs in hardware.


    Pytanie tylko czy nie można włączyć przerwań IRQ wcześniej, w miejscu w kodzie któro zaznaczyłem komentarzem: “<---- To ----„.
    Można tam czy musowo dopiero później?

  • Pomocny post
    #108 21 Lis 2009 23:45
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Można włączyć IRQ wcześniej, ale wtedy masz ZAWSZE zagnieżdżone przerwania, nawet jeśli nie ma to sensu (bo po co długie przerwanie miałoby przerywać inne - bardzo krótkie). Jeśli włączasz je dopiero wewnątrz obsługi danego przerwania, to masz nad tym lepszą kontrolę.

    4\/3!!

  • #109 22 Lis 2009 10:17
    atom1477
    Poziom 43  

    Freddie Chopin napisał:
    Można włączyć IRQ wcześniej, ale wtedy masz ZAWSZE zagnieżdżone przerwania, nawet jeśli nie ma to sensu (bo po co długie przerwanie miałoby przerywać inne - bardzo krótkie). Jeśli włączasz je dopiero wewnątrz obsługi danego przerwania, to masz nad tym lepszą kontrolę.

    4\/3!!


    No ale chyba po to są priorytety przerwań żeby można sobie było ustawić to tak żeby krótkie przerwanie mogło wbić się w długie, ale długie już nie mogło w krótkie. Czy czegoś nie rozumiem?

  • Pomocny post
    #110 22 Lis 2009 11:15
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Można to zrobić tylko priorytetami, ale można też decydować "ręcznie" czy przerwanie może być przerywane czy nie.

    4\/3!!

  • #111 22 Lis 2009 11:22
    atom1477
    Poziom 43  

    Skoro można tylko priorytetami to jak można ręcznie?

    Dodano po 1 [minuty]:

    Mi się zdaje że co najwyżej można zablokować przerywanie jakiegoś przerwania jeżeli nie włączę w nim przerwań IRQ.

  • Pomocny post
    #112 22 Lis 2009 11:32
    Freddie Chopin
    Specjalista - Mikrokontrolery

    No przecież o tym właśnie mówię. Jeśli chcesz żeby przerwanie mogło być przerwane przez inne - włączasz w nim IRQ, jeśli nie chcesz, nie wyłączasz i tyle.

    4\/3!!

  • #113 22 Lis 2009 11:45
    atom1477
    Poziom 43  

    No nie do końca. Bo jeżeli inne przerwanie będzie miało mniejszy priorytet to nie przerwie innego właśnie wykonującego się przerwania nawet jak włączę w nim IRQ.

    Ale łapię bazę. Już nawet wiem jak zorganizować dwa przerwania o takim samym priorytecie aby się wzajemnie nie przerywały oraz jak zrobić żeby jedno przerwanie nie zagnieździło samo siebie (Jak czas wykonania przerwania będzie dłuższy od odstępu pomiędzy wywołaniami przerwania. Np. UART zgłosi przerwanie że ma nowy znak a poprzednie przerwanie przelicza CRC bo poprzedni znak z UARTa zakończył poprzednią ramkę danych).

    Dodano po 1 [minuty]:

    No więc dzięki za pomoc bo chyba to już będzie działało.

  • Pomocny post
    #114 22 Lis 2009 11:55
    Freddie Chopin
    Specjalista - Mikrokontrolery

    No ale z tego co mi wiadomo przerwanie o priorytecie X nie może być przerwane przez inne / to samo o priorytecie X - do "przerwania przerwania przerwaniem" <: priorytet musi być większy.

    4\/3!!

  • #115 26 Lis 2009 14:27
    atom1477
    Poziom 43  

    Tym lepiej.


    EDIT. No to tak.
    Chcę w końcu odpalić ten zapis do FLASHa.
    Jako że sam zapis nie działa, to chciałem uruchomić przynajmniej inne mające współdziałać z tym zapisem rzeczy.
    No więc jeden sektor chcę przeznaczyć na ustawienia.
    Wybrałem ostatni, czyli ten od 0x0007D000 do 0x0007FFFF.
    Walnąłem sobie coś takiego bo domyślam się że to najlepszy sposób:

    Code:

    MEMORY
    {
        rom (rx)    : org = 0x00000000, len = 500k
        eeprom (rwx) : org = 0x0007D000, len = 4k
        ram (rwx)    : org = 0x40000000, len = 64k
        sdram0 (rwx) : org = 0xA0000000, len = 8192k      /* External SDRAM Bank0: 8M */   
    }

    __rom_start = ORIGIN(rom);
    __rom_size = LENGTH(rom);
    __rom_end = __rom_start + __rom_size;

    __eeprom_start = ORIGIN(eeprom);
    __eeprom_size = LENGTH(eeprom);
    __eeprom_end = __eeprom_start + __eeprom_size;

    __ram_start = ORIGIN(ram);
    __ram_size = LENGTH(ram);
    __ram_end = __ram_start + __ram_size;

    __sdram0_start = ORIGIN(sdram0);
    __sdram0_size = LENGTH(sdram0);
    __sdram0_end = __sdram0_start + __sdram0_size;

    PROVIDE(__rom_start = __rom_start);
    PROVIDE(__rom_size = __rom_size);
    PROVIDE(__rom_end = __rom_end);

    PROVIDE(__eeprom_start = __eeprom_start);
    PROVIDE(__eeprom_size = __eeprom_size);
    PROVIDE(__eeprom_end = __eeprom_end);

    PROVIDE(__ram_start = __ram_start);
    PROVIDE(__ram_size = __ram_size);
    PROVIDE(__ram_end = __ram_end);

    PROVIDE(__sdram0_start = __sdram0_start);
    PROVIDE(__sdram0_size = __sdram0_size);
    PROVIDE(__sdram0_end = __sdram0_end);


    Czyli stworzyłem sobie nową sekcję eeprom.
    Potem mogę sobie normalnie tworzyć „zmienne”.
    Code:

    volatile uint8_t Language_eeprom __attribute__ ((section(".eeprom_mem")));


    Sekcję zadeklarowałem jako rwx, ale to chyba nic złego bo i tak nic tam nie będę zapisywał. Co ciekawe zadeklarowanie jej jako rx też pozwala tam później umieszczać zmienne :D
    I w czym problem? W tym że zmiennych chcę mieć dość dużo.
    A do tego takie same odpowiedniki w pamięci RAM. Czyli jak zechcę coś zmienić, to bym zrobił kopiowanie z FLASHa (eepromu) do RAMu, w RAMie zmieniał to co trzeba i wywoływał zapis RAMu do FLASHa.
    Ale to oczywiście wymaga zachowania takie samej kolejności zmiennych we FLASHu i w RAMie.
    No i jak to zrobić?
    Jeżeli kolejność nie będzie taka sama, to jeszcze mogę poprawnie odczytać zmienne, bo zrobię sobie normalne przypisanie:
    Code:

    Language_ram = Language_eeprom;

    I mimo nieodpowiedniej kolejności odpowiednie zmienne EEPROmowe trafią do odpowiednich zmiennych RAMowych.
    Ale przy zapisie już tak nie da rady, bo zapis idzie sektorowo. Czyli muszę podać do zapiania cały sektor 4kB i procedura zapisująca już się nie będzie zastanawiała w jakiej kolejności są zmienne, bo nawet nie będzie wiedziała że tam są jakieś zmienne.
    No więc jaki patent na to proponujecie?
    Może zdefiniować sobie strukturę a później zrobić dwie zmienne strukturalne, jedną we FLASHu a drugą w RAMie? Czy to narzuci jednakową kolejność oraz ciągłość danych?

  • Pomocny post
    #116 26 Lis 2009 14:56
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Po pierwsze upewnij się, że w tych adresach nie siedzi firmowy bootloader, bo mnie się właśnie coś wydaje, że znajduje się on powyżej 500kB.

    Co do skryptu linkera, to jak mniemam poniżej masz jeszcze stworzoną sekcję o nazwie .eeprom_mem podobną do .data, .text itp. ?

    Co do kolejności - tak jak proponujesz sam - taką samą uzyskasz tworząc gigantyczną strukturę i tworząc sobie takową w flash i w ram.

    4\/3!!

  • #117 26 Lis 2009 15:07
    atom1477
    Poziom 43  

    Freddie Chopin napisał:
    Po pierwsze upewnij się, że w tych adresach nie siedzi firmowy bootloader, bo mnie się właśnie coś wydaje, że znajduje się on powyżej 500kB.

    Miałem z tym trochę zabawy, bo znalazłem jedną dokumentację wprowadzającą zamieszanie.
    Ale ostatecznie jest tak:
    504kB programu
    8kB Bootloadera.

    Mój sektor jest od 500 do 503kB, czyli wszystko gra.



    Freddie Chopin napisał:
    Co do skryptu linkera, to jak mniemam poniżej masz jeszcze stworzoną sekcję o nazwie .eeprom_mem podobną do .data, .text itp. ?

    Chodzi o to:
    Code:

    .eeprom_mem (NOLOAD) : { *(.eeprom_mem .eeprom_mem.*) } > eeprom

    No więc tak, mam to :D


    Freddie Chopin napisał:
    Co do kolejności - tak jak proponujesz sam - taką samą uzyskasz tworząc gigantyczną strukturę i tworząc sobie takową w flash i w ram.

    No to dobrze. Ale fajnie by jeszcze było jak by kolejność zmiennych była narzucona.
    Bo już byłem świadkiem tego jak kompilator zmieniał mi adresy zmiennych.
    Zmieniam optymalizację z O0 na Os a tu nagle zmienne idą ACBD zamiast ABCD (A wszystkie były w równym stopniu wykorzystywane w programie. I wszystkie w programie głównym).
    Chodzi o to żeby ta struktura nie uległa zmianie po którejś tam poprawce softu, bo ustawienia chcę także kopiować z urządzenia do urządzenia. I jak jedno z urządzeń będzie starsze to może się okazać ż ustawienia nie podpasują mimo że struktura będzie niby taka sama.
    Da się to zrobić za pomocą czegoś podobnego do:
    #pragma pack(push)
    ...
    ...
    #pragma pack(1)
    #pragma pack(pop)
    ?

  • Pomocny post
    #118 26 Lis 2009 15:25
    Freddie Chopin
    Specjalista - Mikrokontrolery

    1. To (NOLOAD) nie jest Ci potrzebne, bo przecież możesz sobie wgrać jakieś dane default.

    2. Kolejność zmiennych w strukturze jest stała. Opcje kompilatora mogą zmienić adresy zmiennych (dokładnie opcja "packed"), ale kolejności nie. Jeśli aż tak Cię to gnębi, to zrób tablicę, a poszczególne pola tablicy sobie jakoś nazwij i po sprawie: array[PARAMETER_1], array[PARAMETER_XYZ], ...

    4\/3!!

  • #119 26 Lis 2009 15:34
    atom1477
    Poziom 43  

    Freddie Chopin napisał:
    1. To (NOLOAD) nie jest Ci potrzebne, bo przecież możesz sobie wgrać jakieś dane default.

    To znaczy na etapie kompilacji coś tam wstawiać?
    To by było nawet dobre.

    Freddie Chopin napisał:
    2. Kolejność zmiennych w strukturze jest stała. Opcje kompilatora mogą zmienić adresy zmiennych (dokładnie opcja "packed"), ale kolejności nie. Jeśli aż tak Cię to gnębi, to zrób tablicę, a poszczególne pola tablicy sobie jakoś nazwij i po sprawie: array[PARAMETER_1], array[PARAMETER_XYZ], ...

    To znaczy mogą się zmienić wszystkie adresy na przykład o 4 w górę?
    To jeszcze nie tragedia.
    Co do tablicy to to raczej nie przejdzie bo zmienne mają być różnych typów.

    Więc chyba sprawa rozwiązana. Jeszcze tylko muszę uruchomić ten zapis.
    Wielkie dzięki.

  • Pomocny post
    #120 26 Lis 2009 15:44
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Jeśli masz zmienną / stałą, to możesz jej nadać wartośc początkową jak każdej innej - to w jakiej sekcji się znajduje nie ma znaczenia.

    Nie mogą się zmienić o +4. Jeśli masz np uint8_t, uint16_t, uint32_t, to pomiędzy pierwszym a drugim elementem masz 3 bajty "pustki", pomiędzy drugim a trzecim - dwa. Z opcją "packed" dane są - zgodnie z logiką nazwy - upakowane, ale dostęp do nich realizowany jest jako sekwencyjne dostępy 8-bitowe i składanie ich w całość (jeśli typ jest wiekszy niż 8-bitów).

    4\/3!!

 
Promocja -20%
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME
tme