programowanie i kasowanie dwu kostek flash na jednej magistrali

Czy mial ktos z Was do czynienia z konfiguarcją hardware polegającą na

32-bitowym procku (Arm Cortex M4) obsługującym dwie zewnętrzne pamięci flash 16-bitowe (ST:M29W640GL)?

Wydawałoby się, że zadanie trywialne, a jednak kostki nie chcą współpracować... :-)

Obie kostki pamięci mają wspólne sygnały Cs, Oe, We i A0..Axx a magistrala danych po połowie 0..15 i 16..31 przydzielona odpowiednio do 0..15 każdej kostki.

Procek ustawiony na 32bit i aby używał "address shift mode" (EMC Shift Control bit w SCS registrze jest 0) więc "nie wie" ze sa dwi kostki w żaden inny sposob jak tylko to, że zamiast do kasowania sektora wysylac 16-bitowo

0x00AA i 0x0055 a potem 0x0080 wysylam 32-bitowo 0x00AA00AA, 0x00550055 i 0x00800080.

I do tego problem jest ze czasem to dziala a czasem nie dziala. Jak nie dziala to albo przy zmieniajacym sie bicie 2 jest ustawiony bit 5 (error) a czasem juz na samym koncu przy sprawdzeniu odczytu skasowanej lokacji jest jedna kostka skasowana a druga nieskasowana (na szynie jest np 0xFFFF0000).

Czy do takiej konfiguracji pamieci podchodzi sie jakos inaczej do kasowania/programowania? Ktos sie podzieli doswiadczeniem?

Reply to
Pszemol
Loading thread data ...

Gdybyś tak zrobił jedno miejsce przez które przechodzą wszystkie zapisy i odczyty z printfem jakie zapisy idą do pamięci, to by pewnie było już po problemie. Do sprawdzenia:

  1. Reprezentacja danych w pamięci. Czy aby na pewno bajty/słowa nie są zamienione.
  2. Czy w Twoim przypadku rozmiar sektora jest 0x20000 ? A może 0x40000 ? Masz przesunięty adres.
  3. Jak nie jesteś pewny to oscyloskop do łapy i sprawdź czy jest to co Ci się wydaje.

Adam

Reply to
Adam Górski

Hmmm... Nie bardzo rozumiem ten pomysł... Może zasugerowałbyś jakiś przykład? W czasie programowania piszę przecież do pamięci bezpośrednio odwołując się do wskaźników... Przy odczycie, w czasie kasowania i zapisu pamięć przestawia jeden bit (toggle) co wskazuje na operację w toku...

Domyślam się że nie są zamienione, bo gdyby były to nie udawałoby się czasem skasować i zapisać, a czasem się udaje...

Używam kostek M29W640GL. To są pamięci 64Mb z 128 sektorów po 64KB/16KW każdy. Gdybym adresował

8-bitowo to sektor byłby od 0x0000 do 0xffff. Ale tu mi trochę zadałeś klina, bo z jednej strony każda kostka pamięci ma widzieć swój adres, ze swojego lokalnego punktu widzenia a z drugiej strony mam procesor, który myśli że ma pamięć 32-bitową i interpretuje moje wskazniki zgodnie ze swoim rozumieniem adresowania 32-bitowego z przesuniętym A2 na pin A0. Muszę to jeszcze raz przetrawić...

Dobre :-)

Reply to
Pszemol

Sorry - mialem napisac 64KB/32KW oczywiscie...

Reply to
Pszemol

Tak ale można to zrobić poprzez np. makro lub funkcje i przekierować to co wychodzi do flasha i jednocześnie do printfa lub do bufora w ramie tak żeby mieć rejestr z tego co wyszło i przyszło. Jedym słowem logowanie. Tak żeby mieć pewność że sekwencja zapisu zgadza się z teorią.

A nie trzeba tam gdzies czekać na bity ze status registru ?

Tak mi się wydaje.

Czemu dobre ? Życie. No nie mów że dostęp do flasha jest jakiś ekstremalnie szybki lub że nie da się tego zobaczyć. Że o debuggerach nie wspomnę.

Adam Górski

Reply to
Adam Górski

Z tego pytania wnioskuję, że na funkcje zapisu i kasowania jakie tu podałem nawet nie spojrzałeś :-)))

Nie chodzi o szybkość, raczej o ilość potrzebnych do monitorowania wejść. Oscyloskop, nawet 4-kanałowy niewiele pomoże. Moj analizator stanow logicznych też tylko 16 wejsc... No i good luck aby je podłączyć pod procesor w obudowie LQFP208 albo flasha 48-pin TSOP... Nie mam niestety adapterów, musiałbym lutować druty do kostki :-(

Reply to
Pszemol

W dniu 2017-02-08 o 15:07, Pszemol pisze:

--------------------^^^^---------------^^^^ Status zapisu sprawdzasz tylko z jednej pamięci, bo skąd kompilator ma wiedzieś który "*pStatus" jest od której paMIĘCI? podstawia dwa razy to samo. Jedna się wyrobi, druga nie i są błędy.

Reply to
Janusz_k

Zerknij proszę jeszcze raz na deklarację wskaźnika pStatus oraz zmiennych Status1 i Status2. To są obiekty 32-bitowe a więc obie kostki pamięci odpowiedzialne są za ich zapis.

Pamietaj że jedna kostka pamięci podłączona jest do jednej połowy szyny danych (D0..D15) a druga do drugiej połowy (D16..D31). Procesor jest ustawiony aby wszystkie cykle robił 32-bitowe z 4-bajtowym "alignem" adresow... (jak się to po polsku mówi?)

Dwa kolejne odczyty tego samego adresu są robione w pętli aby sprawdzić czy pamięć jest zajęta.

Lecę więc po kolei, zakładając że kostki mogą mieć rózne potrzeby czasu na zapis/kasowanie: najpierw w pętli jednej, czekam aż jedna kostka skończy kasowac testujac bit D2 potem wskakuję w drugą pętle i sprawdzam czy druga kostka też skończyła testujac bit 2+16 czyli D18 a na końcu, dla pewności, sprawdzam czy skasowana lokacja odczytuje się 0x FFFF FFFF czyli czy obie kostki są skasowane. I tu najczęściej się program wywala w debuggerze: test pokazuje odczyt np 0x FFFF 0087. Czyli jedna kostka skasowana a druga ma stara zawartosc....

Reply to
Pszemol

Teraz na ten przykład krokuję program (breakpoint na wejsciu do funkcji kasowania sektora) i widzę, że tak traktowany sprzęt zachowuje się ładniej

- zamiast wywalić się na kasowaniu pierwszego sektora (0x8000 0000) przeszedł ladnie do kasowania

0x800C 0000, 0x800E 0000, 0x8010 0000 zapisujac je po kolei bez zgłaszania błędów i po skasowaniu 0x8012 0000 wykorbił się w czasie zapisu nowych danych:

Górna kostka, ta obsługująca bity D16..D31, zgłosiła błąd zapisu: ustawiony bit D5 kostki (u mnie cpu widzi go jako D21) przy przestawianym wciąż bicie D6 (u mnie D22).

I co teraz? Zaczynam kurna podejrzewać nasz hardware... Może coś jest nie tak z jakością 3V3... Czas przynieść oscylka :-)

Reply to
Pszemol

Kodensatorek osprzegajacy był na innej nodse podpiętej do 3v3 ale po podpieciu dodatkowego 220nF do nozki 43 nic sie nie zmieniło na plus... Dalej sie proces wykorbia w czasie kasowania lub programowania...

Reply to
Pszemol

Spojrzałem. Nie podejmuje się analizowania czegoś takiego jak while( A, B,C ). Nigdzie nie widziałem jeszcze takiej konstrukcji.

Czy możesz podpowiedzieć jaki jest oczekiwany rezultat takiej pętli ? Czy w takim wypadku oczekujesz wszystkich warunków niezerowych czy wystarczy jeden ? Inaczej mówiąc to jest bardziej jak && czy ||. A może tylko jedno jest warunkiem ?

Widziałeś gdzieś definicję takiej pętli ? Wybacz moje niedouczenie.

Z drugiej strony , na ilu szt. hardwaru masz takie zachowanie ? Może normalnie masz zwalony hardware.

Adam

Reply to
Adam Górski

Ostatnie jest warunkiem. Reszta ma się po prostu wykonać przed wyliczeniem warunku.

Piotrek

Reply to
Piotrek

Dzięki. We wszystkich definicjach jakie widziałem zawsze jest while( condition ). Masz może namiar na opis standardu dopuszczającego takie użycie ?

Adam Górski

Reply to
Adam Górski

No i właśnie to condition jest grupą wyrażeń połączonych *operatorem* ,

Było od zawsze ("The C programming Language" A.7.18). Chociaż rzeczywiście widziałem to użyte w kodzie może z pięć razy.

Piotrek

Reply to
Piotrek

W dniu 2017-02-08 o 20:31, Pszemol pisze:

while(Status1 = *pStatus, Status2 = *pStatus, (Status1 ^ Status2) & (1 << 2)) Przepraszam że zawracam głowę, ale jaki jest sens robienia XOR na zmiennych pobierających wartość z tego samego adresu? Tam (praktycznie) zawsze będzie false, chyba że procesor akurat trafi na zmianę statusu drugiej kostki między jednym a drugim odczytem *pStatus, ale z takim szczęściem to lepiej kupony wypełniać niż babrać się w kodzie ;)

Reply to
Piotr Dmochowski

Piotrze, świetne pytanie. Bo to jest ciekawy fragment procesu kasowania pamieci flash i zapisu do niej.

Taka pamięć ma wewnątrz sterownik ktory kontroluje te procesy niejako z wewnątrz kostki. Obsługujesz go przez wspólną magistralę danych i adresów - scalak pracuje w dwu trybach: odczyt danych (wtedy działa jak klasyczny ROM) oraz kasowanie/zapis: wtedy uzyskujesz dostep do wewnetrznego sterownika umówioną sekwencję bajtôw w roli "sezamie otwórz się!" I wtedy możesz wydawać sterownikowi polecenia kasowania/zapisu konkretnych lokalizacji pamięci... A sterownik informuje Cie o postepie operacji kasowania i o błedach ustawiajac stan bitow szyny danych. Miedzy innymi zmienia on stan bitu D6 gdy operacja jest wciaz w toku. Stad w kodzie dwa kolejne odczyty i stad użycie sugestii "volatile" do kompilatora aby tych dwu odczytów nie "zoptymalizowal" myslac ze są bez sensu, tak jak Ty pomyślałes :-))

Nawiasem mówiąc zmiana testu bitu D2 na bit D6 w czasie kasowania pomogla - nie mam juz błędów o ktorych pisałem wcześniej. Muszę jeszcze raz się przyjrzeć tym flołczartom z dataszyta :-) i przypomnieć sobie dlaczego pisząc ten kod uznałem że testowanie D6 będzie dobre w czasie zapisu flash a powinienem testować D2 w czasie kasowania...

Reply to
Pszemol

Widziałem deklarację z volatile, więc wiem że powinny być 2 odczyty. Zastanawia mnie jaki jest sens odczytania danych z jednego adresu i zrobienie na nich XORa. Jeżeli między jednym a drugim odczytem nie będzie zmiany to wynik będzie zerowy i program nie wejdzie do pętli - takie jest moje rozumowanie. Może w praktyce jakoś to działa, ale zastanawiam się jaki jest margines błędu w takim rozwiązaniu. Jak najbardziej rozumiem pobranie jednego statusu i sprawdzenie D6, bez XOR to nie pójdzie? Ja bym dał w pętli odczyt statusu i sprawdzenie D6. Wyjście z pętli jeżeli D6 ma odpowiednią wartość lub liczba sprawdzeń przekroczyła np.

100 (i sygnalizacja błędu przekroczonego czasu trwania operacji).

Chyba że czegoś nie ogarniam i ten odczyt z pamięci ma jakieś dodatkowe skutki i może spowodować zmianę odczytanej wartości, ale bez takiej wiedzy nie do końca mi się to składa w całość.

Tak przy okazji pokazywania kodu - myślę że nawet po jednym zdaniu komentarza przed kawałkiem kodu byłoby dobra zachętą do analizowania przez grupowiczów, a i koledzy w pracy pewnie tez docenią jak będą chcieli coś pozmieniać :)

Reply to
Piotr Dmochowski

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.