Преглед изворни кода

add vfs reader and external import support

Oliver Fabel пре 1 година
родитељ
комит
d2fc1c2283
9 измењених фајлова са 148 додато и 21 уклоњено
  1. 1 1
      README.md
  2. 11 3
      application.fam
  3. 5 0
      examples/import.py
  4. 90 0
      lib/micropython-port/mphalport.c
  5. 0 0
      lib/micropython-port/mphalport.h
  6. 17 4
      mp_flipper_app.c
  7. 21 1
      mpconfigport.h
  8. 0 12
      port/mphalport.c
  9. 3 0
      state.h

+ 1 - 1
README.md

@@ -1,4 +1,4 @@
-# Micropython Flipper Zero
+# MicroPython Flipper Zero
 
 This repository aims to add [Python](https://www.python.org) support to the famous [Flipper Zero](https://flipperzero.one/) gadget.
 The content of this repository is just work in progress at the moment.

+ 11 - 3
application.fam

@@ -5,7 +5,7 @@ App(
     name="uPython",  # Displayed in menus
     apptype=FlipperAppType.EXTERNAL,
     entry_point="mp_flipper_app",
-    stack_size=2 * 1024,
+    stack_size=4 * 1024,
     fap_category="Examples",
     fap_icon="icon.png",  # 10x10 1-bit PNG
     fap_author="Oliver Fabel",
@@ -15,7 +15,7 @@ App(
     sources=[
         "*.c*",
         "!./build-embed",
-        "!./lib/micropython"
+        "!./lib/micropython",
     ],
     fap_private_libs=[
         Lib(
@@ -25,6 +25,14 @@ App(
                 "-w"
             ],
             cincludes=["."]
-        )
+        ),
+        Lib(
+            name="micropython-port",
+            cflags=[
+                "-Wno-error",
+                "-w"
+            ],
+            cincludes=["."]
+        ),
     ]
 )

+ 5 - 0
examples/import.py

@@ -0,0 +1,5 @@
+from greeter import Greeter
+
+buddy = Greeter('buddy')
+
+print(buddy)

+ 90 - 0
lib/micropython-port/mphalport.c

@@ -0,0 +1,90 @@
+#include <stdio.h>
+
+#include <furi.h>
+#include <storage/storage.h>
+
+#include <py/mphal.h>
+#include <py/builtin.h>
+#include <py/reader.h>
+
+#include "state.h"
+
+void mp_hal_stdout_tx_str(const char* str) {
+    printf("%s", str);
+}
+
+mp_import_stat_t mp_import_stat(const char* path) {
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+    FuriString* file_path = furi_string_alloc();
+    mp_import_stat_t stat = MP_IMPORT_STAT_NO_EXIST;
+
+    furi_string_printf(file_path, "%s/%s", root_module_path, path);
+
+    FileInfo* info = NULL;
+
+    if(storage_common_stat(storage, furi_string_get_cstr(file_path), info) == FSE_OK) {
+        stat = (info && info->flags & FSF_DIRECTORY) == FSF_DIRECTORY ? MP_IMPORT_STAT_DIR : MP_IMPORT_STAT_FILE;
+    }
+
+    furi_string_free(file_path);
+    furi_record_close(RECORD_STORAGE);
+
+    return stat;
+}
+
+typedef struct {
+    size_t pointer;
+    char* content;
+    size_t size;
+} FileReaderContext;
+
+FileReaderContext* file_reader_context_alloc(File* file) {
+    FileReaderContext* context = malloc(sizeof(FileReaderContext));
+
+    context->pointer = 0;
+    context->size = storage_file_size(file);
+    context->content = malloc(context->size * sizeof(char));
+
+    storage_file_read(file, context->content, context->size);
+
+    return context;
+}
+
+void file_reader_context_free(FileReaderContext* context) {
+    free(context->content);
+    free(context);
+}
+
+mp_uint_t file_reader_read(void* data) {
+    FileReaderContext* context = data;
+
+    if(context->size == 0 || context->pointer >= context->size) {
+        return MP_READER_EOF;
+    }
+
+    return context->content[context->pointer++];
+}
+
+void file_reader_close(void* data) {
+    file_reader_context_free(data);
+}
+
+void mp_reader_new_file(mp_reader_t* reader, qstr filename) {
+    FuriString* file_path = furi_string_alloc();
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+    File* file = storage_file_alloc(storage);
+
+    furi_string_printf(file_path, "%s/%s", root_module_path, qstr_str(filename));
+
+    if(!storage_file_open(file, furi_string_get_cstr(file_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
+        furi_crash("unable to open file");
+    }
+
+    reader->data = file_reader_context_alloc(file);
+    reader->readbyte = file_reader_read;
+    reader->close = file_reader_close;
+
+    storage_file_free(file);
+    furi_record_close(RECORD_STORAGE);
+    furi_string_free(file_path);
+}

+ 0 - 0
port/mphalport.h → lib/micropython-port/mphalport.h


+ 17 - 4
mp_flipper_app.c

@@ -4,12 +4,15 @@
 
 #include <port/micropython_embed.h>
 
-static void load_python_file(FuriString* code) {
+#include "state.h"
+
+const char* root_module_path;
+
+static void load_python_file(FuriString* file_path, FuriString* code) {
     Storage* storage = furi_record_open(RECORD_STORAGE);
     DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
 
     File* file = storage_file_alloc(storage);
-    FuriString* file_path = furi_string_alloc();
     DialogsFileBrowserOptions browser_options;
 
     dialog_file_browser_set_basic_options(&browser_options, "py", NULL);
@@ -44,7 +47,6 @@ static void load_python_file(FuriString* code) {
 
     storage_file_free(file);
     furi_record_close(RECORD_STORAGE);
-    furi_string_free(file_path);
 }
 
 int32_t mp_flipper_app(void* p) {
@@ -54,13 +56,24 @@ int32_t mp_flipper_app(void* p) {
     const size_t stack_size = 2 * 1024;
     uint8_t* memory = malloc(memory_size * sizeof(uint8_t));
 
+    FuriString* file_path = furi_string_alloc();
     FuriString* code = furi_string_alloc();
-    load_python_file(code);
+
+    load_python_file(file_path, code);
+
+    size_t index = furi_string_search_rchar(file_path, '/');
+
+    furi_check(index != FURI_STRING_FAILURE);
+
+    furi_string_left(file_path, index);
+
+    root_module_path = furi_string_get_cstr(file_path);
 
     mp_embed_init(memory + stack_size, memory_size - stack_size, memory);
     mp_embed_exec_str(furi_string_get_cstr(code));
     mp_embed_deinit();
 
+    furi_string_free(file_path);
     furi_string_free(code);
     free(memory);
 

+ 21 - 1
mpconfigport.h

@@ -1,10 +1,30 @@
-#include <port/mpconfigport_common.h>
+#include <stdint.h>
+
+// Type definitions for the specific machine
+
+typedef intptr_t mp_int_t; // must be pointer size
+typedef uintptr_t mp_uint_t; // must be pointer size
+typedef long mp_off_t;
+
+// Need to provide a declaration/definition of alloca()
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <stdlib.h>
+#else
+#include <alloca.h>
+#endif
+
+#define MICROPY_MPHALPORT_H "lib/micropython-port/mphalport.h"
 
 #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_MINIMUM)
 
 #define MICROPY_ENABLE_COMPILER (1)
 #define MICROPY_ENABLE_GC (1)
+
 #define MICROPY_MIN_USE_CORTEX_CPU (1)
 #define MICROPY_MIN_USE_STM32_MCU (1)
+
 #define MICROPY_HW_BOARD_NAME "Flipper Zero"
 #define MICROPY_HW_MCU_NAME "STM32WB55RG"
+
+#define MICROPY_ENABLE_EXTERNAL_IMPORT (1)
+#define MICROPY_READER_VFS (1)

+ 0 - 12
port/mphalport.c

@@ -1,12 +0,0 @@
-#include <stdio.h>
-
-#include <py/mphal.h>
-
-// Send string of given length to stdout, converting \n to \r\n.
-void mp_hal_stdout_tx_strn_cooked(const char* str, size_t len) {
-    printf("%.*s", (int)len, str);
-}
-
-void mp_hal_stdout_tx_str(const char* str) {
-    printf("%s", str);
-}

+ 3 - 0
state.h

@@ -0,0 +1,3 @@
+#pragma once
+
+extern const char* root_module_path;