--- /dev/null
+# 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)
--- /dev/null
+#
+# 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
+
--- /dev/null
+# 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
+```
+
--- /dev/null
+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
--- /dev/null
+set(COMPONENT_SRCS "semihost_vfs_example_main.c")
+set(COMPONENT_ADD_INCLUDEDIRS ".")
+
+register_component()
--- /dev/null
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
--- /dev/null
+/* 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));
+ }
+}
--- /dev/null
+# need this to detect that OpenOCD is connected
+CONFIG_ESP32_DEBUG_OCDAWARE=y