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] Optymalizacja pamięci RAM w ARM7TDMI z FreeRTOS - unikanie Data Abort

ginar 26 Maj 2011 14:05 3644 24
REKLAMA
  • #1 9546188
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    Witam
    Używam do celów testowych uk z rdzeniem ARM7TDMI flash 32kB RAM 8KB. Niestety nie są to porażające wartości stąd chciałbym możliwie optymalnie je wykorzystać przed ew. zmianą uk.

    Bardzo często program ląduje w uchwycie ldr pc, =Data_Abort_Handler // Data Abort exception
    ...

    Inicjalizacja pamięci:
    Zgodnie z dokumentacją aby uk z rdzeniem ARM7 mogły pracować z Freertos'em muszą być właczone w tryb supervisor
    __undefined_stack_size = 0;
    __supervisor_stack_size = 1024;
    __abort_stack_size = 0;
    __fiq_stack_size = 0;
    __irq_stack_size = 128;
    __user_system_stack_size =0 ;

    co ciekawe ustalenie stosu __supervisor_stack_size=0 czy 1024 nie zmienia działania.
    Pamięć dla tasków:
    Cytat:
    #define configTOTAL_HEAP_SIZE ( ( size_t ) 3000)


    Każdy z kreowanych tasków ma wystarczającą ilość pamięci - korzystam z
    uxTaskGetStackHighWaterMark( NULL );

    a mimo to dodanie np. jakieś funkcji do tasku powoduje często wywołanie data abort. Zwiększenie pamięci dla tego konkretnego tasku nie przynosi rezultatu, pomimi, że: (Suma pamięci dla przydzielonych tasków) x (szerokość stosu = 4B)<configTOTAL_HEAP_SIZE.
    Istnieje może jakiś wiarygodny sposób aby ocenić, że możliwości RAM uk zostały przekroczone?
  • REKLAMA
  • Pomocny post
    #2 9546208
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Ale ty wiesz że te 3000 to jest 12kB?
  • #3 9546434
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    W dokumentacji jest napisane, że configTOTAL_HEAP_SIZE jest w B, a więc 3000=3kB
    The total size (in bytes) of the array is set by the definition configTOTAL_HEAP_SIZE within
    FreeRTOSConfig.h.
  • REKLAMA
  • #4 9546510
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Ok zgadza się, pomyliło mi się z wielkościami stosów podawanych przy tworzeniu tasków
  • #5 9690125
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    Ponawiam pytanie- w jaki sposób ocenić czy pamięć RAM jest niewystarczająca (oczywiście pod FreeRtosem). Korzystam z debbugera od Freddiego, eclips + openocd. Istnieje może jakaś nakładka umożliwiająca podgląd pamięci RAM coś jak pod AVR studio?

    BTW:
    Asekuracyjnie przymierzam się do zmiany uk na coś o większym RAM - LPC17x (cortex-m3)
    Moglą koledzy polecić jakiegoś (polskiego) dostawce bo z tego co widzę tylko tutaj http://www.futureelectronics.com/en/Search.as...k:PartNumberSearch|lpc177|1|,Ny:True,Nea:True
    mają i akurat bez ceny.
  • Pomocny post
    #6 9690237
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    Ja mam na tzw. śmietniku historii pcb z:
    - dwa STM32F103ZET6 połączone ze sobą podwójnym SPI
    - jeden z procków ma 4MB ramu na FSMC
    - drugi ma 256kSłów na FSMC
    - na PCB leży S1D13513 + 4MB SDRAM
    - kontroler ethernetu ENC28j60
    - dekoder adresów FSMC
    - dekoder CSów SPI1/SPI2
    - slot SD/MMC
    - kontroler touchpanela Analog Devices (nie pamietam oznaczenia)
    - CAN
    ..i pare innych. Mogę komuś to sprzedać ;] (w komplecie schemat i pcb w altiumie)
    Ta płytka to poprodukcyjny złom.
  • Pomocny post
    #7 9690632
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Czy jesteś pewny, że układ zawsze jest w trybie supervisor? Próbowałeś dać jakąś niewielką ilość stosu dla innych trybów (szczególnie ostatniego)?

    Tak swoją drogą, to lądowanie w data abort niekoniecznie jest związane ze stosami - wystarczy zła wartość wskaźnika i próba odczytu z nieistniejącego adresu.

    4\/3!!
  • #8 9690676
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    FreeRTOS udostępnia funkcję, która sprawdza stan stosów i to w dwóch wersjach.
    Jeśli nastąpi przepełnienie stosu któregokolwiek taska wtedy RTOS wywołuje callbacka.
    W demach są też przykłady z wyświetlaniem stanu tasków w tym stosów poprzez http.
  • #9 9736070
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    Wszystko pracuje w trybie supervisor poprzez dodanie do standardowego startup'a ostatniej liniki w poniższym kodzie:
    /*
    +-----------------------------------------------------------------------------+
    | Stack setup
    +-----------------------------------------------------------------------------+
    */
    
    	// after reset the core is in Supervisor mode with IRQ & FIQ disabled
    	ldr   sp, =__supervisor_stack_end;				// set the stack for Supervisor mode
    	msr   CPSR_c, #FIQ_MODE | CPSR_I | CPSR_F		// switch to FIQ mode, IRQ & FIQ disabled
    	ldr   sp, =__fiq_stack_end;						// set the stack for FIQ mode
    	msr   CPSR_c, #IRQ_MODE | CPSR_I | CPSR_F 		// switch to IRQ mode, IRQ & FIQ disabled
    	ldr   sp, =__irq_stack_end;						// set the stack for IRQ mode
    	msr   CPSR_c, #ABORT_MODE | CPSR_I | CPSR_F		// switch to Abort mode, IRQ & FIQ disabled
    	ldr   sp, =__abort_stack_end;					// set the stack for Abort mode
    	msr   CPSR_c, #UNDEFINED_MODE | CPSR_I | CPSR_F	// switch to Undefined mode, IRQ & FIQ disabled
    	ldr   sp, =__undefined_stack_end;				// set the stack for Undefined mode
    	msr   CPSR_c, #SYSTEM_MODE					 	// switch to System mode, IRQ & FIQ enabled
    	ldr   sp, =__user_system_stack_end;				// set the stack for User and System mode
    
    
    	/* We want to start in supervisor mode.  Operation will switch to system
    	mode when the first task starts. */
    	msr   CPSR_c, #SUPERVISOR_MODE|CPSR_I|CPSR_F
    /*
    +-----------------------------------------------------------------------------+
    | Branch to low_level_init_0() function (.data and .bss are not initialized!)
    +-----------------------------------------------------------------------------+
    */

    Przyczyną problemu okazuje się być struktura która zostaje przekazywana do funkcji jako parametr.
    A więc po kolei 8kB jest dzielone na..
    W pliku FreeRtosConfig.h rozmiar stosu dla tasków
    #define configTOTAL_HEAP_SIZE		( ( size_t ) 3500)

    (poniżej tego funcka xTaskCreate() nie utworzy wszystkich tasków)
    zostaje 4,5kB. Każdy z tasków ma wystarczającą dla siebie pamięć: uxTaskGetStackHighWaterMark zawsze zwraca kilkanaście wolnych B.
    W pewnym tasku jest wywoływana funkcja która otrzymuje w argumencie strukture tego typu (nie ważne co zawiera -ważny jest jedynie rozmiar tej struktury- struktura jest globalna):
    
    typedef struct
    {
    
    		uint16_t param1;
    		uint8_t param2;
    		uint16_t param3;
    		uint16_t param4;
    		uint8_t param5;
    		//uint8_t param6;
    
    }StructTest;
    

    StructTest test={4,4,4,4,4};
    funkcjaTest( test);

    w takim przypadku to co zostaje przesłane do funkcji funkcjaTest zgadza się z rzeczywistością. Jednak wystarczy zwiększyć strukturę o ostatni parametr (tutaj będzie to 1B) a to co zostaje przesłane do funkcji to jakies śmieci (tj. lokalna struktura na stosie zamiast być kopią struktury test- zawiera jakieś śmieci ).

    Pierwsze co przychodzi na myśl to za mały rozmiar stosu. Jak juz wszesniej pisałem zmiana __supervisor_stack_size nie przynosi żadnego rezultatu. Nawet rozmiar 0 działa tak samo jak __supervisor_stack_size = 200;

    __undefined_stack_size = 0;
    __supervisor_stack_size = 200;
    __abort_stack_size = 0;
    __fiq_stack_size = 0;
    __irq_stack_size = 128;
    __user_system_stack_size = 0;


    Testowałem to samo na PC - tam bez dziwnych niespodzianek.
  • REKLAMA
  • #11 9738471
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    Poustawiałem stosy tasków i przerwań na liczby będące wielokrotnością 8.Wszystkie pola struktury zmieniłem na typ int aby kompilator nie próbował wyrównywać danych w obrębie struktury. Poniżej
    test - globalna struktura
    xx- jej kopia przesłana do funkcji (kopia na stosie):
    [ARM] Optymalizacja pamięci RAM w ARM7TDMI z FreeRTOS - unikanie Data Abort

    dalej funkcja otrzymuje zaśmieconą kopie - aczkolwiek widać jakąś zależnosć. hmm...
  • #12 9738527
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Podejrzyj w dezassemblacji moment wywołania tej funkcji i zdebugguj dokładne wartości wskaźnika stosu w tym momencie. Przy takim rozmiarze struktury przekazywana jest ona przez stos. Jak była mniejsza to działało, bo była przekazywana przez rejestry.

    4\/3!!
  • #13 9738680
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Pierwsze 4 zmienne mogą być przekazywane przez rejestry.
  • REKLAMA
  • #14 9739009
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    Tak, w rejestrach r0 r1 r2 r3 znajdują sie odpowiednio brakujące dane tj 0 1 2 3
    reszta danych jest pchana na stos. Poniżej fragment początkowy w asm tej funkcji
    176       {
              softSPI_CallBack_Device_00_:
    00001924:   sub sp, sp, #16 ; 0x10
    00001928:   push {r11}              ; (str r11, [sp, #-4]!)
    0000192c:   add r11, sp, #0 ; 0x0
    00001930:   sub sp, sp, #12 ; 0xc
    00001934:   add r12, r11, #4        ; 0x4
    00001938:   stm r12, {r0, r1, r2, r3} // tutaj sp=0x40000c20
  • #16 9739285
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    Sourcery G++ Lite
    sprawdziłem teraz na -OS wczesniej był -O0 w obu efekty te same tj. pierwsze 4 brakujące argumenty sa w rejestrach
  • #17 9739326
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Czemu nie przekazujesz tej struktury przez wskaźnik?
  • #18 9739370
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    michalko12 napisał:
    Czemu nie przekazujesz tej struktury przez wskaźnik?

    pewnie i tak w ostateczności zrobię ale ta sprawa znowu trafi do archiwum x :|
    -----
    Zamieniłem poprzednią funkcję tak aby przyjmowała tyle samo bajtów co poprzednia struktura tylko w formie "rozłożonej"
    void softSPI_CallBack_Device_00_(int x0,int x1,int x2,int x3,int x4,int x5,int x6,int x7,int x8,int x9,int x10,int x11,int x12)
    
    i co ciekawe poprzez rejestry r0-r4 także są przesyłane pierwsze 4 argumenty ale po wejściu do tej funkcji wszystkie parametry są ok czyli reszta przez stos dotarła ok.
    Póki co wychodzi na to, że strukturę można przesyłać nie większą niż to co zdołają pomieścić r0-r4.
  • #19 9739548
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Napisz taka funkcję

    typ funkcja( int, int,int,int, struct) i będzie ok :cunning:
  • #20 9739648
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    taki szczególny przypadek działa bo struktura nie jest dzielona przy przesyłaniu. Przesyłanie i odbiór w asm dla
    wersji: softSPI_CallBack_Device_00_(6,6,6,6,test); wszystko ok
    przesyłanie: 
    23        softSPI_CallBack_Device_00_(6,6,6,6,test);
    000020b8:   ldr r3, [pc, #68]       ; 0x2104 <enc28j60Init+88>
    000020bc:   mov lr, sp
    000020c0:   mov r12, r3
    000020c4:   ldm r12!, {r0, r1, r2, r3}
    000020c8:   stmia lr!, {r0, r1, r2, r3}
    000020cc:   ldm r12!, {r0, r1, r2, r3}
    000020d0:   stmia lr!, {r0, r1, r2, r3}
    000020d4:   ldm r12!, {r0, r1, r2, r3}
    000020d8:   stmia lr!, {r0, r1, r2, r3}
    000020dc:   ldr r3, [r12]
    000020e0:   str r3, [lr]
    000020e4:   mov r0, #6      ; 0x6
    000020e8:   mov r1, #6      ; 0x6
    000020ec:   mov r2, #6      ; 0x6
    000020f0:   mov r3, #6      ; 0x6
    
    odbiór:
              softSPI_CallBack_Device_00_:
    00001924:   push {r11}              ; (str r11, [sp, #-4]!)
    00001928:   add r11, sp, #0 ; 0x0
    0000192c:   sub sp, sp, #28 ; 0x1c
    00001930:   str r0, [r11, #-16]
    00001934:   str r1, [r11, #-20]
    00001938:   str r2, [r11, #-24]
    0000193c:   str r3, [r11, #-28]


    softSPI_CallBack_Device_00_(test,6,6,6,6); śmieci
    przesyłanie:
     23       softSPI_CallBack_Device_00_(test,6,6,6,6);
    000020b8:   ldr r4, [pc, #80]       ; 0x2110 <enc28j60Init+100>
    000020bc:   mov r3, #6      ; 0x6
    000020c0:   str r3, [sp, #36]
    000020c4:   mov r3, #6      ; 0x6
    000020c8:   str r3, [sp, #40]
    000020cc:   mov r3, #6      ; 0x6
    000020d0:   str r3, [sp, #44]
    000020d4:   mov r3, #6      ; 0x6
    000020d8:   str r3, [sp, #48]
    000020dc:   mov lr, sp
    000020e0:   add r12, r4, #16        ; 0x10
    000020e4:   ldm r12!, {r0, r1, r2, r3}
    000020e8:   stmia lr!, {r0, r1, r2, r3}
    000020ec:   ldm r12!, {r0, r1, r2, r3}
    000020f0:   stmia lr!, {r0, r1, r2, r3}
    000020f4:   ldr r3, [r12]
    000020f8:   str r3, [lr]
    000020fc:   ldm r4, {r0, r1, r2, r3}
    
    odbiór:
              softSPI_CallBack_Device_00_:
    00001924:   sub sp, sp, #16 ; 0x10
    00001928:   push {r11}              ; (str r11, [sp, #-4]!)
    0000192c:   add r11, sp, #0 ; 0x0
    00001930:   sub sp, sp, #12 ; 0xc
    00001934:   add r12, r11, #4        ; 0x4
    00001938:   stm r12, {r0, r1, r2, r3}
  • #22 9740121
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    (Sourcery G++ Lite 2009q1-161) 4.3.3
  • #24 9740810
    ginar
    Poziom 21  
    Posty: 595
    Pomógł: 26
    Ocena: 34
    W tym przypadku rzeczywiście zmiana kompilatora na wersje 2010 rozwiązała problem :) . Wersja z 2011 wyrzuca błąd
    [ARM] Optymalizacja pamięci RAM w ARM7TDMI z FreeRTOS - unikanie Data Abort
    oczywiście ścieżki i path są take same.

Podsumowanie tematu

✨ Użytkownik pracuje z układem ARM7TDMI z pamięcią flash 32kB i RAM 8kB, napotykając problemy z wyjątkiem Data Abort w FreeRTOS. Pomimo odpowiedniej inicjalizacji pamięci i wystarczającej ilości pamięci dla zadań, dodanie nowych funkcji do zadań często prowadzi do błędów. Uczestnicy dyskusji sugerują sprawdzenie trybu pracy układu, poprawność rozmiarów stosów oraz wyrównanie danych. Wskazano również na możliwość oceny stanu pamięci RAM za pomocą narzędzi debugujących oraz na potrzebę zmiany układu na model z większą pamięcią, jak LPC17x (Cortex-M3). Użytkownik rozważa również aktualizację kompilatora, co ostatecznie rozwiązało część problemów.
Wygenerowane przez model językowy.
REKLAMA