Skocz do zawartości

STM32F107RCT6 - dwa urządzenia na jednym SPI nie chcą działać


Pomocna odpowiedź

Uruchamiam właśnie urządzenie na mikrokontrolerze STM32F107RCT6. Jakiś czas temu uruchomiłem na mim obsługę karty SD za pośrednictwem magistrali SPI3. Wszystko działało idealnie - bez problemu zarówno odczytywałem, jak i zapisywałem dane. Dzisiaj wlutowałem w płytkę kolejny element - tym razem pamięć RAM 23LC1024, która jest podpięta do tej samej magistrali, ale rzecz jasna steruje nią osobny pin GPIO. Na szybko napisałem kilka funkcji do obsługi tej pamięci, wzorowanych na tej bibliotece dla Arduino. Pamięć sama również działa poprawnie. Problem zaczyna się, gdy próbuję w jednym projekcie używać zarówno karty pamięci, jak i pamięci RAM.

Sytuacja wygląda następująco:

  • Urządzenie startuje i zaczyna czytać dane z karty pamięci. Wszystkie odczyty są poprawne.
  • Po 25 sekundach urządzenie po raz pierwszy próbuje zapisać i odczytać dane do 23LC1024. Ta operacja również się udaje.
  • Moment później urządzenie powraca do czytania danych z SD. Tutaj sterownik wywala błąd. Od tego momentu nie da się już czytać danych z SD.
  • Do skutku nie dochodzą też kolejne próby zapisu i odczytu danych do 23LC1024, wykonywane co 25 sekund.

Co sprawdziłem do tej pory:

  • Sterownik SD którego używam działał bez problemu z innymi urządzeniami na jednej magistrali, ale na innych platformach (AVR i PIC32) - tutaj dostosowałem go do STM32 podstawając niskopoziomowe operacje GPIO i SPI na HAL.
  • Nigdzie w kodzie obsługującym pamięć SPI RAM nie zostawiam linii CS w stanie niskim. 
  • Nie używam RTOS ani nie inicjuję transmisji SPI z przerwań, więc nie mam do czynienia z sytuacją, kiedy jeden odczyt/zapis zaczynałby się przed zakończeniem poprzedniego.
  • Próbowałem ustawić spore opóźnienia (nawet 1000 ms) pomiędzy operacjami na SPI RAM i SD. Nie pomogło. Nie chodzi więc o to, że stan jakiejś linii nie zdążył się jeszcze ustabilizować.

Macie jakiś pomysł gdzie szukać przyczyny?

Link to post
Share on other sites
Dnia 4.04.2021 o 20:13, atlantis86 napisał:

Nie używam RTOS ani nie inicjuję transmisji SPI z przerwań, więc nie mam do czynienia z sytuacją, kiedy jeden odczyt/zapis zaczynałby się przed zakończeniem poprzedniego.

Jesteś pewny? Bo to najbardziej na to wygląda. Ale w innym wątku coś wspominałeś o posiadaniu analizatora stanów logicznych więc - podepnij i zobacz co się tak na prawdę dzieje na magistrali i pinach CS.

Link to post
Share on other sites

@kaworu ma rację, obejrzyj to. Możesz przecież psuć ustawienia/konfigurację ustalone wcześniej dla SD, podczas inicjalizacji pracy z RAMem. STM32 mają wiele ustawień w bloku SPI, już pomijając te oczywiste typu polaryzacja czy faza zegara. Zmieniasz jakiś timing i kicha. Porównaj dokładnie jak ustawia SPI biblioteka dla SD a jak ta Twoja dla RAMu. Być może będziesz to musiał przestawiać "w locie".

Link to post
Share on other sites

Problem polega właśnie na tym, że biblioteka do obsług RAM-u nie zmienia niczego w konfiguracji magistrali SPI.

Jej parametry są konfigurowane w następujący sposób:

  • Wstępnie, przez STM32CubeMX, do pracy z niską prędkością.
  • Na początku procedury inicjującej SD jeszcze raz na wszelki wypadek ustawiam dzielnik częstotliwości SPI (inicjacja karty tego wymaga).
  • Po zakończonej pomyślnie inicjacji SD ustawiam niski dzielnik, aby zwiększyć prędkość transmisji danych. Ta jednak mieści się jednak zarówno w specyfikacji karty SD, jak i RAM-u. Zresztą, próbowałem też manipulować tym parametrem - bez skutku.

Po zamontowaniu systemu plików karty SD magistrala SPI jest więc już zainicjowana. Świadczy o tym fakt, że transmisja przebiega prawidłowo. Po tak przeprowadzonej inicjacji SPI RAM też działa o ile nie korzystam wtedy z karty SD.

Problem pojawia się tylko w jednym przypadku: gdy po (udanym) dostępie do RAM-u następuje próba ponownego skorzystania z karty SD. Bo przed pierwszym odwołaniem się do RAM-u karta SD działa prawidłowo.

I tak - jestem pewien. W tym projekcie nie korzystam z RTOS-a.  

Link to post
Share on other sites
37 minut temu, atlantis86 napisał:

W tym projekcie nie korzystam z RTOS-a.  

To nie jest tu poprawny argument. Wciąż używasz przerwań, aczkolwiek w pierwszym poście pisałeś, że podobno nie ma w nich odwołań do SD/RAM. Ale wciąż, to najbardziej prawdopodobna przyczyna.

Jakkolwiek, podłącz analizator i sprawdź. Bo różne rzeczy mogą być przyczyną, jak to że karta SD z jakiegoś powodu ignoruje swój CS (albo jest on permanentnie włączony) i cały czas przyjmuje dane, w efekcie zapis danych do RAM zapisuje coś do karty SD. Także ja tu sobie mogę tylko zgadywać.

Link to post
Share on other sites
Dnia 8.04.2021 o 16:40, kaworu napisał:

To nie jest tu poprawny argument. Wciąż używasz przerwań, aczkolwiek w pierwszym poście pisałeś, że podobno nie ma w nich odwołań do SD/RAM. Ale wciąż, to najbardziej prawdopodobna przyczyna.

W pełni zgodziłbym się z tym, gdyby nie fakt, że na tym etapie nawet nie dodawałem żadnej obsługi przerwań w tym projekcie. Jak widać w sekcji ustawień NVIC w STM32CubeMX, włączone są tylko te domyślne.

1946475490_Zrzutekranuz2021-04-1113-24-57.thumb.png.0f9df4ef4785f8ed91be750cdc9b8d0c.png 

Puste są także ustawienia DMA. Plik stm32f1xx_it.c nie zawiera żadnego mojego kodu. Sterownik do RAM-u napisałem samodzielnie, wzorując się na bibliotece dla Arduino. Sterownik SD na SPI przeportowałem z kodu dla PIC32 (pochodzi z przykładu dołączonego do podręcznika autorstwa Lucio di Jasio). Oryginalnie nie było tam żadnych przerwań, a ja ich nie dodałem.

 

Dnia 8.04.2021 o 16:40, kaworu napisał:

Jakkolwiek, podłącz analizator i sprawdź.

Ok, w wolnej chwili spróbuję robić taki test. Sprawdzać wszystkie linie SPI, czy zacząć od konkretnych? CS?

Dnia 8.04.2021 o 16:40, kaworu napisał:

Bo różne rzeczy mogą być przyczyną, jak to że karta SD z jakiegoś powodu ignoruje swój CS (albo jest on permanentnie włączony) i cały czas przyjmuje dane, w efekcie zapis danych do RAM zapisuje coś do karty SD. Także ja tu sobie mogę tylko zgadywać.

Jak już pisałem, taka sytuacja miała miejsce na początku i udało mi się ją namierzyć za pomocą multimetru. Biblioteka do obsługi w momencie napotkania błędu zwracała jego kod, nie ustawiając linii SD_CS w stan wysoki. Powodowało to, że od tamtego czasu nie udawały się także operacje na RAM-ie. Poprawiłem to.

Nie było to jednak przyczyną, a skutkiem oryginalnego błędu, który powoduje wywalenie operacji funkcji readSector() karty SD, jeśli wcześniej wykonana została operacja odczytu/zapisu z/do pamięci RAM.

Najprostszym wyjaśnieniem takiego zachowania jest właśnie to, że po operacji na pamięci SPI tym razem jej linia CS pozostaje aktywna i dochodzi do konfliktu na magistrali, gdy tylko procesor chce się komunikować z kartą SD. Tyle tylko, że w kodzie do obsługi RAM-u nie mam nigdzie miejsca, które mogłoby zostawić tę linię w stanie niskim. To proste sekwencyjne operacje na zasadzie: ustaw CS w stanie niskim -> wykonaj transfer -> ustaw CS w stanie wysokim -> zwróć dane. Żadnego wcześniejszego opuszczania funkcji ani niczego w tym stylu.

Możesz sam zobaczyć, kod jest na moim GitHubie:

https://github.com/marekw1986/InternetRadioSTM32/tree/main/code
https://github.com/marekw1986/InternetRadioSTM32/blob/main/code/Core/Src/spiram.c
https://github.com/marekw1986/InternetRadioSTM32/blob/main/code/FATFS/Target/sd.c

Zastanawiam się też, czy może nie jest to winą sprzętu. Na schemacie jednak też nie widzę niczego podejrzanego.

SPIRAM.thumb.png.a75becabd5e9e93af6e7723e5aebb4d5.png

Płytka była projektowana z myślą o flashu SST25, ale z tego co widzę mają identyczne z tym RAM-em wyprowadzenia.

Link to post
Share on other sites
Dnia 11.04.2021 o 13:52, atlantis86 napisał:

Oryginalnie nie było tam żadnych przerwań, a ja ich nie dodałem.

No spoko, tylko jeszcze są takie rzeczy jak działający SysTick. Inna sprawa, ze on chyba tylko do pomiaru czasu w domyśle jest.

Dnia 11.04.2021 o 13:52, atlantis86 napisał:

Sprawdzać wszystkie linie SPI, czy zacząć od konkretnych? CS?

Jak Ci wygodnie. Chociaż sprawdzenie CSów na początku chyba faktycznie będzie naprostrze.

Swoją drogą jest jeszcze jedna rzecz, która co prawda nie sądzę aby miała znaczenie w tym przypadku, ale warto być tego świadomym. Biblioteka podaje 8 taktów zegara do karty SD po przełączeniu CS w stan wysoki (potrzebne to karcie).

Dnia 11.04.2021 o 13:52, atlantis86 napisał:

Zastanawiam się też, czy może nie jest to winą sprzętu. Na schemacie jednak też nie widzę niczego podejrzanego.

Wygląda poprawnie, chyba że to wina jakiegoś zimnego lutu.

Link to post
Share on other sites
(edytowany)

Ok, garść nowych informacji:

  1. Podłączyłem analizator stanów logicznych do linii CS karty SD oraz pamięci RAM. Nigdy nie występuje sytuacja, kiedy obydwie linie jednocześnie znajdowałyby się w stanie niskim.
  2. Po zakończeniu operacji na RAM-ie i ustawieniu jego linii w stan wysoki mijają jeszcze trochę ponad trzy ms, zanim w stan niski zostanie ustawiona linia CS karty SD (między tymi operacjami jest printf). To bardzo dużo czasu, żeby stany linii zdążyły się ustabilizować.
  3. Najwyraźniej eksperymentując z projektem coś zrobiłem, tylko nie wiem co... Może chodzi o ustawienie parametru FS_LOCK w FatFS na 0? W każdym razie w tej chwili wywalenie błędu odczytu sektora karty SD (tuż po zakończeniu operacji na RAM-ie) nie powoduje już zatrzymania czytania z pliku. Operacja jest kontynuowana, jednak co 25 sekund (czyli zawsze po ostatnim dostępnie do RAM-u) pojawia się ten błąd.
Edytowano przez atlantis86
Link to post
Share on other sites

Ok, wygląda na to, że udało mi się osiągnąć pewien sukces i pchnąć projekt do przodu.

Na chwilę obecną wygląda to tak, jakby pamięć SPI nie lubiła się z jedną konkretną kartą SD (Kingston). Nie dosyć, że występował wyżej opisany problem, to jeszcze parę razy zaobserwowałem wysypanie się systemu plików (w tym jednym konkretnym urządzeniu, w innym projekcie karta jak na razie zdaje się działać prawidłowo). Po zastosowaniu SanDisca problemy przestały się pojawiać.

Okazuje się jednak, że przydatność 23LC1024 jako podręcznego bufora na próbki audio (zakodowane w MP3) jest mocno ograniczona. Jedyną działającą u mnie konfiguracją jest:

  • Pobierz z bufora w pamięci SPI RAM 32 bajty danych i przekaż je do dekodera (VS1003)
  • Pobierz z karty SD 32 bajty danych i zapisz je w buforze w pamięci SPI RAM.

Jeśli w drugim punkcie próbowałem zapisywać więcej niż 32 bajty (żeby bufor szybciej się zapełniał niż opróżniał) odtwarzanie "rwało".

Chyba jednak będę musiał powrócić do podręcznego bufora w pamięci MCU, a pamięć SPI będzie dobra na bufor wyższego poziomu, do którego będę ładował np. próbki odbierane przez HTTP z radia internetowego.

Link to post
Share on other sites
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.