LinkedIn YouTube Facebook
Szukaj

Newsletter

Proszę czekać.

Dziękujemy za zgłoszenie!

Wstecz
Artykuły

Komunikacja mikrokontrolerów STM32 z pamięciami DataFlash

Właściwości pamięci

Producent deklaruje, że minimalna liczba cykli zapisu układu AT45DB321D wynosi co najmniej 100000, a dane przechowywane mogą być przez 20 lat. 100000 cykli zapisu może wydawać się dość dużą liczbą, ale jeśli aplikacja będzie zbyt często dokonywać zapisu, można się spodziewać, że dopuszczalny limit zostanie szybko wyczerpany i pamięć nie będzie się nadawać do pracy. Aby nie doprowadzić do takiej sytuacji należy unikać cyklicznych lub niekontrolowanych zapisów, np. wyzwalanych z funkcji obsługi jakiegoś przerwania.
Jak już wyżej wspomniano, rozmiar wykorzystanej pamięci to 32 Mb. Cała przestrzeń jest podzielona na strony i bloki. Rozmiar strony pamięci może wynosić 512 lub 528 bajtów (domyślnie), natomiast proces samego kasowania jest dość elastyczny, ponieważ pozwala na wymazanie całej strony, bloku (4 kB), sektora (64 kB) lub tez całego układu (32 Mb).

 

Rys. 3. Schemat blokowy pamięci DataFlash AT45DB321D

Rys. 3. Schemat blokowy pamięci DataFlash AT45DB321D

 

 

Dostęp do pamięci może odbywać się bezpośrednio, lub z użyciem jednego z dwóch buforów. Schemat blokowy ilustrujący relacje pomiędzy buforami, a interfejsem I/O przedstawiono na rysunku 3.
Układ AT45DB321D obsługuje wiele wariacji zapisu i odczytu. Cześć z nich, która wydała się najważniejsza lub najciekawsza została omówiona poniżej.

 

Rys. 4. Budowa rejestru statusu w układzie AT45DB321D

Rys. 4. Budowa rejestru statusu w układzie AT45DB321D

 

 

Odczyt rejestru statusu

Najłatwiejszym, ale zarazem często bardzo istotnym, etapem komunikacji z układem pamięci AT45DB321D jest odczytanie zawartości rejestru statusu. Na rysunku 4 zamieszczono budowę tego rejestru, natomiast funkcję odczytującą jego zawartość przestawiono na listingu 2. Zawartość rejestru statusu jest wystawiana na magistralę po wysłaniu do układu pamięci bajta o wartości 0xD7, według schematu z rysunku 5.

 

Rys. 5. Odczytywanie zawartości rejestru statusu układu pamięci

Rys. 5. Odczytywanie zawartości rejestru statusu układu pamięci

 

 

List. 2. Funkcja odczytująca rejestr statusu AT45DB321D

void readStatusRegister(void)
{
    /* sprawdzanie muteksa */
    while(SPI_InUse);
    /* "weź" muteks */
    SPI_InUse = 0x11;
    SPI_Cmd(SPI1, DISABLE);
    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);
    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE);
    /* pierwszy bajt to komenda, drugi to zawartość rejestru */
    Nof_Bytes_To_TxRx = 2;
    /* Komenda "read status register" */
    TxBuf[0] = 0xD7;
    SPI_Cmd(SPI1, ENABLE);
    GPIO_SetBits(GPIOA, GPIO_Pin_4);
    /* CS w stan niski */
    GPIO_ResetBits(GPIOA, GPIO_Pin_4);
}

 

Ponieważ do wymiany danych zastosowano przerwania, to „sztywne” blokowanie wykonywania programu w oczekiwaniu na zakończenie komunikacji byłoby niemądre. Z tego powodu wykorzystano nieco bardziej skomplikowany mechanizm. Jak będzie można zauważyć dalej, każda funkcja obsługi pamięci DataFlash ma na początku pętlę while(), która będzie się wykonywać dopóki, dopóty zmienna SPI_InUse będzie miała wartość niezerową (prawdziwą w sensie logicznym). Dopiero po niespełnieniu tego warunku program przejdzie do kolejnych instrukcji. Zaraz poniżej wymienionej pętli zmienna SPI_InUse jest z powrotem ustawiana na wartość niezerową (czyli typu PRAWDA).

 

List. 3. Obsługa przerwania od kontrolera SPI

void SPI1_IRQHandler(void)
{
    /* Bufor nadawczy jest pusty */
    if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_TXE) != RESET)
    {
        /* Wyťlij bajt */
        SPI_I2S_SendData(SPI1, TxBuf[TxIdx++]);

        /* Wy??czenie przerwania od SPI i oddanie po?owy muteksa */
        if (TxIdx == Nof_Bytes_To_TxRx)
        {
            SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, DISABLE);
            TxIdx = 0;
            SPI_InUse &= ~0x01;
        }
    }
    /* W buforze odbiorczym jest odebrany bajt */
    if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) != RESET)
    {
    	/* Odczyt odebranego bajta */
    	RxBuf[RxIdx++] = SPI_I2S_ReceiveData(SPI1);

    	/* Wy??czenie przerwania od SPI i oddanie po?owy muteksa */
        if (RxIdx == Nof_Bytes_To_TxRx)
        {
            SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, DISABLE);
            RxIdx = 0;
            SPI_InUse &= ~0x10;
        }
    }
}