• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Делюсь опытом Новые ревизии модулей на базе ESP8266 не умеют писать в SPI Flash...

Paul_B

Member
Сам столкнулся с проблемой описанной здесь: Новые ревизии модулей на базе ESP8266 не умеют писать в SPI Flash
Отлаженный проект, работающий на 10 модулях вдруг перестает работать на новом модуле, достал еще один - тот же эффект.
Китайские поставщики начали использовать микросхему flash-памяти производства PUYA. Это привело к поломке драйверов SPIFFS, которые обычно используюся для сохранения настроек в модулях ESP8266.
Лечиться заменой функции в файле Esp.cpp вот функция, на которую надо поменять. Она универсальная, работает на любых ревизиях модулей. Правда на модулях с памятью puya работает, понятно, медленнее, но работает.
Код:
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) {
    static uint32_t flash_chip_id = 0;
        uint32_t *read_buf=NULL;
    if (flash_chip_id == 0)
        flash_chip_id = getFlashChipId();
    ets_isr_mask(FLASH_INT_MASK);
    int rc;
    uint32_t* ptr = data;
    if ((flash_chip_id & 0x000000ff) == 0x85) { // 0x146085 PUYA
        read_buf=new uint32_t [SPI_FLASH_SEC_SIZE / 4];
        if(!read_buf) return false;
        rc = spi_flash_read(offset, read_buf, size);
        if (rc != 0) {
            delete read_buf;
            ets_isr_unmask(FLASH_INT_MASK);
            return false;
        }
        for (size_t i = 0; i < size / 4; ++i) {
            read_buf[i] &= data[i];
        }
        ptr = read_buf;
    }
    rc = spi_flash_write(offset, ptr, size);
        if(read_buf!=NULL) delete read_buf;
    ets_isr_unmask(FLASH_INT_MASK);
    return rc == 0;
}
 
Последнее редактирование:

Алексей.

Active member
Paul_B,
Забавный код, на строке 10 выделяем буфер, на строке 22 освобождаем, а если не смогли успешно выполнить вызов spi_flash_read на строке 11, то про выделенный буфер забываем и выходим из метода на строке 14.
Типа у нас и так всё работает, а те у кого лики вдруг повалятся, сами пусть ищут где память течет.
Узнаю стиль примеров из MSDN
 

Алексей.

Active member
Лечиться заменой функции в файле Esp.cpp вот функция, на которую надо поменять. Она универсальная, работает на любых ревизиях модулей. Правда на модулях с памятью puya работает, понятно, медленнее, но работает.
Если память не puya то код работает быстрее прежнего?:)
Непонятно почему не под #ifdef - ом, ведь когда собираем - точно знаем зачем это делаем.
 

Paul_B

Member
Непонятно почему не под #ifdef - ом, ведь когда собираем - точно знаем зачем это делаем.
Если не puya, работает так же, вот оригинальная функция:
Код:
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) {
    ets_isr_mask(FLASH_INT_MASK);
    int rc = spi_flash_write(offset, (uint32_t*) data, size);
    ets_isr_unmask(FLASH_INT_MASK);
    return rc == 0;
}
Дело в том, что у меня универсальный код, который заливается при обновлении bin-фалом через http. Как показала практика, модуль с puya может встретиться на ровном месте, не хочу каждый раз править файл ручками и потом компилировать.
Я купил партию ESP-7 где-то полгода назад, вот сейчас начал ставить их в нетребовательные устройства, когда не заработал, ночь просидел, хотел уже все выбросить, ан нет, заработало. Медленно, но заработало.
 

Алексей.

Active member
Дело в том, что у меня универсальный код, который заливается при обновлении bin-фалом через http.
Прежде чем выполнить обновление чего-то нужно сначала инициализировать чем-то. Иначе как то не получается.
У вас начальная загрузка отсутствует? Тогда понятно, модули приходят уже с памятью разного типа и уже готовые к обновлению.
У меня задача по проще (не те объемы чтоб прогруженные модули заказывать), на производстве модули сначала должны пройти диагностику и после отправятся на сборку, чтоб не залить чего лишнего, сначала определяем что за зверь, а уж потом заливаем. Типа попался 'Manufacturer: E0 85' - значит память puya
 
Последнее редактирование:
Сверху Снизу