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

Решено Пример записи и чтения память(flash)

de1m

New member
Хочу сохранять пароль и названия точки в память. Я пример нашел, он работает, вот может кому надо
Код:
static void ICACHE_FLASH_ATTR test() {
   os_printf("SDK version:%s\n", system_get_sdk_version());

    uint32 temp[4]={122323, 13, 14, 15};
    uint32 temp1[4]={0};

    int i = spi_flash_erase_sector(0x8c);
    os_printf("spi_flash_erase_sector: %d\n", i);
    int o = spi_flash_write(0x8c000, temp, sizeof(temp));
    os_printf("spi_flash_write: %d\n", o);

    int p = spi_flash_read(0x8c000, temp1, sizeof(temp1));
    os_printf("spi_flash_read: %d\n", p);

    os_printf("read :%x, %x, %x, %x\n", temp1[0], temp1[1], temp1[2], temp1[3]);
}
А вот это, что я уже написал
Код:
static void ICACHE_FLASH_ATTR test() {
   os_printf("SDK version:%s\n", system_get_sdk_version());

    struct wConf{
       char ssid[32];
       char passwd[64];
    };

    struct wConf wifiApConf;

    os_memcpy(wifiApConf.ssid, "CO2", 3);
    os_memcpy(wifiApConf.passwd, "co2passwd", 64);

    uint32 ssidAp[32];

    int i = spi_flash_erase_sector(0x8c);
    os_printf("spi_flash_erase_sector: %d\n", i);
    int o = spi_flash_write(0x8c00, (uint32 *)&wifiApConf.ssid, 3);
    os_printf("spi_flash_write: %d\n", o);
    int p = spi_flash_read(0x8c00, (uint32 *)&ssidAp[0],4);
    os_printf("spi_flash_read: %d\n", p);
    os_printf("result: %s\n", ssidAp);
}
Выглядит это вот так:
SDK version:1.5.4(baaeaebb)
spi_flash_erase_sector: 0
spi_flash_write: 0
spi_flash_read: 0
result: \0x01\0x08\0x10
Кто подскажет, как надо правильно сохранить и читать? Или может вообще всю эту процедуру подскажет как правильно делать.
 

de1m

New member
Спасибо за пдф, есть полезная информация.
Там есть такая фраза "User parameter area: store user parameters in application", но дальше не понятно где она начинается?
Это user01.bin - 0x01000 или user2.bin - 0x81000 ?
 

Victor

Administrator
Команда форума
в конце, после каждого куска с кодом (туда, где прошили код, из программы ничего не стирайте/записывайте!),
т.е. сразу после user1.bin - это область User Data или в User Param.
User Param:
Для 512k выбираете сектор [inline]3C[/inline], для 4Mbyte - [inline]7С[/inline] (для стирания указывайте номер сектора, при чтении/записи умножайте сектор на [inline]SPI_FLASH_SEC_SIZE[/inline])
User Data надо высчитывать, в зависимости от размера прошивки
Подробнее смотрите Chapter 4 Flash Map Address and layout
ESP8266 SDK Getting Started Guide 2.2
 

Sashad

New member
Еще можете посмотреть в сторону функций system_rtc_mem_write() и system_rtc_mem_read(). Тут предусмотрено место для 512 байт пользовательских данных. Если вам нужно сохранять только пароль и название точки, то 512 байт вам за глаза хватит:
Код:
uint8 data[32];
// ---------------- Write to NV memory (RTC memory) ----------------
    system_rtc_mem_read(64, &data, 32);
    ets_uart_printf("Readed data from RTC: %s\r\n", data);
    if (data[0] != 0x6B)
    {
        os_sprintf(data, "%s", "k305aa_9753751376");
        system_rtc_mem_write(64, &data, 32);
        ets_uart_printf("Data has been written to RTC memory\r\n");
    }
    // -----------------------------------------------------------------
В этой секции вы точно не будете бояться, что затрете что-то нужное. И как бонус, вам не нужно заморачиваться с предварительным стиранием памяти перед записью, это уже спрятано внутри функции.
 

Victor

Administrator
Команда форума
Тут предусмотрено место для 512 байт пользовательских данных.
только не забудьте, что при передергивании питания или [inline]chip enable[/inline] там рандомные данные, т.е. ваши данные хранятся только пока есть питание.
 

de1m

New member
Я тут перечитал некоторые вещи, но должен заметить, что для меня, как начинающего, есть некоторые непонятные моменты.
1.Как надо считать сколько места занимает моя программа?
2.Многие делают вебстаницы, которые сохраняются на чипе, как их сохранять? Делать из всего(html) string, который сохранять во флешь?
3. Как я понял, 4МБ это для всего?
 

Victor

Administrator
Команда форума
Я тут перечитал некоторые вещи, но должен заметить, что для меня, как начинающего, есть некоторые непонятные моменты
1. не считайте, пишите в UserParam небольшие порции данных (настройки, например)
2. удобнее всего хранить html в виде файлов на файловой системе, вроде spiffs или других (для новичка будет сложновато встроить в свою программу файловую системе - лучше начать с чего-то попроще). Кстати, в Arduino для ESP8266 это уже сделано за вас и есть много примеров.
3. да, но можно подключить SD карту если нужно много памяти (потребуется прикрутить файловую систему и SPI драйвер - тоже не для новичка)
 

de1m

New member
Переделал функцию
Код:
  uint32 tosave, toread;
  char ssid[32];
  char ssid2[32];

  os_memcpy(ssid, "CO2", 3);

  int i = spi_flash_erase_sector(0x8c);
  os_printf("spi_flash_erase_sector: %d\n", i);
  int o = spi_flash_write(0x8c000, (uint32*)ssid, sizeof(ssid));
  os_printf("spi_flash_write: %d\n", o);

  int p = spi_flash_read(0x8c000, &toread, sizeof(toread));

  os_memcpy(ssid2, &toread,sizeof(&toread));

  os_printf("Read from flash: %s\n", ssid2);
Выдаёт на выходе теперь "CO2@", немогу понять откуда берётся "@". Я думаю, что-то не то при конвертировании происходит, но моих знаний не хватает понять, что не так.

Кто может подсказать откуда @ и что надо сделать, чтобы было без этого?
 
Последнее редактирование:

Victor

Administrator
Команда форума
Кто может подсказать откуда @ и что надо сделать, чтобы было без этого?
нужно писать блоками по 4 байта, т.е. "выравнивать" данные. в вашем случае должно быть достаточно забить нулями
Код:
перед os_memcpy добавьте
os_memset(&ssid, 0x00, sizeof ssid);
 

de1m

New member
Спасибо, теперь выдаёт правильно, но получаю ошибку "
LoadStoreAlignmentCause", я вот тут как раз читаю, что это такое и как с этим бороться
 

Victor

Administrator
Команда форума
а разве недостаточно вместо...
да, в этом частном случае достаточно.
Но лучше делать структуру со всеми настройками, ее целиком обнулять, затем присваивать нужные значения разных типов не заботясь о концах строк или неприсвоенных значениях и уже потом писать во флеш
 

Сергей_Ф

Moderator
Команда форума
в этом частном случае достаточно.
А можете привести пример, когда недостаточно? Просто я всегда копировал строки ВКЛЮЧАЯ конец строки и считал это правильным. Тем более, если по указателю ssid производится не однократная, а многократная запись (это не об этом топике). При Вашем подходе придется обнулять ssid[] каждый раз, а это некоторое замедление программы и увеличение кода.
Хочу понять, где мой подход может привести к неотлавливаемым "граблям".
 

Victor

Administrator
Команда форума
А можете привести пример, когда недостаточно?
когда строку вообще не присвоили (например, когда несколько строк присваиваются в разных кусках кода). при вашем подходе там будут рандомные данные, а при моем - пустая строка. Но это дело вкуса - я вот готов пожертвовать несколькими тактами процессора ради однозначности, но это не значит, что это единственно правильный путь, так что ваш подход понравится тем, для кого скорость важнее :) Каждый сам выбирает наиболее элегантное решение со своей точки зрения.
 

Сергей_Ф

Moderator
Команда форума
@Victor принято. Но, безусловно, в таком случае я при инициализации или перед планируемыми присвоениями "обнулю" ssid вот так:
Код:
char * ssid = 0;
или
char ssid[0]='\0';
Описанную Вами проблему это решит и много тактов не займёт.
А @de1m подскажу, что в языке Си char[] "CO2" - это 4 символа, а не три, как может показаться на первый взгляд.
 
Последнее редактирование:

Garmin

Member
Код:
static void ICACHE_FLASH_ATTR test() {
   os_printf("SDK version:%s\n", system_get_sdk_version());
    struct wConf
    {
       char ssid[32];
       char passwd[64];
    };
    struct wConf wifiApConf;
    char const ssid_str[32] = "CO2";
    char const pass_str[64] = "co2passwd";
    os_memcpy(wifiApConf.ssid, &ssid_str, sizeof (ssid_str));
    os_memcpy(wifiApConf.passwd, &pass_str, sizeof (pass_str));

    struct wConf ssidAp;
    int i = spi_flash_erase_sector(0x8c);
    os_printf("spi_flash_erase_sector: %d\n", i);
    int o = spi_flash_write(0x8c000, (uint32 *)&wifiApConf, sizeof(wifiApConf));
    os_printf("spi_flash_write: %d\n", o);
    int p = spi_flash_read(0x8c000, (uint32 *)&ssidAp, sizeof(ssidAp));
    os_printf("spi_flash_read: %d\n", p);
    os_printf("result ssid: %s\n", ssidAp.ssid);
    os_printf("result password: %s\n", ssidAp.passwd);
}
 
  • Like
Реакции: de1m

Garmin

Member
Насчёт прошивки я тебе не смогу помочь. Сам долго ковырял makefile, пока смог его заставить собираться по нужным мне адресам. Смотри кроме makefile ещё eagle.app.v6.ld
 
Сверху Снизу