]> granicus.if.org Git - esp-idf/commitdiff
vfs: Adds example for semihosting VFS driver
authorAlexey Gerenkov <alexey@espressif.com>
Tue, 19 Feb 2019 19:57:03 +0000 (22:57 +0300)
committerAlexey Gerenkov <alexey@espressif.com>
Wed, 20 Mar 2019 09:52:52 +0000 (12:52 +0300)
examples/storage/semihost_vfs/CMakeLists.txt [new file with mode: 0644]
examples/storage/semihost_vfs/Makefile [new file with mode: 0644]
examples/storage/semihost_vfs/README.md [new file with mode: 0644]
examples/storage/semihost_vfs/data/host_file.txt [new file with mode: 0644]
examples/storage/semihost_vfs/main/CMakeLists.txt [new file with mode: 0644]
examples/storage/semihost_vfs/main/component.mk [new file with mode: 0644]
examples/storage/semihost_vfs/main/semihost_vfs_example_main.c [new file with mode: 0644]
examples/storage/semihost_vfs/sdkconfig.defaults [new file with mode: 0644]

diff --git a/examples/storage/semihost_vfs/CMakeLists.txt b/examples/storage/semihost_vfs/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5f69441
--- /dev/null
@@ -0,0 +1,6 @@
+# The following lines of boilerplate have to be in your project's CMakeLists
+# in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(semihost_vfs)
diff --git a/examples/storage/semihost_vfs/Makefile b/examples/storage/semihost_vfs/Makefile
new file mode 100644 (file)
index 0000000..6a92821
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# This is a project Makefile. It is assumed the directory this Makefile resides in is a
+# project subdirectory.
+#
+
+PROJECT_NAME := semihost_vfs
+
+include $(IDF_PATH)/make/project.mk
+
diff --git a/examples/storage/semihost_vfs/README.md b/examples/storage/semihost_vfs/README.md
new file mode 100644 (file)
index 0000000..4728f08
--- /dev/null
@@ -0,0 +1,91 @@
+# Semihosting VFS driver example
+
+(See the README.md file in the upper level 'examples' directory for more information about examples.)
+
+This example demonstrates how to use semihosting VFS driver with ESP32. Example does the following steps:
+
+1. Uses `esp_vfs_semihost_register` function to register exposed host directory in VFS, enabling C standard library and POSIX functions to be used.
+2. Redirects `stdout` from the UART to the file on the host using `freopen`.
+3. Prints several messages to the redirected.
+4. Switches back to UART `stdout` using `freopen`.
+5. Opens text file on the host.
+6. Reads the file and prints its content on stdout.
+
+## How to use example
+
+### Hardware and tools required
+
+This example does not require any special hardware, and can be run on any common development board.
+This example requires [OpenOCD](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html#run-openocd).
+NOTE: In order to run this example you need OpenOCD version `v0.10.0-esp32-20190313` or later.
+
+Run OpenOCD using command:
+```
+bin/openocd -s share/openocd/scripts -f interface/ftdi/esp32_devkitj_v1.cfg -c 'set ESP_SEMIHOST_BASEDIR '$IDF_PATH/examples/storage/semihost_vfs/data -f board/esp-wroom-32.cfg
+```
+This command also configures OpenOCD to expose example project `data` subdirectory to the target's semihosting VFS driver.
+
+### Configure the project
+
+If using Make based build system, run `make menuconfig` and set serial port under Serial Flasher Options.
+
+If using CMake based build system, no configuration is required.
+
+### Build and flash
+
+Build the project and flash it to the board, then run monitor tool to view serial output:
+
+```
+make -j4 flash monitor
+```
+
+Or, for CMake based build system (replace PORT with serial port name):
+
+```
+idf.py -p PORT flash monitor
+```
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
+
+## Example output
+
+There are two types of outputs produced by example: 
+1. File `esp32_stdout.txt` in the host directory mounted to the target:
+
+```
+W (274) example: Switched to semihosted stdout
+Semihosted stdout write 0
+Semihosted stdout write 1
+Semihosted stdout write 2
+...
+Semihosted stdout write 98
+Semihosted stdout write 99
+W (274) example: Switch to UART stdout
+```
+
+2. On the boards console:
+
+```
+W (274) example: Switch to semihosted stdout
+W (274) example: Switched back to UART stdout
+I (274) example: Wrote 2798 bytes
+====================== HOST DATA START =========================
+The following are the graphical (non-control) characters defined by
+ISO 8859-1 (1987).  Descriptions in words aren't all that helpful,
+but they're the best we can do in text.  A graphics file illustrating
+the character set should be available from the same archive as this
+file.
+
+Hex Description                 Hex Description
+
+20  SPACE
+...
+7D  RIGHT CURLY BRACKET         FD  SMALL LETTER Y WITH ACUTE
+7E  TILDE                       FE  SMALL LETTER THORN (Icelandic)
+                                FF  SMALL LETTER Y WITH DIAERESIS
+====================== HOST DATA END =========================
+I (694) example: Read 6121 bytes
+```
+
diff --git a/examples/storage/semihost_vfs/data/host_file.txt b/examples/storage/semihost_vfs/data/host_file.txt
new file mode 100644 (file)
index 0000000..f14a8d5
--- /dev/null
@@ -0,0 +1,104 @@
+The following are the graphical (non-control) characters defined by
+ISO 8859-1 (1987).  Descriptions in words aren't all that helpful,
+but they're the best we can do in text.  A graphics file illustrating
+the character set should be available from the same archive as this
+file.
+
+Hex Description                 Hex Description
+
+20  SPACE
+21  EXCLAMATION MARK            A1  INVERTED EXCLAMATION MARK
+22  QUOTATION MARK              A2  CENT SIGN
+23  NUMBER SIGN                 A3  POUND SIGN
+24  DOLLAR SIGN                 A4  CURRENCY SIGN
+25  PERCENT SIGN                A5  YEN SIGN
+26  AMPERSAND                   A6  BROKEN BAR
+27  APOSTROPHE                  A7  SECTION SIGN
+28  LEFT PARENTHESIS            A8  DIAERESIS
+29  RIGHT PARENTHESIS           A9  COPYRIGHT SIGN
+2A  ASTERISK                    AA  FEMININE ORDINAL INDICATOR
+2B  PLUS SIGN                   AB  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+2C  COMMA                       AC  NOT SIGN
+2D  HYPHEN-MINUS                AD  SOFT HYPHEN
+2E  FULL STOP                   AE  REGISTERED SIGN
+2F  SOLIDUS                     AF  OVERLINE
+30  DIGIT ZERO                  B0  DEGREE SIGN
+31  DIGIT ONE                   B1  PLUS-MINUS SIGN
+32  DIGIT TWO                   B2  SUPERSCRIPT TWO
+33  DIGIT THREE                 B3  SUPERSCRIPT THREE
+34  DIGIT FOUR                  B4  ACUTE ACCENT
+35  DIGIT FIVE                  B5  MICRO SIGN
+36  DIGIT SIX                   B6  PILCROW SIGN
+37  DIGIT SEVEN                 B7  MIDDLE DOT
+38  DIGIT EIGHT                 B8  CEDILLA
+39  DIGIT NINE                  B9  SUPERSCRIPT ONE
+3A  COLON                       BA  MASCULINE ORDINAL INDICATOR
+3B  SEMICOLON                   BB  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+3C  LESS-THAN SIGN              BC  VULGAR FRACTION ONE QUARTER
+3D  EQUALS SIGN                 BD  VULGAR FRACTION ONE HALF
+3E  GREATER-THAN SIGN           BE  VULGAR FRACTION THREE QUARTERS
+3F  QUESTION MARK               BF  INVERTED QUESTION MARK
+40  COMMERCIAL AT               C0  CAPITAL LETTER A WITH GRAVE
+41  CAPITAL LETTER A            C1  CAPITAL LETTER A WITH ACUTE
+42  CAPITAL LETTER B            C2  CAPITAL LETTER A WITH CIRCUMFLEX
+43  CAPITAL LETTER C            C3  CAPITAL LETTER A WITH TILDE
+44  CAPITAL LETTER D            C4  CAPITAL LETTER A WITH DIAERESIS
+45  CAPITAL LETTER E            C5  CAPITAL LETTER A WITH RING ABOVE
+46  CAPITAL LETTER F            C6  CAPITAL LETTER AE
+47  CAPITAL LETTER G            C7  CAPITAL LETTER C WITH CEDILLA
+48  CAPITAL LETTER H            C8  CAPITAL LETTER E WITH GRAVE
+49  CAPITAL LETTER I            C9  CAPITAL LETTER E WITH ACUTE
+4A  CAPITAL LETTER J            CA  CAPITAL LETTER E WITH CIRCUMFLEX
+4B  CAPITAL LETTER K            CB  CAPITAL LETTER E WITH DIAERESIS
+4C  CAPITAL LETTER L            CC  CAPITAL LETTER I WITH GRAVE
+4D  CAPITAL LETTER M            CD  CAPITAL LETTER I WITH ACUTE
+4E  CAPITAL LETTER N            CE  CAPITAL LETTER I WITH CIRCUMFLEX
+4F  CAPITAL LETTER O            CF  CAPITAL LETTER I WITH DIAERESIS
+50  CAPITAL LETTER P            D0  CAPITAL LETTER ETH (Icelandic)
+51  CAPITAL LETTER Q            D1  CAPITAL LETTER N WITH TILDE
+52  CAPITAL LETTER R            D2  CAPITAL LETTER O WITH GRAVE
+53  CAPITAL LETTER S            D3  CAPITAL LETTER O WITH ACUTE
+54  CAPITAL LETTER T            D4  CAPITAL LETTER O WITH CIRCUMFLEX
+55  CAPITAL LETTER U            D5  CAPITAL LETTER O WITH TILDE
+56  CAPITAL LETTER V            D6  CAPITAL LETTER O WITH DIAERESIS
+57  CAPITAL LETTER W            D7  MULTIPLICATION SIGN
+58  CAPITAL LETTER X            D8  CAPITAL LETTER O WITH STROKE
+59  CAPITAL LETTER Y            D9  CAPITAL LETTER U WITH GRAVE
+5A  CAPITAL LETTER Z            DA  CAPITAL LETTER U WITH ACUTE
+5B  LEFT SQUARE BRACKET         DB  CAPITAL LETTER U WITH CIRCUMFLEX
+5C  REVERSE SOLIDUS             DC  CAPITAL LETTER U WITH DIAERESIS
+5D  RIGHT SQUARE BRACKET        DD  CAPITAL LETTER Y WITH ACUTE
+5E  CIRCUMFLEX ACCENT           DE  CAPITAL LETTER THORN (Icelandic)
+5F  LOW LINE                    DF  SMALL LETTER SHARP S (German)
+60  GRAVE ACCENT                E0  SMALL LETTER A WITH GRAVE
+61  SMALL LETTER A              E1  SMALL LETTER A WITH ACUTE
+62  SMALL LETTER B              E2  SMALL LETTER A WITH CIRCUMFLEX
+63  SMALL LETTER C              E3  SMALL LETTER A WITH TILDE
+64  SMALL LETTER D              E4  SMALL LETTER A WITH DIAERESIS
+65  SMALL LETTER E              E5  SMALL LETTER A WITH RING ABOVE
+66  SMALL LETTER F              E6  SMALL LETTER AE
+67  SMALL LETTER G              E7  SMALL LETTER C WITH CEDILLA
+68  SMALL LETTER H              E8  SMALL LETTER E WITH GRAVE
+69  SMALL LETTER I              E9  SMALL LETTER E WITH ACUTE
+6A  SMALL LETTER J              EA  SMALL LETTER E WITH CIRCUMFLEX
+6B  SMALL LETTER K              EB  SMALL LETTER E WITH DIAERESIS
+6C  SMALL LETTER L              EC  SMALL LETTER I WITH GRAVE
+6D  SMALL LETTER M              ED  SMALL LETTER I WITH ACUTE
+6E  SMALL LETTER N              EE  SMALL LETTER I WITH CIRCUMFLEX
+6F  SMALL LETTER O              EF  SMALL LETTER I WITH DIAERESIS
+70  SMALL LETTER P              F0  SMALL LETTER ETH (Icelandic)
+71  SMALL LETTER Q              F1  SMALL LETTER N WITH TILDE
+72  SMALL LETTER R              F2  SMALL LETTER O WITH GRAVE
+73  SMALL LETTER S              F3  SMALL LETTER O WITH ACUTE
+74  SMALL LETTER T              F4  SMALL LETTER O WITH CIRCUMFLEX
+75  SMALL LETTER U              F5  SMALL LETTER O WITH TILDE
+76  SMALL LETTER V              F6  SMALL LETTER O WITH DIAERESIS
+77  SMALL LETTER W              F7  DIVISION SIGN
+78  SMALL LETTER X              F8  SMALL LETTER O WITH STROKE
+79  SMALL LETTER Y              F9  SMALL LETTER U WITH GRAVE
+7A  SMALL LETTER Z              FA  SMALL LETTER U WITH ACUTE
+7B  LEFT CURLY BRACKET          FB  SMALL LETTER U WITH CIRCUMFLEX
+7C  VERTICAL LINE               FC  SMALL LETTER U WITH DIAERESIS
+7D  RIGHT CURLY BRACKET         FD  SMALL LETTER Y WITH ACUTE
+7E  TILDE                       FE  SMALL LETTER THORN (Icelandic)
+                                FF  SMALL LETTER Y WITH DIAERESIS
diff --git a/examples/storage/semihost_vfs/main/CMakeLists.txt b/examples/storage/semihost_vfs/main/CMakeLists.txt
new file mode 100644 (file)
index 0000000..34d60ad
--- /dev/null
@@ -0,0 +1,4 @@
+set(COMPONENT_SRCS "semihost_vfs_example_main.c")
+set(COMPONENT_ADD_INCLUDEDIRS ".")
+
+register_component()
diff --git a/examples/storage/semihost_vfs/main/component.mk b/examples/storage/semihost_vfs/main/component.mk
new file mode 100644 (file)
index 0000000..a98f634
--- /dev/null
@@ -0,0 +1,4 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
diff --git a/examples/storage/semihost_vfs/main/semihost_vfs_example_main.c b/examples/storage/semihost_vfs/main/semihost_vfs_example_main.c
new file mode 100644 (file)
index 0000000..edbeabb
--- /dev/null
@@ -0,0 +1,92 @@
+/* SPIFFS filesystem example.
+   This example code is in the Public Domain (or CC0 licensed, at your option.)
+
+   Unless required by applicable law or agreed to in writing, this
+   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, either express or implied.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_vfs_semihost.h"
+
+static const char *TAG = "example";
+
+#define STRINGIFY(s) STRINGIFY2(s)
+#define STRINGIFY2(s) #s
+
+static uint8_t s_buf[512];
+
+void app_main(void)
+{
+    // Register host FS at '/host'. On the host file will be written/read in the current semihosting dir of OpenOCD
+    esp_err_t ret = esp_vfs_semihost_register("/host", NULL);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to register semihost driver (%s)!", esp_err_to_name(ret));
+        return;
+    }
+
+    ESP_LOGW(TAG, "Switch to semihosted stdout");
+    FILE *fout = freopen("/host/esp32_stdout.txt", "w", stdout);
+    if (fout == NULL) {
+        ESP_LOGE(TAG, "Failed to reopen stdout (%d)!", errno);
+        return;
+    }
+    // Increase file buffer to perform data transfers using larger chunks.
+    // Every read/write triggers breakpoint, so transfering of small chunks is quite inefficient.
+    setvbuf(fout, (char *)s_buf, _IOFBF, sizeof(s_buf));
+
+    // this will be printed to the file on host
+    ESP_LOGW(TAG, "Switched to semihosted stdout");
+    for (int i = 0; i < 100; i++) {
+        // printf is also redirected and sends data to the file on host
+        printf("Semihosted stdout write %d\n", i);
+    }
+    ESP_LOGW(TAG, "Switch to UART stdout");
+    fflush(fout); // ensure that all data are sent to the host file
+    // ftell can also be used, get file size before closing it in `freopen`
+    int count = ftell(fout);
+    stdout = freopen("/dev/uart/" STRINGIFY(CONFIG_CONSOLE_UART_NUM), "w", fout);
+    if (stdout == NULL) {
+        ESP_LOGE(TAG, "Failed to reopen semihosted stdout (%d)!", errno);
+        return;
+    }
+    // all remaining messages will be printed to UART
+    ESP_LOGW(TAG, "Switched back to UART stdout");
+    ESP_LOGI(TAG, "Wrote %d bytes", count);
+
+    printf("====================== HOST DATA START =========================\n");
+    // open() can also be used to access files on the host
+    int fd = open("/host/host_file.txt", O_RDONLY, 0);
+    if (fd == -1) {
+        ESP_LOGE(TAG, "Failed to open file (%d)!", errno);
+        return;
+    }
+    ssize_t read_bytes;
+    count = 0;
+    do {
+        read_bytes = read(fd, s_buf, sizeof(s_buf));
+        if(read_bytes == -1) {
+            ESP_LOGE(TAG, "Failed to read file (%d)!", errno);
+        } else if(read_bytes > 0) {
+            fwrite(s_buf, 1, read_bytes, stdout);
+            count += read_bytes;
+        }
+    } while(read_bytes > 0);
+    printf("====================== HOST DATA END =========================\n");
+    ESP_LOGI(TAG, "Read %d bytes", count);
+    if (close(fd) == -1) {
+        ESP_LOGE(TAG, "Failed to close file (%d)!", errno);
+    }
+
+    ret = esp_vfs_semihost_unregister("/host");
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to unregister semihost driver (%s)!", esp_err_to_name(ret));
+    }
+}
diff --git a/examples/storage/semihost_vfs/sdkconfig.defaults b/examples/storage/semihost_vfs/sdkconfig.defaults
new file mode 100644 (file)
index 0000000..989d01c
--- /dev/null
@@ -0,0 +1,2 @@
+# need this to detect that OpenOCD is connected
+CONFIG_ESP32_DEBUG_OCDAWARE=y