Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Czytnik kart SD na STM32F4Discovery

Tytus Kosiarski 13 Wrz 2013 12:48 8643 13
  • Czytnik kart SD na STM32F4Discovery

    Witam wszystkich

    Tym razem chciałbym zaprezentować kolejny programowy projekt czytnika kart SD uruchomiony na płytce STM32F4Discovery. Programowy, gdyż również wejdzie on w skład większego projektu sprzętowo-programowego. Poprawność funkcjonowania tego czytnika sprawdziłem na dwóch kartach SDHC 16GB z systemem plików FAT32 i jednej karcie SD 2GB z FAT16. Czytnik współpracuje z komputerem przez USB Full Speed i przetestowane przeze mnie osiągi były następujace: prędkość odczytu karty wynosiła około 860kB/s, natomiast prędkość zapisu karty była na poziomie ok. 530kB/s. Karta komunikuje się z mikrokontrolerem na płytce przez interfejs SDIO z 4-bitową szerokością magistrali danych. Konfig zegarów mikrokontrolera i portów do współpracy z kartą i LED-ami zrobiłem "na piechotę" poprzez bezpośrednie wpisy do odpowiednich rejestrów, natomiast do oprogramowania USB FS i SDIO w mikrokontrolerze wykorzystałem gotowe biblioteki producenta, które zmodyfikowałem tak, by zmniejszyć zajętość obszaru .bss w pamięci RAM i zwiększyć rozmiar bufora dla danych zapisywanych na/odczytywanych z karty SD z 4kB producenta do 48kB (definicja MSC_MEDIA_PACKET w pliku usbd_conf.h). Ponadto usunąłem błąd w dwóch plikach z tej biblioteki, który skutkował tym, że po podłączeniu czytnika komputer widział dwa napędy o identycznej zawartości. Usunięcie tego błędu polegało na zmianie wartości zwracanej przez funkcję STORAGE_GetMaxLun w pliku usbd_storage_msd.c (obecnie jest pomniejszona o 1 zwracana wartość STORAGE_LUN_NBR) i zmiana warunku na if(USBD_MSC_MaxLun >= 0) w funkcji USBD_MSC_Setup w pliku usbd_msc_core.c. Wybrałem tryb Full Speed, gdyż biblioteka producenta po skompilowaniu na ten tryb ruszyła praktycznie "od pierwszego kopa" a w trybie HS napotkałem na (już nie pamiętam, jakie) problemy, na rozwiązywanie których już nie chciałem poświęcać czasu. Na gotowej płytce Discovery, oprócz podłączenia karty w sposób opisany w komentarzu na początku pliku main.c, nie trzeba nic więcej zmieniać. Płytka zasilana jest przez złącze CN1 typu USB mini A, natomiast komunikacja z komputerem odbywa się poprzez złącze CN5 typu USB mini B. Praca czytnika jest wizualizowana za pomocą dwóch LED: pomarańczowej, sygnalizującej 1ms przerwania od SysTick'a i zielonej, sygnalizującej operacje odczytu/zapisu karty SD (jak LED od HDD).
    Program napisałem i uruchomiłem w środowisku Rowley Crossworks ver.2.0.11. W tym projekcie nie są wykorzystane styki obecności karty w slocie oraz zabezpieczenia jej przed zapisem.
    Pozdrawiam, KT

    Czytnik kart SD na STM32F4DiscoveryCzytnik kart SD na STM32F4DiscoveryCzytnik kart SD na STM32F4DiscoveryCzytnik kart SD na STM32F4DiscoveryCzytnik kart SD na STM32F4Discovery

    Fajne! Ranking DIY
    Potrafisz napisać podobny artykuł? Wyślij do mnie a otrzymasz kartę SD 64GB.
    O autorze
    Tytus Kosiarski
    Poziom 14  
    Offline 
    Specjalizuje się w: programowanie mikrokontrolerów
    Tytus Kosiarski napisał 183 postów o ocenie 288, pomógł 8 razy. Jest z nami od 2007 roku.
  • #2
    lukash90
    Poziom 16  
    Mógłbyś opisać szerzej jak działa obsługa karty? Nie zauważyłem w paczce plików z biblioteki FatFs a jedynie plik SD_card_functions w którym to domyślam się są w większości funkcje obsługi błędów. Skąd zatem bierzesz obsługę systemu FAT?
  • #3
    kitor
    Poziom 34  
    W czytniku podłączonym do komputera takimi rzeczami zajmuje się system operacyjny.
  • #4
    Tytus Kosiarski
    Poziom 14  
    Do lukash90: Kiedy już interfejs USB jest skonfigurowany i może nastąpić przezeń transfer danych, to w programie czytnika wywoływana jest funkcja STORAGE_Init z pliku usbd_storage_msd.c. W tej funkcji karta jest konfigurowana i odczytywane są jej parametry przy pomocy wywołań funkcji, których ciała zawarte są w pliku SD_card_functions.c, które później będą odesłane komputerowi. Komputer traktuje ten czytnik jako urządzenie SCSI i i wysyła serię poleceń SCSI: INQUIRY, REQUEST_SENSE, MODE_SENSE(6), MODE_SENSE(10), READ_FORMAT_CAPACITIES, READ_CAPACITY(10), by dowiedzieć się coś o podłączonej karcie SD. Program czytnika poprzez realizację funkcji SCSI_ProcessCmd z pliku usbd_msc_scsi.c, korzystając z wcześniej odczytanych parametrów karty SD, odsyła komputerowi odpowiedzi na powyższe polecenia. Następnie komputer wysyła polecenie SCSI: READ(10) i odczytuje zawartość karty, którą można następnie wyświetlić w "Mój komputer". Po tym wszystkim komputer cyklicznie wysyła polecenie SCSI: TEST_UNIT_READY, na które czytnik musi odsyłać odpowiedź poprzez realizację funkcji SCSI_TestUnitReady z pliku usbd_msc_scsi.c. To tak w dużym uproszczeniu. Samym rozpoznaniem systemu plików i jego obsługą zajmuje się już system operacyjny komputera, jak zauważył Kol. kitor.

    Natomiast, gdy chce się użyć systemu plików na karcie we własnej aplikacji, to trzeba użyć np. FatFS. Ja popróbowałem innego rozwiązania FAT16/32 File System Library, dostępnego tutaj: http://ultra-embedded.com/?fat_filelib
    Według mnie jest bardziej przyjazny do implementacji niż FatFS.
    KT
  • #5
    polprzewodnikowy
    Poziom 26  
    Tytus Kosiarski napisał:
    Wybrałem tryb Full Speed, gdyż biblioteka producenta po skompilowaniu na ten tryb ruszyła praktycznie "od pierwszego kopa" a w trybie HS napotkałem na (już nie pamiętam, jakie) problemy, na rozwiązywanie których już nie chciałem poświęcać czasu.


    Wiele by ci to nie dało, do USB HS potrzebujesz zewnętrznego PHY. Bez niego USB "HS" będzie działać w trybie FS.

    PS. Widzę, że nie tylko mnie doskwierał problem braku gniazda SD w tym zestawie ;)
  • #6
    markoz7874
    Poziom 31  
    Drobna uwaga do sposobu prezentacji projektu - masz poruszone zdjęcia.
    Aby tego uniknąć, włącz samowyzwalacz, oprzyj aparat na jakimś pudełku i naciśnij spust migawki.
    Prosty patent, a jakość zdjęć zdecydowanie lepsza - polecam :)
  • #7
    Tytus Kosiarski
    Poziom 14  
    Dzięki za poradę, nie wpadłbym na to. Faktycznie, zdjęcia robiłem aparatem trzymanym w rękach, choć próbowałem trzymać go sztywno, opierając łokcie o stół. Efekt nie jest jednak zadowalający.
    Pozdrawiam, KT
  • #8
    rasz
    Poziom 21  
    Czy SDIO w STM32F4 może pracować w trybie slave? Tzn. emulować kartę?
  • #10
    rasz
    Poziom 21  
    emulowac karte czyli byc slavem SDIO, czyli np wpiac sie w aparat fotograficzny i udawac ze jest sie karta

    glownym wymogiem jest mozliwosc skonfigurowania zewnetrznego zrodla zegara dla SDIO
  • #11
    Tytus Kosiarski
    Poziom 14  
    Zajrzałem do PDF-a tego mikrokontrolera, nigdzie jasno nie jest napisane, że SDIO może być slave'em, natomiast na str.850 tego PDF-a (DM00031020.pdf) jest jasno napisane, że jest masterem.
  • #12
    7dexter
    Poziom 2  
    Cześć,

    Może nie do końca do DIY, ale temat bardzo związany.

    Akurat tak się złożyło, że również uruchamiam analogiczną rzecz, tyle że na stm32f205, o ile sama biblioteka od usb zdaje się u mnie działać i osobno od karty sd, o tyle razem mają niejaki problem. Po uporządkowaniu całej konfiguracji, utknąłem w momencie gdzie windows widzi poprawnie urządzenie w menadżerze urządzeń, jako dysk, jednak pokazuje kartę jako niesformatowaną.
    Tej samej biblioteki obsługi karty sd używam w FatFs i tam działa bezbłędnie i przy odczycie, i przy zapisie, także przyczynę po tej stronie wstępnie bym wykluczył.

    Przejrzałem to co było do przejrzenia u kolegi, niestety nie doszukałem się kluczowych różnic między naszymi kodami, może poza tym, że ja bardziej standardowej wersji używam biblioteki usb.

    Spotkał się kolega z podobnym zachowaniem tudzież ma jakieś sensowne źródło informacji na temat tego jak to poskładać w całość? Moim zdaniem manual do biblioteki od USB jest tragiczny, niestety.

    Pozdrawiam,
    Decks.

    EDIT:
    W pewnym sensie wydaje mi się, że znalazłem winowajcę, chociaż nie wiem co z nim zrobić, przy odczycie zerowego bloku karta pamięci dostaje timeoutuje, przynajmniej w/g sdio->sta.
  • #13
    Tytus Kosiarski
    Poziom 14  
    Witam
    Przepraszam, że tak późno (brak czasu), ale może jeszcze się przyda...
    Proponuję uruchomić układ w debugu. Potem, gdy USB jest już skonfigurowane, zatrzymać wykonanie programu (przez breakpoint) na funkcji Storage_init z pliku usb_storage_msd.c. U mnie jest inicjacja karty jak w poniższym kodzie:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zmienna result w powyższej funkcji musi przyjąć wartość SD_OK.
    Następnie zatrzymać program na funkcji STORAGE_GetCapacity. U mnie wygląda ona tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    W niej odsyłane są komputerowi dwa parametry: rozmiar sektora (pole CardBlockSize struktury SDCardInfo) ma mieć wartość 512 oraz liczba sektorów na karcie będąca ilorazem wartości z pól CardCapacity i CardBlockSize tej struktury. Uwaga: pole CardCapacity MUSI być liczbą 64-bitową, o ile sobie przypominam, w oryginalnej bibliotece obsługi karty SD od producenta, liczba ta była deklarowana jako 32-bit. Dlaczego 64-bitową? Pole CardCapacity przechowuje pojemność karty w bajtach, stąd dla kart >4GB był błąd, gdyż takiej liczby bajtów pojemności nie da się zmieścić w 32-bit zmiennej. Wspomniana struktura jest wypełniana podczas realizacji funkcji SD_GetCardInfo z pliku SD_card_functions.c (u mnie) - sprawdź poprawność jej wypełnienia tamże.

    W następnym kroku proszę zatrzymać wykonanie programu na funkcji STORAGE_Read. Tam odczytywana jest już zawartość karty. Gdy tam będą błędy odczytu, komputer nie zobaczy i nie wyświetli zawartości karty. U mnie ta funkcja ma postać:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Szczególną uwagę trzeba zwrócić na wartość pola CardType, gdyż od jej wartości zależy adresowanie sektorów na karcie. Błędna adresacja sektorów spowoduje zwrot błędu zamiast wypełnienia tablicy wskazywanej przez wskaźnik buf. Gdy odczyt wydaje się OK, sprawdź zawartość tablicy buf, porównując ją chociażby ze zrzutem sektora tej samej karty uzyskanym w programie dskprobe.exe

    Mam nadzieję, że trochę pomogłem :) Pozdrawiam, KT
  • #14
    7dexter
    Poziom 2  
    Well, wszystko się zgadza, tylko w Windowsie i pod Linuksem, pokazuje, że dysk jest nieobecny w czytniku.

    Wszystkie wspomniane przez Ciebie funkcje zwracają dane zgodnie z oczekiwaniami, tak samo w funkcji STORAGE_Read buf ma wartość taką samą jakie są rzeczywiście na karcie. Najpierw odczytuje MBR (u mnie robi to wielokrotnie, nie wiem czy to normalne), potem odczytuje bloki od adresu 0x800 (adres w blokach), co wygląda z grubsza jak początek partycji.

    Przy czasie zbuduję analogiczny układ na discovery f4, będzie większa pewność co do prawidłowego działania sprzętu, a potem spróbuję przenosić kod na własny hardware. Testowane na karcie 512MB SD SC v2 jak i 8GB SDHC.

    Pewnie gdzieś robię jakiś czeski głupi błąd, jak to zwykle bywa.

    Wielkie dzięki za pomoc :)