1 /* SPIFFS filesystem example.
2    This example code is in the Public Domain (or CC0 licensed, at your option.)
3 
4    Unless required by applicable law or agreed to in writing, this
5    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
6    CONDITIONS OF ANY KIND, either express or implied.
7 */
8 
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <sys/unistd.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include "esp_err.h"
16 #include "esp_log.h"
17 #include "esp_vfs_semihost.h"
18 
19 static const char *TAG = "example";
20 
21 #define STRINGIFY(s) STRINGIFY2(s)
22 #define STRINGIFY2(s) #s
23 
24 static uint8_t s_buf[512];
25 
app_main(void)26 void app_main(void)
27 {
28     // Register host FS at '/host'. On the host file will be written/read in the current semihosting dir of OpenOCD
29     esp_err_t ret = esp_vfs_semihost_register("/host", NULL);
30     if (ret != ESP_OK) {
31         ESP_LOGE(TAG, "Failed to register semihost driver (%s)!", esp_err_to_name(ret));
32         return;
33     }
34 
35     ESP_LOGW(TAG, "Switch to semihosted stdout");
36     FILE *fout = freopen("/host/esp32_stdout.txt", "w", stdout);
37     if (fout == NULL) {
38         ESP_LOGE(TAG, "Failed to reopen stdout (%d)!", errno);
39         return;
40     }
41     // Increase file buffer to perform data transfers using larger chunks.
42     // Every read/write triggers breakpoint, so transferring of small chunks is quite inefficient.
43     setvbuf(fout, (char *)s_buf, _IOFBF, sizeof(s_buf));
44 
45     // this will be printed to the file on host
46     ESP_LOGW(TAG, "Switched to semihosted stdout");
47     for (int i = 0; i < 100; i++) {
48         // printf is also redirected and sends data to the file on host
49         printf("Semihosted stdout write %d\n", i);
50     }
51     ESP_LOGW(TAG, "Switch to UART stdout");
52     fflush(fout); // ensure that all data are sent to the host file
53     // ftell can also be used, get file size before closing it in `freopen`
54     int count = ftell(fout);
55     stdout = freopen("/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM), "w", fout);
56     if (stdout == NULL) {
57         ESP_LOGE(TAG, "Failed to reopen semihosted stdout (%d)!", errno);
58         return;
59     }
60     // all remaining messages will be printed to UART
61     ESP_LOGW(TAG, "Switched back to UART stdout");
62     ESP_LOGI(TAG, "Wrote %d bytes", count);
63 
64     printf("====================== HOST DATA START =========================\n");
65     // open() can also be used to access files on the host
66     int fd = open("/host/host_file.txt", O_RDONLY, 0);
67     if (fd == -1) {
68         ESP_LOGE(TAG, "Failed to open file (%d)!", errno);
69         return;
70     }
71     ssize_t read_bytes;
72     count = 0;
73     do {
74         read_bytes = read(fd, s_buf, sizeof(s_buf));
75         if(read_bytes == -1) {
76             ESP_LOGE(TAG, "Failed to read file (%d)!", errno);
77         } else if(read_bytes > 0) {
78             fwrite(s_buf, 1, read_bytes, stdout);
79             count += read_bytes;
80         }
81     } while(read_bytes > 0);
82     printf("====================== HOST DATA END =========================\n");
83     ESP_LOGI(TAG, "Read %d bytes", count);
84     if (close(fd) == -1) {
85         ESP_LOGE(TAG, "Failed to close file (%d)!", errno);
86     }
87 
88     ret = esp_vfs_semihost_unregister("/host");
89     if (ret != ESP_OK) {
90         ESP_LOGE(TAG, "Failed to unregister semihost driver (%s)!", esp_err_to_name(ret));
91     }
92 }
93