3 votos

Forma eficiente de escribir en la memoria flash sin perder datos

Para mi proyecto, estoy escribiendo un código que obtiene algunos resultados y quiero almacenar estos resultados en una memoria flash externa. La memoria flash externa en cuestión es una MX25R8035F . Descubrí que escribir sin borrar sólo funciona la primera vez que escribo algo en una dirección.

Pero debido a esto me estoy encontrando con algunos problemas de memoria. El borrado más pequeño es un borrado de sector (4096 bytes.) Si quiero escribir en una dirección específica primero tendría que leer el sector que contiene esa dirección, cambiar los bytes que quiero que se cambien y luego escribir todo el sector (la escritura es sólo por página.)

¿Existe una forma más eficiente de utilizar esta memoria flash externa? Específicamente usando menos memoria para cambiar uno o dos bytes.

La función que utilizo ahora esto se puede encontrar a continuación:

uint8_t EXT_FLASH_write(size_t address, uint8_t *buf, size_t length) {

/*
 * The entire sector will be erased when writing to an offset inside that sector
 * Therefore this function will first retrieve all data inside the sector and update the retrieved
 * data with the values inside buff which and will then write the entire content back to the sector
 */

    uint8_t wbuf[4];
    SPI_Transaction transaction;
    uint32_t sectorBaseAddr;
    uint8_t temp[EXT_FLASH_ERASE_SECTOR_SIZE];
    uint8_t tries;
    size_t ilen; /* interim length per instruction */
    uint32_t bufIndex = 0;
    uint8_t pageIterations;

    while (length > 0) {
        // first retrieve entire sector so it can be erased on the chip
        sectorBaseAddr = EXT_FLASH_SECTOR_BASE_ADDR(address);
        EXT_FLASH_read(sectorBaseAddr, temp, EXT_FLASH_ERASE_SECTOR_SIZE);

        // Erase the sector on the chip
        EXT_FLASH_erase(address, EXT_FLASH_ERASE_SECTOR_SIZE);

        ilen = EXT_FLASH_PROGRAM_PAGE_SIZE
                - (address % EXT_FLASH_PROGRAM_PAGE_SIZE);
        if (length < ilen)
            ilen = length;

        memcpy(temp + (address - sectorBaseAddr), buf + bufIndex, length);

        bufIndex += ilen;
        address += ilen;
        length -= ilen;

        tries = 0;
        if (EXT_FLASH_writeEnable() != 0) {
            if (tries == EXT_FLASH_MAX_TRIES) {
                return 1;
            }
            tries++;
        }
        tries = 0;
        while (EXT_FLASH_waitReady() != 2) {
            if (tries == EXT_FLASH_MAX_TRIES) {
                return 1;
            }
            EXT_FLASH_writeEnable();
            tries++;
        }

        // programming the external flash can only be done in pages
        // so divide current sector into pages and write each page separately
         for (pageIterations = 0;
                 pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE
                         < EXT_FLASH_ERASE_SECTOR_SIZE; pageIterations++) {
            EXT_FLASH_select();

            wbuf[0] = EXT_FLASH_CODE_PROGRAM;
            wbuf[1] = ((sectorBaseAddr
                    + (pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE)) >> 16)
                    & 0xff;
            wbuf[2] = ((sectorBaseAddr
                    + (pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE)) >> 8)
                    & 0xff;
            wbuf[3] = (sectorBaseAddr
                    + (pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE)) & 0xff;

            // Configure the transaction
            transaction.count = sizeof(wbuf);
            transaction.txBuf = wbuf;
            transaction.rxBuf = NULL;

            if (!SPI_transfer(masterSpi, &transaction)) {
                /* failure */
                EXT_FLASH_deselect();
                return 1;
            }
            // Configure the transaction
            transaction.count = EXT_FLASH_PROGRAM_PAGE_SIZE;
            transaction.txBuf = temp
                    + (pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE);
            transaction.rxBuf = NULL;

            if (!SPI_transfer(masterSpi, &transaction)) {
                /* failure */
                EXT_FLASH_deselect();
                return 1;
            }

            EXT_FLASH_deselect();
        }
    }
    return 0;
}

3 votos

Has caracterizado mal la pieza y has titulado mal tu pregunta, no se trata de una EEPROM, sino de un dispositivo flash. Con una memoria de este tipo no se "cambian algunos bytes", ya que eso es un gran desperdicio. Repiensa cómo estás haciendo las cosas y encuentra un método que no requiera eso, tal vez algo de un diario.

1 votos

Um, Flash es un tipo de EEPROM

1 votos

El gran tamaño de borrado es un problema bien conocido de las memorias flash, que a menudo las hace inadecuadas para almacenar datos cambiantes. Los fabricantes de memorias suelen tener tipos especiales de memoria comercializados como "flash de datos" con tamaños de borrado más pequeños, similares a lo que antes se llamaba EEPROM. Sin embargo, para el propósito de registrar, etc., con muchas escrituras, podrías considerar tipos de memoria alternativos, como la "FRAM" o la "MRAM" que varias compañías han desarrollado en los últimos años. No tienen la limitación de ciclos de escritura ni el problema de retención de datos de las memorias flash.

4voto

Hamsteriffic Puntos 367

La FLASH es barata y proporciona mucha memoria, pero tiene el coste del borrado de sectores. Por lo tanto, es posible que desee utilizar EEPROM en su lugar.

Por supuesto, es posible superar esta limitación del flash con algún software inteligente, que rastrea los bits y bytes con un revista (es decir, no se sobrescribe un valor de byte sino que se escribe una nueva copia del mismo y se anota en el diario que el nuevo byte es el reciente). Pero esto es una sobrecarga de software muy grande y es posible que no quieras hacerlo.

0 votos

Ya que realmente no puedo elegir el hardware que estoy utilizando. Supongo que el diario es la mejor solución.

2 votos

No subestimes el trabajo necesario para conseguir una implementación del diario totalmente funcional y sin errores. Tampoco es trivial decidir si un diario es factible para su aplicación. ¿De cuánto espacio dispone? ¿Cuánto se utilizará al máximo? ¿Cuántas reescrituras por página se esperan? ¿Puede su aplicación incluso trabajar con una función de escritura indeterminada en el tiempo? A menos que ya esté en preproducción, tendrá mucho más sentido cambiar la lista de materiales por algo que se ajuste más a su aplicación.

0 votos

¿Algún libro o artículo que recomiende para leer sobre las revistas?

2voto

Mike Puntos 380

Hay una nota de aplicación muy buena de microchip. El algoritmo de esta nota de aplicación soporta EEPROMs de datos múltiples y seleccionables con un tamaño total de hasta múltiplos de 255 ubicaciones. La sobrecarga en este diario no es tan grande y es realmente fácil y cómodo de usar.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X