Skocz do zawartości

STM32F429ZI odczyt i zapis z SDRAM


MikePiw

Pomocna odpowiedź

To mój pierwszy post, więc cześć wszystkim! 😄

 

Tworzę program na STM32F429I-DISC1, w którym będę zapisywał i odczytywał sporo danych z zewnętrznego RAMu. Korzystam z bibliotek Mbed i on-line'owego kompilatora Mbed. Pojawił się jednak problem- dane po odczycie różnią się od tych zapisanych. Napisałem prosty przykład, który dobrze obrazuje problem. Przykład bazuje na kodzie z linku.

#include "mbed.h"
#include "SDRAM_DISCO_F429ZI.h"
SDRAM_DISCO_F429ZI sdram;
DigitalOut led_green(LED1);
DigitalOut led_red(LED2);
 
int main()
{
    uint32_t buff[1];
    uint32_t WriteBuffer[4];
    uint32_t ReadBuffer[1];
    uint32_t adr = 0x30000;
    
    led_green = 0;
    led_red = 0;
    
    wait_ms(500);
    
    uint32_t i;
    for (i = 0; i<=3; i++)
    {
        WriteBuffer[i]=i;
        buff[0] = i;
        sdram.WriteData(SDRAM_DEVICE_ADDR + adr + i, buff, 0x0001);  
    }
    
    for (i = 0; i<=3; i++)
    {
        led_green = 1;
        led_red = 1;
        wait_ms(500);
        
        sdram.ReadData(SDRAM_DEVICE_ADDR + adr + i, ReadBuffer, 0x0001);
        
        if (WriteBuffer[i] == ReadBuffer [0])
        {
            led_green = 1;
            led_red = 0;
        }
        else
        {
            led_green = 0;
            led_red = 1;
        }
        wait_ms(1000);
    }       
  return 0;
}

 

Po wykonaniu programu w pierwszych trzech obiegach pętli zapala się dioda czerwona (wartość odczyta jest inna od zapisanej), dopiero za czwartym razem (ostatnim) wartości są zgodne (dioda zielona).

Widzę 3 ewentualności:

1) Mam uszkodzoną płytkę,

2) On-line'owy kompilator m-bed źle kompiluje kod

3) Coś robię nie tak... Pytanie co?

 

Będę wdzięczny za każdą sugestię!

Edytowano przez MikePiw
Link do komentarza
Share on other sites

1) Wgraj jakiś sprawdzony program, chociażby przykład który był na płytce początkowo. Jak działa to sprzęt jest ok.

2) Kompilatory na ogół działają dobrze, z programistami bywa różnie. Ale i tak lepiej mieć kompilator u siebie - chociażby dlatego że debugger czasem się przydaje

3) Dobre pytanie. Ciężko powiedzieć - proponuję uprościć test, zapisywać i odczytywać tylko jedną zmienną. Jakoś nie sądzę, żeby uszkodzenie pamięci, albo błąd kompilatora mogło poprawnie odczytywać tylko czwartą wartość - więc błąd jest pewnie w programie, ale w tej chwili go nie widzę

 

I jeszcze z drobnych uwag - pamiętaj o pętli nieskończonej na końcu programu, a jeśli planujesz faktycznie dużo operacji na pamięci to wyrzuć powolne sdram.WriteData() - to straszne marnowanie czasu procesora.

Ok, chyba już wiem co jest źle - próbowałeś uruchomić testowy program dołączony do biblioteki? https://os.mbed.com/teams/ST/code/DISCO-F429ZI_SDRAM_demo/file/5702fea0c868/main.cpp/

Sprawdź czy on zadziała.

Link do komentarza
Share on other sites

Dzięki za uwagi- załączony kod jest uproszczony, żeby pokazać o co chodzi.

Testowy program dołączony do biblioteki działa- miga cały czas zieloną diodą.

Co do mojego programu- jeżeli odczyt i zapis danych zrobię w jednej i tej samej pętli wszystko działa. Problem pojawia się, gdy całość rozbijam na dwie pętle. Najpierw ładuję dane do RAM'u w kilku tablicach (tak będzie w docelowym programie), a po dłuższym czasie będę je odczytywał- stąd druga pętla.

Jednak niezależnie od ilości tablic które umieszczam w pamięci RAM, tylko ostatnia z odczytanych ma poprawne wartości.

Link do komentarza
Share on other sites

Skoro testowy program z biblioteki działa poprawnie, to chyba masz odpowiedź na większość swoich pytań:

1) sprzęt jest sprawny

2) kompilator działa poprawnie

3) no właśnie - podpowiem, czegoś w Twoim programie brakuje, np.

    // Issue self-refresh command to SDRAM device
    SDRAMCommandStructure.CommandMode            = FMC_SDRAM_CMD_SELFREFRESH_MODE;
    SDRAMCommandStructure.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
    SDRAMCommandStructure.AutoRefreshNumber      = 1;
    SDRAMCommandStructure.ModeRegisterDefinition = 0;
    if (sdram.Sendcmd(&SDRAMCommandStructure) != HAL_OK) 
    {
      led_red = 1;
      error("BSP_SDRAM_Sendcmd FAILED\n");
    }

 

Z drugiej strony patrząc dokładniej na przykład sam już nie wiem... Ale zła konfiguracja odświeżania pamięci pasuje idealnie.

Proponuję zrobić tak: skoro przykład działa, po prostu dodaj swoje testy w miejsce tych z przykładu.

Link do komentarza
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

(edytowany)

Też stawiałem na odświeżanie pamięci- nic nie pomogło. Sprawdziłem też na innej płytce STM u kolegi. Dało to taki sam efekt jak na mojej, czyli płytka jest sprawna.

 

Po długich bojach znalazłem wreszcie sposób i program zadziałał, ale nie do końca tak jak sobie wyobrażałem- więc pojawiają się kolejne pytania.

Otóż jeżeli w zapisie i odczycie licznik "i" pomnożę przez liczbę 4 lub większą (tak jak linijkę niżej), to program działa poprawnie (wartości odczytane są równe zapisanym).

for (i = 0; i<=3; i++) {
        (...)
        sdram.WriteData(SDRAM_DEVICE_ADDR + adr + i*4, buff, 0x0001);  
    }

Oznacza to jednak, że adres  zapisywanych danych w RAM nie może zmieniać się o 1, a co najmniej o 4.

Stąd pytanie- czy to ułomność funkcji z bibliotek mbed i mam do dyspozycji tylko 1/4 pamięci RAM, czy może błędnie adresuję RAM? Jaki w takim razie jest zakres adresów?

Edytowano przez MikePiw
Link do komentarza
Share on other sites

Moje gratulacje - nie ma to jak oczywiste rozwiązanie które jest przed nosem, a go nie widać 🙂

Oczywiście, że adresy trzeba mnożyć przez 4. Ta dziwna biblioteka udostępnia tylko adresowanie słowami, dlatego wszystkie bufory są typu uint32_t. Skoro dostęp słowami to i adresy muszą być odpowiednio wyrównane.

Napisałem wcześniej, że używanie ReadData() i WriteData() to strata czasu, teraz doszedł jeszcze argument adresowania.

A pamięci nie masz mniej - każdy zapis lub odczyt odbywa się wielokrotnościach 4B. Więc ostatni parametr (size) równy 1 oznacza 4 bajty. Natomiast adres dla zmyłki liczony jest w bajtach. Stąd konieczność mnożenia.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

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.