fix(storage): Fix SD card examples for SoCs with SOC_SDMMC_IO_POWER_EXTERNAL 1

This commit is contained in:
Adam Múdry 2024-05-08 11:52:11 +02:00
parent 3f632df143
commit 2f10ca582b
11 changed files with 185 additions and 41 deletions

View File

@ -54,14 +54,14 @@ This example doesn't utilize card detect (CD) and write protect (WP) signals fro
The table below shows the default pin assignments.
SD card pin | SPI pin | ESP32 pin | ESP32-S2 | ESP32-S3 | ESP32-H2 | ESP32-C3 and other chips | Notes
------------|---------|---------------|----------|----------|----------|--------------------------|-------------
D0 | MISO | GPIO2 | GPIO37 | GPIO37 | GPIO0 | GPIO6 | 10k pullup
D1 | - | GPIO4 | - | GPIO38 | - | - | not used in 1-line SD mode; 10k pullup in 4-line mode
D2 | - | GPIO12 (MTDI) | - | GPIO33 | - | - | not used in 1-line SD mode; 10k pullup in 4-line mode
D3 | CS | GPIO13 (MTCK) | GPIO34 | GPIO34 | GPIO1 | GPIO1 | not used in 1-line SD mode, but card's D3 pin must have a 10k pullup
CLK | SCK | GPIO14 (MTMS) | GPIO36 | GPIO36 | GPIO4 | GPIO5 | 10k pullup
CMD | MOSI | GPIO15 (MTDO) | GPIO35 | GPIO35 | GPIO5 | GPIO4 | 10k pullup
SD card pin | SPI pin | ESP32 pin | ESP32-S2 | ESP32-S3 | ESP32-P4 SDMMC | ESP32-P4 SDSPI | ESP32-H2 | ESP32-C3 and other chips | Notes
------------|---------|---------------|----------|----------|----------------|----------------|----------|--------------------------|-------------
D0 | MISO | GPIO2 | GPIO37 | GPIO37 | GPIO43 | GPIO13 | GPIO0 | GPIO6 | 10k pullup
D1 | - | GPIO4 | - | GPIO38 | GPIO44 | - | - | - | not used in 1-line SD mode; 10k pullup in 4-line mode
D2 | - | GPIO12 (MTDI) | - | GPIO33 | GPIO39 | - | - | - | not used in 1-line SD mode; 10k pullup in 4-line mode
D3 | CS | GPIO13 (MTCK) | GPIO34 | GPIO34 | GPIO40 | GPIO10 | GPIO1 | GPIO1 | not used in 1-line SD mode, but card's D3 pin must have a 10k pullup
CLK | SCK | GPIO14 (MTMS) | GPIO36 | GPIO36 | GPIO41 | GPIO12 | GPIO4 | GPIO5 | 10k pullup
CMD | MOSI | GPIO15 (MTDO) | GPIO35 | GPIO35 | GPIO42 | GPIO11 | GPIO5 | GPIO4 | 10k pullup
### 4-line and 1-line SD modes
@ -97,6 +97,21 @@ This command will burn the `XPD_SDIO_TIEH`, `XPD_SDIO_FORCE`, and `XPD_SDIO_REG`
See [the document about pullup requirements](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/sd_pullup_requirements.html) for more details about pullup support and compatibility of modules and development boards.
#### ESP32-P4 related notes
This only applies when `Test SD card` setting in `Performance Benchmark Example Configuration` is enabled.
On ESP32-P4, Slot 1 of the SDMMC peripheral is connected to GPIO pins using GPIO matrix. This allows arbitrary GPIOs to be used to connect an SD card. In this example, GPIOs can be configured in two ways:
1. Using menuconfig: Run `idf.py menuconfig` in the project directory and open `Performance Benchmark Example Configuration` menu.
2. In the source code: See the initialization of `sdmmc_slot_config_t slot_config` structure in the example code.
If pins selected correspond with default pins used for ESP32-P4 SDMMC (i.e. SD card slot is connected to them), possibly an additional setting up needs to be done.
These pins are able to connect to an ultra high-speed SD card (UHS-I) which requires 1.8V switching (instead of the regular 3.3V). This means the user has to provide an external LDO power supply to use them, or to enable and configure an internal LDO via `idf.py menuconfig` -> `SD/MMC Example Configuration` -> `SD power supply comes from internal LDO IO`.
When using different GPIO pins this is not required and `SD power supply comes from internal LDO IO` setting can be disabled.
### Note about SPIFFS
The test for SPIFFS is run only once, because SPIFFS has a problem with deleting files.

View File

@ -179,28 +179,34 @@ menu "Performance Benchmark Example Configuration"
config EXAMPLE_PIN_CMD
int "CMD GPIO number"
default 35 if IDF_TARGET_ESP32S3
default 44 if IDF_TARGET_ESP32P4
config EXAMPLE_PIN_CLK
int "CLK GPIO number"
default 36 if IDF_TARGET_ESP32S3
default 43 if IDF_TARGET_ESP32P4
config EXAMPLE_PIN_D0
int "D0 GPIO number"
default 37 if IDF_TARGET_ESP32S3
default 39 if IDF_TARGET_ESP32P4
if EXAMPLE_SDMMC_BUS_WIDTH_4
config EXAMPLE_PIN_D1
int "D1 GPIO number"
default 38 if IDF_TARGET_ESP32S3
default 40 if IDF_TARGET_ESP32P4
config EXAMPLE_PIN_D2
int "D2 GPIO number"
default 33 if IDF_TARGET_ESP32S3
default 41 if IDF_TARGET_ESP32P4
config EXAMPLE_PIN_D3
int "D3 GPIO number"
default 34 if IDF_TARGET_ESP32S3
default 42 if IDF_TARGET_ESP32P4
endif # EXAMPLE_SDMMC_BUS_WIDTH_4
@ -243,6 +249,22 @@ menu "Performance Benchmark Example Configuration"
endif # EXAMPLE_USE_SDSPI
config EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
depends on SOC_SDMMC_IO_POWER_EXTERNAL
bool "SD power supply comes from internal LDO IO (READ HELP!)"
default y
help
Only needed when the SD card is connected to specific IO pins which can be used for high-speed SDMMC.
Please read the schematic first and check if the SD VDD is connected to any internal LDO output.
Unselect this option if the SD card is powered by an external power supply.
config EXAMPLE_SD_PWR_CTRL_LDO_IO_ID
depends on SOC_SDMMC_IO_POWER_EXTERNAL && EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
int "LDO ID"
default 4 if IDF_TARGET_ESP32P4
help
Please read the schematic first and input your LDO ID.
endmenu # "SD card test config"
endmenu # "Performance Monitor Example Configuration"

View File

@ -13,6 +13,10 @@
#if SOC_SDMMC_HOST_SUPPORTED
#include "driver/sdmmc_host.h"
#endif
#if SOC_SDMMC_IO_POWER_EXTERNAL
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
#endif
#include "esp_err.h"
#include "esp_log.h"
#ifdef CONFIG_EXAMPLE_TEST_SD_CARD
@ -32,6 +36,22 @@ void init_sd_config(sdmmc_host_t *out_host, sdmmc_slot_config_t *out_slot_config
void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_config, int freq_khz) {
#endif // CONFIG_EXAMPLE_USE_SDSPI
// For SoCs where the SD power can be supplied both via an internal or external (e.g. on-board LDO) power supply.
// When using specific IO pins (which can be used for ultra high-speed SDMMC) to connect to the SD card
// and the internal LDO power supply, we need to initialize the power supply first.
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
sd_pwr_ctrl_ldo_config_t ldo_config = {
.ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
};
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
esp_err_t sd_pwr_ctrl_ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
if (sd_pwr_ctrl_ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to create a new an on-chip LDO power control driver");
ESP_ERROR_CHECK(sd_pwr_ctrl_ret);
}
#endif // CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
// By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz)
// For setting a specific frequency, use host.max_freq_khz
// (range 400kHz - 40MHz for SDMMC, 400kHz - 20MHz for SDSPI)
@ -91,6 +111,11 @@ void init_sd_config(sdmmc_host_t *out_host, sdspi_device_config_t *out_slot_conf
slot_config.gpio_cs = CONFIG_EXAMPLE_PIN_CS;
slot_config.host_id = host.slot;
#endif // CONFIG_EXAMPLE_USE_SDSPI
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
host.pwr_ctrl_handle = pwr_ctrl_handle;
#endif // CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
*out_host = host;
*out_slot_config = slot_config;
}
@ -137,6 +162,18 @@ void deinit_sd_card(sdmmc_card_t **card) {
#else // CONFIG_EXAMPLE_USE_SDMMC
sdspi_host_deinit();
#endif // CONFIG_EXAMPLE_USE_SDSPI
// Deinitialize the power control driver if it was used
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
sd_pwr_ctrl_handle_t pwr_ctrl_handle = (*card)->host.pwr_ctrl_handle;
esp_err_t ret = sd_pwr_ctrl_del_on_chip_ldo(pwr_ctrl_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver");
ESP_ERROR_CHECK(ret);
}
pwr_ctrl_handle = NULL;
#endif
free(*card);
*card = NULL;
}

View File

@ -70,7 +70,7 @@ GPIO34 | D3 | not used in 1-line SD mode, but card's D3 pin must
On ESP32-P4, Slot 1 of the SDMMC peripheral is connected to GPIO pins using GPIO matrix. This allows arbitrary GPIOs to be used to connect an SD card. In this example, GPIOs can be configured in two ways:
1. Using menuconfig: Run `idf.py menuconfig` in the project directory and open "SD/MMC Example Configuration" menu.
1. Using menuconfig: Run `idf.py menuconfig` in the project directory and open `SD/MMC Example Configuration` menu.
2. In the source code: See the initialization of `sdmmc_slot_config_t slot_config` structure in the example code.
The table below lists the default pin assignments.
@ -84,6 +84,10 @@ GPIO40 | D1 | not used in 1-line SD mode; 10k pullup in 4-line m
GPIO41 | D2 | not used in 1-line SD mode; 10k pullup in 4-line mode
GPIO42 | D3 | not used in 1-line SD mode, but card's D3 pin must have a 10k pullup
Default dedicated pins on ESP32-P4 are able to connect to an ultra high-speed SD card (UHS-I) which requires 1.8V switching (instead of the regular 3.3V). This means the user has to provide an external LDO power supply to use them, or to enable and configure an internal LDO via `idf.py menuconfig` -> `SD/MMC Example Configuration` -> `SD power supply comes from internal LDO IO`.
When using different GPIO pins this is not required and `SD power supply comes from internal LDO IO` setting can be disabled.
### 4-line and 1-line SD modes
By default, this example uses 4 line SD mode, utilizing 6 pins: CLK, CMD, D0 - D3. It is possible to use 1-line mode (CLK, CMD, D0) by changing "SD/MMC bus width" in the example configuration menu (see `CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_1`).

View File

@ -152,18 +152,19 @@ menu "SD/MMC Example Configuration"
endif # EXAMPLE_SDMMC_BUS_WIDTH_4
config EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO
config EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
depends on SOC_SDMMC_IO_POWER_EXTERNAL
bool "SDMMC IO power supply comes from internal LDO (READ HELP!)"
bool "SD power supply comes from internal LDO IO (READ HELP!)"
default y
help
Please read the schematic first and check if the SDMMC VDD is connected to any internal LDO output.
If the SDMMC is powered by an external supplier, unselect me
Only needed when the SD card is connected to specific IO pins which can be used for high-speed SDMMC.
Please read the schematic first and check if the SD VDD is connected to any internal LDO output.
Unselect this option if the SD card is powered by an external power supply.
config EXAMPLE_SDMMC_IO_LDO_ID
depends on SOC_SDMMC_IO_POWER_EXTERNAL
config EXAMPLE_SD_PWR_CTRL_LDO_IO_ID
depends on SOC_SDMMC_IO_POWER_EXTERNAL && EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
int "LDO ID"
default 4
default 4 if IDF_TARGET_ESP32P4
help
Please read the schematic first and input your LDO ID
Please read the schematic first and input your LDO ID.
endmenu

View File

@ -15,7 +15,9 @@
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
#include "sd_test_io.h"
#if SOC_SDMMC_IO_POWER_EXTERNAL
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
#endif
#define EXAMPLE_MAX_CHAR_SIZE 64
@ -127,18 +129,18 @@ void app_main(void)
// Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
/**
* On these chips, the SDMMC IO power is supplied externally
*/
#if CONFIG_EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO
// For SoCs where the SD power can be supplied both via an internal or external (e.g. on-board LDO) power supply.
// When using specific IO pins (which can be used for ultra high-speed SDMMC) to connect to the SD card
// and the internal LDO power supply, we need to initialize the power supply first.
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
sd_pwr_ctrl_ldo_config_t ldo_config = {
.ldo_chan_id = 4, // `LDO_VO4` is used as the SDMMC IO power
.ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
};
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to new an on-chip ldo power control driver");
ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
return;
}
host.pwr_ctrl_handle = pwr_ctrl_handle;
@ -237,7 +239,7 @@ void app_main(void)
ESP_LOGI(TAG, "file still exists");
return;
} else {
ESP_LOGI(TAG, "file doesnt exist, format done");
ESP_LOGI(TAG, "file doesn't exist, formatting done");
}
#endif // CONFIG_EXAMPLE_FORMAT_SD_CARD
@ -257,14 +259,14 @@ void app_main(void)
// All done, unmount partition and disable SDMMC peripheral
esp_vfs_fat_sdcard_unmount(mount_point, card);
ESP_LOGI(TAG, "Card unmounted");
#if SOC_SDMMC_IO_POWER_EXTERNAL
// Deinitialize the power control driver if it was used
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
ret = sd_pwr_ctrl_del_on_chip_ldo(pwr_ctrl_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to delete on-chip ldo power control driver");
ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver");
return;
}
#endif
ESP_LOGI(TAG, "Card unmounted");
}

View File

@ -1,7 +1,5 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import logging
import re
@ -32,7 +30,7 @@ def test_examples_sd_card_sdmmc(dut: Dut) -> None:
'Reading file /sdcard/foo.txt',
"Read from file: 'Hello {}!'".format(name))
sd_card_format = re.compile(str.encode('Formatting card, allocation unit size=\\S+'))
message_list2 = ('file doesnt exist, format done',
message_list2 = ("file doesn't exist, formatting done",
'Opening file /sdcard/nihao.txt',
'File written',
'Reading file /sdcard/nihao.txt',

View File

@ -41,12 +41,12 @@ This example doesn't utilize card detect (CD) and write protect (WP) signals fro
The table below shows the default pin assignments.
SD card pin | SPI pin | ESP32 pin | ESP32-S2, ESP32-S3 | ESP32-H2 | ESP32-C3 and other chips | Notes
------------|---------|---------------|--------------------|----------|---------------------------|-------------
D0 | MISO | GPIO2 | GPIO37 | GPIO0 | GPIO6 |
D3 | CS | GPIO13 (MTCK) | GPIO34 | GPIO1 | GPIO1 |
CLK | SCK | GPIO14 (MTMS) | GPIO36 | GPIO4 | GPIO5 |
CMD | MOSI | GPIO15 (MTDO) | GPIO35 | GPIO5 | GPIO4 | 10k pullup
SD card pin | SPI pin | ESP32 pin | ESP32-S2, ESP32-S3 | ESP32-P4 | ESP32-H2 | ESP32-C3 and other chips | Notes
------------|---------|---------------|--------------------|----------|----------|--------------------------|------------
D0 | MISO | GPIO2 | GPIO37 | GPIO13 | GPIO0 | GPIO6 |
D3 | CS | GPIO13 (MTCK) | GPIO34 | GPIO10 | GPIO1 | GPIO1 |
CLK | SCK | GPIO14 (MTMS) | GPIO36 | GPIO12 | GPIO4 | GPIO5 |
CMD | MOSI | GPIO15 (MTDO) | GPIO35 | GPIO11 | GPIO5 | GPIO4 | 10k pullup
#### ESP32 related notes
@ -63,6 +63,28 @@ With the default pin assignments, this example is compatible ESP32-S2-USB-OTG an
For other development boards, adjust the pin assignments as explained above.
#### ESP32-P4 related notes
On ESP32-P4, Slot 1 of the SDMMC peripheral is connected to GPIO pins using GPIO matrix. This allows arbitrary GPIOs to be used to connect an SD card. In this example, GPIOs can be configured in two ways:
1. Using menuconfig: Run `idf.py menuconfig` in the project directory and open `SD SPI Example Configuration` menu.
2. In the source code: See the initialization of `sdmmc_slot_config_t slot_config` structure in the example code.
Default pins for SDSPI are listed in the table above [Pin assignments](#1-pin-assignments) and using them doesn't require any additional settings.
However on some development boards the SD card slot can be wired to default dedicated pins for SDMMC, which are listed in the table below.
SD card pin | ESP32-P4 pin
------------|--------------
D0 (MISO) | GPIO39
D3 (CS) | GPIO42
CLK (SCK) | GPIO43
CMD (MOSI) | GPIO44
These pins are able to connect to an ultra high-speed SD card (UHS-I) which requires 1.8V switching (instead of the regular 3.3V). This means the user has to provide an external LDO power supply to use them, or to enable and configure an internal LDO via `idf.py menuconfig` -> `SD/MMC Example Configuration` -> `SD power supply comes from internal LDO IO`.
When using different GPIO pins this is not required and `SD power supply comes from internal LDO IO` setting can be disabled.
#### Notes for ESP32-C3 and other chips
Espressif doesn't offer development boards with an SD card slot for these chips. Please check the pin assignments and adjust them for your board if necessary. The process to change pin assignments is described above.

View File

@ -93,4 +93,19 @@ menu "SD SPI Example Configuration"
default 6 if IDF_TARGET_ESP32S3
default 1
config EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
depends on SOC_SDMMC_IO_POWER_EXTERNAL
bool "SD power supply comes from internal LDO IO (READ HELP!)"
default n
help
Only needed when the SD card is connected to specific IO pins which can be used for high-speed SDMMC.
Please read the schematic first and check if the SD VDD is connected to any internal LDO output.
Unselect this option if the SD card is powered by an external power supply.
config EXAMPLE_SD_PWR_CTRL_LDO_IO_ID
depends on SOC_SDMMC_IO_POWER_EXTERNAL && EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
int "LDO ID"
default 4 if IDF_TARGET_ESP32P4
help
Please read the schematic first and input your LDO ID.
endmenu

View File

@ -14,6 +14,9 @@
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "sd_test_io.h"
#if SOC_SDMMC_IO_POWER_EXTERNAL
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
#endif
#define EXAMPLE_MAX_CHAR_SIZE 64
@ -120,6 +123,23 @@ void app_main(void)
// Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
// For SoCs where the SD power can be supplied both via an internal or external (e.g. on-board LDO) power supply.
// When using specific IO pins (which can be used for ultra high-speed SDMMC) to connect to the SD card
// and the internal LDO power supply, we need to initialize the power supply first.
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
sd_pwr_ctrl_ldo_config_t ldo_config = {
.ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
};
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
return;
}
host.pwr_ctrl_handle = pwr_ctrl_handle;
#endif
spi_bus_config_t bus_cfg = {
.mosi_io_num = PIN_NUM_MOSI,
.miso_io_num = PIN_NUM_MISO,
@ -128,6 +148,7 @@ void app_main(void)
.quadhd_io_num = -1,
.max_transfer_sz = 4000,
};
ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize bus.");
@ -205,7 +226,7 @@ void app_main(void)
ESP_LOGI(TAG, "file still exists");
return;
} else {
ESP_LOGI(TAG, "file doesnt exist, format done");
ESP_LOGI(TAG, "file doesn't exist, formatting done");
}
#endif // CONFIG_EXAMPLE_FORMAT_SD_CARD
@ -229,4 +250,13 @@ void app_main(void)
//deinitialize the bus after all devices are removed
spi_bus_free(host.slot);
// Deinitialize the power control driver if it was used
#if CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_INTERNAL_IO
ret = sd_pwr_ctrl_del_on_chip_ldo(pwr_ctrl_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver");
return;
}
#endif
}

View File

@ -1,7 +1,5 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import logging
import re
@ -33,7 +31,7 @@ def test_examples_sd_card_sdspi(dut: Dut) -> None:
'Reading file /sdcard/foo.txt',
"Read from file: 'Hello {}!'".format(name))
sd_card_format = re.compile(str.encode('Formatting card, allocation unit size=\\S+'))
message_list2 = ('file doesnt exist, format done',
message_list2 = ("file doesn't exist, formatting done",
'Opening file /sdcard/nihao.txt',
'File written',
'Reading file /sdcard/nihao.txt',