vfs
This commit is contained in:
@@ -5,3 +5,5 @@ framework = espidf
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
board_build.partitions = partitions.csv
|
board_build.partitions = partitions.csv
|
||||||
|
|
||||||
|
monitor_filters = esp32_exception_decoder, colorize
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
void shell_init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef SHELL_HPP
|
#ifndef SHELL_HPP
|
||||||
#define SHELL_HPP
|
#define SHELL_HPP
|
||||||
|
|
||||||
|
void shell_init();
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+8
-41
@@ -1,6 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <sys/dirent.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
#include "boot/entry.hpp"
|
#include "boot/entry.hpp"
|
||||||
#include "boot/answer_code.hpp"
|
#include "boot/answer_code.hpp"
|
||||||
#include "lib/runtime/RT.hpp"
|
#include "lib/runtime/RT.hpp"
|
||||||
|
#include "lib/service/uart.hpp"
|
||||||
|
|
||||||
extern Handler_vfs boot_handler;
|
extern Handler_vfs boot_handler;
|
||||||
|
|
||||||
@@ -20,7 +22,7 @@ void log_result(int res, char *service_name){
|
|||||||
if (res == OS_OK) {
|
if (res == OS_OK) {
|
||||||
printf("[ \033[0;32mOK\033[0m ] %s\n", service_name);
|
printf("[ \033[0;32mOK\033[0m ] %s\n", service_name);
|
||||||
} else {
|
} else {
|
||||||
char *err_text = "Error";
|
const char *err_text = "Error";
|
||||||
const char *msg = get_error(res);
|
const char *msg = get_error(res);
|
||||||
if (strncmp(msg, err_text, 5) == 0) {
|
if (strncmp(msg, err_text, 5) == 0) {
|
||||||
printf("[ \033[0;31mEROR\033[0m ] %s initialization: %s (%d)\n", service_name, msg, res);
|
printf("[ \033[0;31mEROR\033[0m ] %s initialization: %s (%d)\n", service_name, msg, res);
|
||||||
@@ -31,55 +33,20 @@ void log_result(int res, char *service_name){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result test_fn(descriptor *fn) {
|
Result test_fn(descriptor *fn) {
|
||||||
/*printf("Вызов функции %s\n", fn->name);
|
printf("Вызов функции %s\n", fn->name);
|
||||||
fn->ret.int_v = 42;*/
|
fn->ret.int_v = 42;
|
||||||
return {OS_OK, *fn};
|
return {OS_OK, *fn};
|
||||||
}
|
}
|
||||||
|
|
||||||
int main_entry()
|
int main_entry()
|
||||||
{
|
{
|
||||||
printf("Free IRAM: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT | MALLOC_CAP_EXEC));
|
|
||||||
printf("Largest IRAM block: %d bytes\n", heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT | MALLOC_CAP_EXEC));
|
|
||||||
|
|
||||||
//printf("\033[2J\033[H");
|
|
||||||
printf("OS started\n");
|
printf("OS started\n");
|
||||||
|
|
||||||
log_result(init_fs(), "VFS");
|
log_result(init_fs(), "VFS");
|
||||||
|
log_result(mount(MOUNT_HANDLER, boot_handler.path, boot_handler.path, &boot_handler), "MOUNT_BOOT");
|
||||||
|
log_result(regist_uart(), "UART");
|
||||||
|
|
||||||
mount(MOUNT_HANDLER, boot_handler.path, boot_handler.path, &boot_handler);
|
list_files_recursive("/");
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
boot_handler.link_function("/test_fn", test_fn);
|
|
||||||
|
|
||||||
int fd = open("/boot/test_fn", O_RDWR | O_CREAT | O_TRUNC);
|
|
||||||
if (fd >= 0) {
|
|
||||||
//write(fd, "Hello, world!", 13);
|
|
||||||
|
|
||||||
Result res_buffer;
|
|
||||||
ssize_t bytes_read = read(fd, &res_buffer, sizeof(Result));
|
|
||||||
|
|
||||||
if (bytes_read == sizeof(Result)) {
|
|
||||||
printf("Структура успешно получена напрямую из ядра! [%d]\n", res_buffer.data.ret.int_v);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
printf("Free IRAM: %u bytes\n",
|
|
||||||
heap_caps_get_free_size(MALLOC_CAP_EXEC));
|
|
||||||
|
|
||||||
printf("Largest IRAM block: %u bytes\n",
|
|
||||||
heap_caps_get_largest_free_block(MALLOC_CAP_EXEC));
|
|
||||||
|
|
||||||
run_app_from_iram();
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+51
-1
@@ -5,6 +5,7 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
|
||||||
#include "esp_vfs.h"
|
#include "esp_vfs.h"
|
||||||
#include "esp_vfs_fat.h"
|
#include "esp_vfs_fat.h"
|
||||||
#include "esp_spiffs.h"
|
#include "esp_spiffs.h"
|
||||||
@@ -75,7 +76,6 @@ void create_fs() {
|
|||||||
printf("user_password_sha256: %s\n", user_password_sha256);
|
printf("user_password_sha256: %s\n", user_password_sha256);
|
||||||
|
|
||||||
int total_prograss = 0;
|
int total_prograss = 0;
|
||||||
int max_prograss = 15;
|
|
||||||
|
|
||||||
mkdir("/bin", 0777); total_prograss++;
|
mkdir("/bin", 0777); total_prograss++;
|
||||||
mkdir("/boot", 0777); total_prograss++;
|
mkdir("/boot", 0777); total_prograss++;
|
||||||
@@ -107,6 +107,42 @@ void create_fs() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void list_files_recursive(const char *path) {
|
||||||
|
DIR *dir = opendir(path);
|
||||||
|
if (dir == NULL) return;
|
||||||
|
|
||||||
|
struct dirent *entry;
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *type = (entry->d_type == DT_DIR) ? " DIR" : "FILE";
|
||||||
|
|
||||||
|
// ИСПРАВЛЕНИЕ: Красивый вывод без //
|
||||||
|
if (strcmp(path, "/") == 0) {
|
||||||
|
printf("[%s] /%s\n", type, entry->d_name);
|
||||||
|
} else {
|
||||||
|
printf("[%s] %s/%s\n", type, path, entry->d_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->d_type == DT_DIR) {
|
||||||
|
char next_path[300];
|
||||||
|
|
||||||
|
// ИСПРАВЛЕНИЕ: Безопасное склеивание корня
|
||||||
|
if (strcmp(path, "/") == 0) {
|
||||||
|
snprintf(next_path, sizeof(next_path), "/%s", entry->d_name);
|
||||||
|
} else {
|
||||||
|
snprintf(next_path, sizeof(next_path), "%s/%s", path, entry->d_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_files_recursive(next_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void list_files(const char *path) {
|
void list_files(const char *path) {
|
||||||
printf("Чтение директории: %s\n", path);
|
printf("Чтение директории: %s\n", path);
|
||||||
|
|
||||||
@@ -187,10 +223,24 @@ uint32_t mount(fs_type_t type, const char *path, const char *label, const Handle
|
|||||||
esp_vfs_t conf = {};
|
esp_vfs_t conf = {};
|
||||||
memset(&conf, 0, sizeof(conf));
|
memset(&conf, 0, sizeof(conf));
|
||||||
conf.flags = ESP_VFS_FLAG_CONTEXT_PTR;
|
conf.flags = ESP_VFS_FLAG_CONTEXT_PTR;
|
||||||
|
|
||||||
|
// Основные операции с файлами
|
||||||
conf.open_p = &Handler_vfs::open_vfs;
|
conf.open_p = &Handler_vfs::open_vfs;
|
||||||
conf.read_p = &Handler_vfs::read_vfs;
|
conf.read_p = &Handler_vfs::read_vfs;
|
||||||
conf.write_p = &Handler_vfs::write_vfs;
|
conf.write_p = &Handler_vfs::write_vfs;
|
||||||
conf.close_p = &Handler_vfs::close_vfs;
|
conf.close_p = &Handler_vfs::close_vfs;
|
||||||
|
|
||||||
|
// Операции с директориями
|
||||||
|
conf.opendir_p = &Handler_vfs::opendir_vfs;
|
||||||
|
conf.readdir_p = &Handler_vfs::readdir_vfs;
|
||||||
|
conf.closedir_p = &Handler_vfs::closedir_vfs;
|
||||||
|
|
||||||
|
// Получение информации о файлах/директориях
|
||||||
|
conf.stat_p = &Handler_vfs::stat_vfs;
|
||||||
|
|
||||||
|
// Переименование
|
||||||
|
conf.rename_p = &Handler_vfs::rename_vfs;
|
||||||
|
|
||||||
switch (esp_vfs_register(path, &conf, (void*)class_fs))
|
switch (esp_vfs_register(path, &conf, (void*)class_fs))
|
||||||
{
|
{
|
||||||
case ESP_OK: return OS_OK;
|
case ESP_OK: return OS_OK;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ typedef enum {
|
|||||||
int init_fs();
|
int init_fs();
|
||||||
|
|
||||||
void list_files(const char *path);
|
void list_files(const char *path);
|
||||||
|
void list_files_recursive(const char *path);
|
||||||
bool file_exists(const char *path);
|
bool file_exists(const char *path);
|
||||||
uint32_t mount(fs_type_t type, const char *path, const char *label, const Handler_vfs *class_fs = NULL);
|
uint32_t mount(fs_type_t type, const char *path, const char *label, const Handler_vfs *class_fs = NULL);
|
||||||
int unmount();
|
int unmount();
|
||||||
|
|||||||
+210
-14
@@ -1,5 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "boot/answer_code.hpp"
|
#include "boot/answer_code.hpp"
|
||||||
#include "drivers/fs/handlers.hpp"
|
#include "drivers/fs/handlers.hpp"
|
||||||
@@ -7,6 +8,80 @@
|
|||||||
|
|
||||||
Handler_vfs boot_handler("/boot");
|
Handler_vfs boot_handler("/boot");
|
||||||
|
|
||||||
|
void parse_and_fill_arg_c(const char* start, size_t len, arg* out_arg) {
|
||||||
|
if (len == 0) {
|
||||||
|
out_arg->type = argNONE_t;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t copy_len = (len > 31) ? 31 : len;
|
||||||
|
char tmp[33];
|
||||||
|
memcpy(tmp, start, copy_len);
|
||||||
|
tmp[copy_len] = '\0';
|
||||||
|
|
||||||
|
char* endptr;
|
||||||
|
|
||||||
|
long int_val = strtol(tmp, &endptr, 10);
|
||||||
|
if (*endptr == '\0') {
|
||||||
|
out_arg->type = argINT_t;
|
||||||
|
out_arg->value.valueINT = (int)int_val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float float_val = strtof(tmp, &endptr);
|
||||||
|
if (*endptr == '\0') {
|
||||||
|
out_arg->type = argFLOAT_t;
|
||||||
|
out_arg->value.valueFLOAT = float_val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_arg->type = argSTRING_t;
|
||||||
|
memcpy(out_arg->value.valueSTRING, tmp, copy_len + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_args_c_style(const char* input, arg* args_array) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
args_array[i].type = argNONE_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input == nullptr) return;
|
||||||
|
|
||||||
|
const char* token_start = input;
|
||||||
|
|
||||||
|
if (input[0] == '\\' && input[1] == '$') {
|
||||||
|
input += 2;
|
||||||
|
token_start = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arg_index = 0;
|
||||||
|
|
||||||
|
while (*input != '\0') {
|
||||||
|
if (*input == '\\' && *(input + 1) == '$') {
|
||||||
|
if (input != token_start && *(input - 1) == '\\') {
|
||||||
|
input += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t token_len = input - token_start;
|
||||||
|
|
||||||
|
if (arg_index < 8) {
|
||||||
|
parse_and_fill_arg_c(token_start, token_len, &args_array[arg_index]);
|
||||||
|
arg_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
input += 2;
|
||||||
|
token_start = input;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
input++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t last_len = input - token_start;
|
||||||
|
if (last_len > 0 && arg_index < 8) {
|
||||||
|
parse_and_fill_arg_c(token_start, last_len, &args_array[arg_index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Handler_vfs::Handler_vfs(const char *path) {
|
Handler_vfs::Handler_vfs(const char *path) {
|
||||||
strcpy(this->path, path);
|
strcpy(this->path, path);
|
||||||
count_fn = 0;
|
count_fn = 0;
|
||||||
@@ -18,9 +93,8 @@ Handler_vfs::Handler_vfs(const char *path) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Handler_vfs::~Handler_vfs() {
|
Handler_vfs::~Handler_vfs() {
|
||||||
if (functions != nullptr) {
|
if (functions != nullptr) free(functions);
|
||||||
free(functions);
|
if (descriptors != nullptr) free(descriptors);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Handler_vfs::link_function(const char *name, func_t func) {
|
int Handler_vfs::link_function(const char *name, func_t func) {
|
||||||
@@ -29,7 +103,6 @@ int Handler_vfs::link_function(const char *name, func_t func) {
|
|||||||
size_t new_size = new_capacity * sizeof(function_file);
|
size_t new_size = new_capacity * sizeof(function_file);
|
||||||
|
|
||||||
function_file* temp = (function_file*)realloc(functions, new_size);
|
function_file* temp = (function_file*)realloc(functions, new_size);
|
||||||
|
|
||||||
if (temp != nullptr) {
|
if (temp != nullptr) {
|
||||||
functions = temp;
|
functions = temp;
|
||||||
capacity_fn = new_capacity;
|
capacity_fn = new_capacity;
|
||||||
@@ -38,13 +111,14 @@ int Handler_vfs::link_function(const char *name, func_t func) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(functions[count_fn].name, name, 32);
|
strncpy(functions[count_fn].name, name, 31);
|
||||||
|
functions[count_fn].name[31] = '\0';
|
||||||
functions[count_fn].handler = func;
|
functions[count_fn].handler = func;
|
||||||
|
|
||||||
count_fn++;
|
count_fn++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Handler_vfs::unlink_function(const char *name) {
|
int Handler_vfs::unlink_function(const char *name) {
|
||||||
int index = -1;
|
int index = -1;
|
||||||
for (int i = 0; i < count_fn; i++) {
|
for (int i = 0; i < count_fn; i++) {
|
||||||
@@ -59,7 +133,6 @@ int Handler_vfs::unlink_function(const char *name) {
|
|||||||
for (int i = index; i < count_fn - 1; i++) {
|
for (int i = index; i < count_fn - 1; i++) {
|
||||||
functions[i] = functions[i + 1];
|
functions[i] = functions[i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
count_fn--;
|
count_fn--;
|
||||||
|
|
||||||
if (capacity_fn - count_fn >= 15 && capacity_fn > 10) {
|
if (capacity_fn - count_fn >= 15 && capacity_fn > 10) {
|
||||||
@@ -79,7 +152,10 @@ int Handler_vfs::unlink_function(const char *name) {
|
|||||||
int Handler_vfs::open(const char *name, int flags, int mode) {
|
int Handler_vfs::open(const char *name, int flags, int mode) {
|
||||||
int fn_idx = -1;
|
int fn_idx = -1;
|
||||||
for (int i = 0; i < count_fn; i++) {
|
for (int i = 0; i < count_fn; i++) {
|
||||||
if (strcmp(functions[i].name, name) == 0) { { fn_idx = i; break; } }
|
if (strcmp(functions[i].name, name) == 0) {
|
||||||
|
fn_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (fn_idx == -1) return OS_ERR_NOT_FOUND;
|
if (fn_idx == -1) return OS_ERR_NOT_FOUND;
|
||||||
|
|
||||||
@@ -107,22 +183,26 @@ int Handler_vfs::open(const char *name, int flags, int mode) {
|
|||||||
strncpy(descriptors[target_fd].name, name, 31);
|
strncpy(descriptors[target_fd].name, name, 31);
|
||||||
descriptors[target_fd].handler = functions[fn_idx].handler;
|
descriptors[target_fd].handler = functions[fn_idx].handler;
|
||||||
|
|
||||||
|
for(int i=0; i<8; ++i) descriptors[target_fd].args[i].type = argNONE_t;
|
||||||
|
|
||||||
return target_fd;
|
return target_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Handler_vfs::open_vfs(void* ctx, const char *path, int flags, int mode) {
|
int Handler_vfs::open_vfs(void* ctx, const char *path, int flags, int mode) {
|
||||||
Handler_vfs* self = (Handler_vfs*)ctx;
|
Handler_vfs* self = (Handler_vfs*)ctx;
|
||||||
return self->open(path, flags, mode);
|
return self->open(path, flags, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Handler_vfs::read(int fd, void *dst, size_t size) {
|
ssize_t Handler_vfs::read(int fd, void *dst, size_t size) {
|
||||||
|
|
||||||
if (fd < 0 || fd >= count_ds || descriptors[fd].handler == nullptr) return OS_ERR_NOT_FOUND;
|
if (fd < 0 || fd >= count_ds || descriptors[fd].handler == nullptr) return OS_ERR_NOT_FOUND;
|
||||||
if (dst == nullptr) return OS_ERR_NOT_FOUND;
|
if (dst == nullptr) {
|
||||||
|
descriptors[fd].handler(&descriptors[fd]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (size < sizeof(Result)) return OS_ERR_NO_MEMORY;
|
if (size < sizeof(Result)) return OS_ERR_NO_MEMORY;
|
||||||
|
|
||||||
Result res = descriptors[fd].handler(&descriptors[fd]);
|
Result res = descriptors[fd].handler(&descriptors[fd]);
|
||||||
|
|
||||||
memcpy(dst, &res, sizeof(res));
|
memcpy(dst, &res, sizeof(res));
|
||||||
|
|
||||||
return sizeof(res);
|
return sizeof(res);
|
||||||
@@ -134,9 +214,22 @@ ssize_t Handler_vfs::read_vfs(void* ctx, int fd, void *dst, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Handler_vfs::write(int fd, const void *src, size_t size) {
|
ssize_t Handler_vfs::write(int fd, const void *src, size_t size) {
|
||||||
//printf("Handler write [%d]\n", fd);
|
if (fd < 0 || fd >= count_ds || descriptors[fd].handler == nullptr) {
|
||||||
return 0;
|
return OS_ERR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
if (src == nullptr || size == 0) {
|
||||||
|
return OS_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
char tmp_input[128];
|
||||||
|
size_t copy_size = (size > 127) ? 127 : size;
|
||||||
|
|
||||||
|
memcpy(tmp_input, src, copy_size);
|
||||||
|
tmp_input[copy_size] = '\0';
|
||||||
|
parse_args_c_style(tmp_input, descriptors[fd].args);
|
||||||
|
|
||||||
|
return (ssize_t)size;
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t Handler_vfs::write_vfs(void* ctx, int fd, const void *src, size_t size) {
|
ssize_t Handler_vfs::write_vfs(void* ctx, int fd, const void *src, size_t size) {
|
||||||
Handler_vfs* self = (Handler_vfs*)ctx;
|
Handler_vfs* self = (Handler_vfs*)ctx;
|
||||||
return self->write(fd, src, size);
|
return self->write(fd, src, size);
|
||||||
@@ -147,16 +240,119 @@ int Handler_vfs::close(int fd) {
|
|||||||
descriptors[fd].handler = nullptr;
|
descriptors[fd].handler = nullptr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Handler_vfs::close_vfs(void* ctx, int fd) {
|
int Handler_vfs::close_vfs(void* ctx, int fd) {
|
||||||
Handler_vfs* self = (Handler_vfs*)ctx;
|
Handler_vfs* self = (Handler_vfs*)ctx;
|
||||||
return self->close(fd);
|
return self->close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Handler_vfs::rename(const char *src, const char *dst) {
|
int Handler_vfs::rename(const char *src, const char *dst) {
|
||||||
printf("Handler rename [%s] [%s]\n", src, dst);
|
int fn_idx = -1;
|
||||||
|
for (int i = 0; i < count_fn; i++) {
|
||||||
|
if (strcmp(functions[i].name, src) == 0) {
|
||||||
|
fn_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fn_idx == -1) return OS_ERR_NOT_FOUND;
|
||||||
|
|
||||||
|
strncpy(functions[fn_idx].name, dst, 31);
|
||||||
|
functions[fn_idx].name[31] = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Handler_vfs::rename_vfs(void* ctx, const char *src, const char *dst) {
|
int Handler_vfs::rename_vfs(void* ctx, const char *src, const char *dst) {
|
||||||
Handler_vfs* self = (Handler_vfs*)ctx;
|
Handler_vfs* self = (Handler_vfs*)ctx;
|
||||||
return self->rename(src, dst);
|
return self->rename(src, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- РЕАЛИЗАЦИЯ РАБОТЫ С ДИРЕКТОРИЯМИ И STAT ---
|
||||||
|
|
||||||
|
DIR* Handler_vfs::opendir(const char* name) {
|
||||||
|
// Выделяем память для состояния директории
|
||||||
|
descriptor_dir* dd = new descriptor_dir();
|
||||||
|
strncpy(dd->path, name, 127);
|
||||||
|
dd->path[127] = '\0';
|
||||||
|
dd->current_index = 0;
|
||||||
|
dd->handler = this;
|
||||||
|
|
||||||
|
// Cast в DIR*, так как для VFS это просто непрозрачный указатель
|
||||||
|
return (DIR*)dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
DIR* Handler_vfs::opendir_vfs(void* ctx, const char* name) {
|
||||||
|
Handler_vfs* self = (Handler_vfs*)ctx;
|
||||||
|
return self->opendir(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dirent* Handler_vfs::readdir(DIR* pdir) {
|
||||||
|
if (!pdir) return nullptr;
|
||||||
|
|
||||||
|
descriptor_dir* dd = (descriptor_dir*)pdir;
|
||||||
|
Handler_vfs* self = dd->handler;
|
||||||
|
|
||||||
|
if (dd->current_index >= self->count_fn) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dirent entry;
|
||||||
|
memset(&entry, 0, sizeof(entry));
|
||||||
|
|
||||||
|
const char* fn_name = self->functions[dd->current_index].name;
|
||||||
|
|
||||||
|
if (fn_name[0] == '/') {
|
||||||
|
fn_name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(entry.d_name, fn_name, sizeof(entry.d_name) - 1);
|
||||||
|
entry.d_name[sizeof(entry.d_name) - 1] = '\0';
|
||||||
|
|
||||||
|
dd->current_index++;
|
||||||
|
|
||||||
|
return &entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct dirent* Handler_vfs::readdir_vfs(void* ctx, DIR* pdir) {
|
||||||
|
Handler_vfs* self = (Handler_vfs*)ctx;
|
||||||
|
return self->readdir(pdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Handler_vfs::closedir(DIR* pdir) {
|
||||||
|
if (!pdir) return -1;
|
||||||
|
descriptor_dir* dd = (descriptor_dir*)pdir;
|
||||||
|
delete dd; // Освобождаем память, выделенную в opendir
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Handler_vfs::closedir_vfs(void* ctx, DIR* pdir) {
|
||||||
|
Handler_vfs* self = (Handler_vfs*)ctx;
|
||||||
|
return self->closedir(pdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Handler_vfs::stat(const char * path, struct stat * st) {
|
||||||
|
if (!st) return -1;
|
||||||
|
memset(st, 0, sizeof(struct stat));
|
||||||
|
|
||||||
|
// Ищем, является ли путь именем зарегистрированной функции (файлом)
|
||||||
|
for (int i = 0; i < count_fn; i++) {
|
||||||
|
if (strcmp(functions[i].name, path) == 0) {
|
||||||
|
st->st_mode = S_IFREG | 0666; // Обычный файл
|
||||||
|
st->st_size = sizeof(Result);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, является ли путь самой директорией (точкой монтирования)
|
||||||
|
if (strcmp(path, this->path) == 0 || strcmp(path, "/") == 0) {
|
||||||
|
st->st_mode = S_IFDIR | 0777; // Директория
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1; // Не найдено
|
||||||
|
}
|
||||||
|
|
||||||
|
int Handler_vfs::stat_vfs(void* ctx, const char * path, struct stat * st) {
|
||||||
|
Handler_vfs* self = (Handler_vfs*)ctx;
|
||||||
|
return self->stat(path, st);
|
||||||
|
}
|
||||||
@@ -4,13 +4,15 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/dirent.h>
|
#include <sys/dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
struct descriptor;
|
struct descriptor;
|
||||||
struct Result;
|
struct Result;
|
||||||
|
class Handler_vfs; // Предварительное объявление
|
||||||
|
|
||||||
typedef Result (*func_t)(descriptor*);
|
typedef Result (*func_t)(descriptor*);
|
||||||
|
|
||||||
enum arg_t { argINT_t, argFLOAT_t, argSTRING_t };
|
enum arg_t { argINT_t, argFLOAT_t, argSTRING_t, argNONE_t };
|
||||||
|
|
||||||
struct arg {
|
struct arg {
|
||||||
arg_t type;
|
arg_t type;
|
||||||
@@ -33,6 +35,14 @@ struct descriptor
|
|||||||
func_t handler;
|
func_t handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Обновленная структура для хранения состояния открытой директории
|
||||||
|
struct descriptor_dir
|
||||||
|
{
|
||||||
|
char path[128];
|
||||||
|
int current_index;
|
||||||
|
Handler_vfs* handler;
|
||||||
|
};
|
||||||
|
|
||||||
struct function_file {
|
struct function_file {
|
||||||
char name[32];
|
char name[32];
|
||||||
func_t handler;
|
func_t handler;
|
||||||
@@ -50,6 +60,7 @@ class Handler_vfs {
|
|||||||
|
|
||||||
Handler_vfs(const char *path);
|
Handler_vfs(const char *path);
|
||||||
~Handler_vfs();
|
~Handler_vfs();
|
||||||
|
|
||||||
int link_function(const char *name, func_t func);
|
int link_function(const char *name, func_t func);
|
||||||
int unlink_function(const char *name);
|
int unlink_function(const char *name);
|
||||||
|
|
||||||
@@ -68,9 +79,22 @@ class Handler_vfs {
|
|||||||
int rename(const char *src, const char *dst);
|
int rename(const char *src, const char *dst);
|
||||||
static int rename_vfs(void* ctx, const char *src, const char *dst);
|
static int rename_vfs(void* ctx, const char *src, const char *dst);
|
||||||
|
|
||||||
|
DIR* opendir(const char* name);
|
||||||
|
static DIR* opendir_vfs(void* ctx, const char* name);
|
||||||
|
|
||||||
|
struct dirent* readdir(DIR* pdir);
|
||||||
|
static struct dirent* readdir_vfs(void* ctx, DIR* pdir);
|
||||||
|
|
||||||
|
int closedir(DIR* pdir);
|
||||||
|
static int closedir_vfs(void* ctx, DIR* pdir);
|
||||||
|
|
||||||
|
int stat(const char * path, struct stat * st);
|
||||||
|
static int stat_vfs(void* ctx, const char * path, struct stat * st);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
function_file* functions;
|
function_file* functions;
|
||||||
descriptor* descriptors;
|
descriptor* descriptors;
|
||||||
|
descriptor_dir* descriptors_dirs;
|
||||||
int count_fn = 0;
|
int count_fn = 0;
|
||||||
int count_ds = 0;
|
int count_ds = 0;
|
||||||
int capacity_fn = 0;
|
int capacity_fn = 0;
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "esp_heap_caps.h"
|
|
||||||
#include "esp_cpu.h"
|
|
||||||
|
|
||||||
typedef int (*func_t)(void);
|
|
||||||
|
|
||||||
void run_app_from_iram(void)
|
|
||||||
{
|
|
||||||
uint8_t code[] = {
|
|
||||||
0x36, 0x41, 0x00, 0x2c, 0xa2, 0x1d, 0xf0
|
|
||||||
};
|
|
||||||
|
|
||||||
void *exec = heap_caps_malloc(sizeof(code),
|
|
||||||
MALLOC_CAP_EXEC | MALLOC_CAP_8BIT);
|
|
||||||
|
|
||||||
memcpy(exec, code, sizeof(code));
|
|
||||||
|
|
||||||
//esp_cpu_invalidate_icache_all();
|
|
||||||
|
|
||||||
func_t f = (func_t)exec;
|
|
||||||
|
|
||||||
int result = f();
|
|
||||||
|
|
||||||
printf("Result = %d\n", result); // Должно быть 42
|
|
||||||
|
|
||||||
heap_caps_free(exec);
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
#ifndef RT_HPP
|
#ifndef RT_HPP
|
||||||
#define RT_HPP
|
#define RT_HPP
|
||||||
|
|
||||||
void run_app_from_iram();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#ifndef UART_HPP
|
||||||
|
#define UART_HPP
|
||||||
|
|
||||||
|
#include "drivers/fs/handlers.hpp"
|
||||||
|
#include "boot/answer_code.hpp"
|
||||||
|
|
||||||
|
extern Handler_vfs boot_handler;
|
||||||
|
|
||||||
|
Result uart_read(descriptor *fn) {
|
||||||
|
int c = getchar();
|
||||||
|
fn->ret.int_v = c;
|
||||||
|
return {OS_OK, *fn};
|
||||||
|
|
||||||
|
}
|
||||||
|
Result uart_write(descriptor *fn) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (fn->args[i].type == argNONE_t) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (fn->args[i].type) {
|
||||||
|
case argINT_t:
|
||||||
|
printf("%d",fn->args[i].value.valueINT);
|
||||||
|
break;
|
||||||
|
case argFLOAT_t:
|
||||||
|
printf("%f",fn->args[i].value.valueFLOAT);
|
||||||
|
break;
|
||||||
|
case argSTRING_t:
|
||||||
|
printf("%s", fn->args[i].value.valueSTRING);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {OS_OK, *fn};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t regist_uart() {
|
||||||
|
uint32_t err;
|
||||||
|
err = boot_handler.link_function("/uart/read", uart_read);
|
||||||
|
printf("\tmount uart_read: ");
|
||||||
|
if (err != OS_OK) {
|
||||||
|
return err;
|
||||||
|
printf("err(%s)\n", get_error(err));
|
||||||
|
}
|
||||||
|
printf("ok\n");
|
||||||
|
err = boot_handler.link_function("/uart/write", uart_write);
|
||||||
|
printf("\tmount uart_write: ");
|
||||||
|
if (err != OS_OK) {
|
||||||
|
return err;
|
||||||
|
printf("err(%s)\n", get_error(err));
|
||||||
|
}
|
||||||
|
printf("ok\n");
|
||||||
|
return OS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user