Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

STM32F030 - emulacja EEPROM

matti0010 31 Mar 2017 19:39 1965 34
  • #1 31 Mar 2017 19:39
    matti0010
    Poziom 11  

    Witajcie,

    od pewnego czasu tak się zastanawiam jak zrobić, by mikrokontroler zapisywał podczas pracy jakąś daną do pamięci stałej. Taki emulator EEPROM (wiele STMów nie ma wbudowanej pamięci EEPROM). Szukałem informacji, znalazłem kilka przykładów lecz ani jednego pod STM32F030. Mam więc następujące pytania:

    1) Czy dobrze rozumie, że można wykorzystać kawałek pamięci flash w dowolnym STM jako imitację EEPROM?
    2) Jak się zabrać do tego by zrealizować taki zapis do flash (emulowanego EEPROM)? Nie mam pomysłu a niczego wartego uwagi nie znalazłem.
    3) Czy może to spowodować jakieś problemy bo np. zapiszę w miejscu które mikrokontroler wykorzystuje i nawet o tym się nie dowiem do czasu aż układ padnie?

    Dzięki z góry za pomoc :)

  • Pomocny post
    #2 31 Mar 2017 20:55
    rb401
    Poziom 30  

    matti0010 napisał:
    2) Jak się zabrać do tego by zrealizować taki zapis do flash (emulowanego EEPROM)? Nie mam pomysłu a niczego wartego uwagi nie znalazłem.


    Nie trzeba nic wymyślać bo STM ma własny, stosunkowo dobrze opisany algorytm na emulację EEPROM dla całego szeregu procesorów w tym F0. Który jest atrakcyjny, dlatego że w bardzo małym stopniu "zużywa" limit żywotności (chodzi o liczbę zapisów, a ściśle mówiąc, kasowań) pamięci FLASH.
    Zobacz:
    EEPROM emulation in STM32F0xx microcontrollers (AN4061)

    Do tego algorytmu są opublikowane przez STM przykłady programów oparte i na SPL , i HAL.
    W przypadku F030 jest pewien drobny niuans, polegający na tym że że te kości mają małe strony FLASH (1KB) a przykłady STMa bazują na pojedynczych stronach.
    Daje to ograniczenie na ilość jednocześnie używanych zmiennych (o ile to w konkretnym przypadku posiada znaczenie).
    Oczywiście algorytm STMa można bez problemu zmodyfikować pod tym kątem (wyznaczyć obszary złożone z wielu stron).
    Przykładowo pod mbed (czyli HAL) była taka próba:
    00_eeprom_emulation_f030.

  • #3 31 Mar 2017 21:25
    matti0010
    Poziom 11  

    Do tego pierwszego linku dotarłem, i skopiowałem pliki eeprom.h i eeprom.c. Niestety pokazało mi błąd bo używam HALa a tam chyba był SPL. Wystarczy w odpowiednim miejscu zastąpić #include "stm32f0xx.h" na #include "stm32f0xx_hal.h" ?

    Do tego drugiego linku nie dotarłem, dziękuje. Czyli w najprostszej wersji wystarczy, że skopiuję do projektu eeprom.h i eeprom.c i tyle? A jak to wygląda z wyborem adresu pod którym chcę coś zapisać do pamięci? Nie bardzo zrozumiałem czym tu się kierować. Mogę wpisać np. 0x5555 jak jest w przykładach i będzie OK, czy raczej nie bardzo? Ewentualnie od czego to zależy (jakie przedziały z pamięci można wybierać)?

    Nie do końca znalazłem wszystkie informacje na temat tej emulacji a chciałbym to w pełni zrozumieć, nie połowicznie.

  • #4 31 Mar 2017 22:01
    Freddie Chopin
    Specjalista - Mikrokontrolery

    matti0010 napisał:
    Nie do końca znalazłem wszystkie informacje na temat tej emulacji a chciałbym to w pełni zrozumieć, nie połowicznie.

    Więc z pierwszego linku do którego dotarłeś po prostu przeczytaj ze zrozumieniem dołączonego PDFa, a nie po prostu skopiuj dwa pliki i "nie działa mi".

  • Pomocny post
    #5 31 Mar 2017 22:03
    rb401
    Poziom 30  

    matti0010 napisał:
    Do tego pierwszego linku dotarłem, i skopiowałem pliki eeprom.h i eeprom.c. Niestety pokazało mi błąd bo używam HALa a tam chyba był SPL. Wystarczy w odpowiednim miejscu zastąpić #include "stm32f0xx.h" na #include "stm32f0xx_hal.h" ?
    .

    Nie wystarczy, bo jest też kwestia użycia innych funkcji sprzętowych (zapis i kasowanie FLASH).
    Może jednak prościej było by skopiować te dwa piliki z tego linku na mbed.

    Co do użycia. To musisz określić ile zmiennych będziesz zapisywanych do EEPROM używał w programie i wpisać tą ilość do pliku eeprom.h tu:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Następnie deklarujesz tablicę:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    gdzie przypisujesz sobie dowolne indeksy do zmiennych, za pomocą których będziesz się do tych zmiennych odwoływał przy zapisie i odczycie.

  • #6 31 Mar 2017 22:10
    matti0010
    Poziom 11  

    Freddie Chopin napisał:
    matti0010 napisał:
    Nie do końca znalazłem wszystkie informacje na temat tej emulacji a chciałbym to w pełni zrozumieć, nie połowicznie.

    Więc z pierwszego linku do którego dotarłeś po prostu przeczytaj ze zrozumieniem dołączonego PDFa, a nie po prostu skopiuj dwa pliki i "nie działa mi".


    Czytałem, lecz mam parę pytań, które tu zadałem. Inaczej nie traciłbym czasu na pisanie posta tylko zagłębiłbym się w PDFa. Najbardziej zależy mi na zrozumieniu (o czym wspomniałem), działający kod to drugorzędna sprawa.


    rb401 napisał:
    matti0010 napisał:
    Do tego pierwszego linku dotarłem, i skopiowałem pliki eeprom.h i eeprom.c. Niestety pokazało mi błąd bo używam HALa a tam chyba był SPL. Wystarczy w odpowiednim miejscu zastąpić #include "stm32f0xx.h" na #include "stm32f0xx_hal.h" ?
    .

    Nie wystarczy, bo jest też kwestia użycia innych funkcji sprzętowych (zapis i kasowanie FLASH).
    Może jednak prościej było by skopiować te dwa piliki z tego linku na mbed.

    Co do użycia. To musisz określić ile zmiennych będziesz zapisywanych do EEPROM używał w programie i wpisać tą ilość do pliku eeprom.h tu:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    To z rozmiarem rozumie i znalazłem. Nie wiem tylko do końca z jakich zakresów pamięci mogę korzystać (najlepiej gdzie tego mniej więcej szukać w dokumentacji bym mógł potem sam sobie poradzić w innymi układami).
    Spróbuję pozmieniać to jakoś, mniej więcej chyba będę wiedział jak. W razie czego ten drugi link wygląda obiecująco jako wzorzec :)

  • Pomocny post
    #7 31 Mar 2017 22:19
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Jedyne "pewne" podejście do tej kwestii, to zmniejszenie rozmiaru flash w skrypcie linkera o rozmiar przynajmniej dwóch ostatnich stron i użycie właśnie tych dwóch ostatnich stron. Każda inna opcja to proszenie się o kłopoty.

  • #8 31 Mar 2017 22:26
    matti0010
    Poziom 11  

    Freddie Chopin napisał:
    Jedyne "pewne" podejście do tej kwestii, to zmniejszenie rozmiaru flash w skrypcie linkera o rozmiar przynajmniej dwóch ostatnich stron i użycie właśnie tych dwóch ostatnich stron. Każda inna opcja to proszenie się o kłopoty.


    Cenna informacja. Tego pewnie nie napisali w tamtym PDF? :P Dziękuję za podpowiedź. Nigdy nie grzebałem w linkerze, ale na pewno znajdę jakieś materiały w sieci i spróbuję się tym pobawić. Wychodzi na to, że moje obawy były uzasadnione (bałem się, że wpisując coś na chama do flash mogę naruszyć strukturę tego co tam docelowo ma być wgrane).

  • Pomocny post
    #9 31 Mar 2017 22:53
    rb401
    Poziom 30  

    matti0010 napisał:
    To z rozmiarem rozumie i znalazłem.


    Uzupełnię ten wcześniejszy opis w poście #5, bo mi się wcisnął nie ten klawisz :oops: :

    Na początku swojego programu dajesz:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    i używasz tych dwóch funkcji wedle własnej woli:

    uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data);

    uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data);

    i to chyba wszystko jak chodzi o obsługę.


    matti0010 napisał:
    Wychodzi na to, że moje obawy były uzasadnione (bałem się, że wpisując coś na chama do flash mogę naruszyć strukturę tego co tam docelowo ma być wgrane).



    Tam na mbed w pliku eeprom.c jest taki trik z zasłonięciem używanego przez eeprom obszaru atrapowymi zmiennymi:

    Kod: c
    Zaloguj się, aby zobaczyć kod



    Wtedy linker tego obszaru nie ruszy, nawet jeśli musi z kodem programu przeskoczyć ten obszar. Tak że nie trzeba w tym wariancie nic gdzie indziej ustawiać a obszar eeprom może być prawie wszędzie, bez różnicy.
    Tylko jest kwestia czy w Twoim kompilatorze akurat to zadziała (mbed jest na Keilu).

  • #10 31 Mar 2017 23:19
    Freddie Chopin
    Specjalista - Mikrokontrolery

    rb401 napisał:
    Tam na mbed w pliku eeprom.c jest taki trik z zasłonięciem używanego przez eeprom obszaru atrapowymi zmiennymi:

    Świetny trik (; Dzięki temu każde wgranie programu (np. podczas debuggowania) kasuje całą zawartość tego EEPROMu (; Nie no, serio, jedyną sensowną opcją jest wydzielenie sobie do tego celu jakiegoś obszaru przez skrypt linkera...

  • #11 31 Mar 2017 23:33
    Piotrus_999
    Poziom 39  

    Freddie Chopin napisał:
    Świetny trik (; Dzięki temu każde wgranie programu (np. podczas debuggowania) kasuje całą zawartość tego EEPROMu (; Nie no, serio, jedyną sensowną opcją jest wydzielenie sobie do tego celu jakiegoś obszaru przez skrypt linkera...

    W mbed to nie za bardzo jest taka możliwość - jako że kompilując online nie za bardzo jest to niego dostep :). Tak że branie tych plików jako wzorcowych nie jest najlepszym pomysłem - musza uwzględniać ograniczenia mbed.

  • #12 31 Mar 2017 23:36
    matti0010
    Poziom 11  

    Korzystam z SW4STM32 (System Workbench for STM32). Próbowałem najpierw skopiować "na głupiego" kod z drugiego linku, niestety zawieszał się w EE_Init();. Popróbuję jeszcze jutro na spokojnie i to przetrawię :) bo takie kopiowanie nigdy się nie sprawdza. Dzięki za wszystkie pomysły, dam jutro znać.

  • #13 01 Kwi 2017 07:16
    rb401
    Poziom 30  

    matti0010 napisał:
    Próbowałem najpierw skopiować "na głupiego" kod z drugiego linku, niestety zawieszał się w EE_Init();


    Spróbowałem ten cały przykład z mbed przenieść do SW4STM (ale bez biblioteki mbed, tylko do szablonu z CubeMX) i po drobnej kosmetyce chodzi całkiem dobrze.
    Kod jest dobry a przyczyną zawieszania pod SW4STM jest, jak się obawiałem, nieskuteczność tego triku z atrapowymi zmiennymi, przy równoczesnym ustawieniu jednego z obszarów dość nisko w pamięci w ustawieniach tego demo. GCC nie rozumie po prostu składni Keila. Ale to nie jest jakiś wielki problem.

    Jak zmieniłem numery stron Flash w eeprom.h, tak by były w górze pamięci to zaczęło chodzić:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zastrzegam że to dotyczy konkretnie STM32F030R8 (a nie wiem jaki Ty używasz).
    Tak że generalnie, żeby zrobić a się nie narobić, można po prostu upchnąć obszary emulacji EEPROM na sam koniec Flash a po kompilacji upewnić się tylko czy rozmiar kodu jest mniejszy niż cały Flash minus obszary EEPROM. Którym to obszarom można też regulować rozmiar, przyjmując inną liczbę fizycznych stron. Teraz tam jest akurat ustawione po 4 strony na obszar (PAGE_NB_PVP) , czyli dwa obszary razy cztery KB zajmują 8KB.

    Niestety to ułatwione podejście nie przyda się w przypadku, np. F4, bo tam są różnej wielkości strony Flash i tam rzeczywiście już będzie konieczne ustawienie linkera, lub choćby takie atrapowe zmienne ale w wersji zrozumiałej dla GCC.

  • #14 01 Kwi 2017 09:03
    niveasoft
    Poziom 34  

    Może to nie stricte na temat, ale w samochodówce taką emulację stosują rzadko.
    Zapisują tak dane jednorazowo, na przykład VIN przypisując ster do auta.
    Kiedy sterownik ma coś zapamietywać na bieżąco a procesor nie ma wewnętrznego eeproma to obok sadzają pamięć SPI, na przykład ST95080, ST95160.
    Chyba mają w tym jakieś doświadczenie...

  • #15 01 Kwi 2017 10:01
    matti0010
    Poziom 11  

    rb401 napisał:
    matti0010 napisał:
    Próbowałem najpierw skopiować "na głupiego" kod z drugiego linku, niestety zawieszał się w EE_Init();


    Spróbowałem ten cały przykład z mbed przenieść do SW4STM (ale bez biblioteki mbed, tylko do szablonu z CubeMX) i po drobnej kosmetyce chodzi całkiem dobrze.
    Kod jest dobry a przyczyną zawieszania pod SW4STM jest, jak się obawiałem, nieskuteczność tego triku z atrapowymi zmiennymi, przy równoczesnym ustawieniu jednego z obszarów dość nisko w pamięci w ustawieniach tego demo. GCC nie rozumie po prostu składni Keila. Ale to nie jest jakiś wielki problem.

    Jak zmieniłem numery stron Flash w eeprom.h, tak by były w górze pamięci to zaczęło chodzić:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zastrzegam że to dotyczy konkretnie STM32F030R8 (a nie wiem jaki Ty używasz).
    Tak że generalnie, żeby zrobić a się nie narobić, można po prostu upchnąć obszary emulacji EEPROM na sam koniec Flash a po kompilacji upewnić się tylko czy rozmiar kodu jest mniejszy niż cały Flash minus obszary EEPROM. Którym to obszarom można też regulować rozmiar, przyjmując inną liczbę fizycznych stron. Teraz tam jest akurat ustawione po 4 strony na obszar (PAGE_NB_PVP) , czyli dwa obszary razy cztery KB zajmują 8KB.

    Niestety to ułatwione podejście nie przyda się w przypadku, np. F4, bo tam są różnej wielkości strony Flash i tam rzeczywiście już będzie konieczne ustawienie linkera, lub choćby takie atrapowe zmienne ale w wersji zrozumiałej dla GCC.


    Obecnie korzystam z STM32F030F4P6.
    Czyli jak rozumie ustawione są dwa obszary po cztery strony co daje te 8KB, a 1K to jedna strona? Chcę się tylko upewnić. W takim razie jeżeli chcę zapisać mniej niż 1KB to ustawiam tylko jedną stronę jednego obszaru (czyli 1KB) czy muszę ustawić 4 strony jednego obszaru i tym samym co najmniej te 4KB rezerwować. Mój układ ma 16KB więc mam 16 stron czyli 4 obszary? W RM oczywiście wsadzili od razu opis kilku innych mikrokontrolerów i jest burdel... Na stronie 47 od RM widzę, że adresy zaczynają się od 0x0800 0000.

    Jeżeli chciałbym, by EEPROM zapisywał mi od strony załóżmy 15, to wtedy ta linijka kodu przyjmie taką postać?:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Nawet jak na koniec pamięci to zapiszę, to tak czy inaczej skasuję tę daną po wgraniu nowego programu? Ewentualnie jaka wartość tam będzie przy inicjalizacji (kasowaniu)? Same 0 czy 1? Teraz nie potrzebuję tego, ale ogólnie taka wiedza się przyda. Chyba już mniej więcej rozumie o co chodzi i bardzo za to Tobie dziękuję.

    niveasoft napisał:
    Może to nie stricte na temat, ale w samochodówce taką emulację stosują rzadko.
    Zapisują tak dane jednorazowo, na przykład VIN przypisując ster do auta.
    Kiedy sterownik ma coś zapamietywać na bieżąco a procesor nie ma wewnętrznego eeproma to obok sadzają pamięć SPI, na przykład ST95080, ST95160.
    Chyba mają w tym jakieś doświadczenie...


    Jak by nie patrzeć przy większej liczbie danych zewnętrzny EEPROM często wyjdzie taniej niż dodanie większego mikrokontrolera, do tego ten EEPROM ma większą liczbę zapisów/odczytów (zapewne) i jak padnie to taniej jest go wymienić (bo pewnie kosztuje grosze) niż cały mikrokontroler. Sam mam zamiar używać flash jako EEPROM tylko wtedy gdy chcę zapisać pojedyncze bajty, przy większej ilości dam od razu zewnętrznego EEPROMa tak jak dotąd to robiłem :)

  • #16 01 Kwi 2017 17:38
    BlueDraco
    Specjalista - Mikrokontrolery

    Zieeew... Cały kod emulacji EEPROM dla F030 - to jakieś 30 linijek w C (przy operacjach na rejestrach FLASH). Ile wierszy tekstu napisał już Autor w tym wątku? Czy nie szybciej byłoby przejrzeć ze dwa dokumenty i napisać ten program samemu?

  • #18 01 Kwi 2017 19:21
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Piotrus_999 napisał:
    Zieeew... Cały kod emulacji EEPROM dla F030 - to jakieś 30 linijek w C (przy operacjach na rejestrach FLASH).

    Zieeew... pokaże te Twoje 30 linijek, to policzymy.

  • #19 02 Kwi 2017 04:27
    rb401
    Poziom 30  

    matti0010 napisał:
    Obecnie korzystam z STM32F030F4P6.


    No to nie masz dużego wyboru. Jeśli masz tych zmiennych nie więcej niż kilkadziesiąt, to wystarczy jeśli zajmiesz na eeprom dwa obszary 1k. Czyli stronę 14 i 15 a PAGE_NB_PVP ustawisz na 1.
    matti0010 napisał:
    Jeżeli chciałbym, by EEPROM zapisywał mi od strony załóżmy 15, to wtedy ta linijka kodu przyjmie taką postać?:


    #define EEPROM_START_ADDRESS ((uint32_t)ADDR_FLASH_PAGE_15) /* EEPROM emulation start address */



    Algorytm potrzebuje dwóch oddzielnych obszarów Flash, które można osobno kasować. Obszar (w znaczeniu algorytmu) musi obejmować jedną lub więcej stron (FLASH page). Dlatego nie możesz użyć tylko 15 strony. Minimum 14 i 15.

    Czyli by nie przedłużać tłumaczenia, bo koledzy tu na wątku mocno ziewają, spróbuj takiego ustawienia eeprom.h:

    Kod: c
    Zaloguj się, aby zobaczyć kod



    matti0010 napisał:
    Nawet jak na koniec pamięci to zapiszę, to tak czy inaczej skasuję tę daną po wgraniu nowego programu?


    Nie skasujesz o ile nie będziesz używał funkcji "Erase chip" Ale musisz bezwzględnie pilnować by długość kodu po kompilacji nie przekroczyła, w Twoim przypadku 14KB. Jeśli będzie dłuższa to nie ma sensu wgrywać.

    matti0010 napisał:
    Ewentualnie jaka wartość tam będzie przy inicjalizacji (kasowaniu)? Same 0 czy 1?


    To inaczej działa.

    Funkcja odczytu:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    zwraca rezultat mówiący o tym czy dana zmienna była wcześniej zapisana (0) czy nie była (1) (np. użycie eepromu po kasowaniu chipu). Zwykle jednak ten rezultat nie bierze się pod uwagę.

    Ale ta funkcja ma jeszcze ciekawą właściwość, taką że jeśli zmienna nie została jeszcze ani razu zapisana, to funkcja nie modyfikuje zmiennej wskazywanej przez parametr Data.
    Daje to możliwość łatwego ustalenia wartości domyślnych zmiennych (wartości fabrycznych urządzenia).
    Np. jeśli mamy zmienną i zrobimy tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    to na wyjściu nawet przy pierwszym uruchomieniu po wgraniu do świeżej kości zmienna będzie już miała sensowną, ustaloną wartość domyślną. Jeśli będzie zrobiony zapis, to oczywiście już będzie miała tą nową wartość. Zwykle (np. na klasycznym EEPROM) zrobienie takiej funkcjonalności wymaga nieco wysiłku i nie jest może tak niezawodne, a tu jest "w pakiecie", bez roboty.


    matti0010 napisał:
    Jak by nie patrzeć przy większej liczbie danych zewnętrzny EEPROM często wyjdzie taniej niż dodanie większego mikrokontrolera, do tego ten EEPROM ma większą liczbę zapisów/odczytów (zapewne) i jak padnie to taniej jest go wymienić (bo pewnie kosztuje grosze) niż cały mikrokontroler.






    Algorytm emulacji wcale nie jest taki zły. Ma kilka wyraźnych zalet.
    Weźmy opisany w AN4061 przykład zastosowania wymagającego ok 50mln zapisów. Pospolite kostki EEPROM mają limit rzędu miliona zapisów, czyli trzeba ich mieć całą garść na wymianę, no i je wymieniać. Bezsens.
    A w przypadku emulowanej EEPROM, osiągnięcie 50mln zapisów to żaden problem. Trzeba po prostu zająć odpowiednią do wymagań ilość Flash. I to pomimo, na pierwszy rzut oka, znacznie mniejszego limitu dotyczącego cykli zapisu.

    Emulowanie może też być szybsze niż zewnętrzna kość, szczególnie przy wolniejszej relatywnie magistrali (np. I2C).
    Do tego nie jest wrażliwe na szczególnie intensywne zapisywanie jednej i tej samej komórki pamięci (bo emulacja używa równomiernie obszar Flash, niezależnie od wirtualnego adresu) a w przypadku normalnego EEPROMU to taka sytuacja szczególnie sprzyja awarii.
    Powtórzę jeszcze raz już wyżej wymienioną zaletę, bo osobiście mi się bardzo podoba, to że w emulacji dostaję też dodatkową informację czy zmienna była "ruszana" czy nie. I w konsekwencji, jak prosto realizuje się wartości domyślne.



    Freddie Chopin napisał:
    Piotrus_999 napisał:
    Zieeew... Cały kod emulacji EEPROM dla F030 - to jakieś 30 linijek w C (przy operacjach na rejestrach FLASH).

    Zieeew... pokaże te Twoje 30 linijek, to policzymy.


    Też jestem bardzo ciekaw :-?

  • Pomocny post
    #20 02 Kwi 2017 11:29
    BlueDraco
    Specjalista - Mikrokontrolery

    Proszę bardzo! Wersja minimalna - zapamiętywanie jednej zmiennej na F0. No fakt, aż 36 wierszy.
    Funkcja getmode() odtwarza ostatnią wartość zmiennej przy starcie, Funkcja storemode() zapamiętuje nową wartość. W tym konkretnym przypadku jest ona wołana z przerwanie zaniku zasilania, więc wartość zapamiętuje się tylko jeden raz w cyklu pracy urządzenia.
    Wersja dla 256 zmiennych z dowolną liczbą zapisów ma ze 20 wierszy więcej.

    Kod: c
    Zaloguj się, aby zobaczyć kod

  • #21 02 Kwi 2017 21:17
    rb401
    Poziom 30  

    BlueDraco napisał:
    zapamiętywanie jednej zmiennej na F0. No fakt, aż 36 wierszy.


    Niby tak. Da się w pewnym określonym kontekście (ostre wymaganie na wartości zmiennej, tylko jedna zmienna itp.) upchnąć funkcjonalność, zastępującą EEPROM, w ca. 30 liniach. Zgadza się.
    Ale do jakieś funkcjonalnie kompletnej emulacji to chyba droga daleka.
    Tu mi się nasuwa skojarzenie "zupy z gwoździa". Jest emulacja, tylko jak dorzucić trochę linii to będzie to, trochę więcej będzie tamto i tak właściwie dojdziemy do czegoś podobnego do implementacji STMa o podobnej wielkości.
    No ale jeśli ktoś potrzebuje akurat takiej funkcjonalności jak licznik czasu pracy to pokazane rozwiązanie wydaje mi się sympatyczne i w sam raz.

  • #22 02 Kwi 2017 21:26
    matti0010
    Poziom 11  

    Przepraszam, że odpisuję dopiero po dwóch dniach (mimo, że jestem autorem posta). Chyba uzyskałem odpowiedzi na wszystkie nurtujące mnie pytania. Muszę to na spokojnie "przetrawić", przetestować i zobaczę co z tego wyjdzie (nie potrzebuję tego pod konkretny projekt, po prostu od pewnego czasu zagadnienie emulacji EEPROMu mnie interesowało ale z PDF od ST nie wszystko zrozumiałem lub znalazłem).

    Największe podziękowania kieruję do @rb401, jesteś wielki. Dziękuję za cierpliwość i bardzo obszerne wyjaśnienia :) aż miło na takich ludzi trafiać.

    Reszcie również dziękuję i proszę, nie kłóćcie się. To nie o to chodzi.

    Pomysł z przerwaniem od zaniku zasilania w sumie również jest świetny. Często trzeba zapisać zmienną jedynie w momencie zaniku, więc takie rozwiązanie jest interesujące (nie pomyślałem o tym dotąd, ale w sumie nie potrzebowałem :P ). Po wpisie od @BlueDraco poszukałem trochę pod tym kątem wujka gooogle i znalazłem coś takiego: Link. To również muszę przetestować, wygląda ciekawie. Ktoś próbował tego i może się wypowiedzieć (nie wszystko co znajduje się w Internecie jest sensowne)?

  • Pomocny post
    #23 02 Kwi 2017 21:45
    Freddie Chopin
    Specjalista - Mikrokontrolery

    BlueDraco napisał:
    Proszę bardzo! Wersja minimalna - zapamiętywanie jednej zmiennej na F0. No fakt, aż 36 wierszy.

    Nie no błagam... nie rozśmieszaj mnie. Chodziło o kod który dla DOWOLNEJ ilości zmiennych (oczywiście w granicach rozsądku tak aby wszystkie mieściły się w emulowanym EEPROMie) pozwala NA ŻĄDANIE odczytać/zapisać WYBRANĄ zmienną. A ty wrzucasz tu jakieś takie pseudo-coś... Przecież Twój kod nie ma nawet 10% funkcjonalności tego o czym się tu dyskutuje. Sam piszesz, że dla większej ilości zmiennych jest już "ze 20 więcej", więc jakbyś to wrzucił, to pewnie okazałoby się, że jest "jednak 70-kilka", a jakbyś dorzucił wszystkie wybrane funkcjonalności, to już by było pewnie ponad 100. I tyle są właśnie warte te Twoje nudne wrzutki w co drugim temacie o treści "zieew, przecież to 10 linijek". Nawet dla wersji minimalnej i tak się pomyliłeś o drobne 20%...

    Oczywiście w całym kodzie nie ma nawet śladu obsługi błędów, czekania na zakończenie, sprawdzania flagi busy, czy choćby odblokowywania dostępu do rejestrów FLASH.

    Przypomnę Ci co napisałeś, podkreślając to istotne słówko które być może Ci umknęło:

    BlueDraco napisał:
    Zieeew... Cały kod emulacji EEPROM dla F030 - to jakieś 30 linijek w C (przy operacjach na rejestrach FLASH).


    Wrzucę ten Twój "cały" kod do układu i ZAŁOŻĘ SIĘ, że nie zadziała. Zieeew...
    Dodano po 4 [minuty]:
    matti0010 napisał:
    Pomysł z przerwaniem od zaniku zasilania w sumie również jest świetny.

    Jest bardzo słaby, ponieważ przy PEŁNEJ emulacje EEPROMu (a nie takiej protezie dla ubogich którą tu BD wrzucił), zapis zmiennej może wymagać skasowania strony i wielu kolejnych zapisów (dzieje się to gdy jedna strona się przepełni). W takim wypadku czas całej operacji staje się znacząco dłuższy (czas kasowania strony to typowo 30ms). Gdy używasz więcej niż 2 stron do tej emulacji, to czas rośnie jeszcze bardziej.

  • #24 02 Kwi 2017 22:11
    BlueDraco
    Specjalista - Mikrokontrolery

    Freddie: kod powyżej jest używany w kilku moich projektach, i, o dziwo, wszystkie działają poprawnie.
    Mam parę wersji kodu o takiej funkcjonalności, o jakiej piszesz, działającego na trzech różnych rodzinach uC z rdzeniami Cortex - przechowywanie kilkuset bajtów parametrów konfiguracyjnych z odtwarzaniem struktury danych przy starcie i modyfikacją dowolnych parametrów w dowolnym momencie. Kod powyżej pokazuje zasadę działania. Przy składowaniu wielu parametrów procedura ładowania wydłuża się o 2 wiersze - pojedynczy wpis w pamięci zawiera indeks i wartość bajtu. Procedura składowania ma jeszcze inkrementację pozycji, sprawdzenie "przewinięcia" przez granicę obszarów Flash i odpowiednią obsługę tego przewinięcia - razem jakieś 15 linii kodu. To naprawdę nic wielkiego i nie idzie w żadne setki linii, a nawet w jedną setkę.
    Tutaj na ogół dajemy wędki, a nie ryby, więc pozwól, że kodu, który opisałem, a który jest używany w kilku rozwiązaniach komercyjnych nie pokażę w całości.

    Na co trzeba zwrócić uwagę? Po kolei:
    1. Potrzebujemy dwóch obszarów we Flash, a każdy z nich musi mieścić taką liczbę wpisów, żeby można było w nim przechować całą strukturę i sensowną liczbę modyfikacji. Co to jest "sensowna liczba" - zależy od zastosowania. W moich zastosowaniach jest to 2 x tyle wpisów, ile wartości w strukturze danych konfiguracyjnych. Obszar nie może być mniejszy niż jedna strona Flash; często musi być większy.
    2. W danej chwili jest używany jeden obszar. Po wypełnieniu całego obszaru, przy kolejnej modyfikacji, kopiujemy na początek drugiego obszaru dane dot. całej struktury, a następnie kasujemy obszar pierwszy. Ponieważ operacja ta nie musi się udać (bo np. w międzyczasie znikło zasilanie), potrzebny jest punkt 3:
    3. Przy starcie sprawdzamy, czy tylko jeden obszar jest używany. Jeśli dwa - oznacz ato, że nie powiodła się operacja opisana w 2. W takim przypadku kasujemy nowszy obszar (który zaczęliśmy wypełniać).

    I to w zasadzie wszystko.

  • #25 02 Kwi 2017 22:26
    matti0010
    Poziom 11  

    Dziękuję za wszystkie wyjaśnienia. Jak ktoś ma jeszcze jakieś wskazówki, to chętnie przygarnę.

    BlueDraco napisał:

    Tutaj na ogół dajemy wędki, a nie ryby, więc pozwól, że kodu, który opisałem, a który jest używany w kilku rozwiązaniach komercyjnych nie pokażę w całości.


    Prosiłem o wędki :) Od samego początku pisałem, że chcę tylko to zrozumieć. Co mi po gotowcach jak nie będę potrafił go potem wykorzystać na innym układzie... Nie lubię iść na łatwiznę i jedynie kopiować, chyba że się uczę i "do testów" mieć jakiś tam wzór (które już otrzymałem od Was i za nie dziękuje).

    Tak przy okazji zapytam, czy jak chcę wykorzystać przerwanie od zaniku zasilania to muszę na coś konkretnego uważać? Istnieją jakieś pułapki bądź rzeczy, o których warto wiedzieć a niekoniecznie o nich napisali w PDF?

  • #27 02 Kwi 2017 22:37
    Freddie Chopin
    Specjalista - Mikrokontrolery

    BlueDraco napisał:
    Tutaj na ogół dajemy wędki, a nie ryby, więc pozwól, że kodu, który opisałem, a który jest używany w kilku rozwiązaniach komercyjnych nie pokażę w całości.

    Ten wątek dyskusji nie jest o tym czy dawać wędkę czy rybę, tylko o Twoich - naprawdę już nudnych i jak widać "mocno nieprecyzyjnych" - wrzutkach o treści "zieeeew... przecież to 10 linijek kodu", których chyba jedynym celem jest pokazanie jaki to z Ciebie h4x0r że takie cuda robisz w 3 liniach kodu.

    BlueDraco napisał:
    Freddie: kod powyżej jest używany w kilku moich projektach, i, o dziwo, wszystkie działają poprawnie.

    Pierwsze jest bez znaczenia. Drugie jest nieprawdą, ponieważ kod który wrzuciłeś NIE JEST KOMPLETNY. Domyślna wartość bitu LOCK w rejestrze FLASH->CR to "1" (zablokowany), a w Twoim kodzie nie ma nigdzie odblokowania. Nie chce mi się myśleć czego jeszcze tam nie ma (bo jest gdzieś indziej), bo mało mnie to interesuje. Chodzi - ponownie to napiszę - tylko o Twoje wrzutki że ile to cudów można zrobić w 5 liniach kodu, które w rzeczywistości okazują się oznaczać, że "absolutnie minimalna funkcjonalność przycięta siekierką do jednego bardzo konkretnego zastosowania zajmuje 5 linijek tutaj, a kolejnych 15 jeszcze jest rozrzucone w innych miejscach, ale 5 wygląda bardziej pr0 niż 20, więc piszę 5".

    Przypomnę ponownie co napisałeś:

    BlueDraco napisał:
    Zieeew... Cały kod emulacji EEPROM dla F030 - to jakieś 30 linijek w C (przy operacjach na rejestrach FLASH).


    To co wrzuciłeś ani nie jest "całe", ani nie jest "emulacją EEPROMu" (chyba że takiego o pojemności 2 bajtów, ale takiego małego to jeszcze nie widziałem), ani też nie zajmuje 30 linijek.

    BlueDraco napisał:
    ... - razem jakieś 15 linii kodu.

    Siur. Pewnie jakby policzyć rzetelnie, to by wyszło ze 2x tyle.

    Poza tym czy to jest jakiś konkurs "kto napisze to w mniejszej ilości linii"? Zwłaszcza że porównanie funkcjonalności wypada mniej-więcej jak między łopatką do piasku a metalowym szpadlem... Jeśli uważasz się za mistrza kompresji kodu źródłowego, to właśnie dla Ciebie jest taki oto konkurs - http://www.ioccc.org/ . Tam faktycznie może komuś zaimponować to jak mało linii ma Twój program.

  • Pomocny post
    #28 02 Kwi 2017 22:40
    BlueDraco
    Specjalista - Mikrokontrolery

    O wszystkim napisano w RefMan - pewnie w pięciu różnych rozdziałach, ale jest parę faktów zdroworozsądkowych, które RefMan przemilcza.

    Po włączeniu monitora zasilania trzeba poczekać, aż pokaże on, że osiągnęliśmy napięcie powyżej ostrzegania, i dopiero wtedy włączyć przerwanie w paru miejscach po kolei. Bez tego od razu dostaniemy przerwanie zaniku zasilania, bo napięcie jeszcze się nie zdążyło ustalić. Bezpośrednio przed włączeniem przerwania trzeba skasować bit znacznika przerwania w rejestrze EXTI, bo "mogło się zgłosić wcześniej". Jak już wpadniemy w przerwanie, można np. w nim zawisnąć, zresetować uC lub zrobić coś równie inteligentnego, żeby nie wpaść w nie bez sensu jeszcze raz przy tym samym wyłączeniu zasilania.

  • #29 02 Kwi 2017 22:51
    matti0010
    Poziom 11  

    grko napisał:
    @matti0010 W tym temacie może znajdziesz coś ciekawego:
    https://www.elektroda.pl/rtvforum/viewtopic.php?p=13684159&highlight=#13684159


    Poczytam, dzięki :) Mam nadzieję, że szybko znajdę chwilę by przetestować wszystkie rady jakie tu otrzymałem. Teraz wiem chyba jak do tego podejść, gdzie szukać i na co uważać.



    BlueDraco napisał:
    O wszystkim napisano w RefMan - pewnie w pięciu różnych rozdziałach, ale jest parę faktów zdroworozsądkowych, które RefMan przemilcza.

    Po włączeniu monitora zasilania trzeba poczekać, aż pokaże on, że osiągnęliśmy napięcie powyżej ostrzegania, i dopiero wtedy włączyć przerwanie w paru miejscach po kolei. Bez tego od razu dostaniemy przerwanie zaniku zasilania, bo napięcie jeszcze się nie zdążyło ustalić. Bezpośrednio przed włączeniem przerwania trzeba skasować bit znacznika przerwania w rejestrze EXTI, bo "mogło się zgłosić wcześniej". Jak już wpadniemy w przerwanie, można np. w nim zawisnąć, zresetować uC lub zrobić coś równie inteligentnego, żeby nie wpaść w nie bez sensu jeszcze raz przy tym samym wyłączeniu zasilania.


    Właśnie o takich ciekawostkach mówiłem, dzięki :) W sumie najłatwiej byłoby po prostu na start dać opóźnienie, tak by w czasie jego trwania zasilanie się ustabilizowało. Co prawda rozwiązanie to jest głupie, ale jednocześnie najprostsze.
    Dokumentacja do STM32 i innych układów z ARMem to zmora. Jedno zagadnienie potrafi być rozwalone i poupychane w wielu rozdziałach albo co gorsza wielu dokumentach. Kiedyś zupełnie się w tym gubiłem, teraz już jest lepiej ale jednak czasem trudno coś znaleźć (pewnie nawet Ci super doświadczeni nie zawsze od razu wszystko znajdą :P ).

  • #30 10 Kwi 2017 11:14
    Chris_W
    Poziom 36  

    Do edukacji jak działa, dobry jest taki kawałek:
    To jest zapis "czegoś" na jednej stronie flasha, żadnych innych "bajerów".

    Code:


    #define Page_63           0x800FC00
    uint8_t test_str[64]={"to jest test zapisywania w pamięci flash 1234567890"};

    void savetoflash(){
       uint16_t d;
       uint16_t i;
       // odblokuj pamięc flash
       FLASH->KEYR = FLASH_KEY1;
       FLASH->KEYR = FLASH_KEY2;
       // poczekaj na gotowość flasha
       while((FLASH->SR&FLASH_SR_BSY));
       // ustaw kasowanie całej strony
       FLASH->CR |= FLASH_CR_PER;
       // ustaw adres kasowanej strony
       FLASH->AR = Page_63;
       // rozpocznij kasowanie strony
       FLASH->CR |= FLASH_CR_STRT;
       // czekaj na zakończenie
       while((FLASH->SR&FLASH_SR_BSY));
       // wyłącz flagę kasowania strony
       FLASH->CR &= ~FLASH_CR_PER;
       // rozpocznij zapisywanie do pamięci flash
       FLASH->CR |= FLASH_CR_PG;
       // powtarzaj dla kolejnych danych...
       for(i=0; i<40; i+=2) {
          // czekaj na gotowość pamięci
          while((FLASH->SR&FLASH_SR_BSY));
          // zapisz
          d=(uint16_t)(((test_str[i+1])<<8) + (test_str[i]));
           *(__IO uint16_t*)(Page_63 + i) = d;
       }
       // wyłącz zapisywanie pamięci flash
       FLASH->CR &= ~FLASH_CR_PG;
       // zablokuj zapis do pamięci flash
       FLASH->CR |= FLASH_CR_LOCK;
    }

 Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME