diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index 470a41853895ef3fbaec66ebea29cb2a8e68490c..4456a0bbf455ade1e3f72ca16f7f28e0daef8d80 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -48,6 +48,14 @@ typedef unsigned int size_t; #define API_DISP_RECT 0x16 #define API_DISP_CIRC 0x17 #define API_DISP_PIXEL 0x18 + +#define API_FILE_OPEN 0x30 +#define API_FILE_CLOSE 0x31 +#define API_FILE_READ 0x32 +#define API_FILE_WRITE 0x34 +#define API_FILE_FLUSH 0x35 +#define API_FILE_SEEK 0x36 //NYI +#define API_FILE_TELL 0x37 //NYI /* clang-format on */ typedef uint32_t api_int_id_t; @@ -439,4 +447,20 @@ API(API_LIGHT_SENSOR_GET, int epic_light_sensor_get(uint16_t* value)); */ API(API_LIGHT_SENSOR_STOP, int epic_light_sensor_stop()); +/** + * File + * ==== + * + * Except for epic_open, which models C stdio's fopen function, close, read and write + * model close (3), read (3) and write(3) + * All file-related functions return >= 0 on success and -Exyz on failure, with error + * codes from errno.h (EIO, EINVAL etc.) + * + */ +API(API_FILE_OPEN, int32_t epic_open(const char* filename, const char* modeString)); +API(API_FILE_CLOSE, int32_t epic_close(int32_t fd)); +API(API_FILE_READ, int32_t epic_read(int32_t fd, void* buf, uint32_t nbytes)); +API(API_FILE_WRITE, int32_t epic_write(int32_t fd, const void* buf, uint32_t nbytes)); +API(API_FILE_FLUSH, int32_t epic_flush(int32_t fd)); + #endif /* _EPICARDIUM_H */ diff --git a/epicardium/modules/fatfs.c b/epicardium/modules/fatfs.c index fc76bb5532640d8a2e3a2484e7880f20e15c49ef..84622d264287b872b793ca432b6c8e63a2f94755 100644 --- a/epicardium/modules/fatfs.c +++ b/epicardium/modules/fatfs.c @@ -2,68 +2,118 @@ * support routines for FatFs */ -#include <stddef.h> //NULL +#include <errno.h> +#include <stddef.h> #include <stdio.h> #include <stdbool.h> +#include <stdlib.h> + #include <ff.h> #include <FreeRTOS.h> #include <semphr.h> +#include "modules.h" + +#ifndef EPIC_FAT_STATIC_SEMAPHORE +#define EPIC_FAT_STATIC_SEMAPHORE 0 +#endif + static const TCHAR *rcstrings = - _T("OK\0DISK_ERR\0INT_ERR\0NOT_READY\0NO_FILE\0NO_PATH\0INVALID_NAME\0") - _T("DENIED\0EXIST\0INVALID_OBJECT\0WRITE_PROTECTED\0INVALID_DRIVE\0") - _T("NOT_ENABLED\0NO_FILESYSTEM\0MKFS_ABORTED\0TIMEOUT\0LOCKED\0") - _T("NOT_ENOUGH_CORE\0TOO_MANY_OPEN_FILES\0INVALID_PARAMETER\0"); + _T("OK\0DISK_ERR\0INT_ERR\0NOT_READY\0NO_FILE\0NO_PATH\0INVALID_NAME\0") + _T("DENIED\0EXIST\0INVALID_OBJECT\0WRITE_PROTECTED\0INVALID_DRIVE\0") + _T("NOT_ENABLED\0NO_FILESYSTEM\0MKFS_ABORTED\0TIMEOUT\0LOCKED\0") + _T("NOT_ENOUGH_CORE\0TOO_MANY_OPEN_FILES\0INVALID_PARAMETER\0"); + +// this table converts from FRESULT to POSIX errno +const int fresult_to_errno_table[20] = { + [FR_OK] = 0, + [FR_DISK_ERR] = EIO, + [FR_INT_ERR] = EIO, + [FR_NOT_READY] = EBUSY, + [FR_NO_FILE] = ENOENT, + [FR_NO_PATH] = ENOENT, + [FR_INVALID_NAME] = EINVAL, + [FR_DENIED] = EACCES, + [FR_EXIST] = EEXIST, + [FR_INVALID_OBJECT] = EINVAL, + [FR_WRITE_PROTECTED] = EROFS, + [FR_INVALID_DRIVE] = ENODEV, + [FR_NOT_ENABLED] = ENODEV, + [FR_NO_FILESYSTEM] = ENODEV, + [FR_MKFS_ABORTED] = EIO, + [FR_TIMEOUT] = EIO, + [FR_LOCKED] = EIO, + [FR_NOT_ENOUGH_CORE] = ENOMEM, + [FR_TOO_MANY_OPEN_FILES] = EMFILE, + [FR_INVALID_PARAMETER] = EINVAL, +}; + +enum FatObjectType { FO_Nil, FO_File, FO_Dir }; +struct FatObject { + enum FatObjectType type; + union { + FIL file; + DIR dir; + }; +}; static bool mount(void); +static int +get_fat_object(int i, enum FatObjectType expected, struct FatObject **res); DIR dir; FATFS FatFs; +static struct FatObject s_openedObjects[EPIC_FAT_MAX_OPENED]; + +#if (EPIC_FAT_STATIC_SEMAPHORE == 1) +StaticSemaphore_t xSemaphoreBuffer; +#endif static volatile struct { - bool initiaized; + bool initiaized; } s_state = { - .initiaized = false, + .initiaized = false, }; void fatfs_init() { - if (mount()) { - s_state.initiaized = true; - printf("FatFs mounted\n"); - } + if (mount()) { + s_state.initiaized = true; + printf("FatFs mounted\n"); + } } const char *f_get_rc_string(FRESULT rc) { - FRESULT i; - const char *p = rcstrings; - - for (i = 0; i != rc && *p; i++) { - while (*p++) - ; - } - return p; + FRESULT i; + const char *p = rcstrings; + + for (i = 0; i != rc && *p; i++) { + while (*p++) + ; + } + return p; } static bool mount() { - FRESULT res; - res = f_mount(&FatFs, "/", 0); - if (res != FR_OK) { - printf("f_mount error %s\n", f_get_rc_string(res)); - return false; - } - - res = f_opendir(&dir, "0:"); - if (res != FR_OK) { - printf("f_opendir error %s\n", f_get_rc_string(res)); - return false; - } - - return true; + FRESULT res; + res = f_mount(&FatFs, "/", 0); + if (res != FR_OK) { + printf("f_mount error %s\n", f_get_rc_string(res)); + return false; + } + + res = f_opendir(&dir, "0:"); + if (res != FR_OK) { + printf("f_opendir error %s\n", f_get_rc_string(res)); + return false; + } + + return true; } + /*------------------------------------------------------------------------*/ /* Create a Synchronization Object */ /*------------------------------------------------------------------------*/ @@ -79,8 +129,13 @@ static bool mount() */ int ff_cre_syncobj(BYTE vol, FF_SYNC_t *sobj) { - *sobj = xSemaphoreCreateMutex(); - return (int)(*sobj != NULL); +#if (EPIC_FAT_STATIC_SEMAPHORE == 1) + *sobj = xSemaphoreCreateMutexStatic(&xSemaphoreBuffer); +#else + *sobj = xSemaphoreCreateMutex(); +#endif //EPIC_FAT_STATIC_SEMAPHORE + + return (int)(*sobj != NULL); } /*------------------------------------------------------------------------*/ @@ -98,10 +153,9 @@ int ff_cre_syncobj(BYTE vol, FF_SYNC_t *sobj) */ int ff_del_syncobj(FF_SYNC_t sobj) { - printf("%s\n", __PRETTY_FUNCTION__); - /* FreeRTOS */ - vSemaphoreDelete(sobj); - return 1; + /* FreeRTOS */ + vSemaphoreDelete(sobj); + return 1; } /*------------------------------------------------------------------------*/ @@ -118,8 +172,8 @@ int ff_del_syncobj(FF_SYNC_t sobj) */ int ff_req_grant(FF_SYNC_t sobj) { - /* FreeRTOS */ - return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); + /* FreeRTOS */ + return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); } /*------------------------------------------------------------------------*/ @@ -130,6 +184,145 @@ int ff_req_grant(FF_SYNC_t sobj) void ff_rel_grant(FF_SYNC_t sobj) { - /* FreeRTOS */ - xSemaphoreGive(sobj); + /* FreeRTOS */ + xSemaphoreGive(sobj); +} + +int get_fat_object(int i, enum FatObjectType expected, struct FatObject **res) +{ + if (i < 0 || i >= EPIC_FAT_MAX_OPENED) { + *res = NULL; + return EBADF; + } + if (s_openedObjects[i].type != expected) { + *res = NULL; + return EBADF; + } + *res = &s_openedObjects[i]; + return 0; +} + +int32_t epic_open(const char *filename, const char *modeString) +{ + struct FatObject *o = NULL; + const char *mode_s = modeString; + int i; + int mode = 0; + + //find free object to use + for (i = 0; i < EPIC_FAT_MAX_OPENED; ++i) { + if (s_openedObjects[i].type == FO_Nil) { + break; + } + } + if (i == EPIC_FAT_MAX_OPENED) { + return -fresult_to_errno_table[FR_TOO_MANY_OPEN_FILES]; + } + o = &s_openedObjects[i]; + + while (*mode_s) { + switch (*mode_s++) { + case 'r': + mode |= FA_READ; + break; + case 'w': + mode |= FA_WRITE | FA_CREATE_ALWAYS; + break; + case 'x': + mode |= FA_WRITE | FA_CREATE_NEW; + break; + case 'a': + mode |= FA_WRITE | FA_OPEN_ALWAYS; + break; + case '+': + mode |= FA_READ | FA_WRITE; + break; + } + } + + int res = f_open(&o->file, filename, mode); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + o->type = FO_File; + + // for 'a' mode, we must begin at the end of the file + if ((mode & FA_OPEN_ALWAYS) != 0) { + f_lseek(&o->file, f_size(&o->file)); + } + + return i; +} + +int32_t epic_close(int32_t fd) +{ + int res; + struct FatObject *o; + res = get_fat_object(fd, FO_File, &o); + if (res) { + return -res; + } + + res = f_close(&o->file); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + + o->type = FO_Nil; + return 0; } + + +int32_t epic_read(int32_t fd, void *buf, uint32_t nbytes) +{ + unsigned int nread = 0; + + int res; + struct FatObject *o; + res = get_fat_object(fd, FO_File, &o); + if (res) { + return -res; + } + + res = f_read(&o->file, buf, nbytes, &nread); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + + return nread; +} + +int32_t epic_write(int32_t fd, const void *buf, uint32_t nbytes) +{ + unsigned int nwritten = 0; + + int res; + struct FatObject *o; + res = get_fat_object(fd, FO_File, &o); + if (res) { + return -res; + } + res = f_write(&o->file, buf, nbytes, &nwritten); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + + return nwritten; +} + +int32_t epic_flush(int32_t fd) { + + int res; + struct FatObject *o; + res = get_fat_object(fd, FO_File, &o); + if (res) { + return -res; + } + res = f_sync(&o->file); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + + return 0; +} + diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h index 214545f6029e5201db4f3518a1224bc8ad6f12bd..f02298e36b2e538237fc75bfe0710517c11e33ab 100644 --- a/epicardium/modules/modules.h +++ b/epicardium/modules/modules.h @@ -1,7 +1,10 @@ #ifndef MODULES_H #define MODULES_H -/* FatFS */ +/* ---------- FAT fs ------------------------------------------------------ */ +/* max no. of descriptors (file & directory) that can be open at a time */ +#define EPIC_FAT_MAX_OPENED 16 +#define EPIC_FAT_STATIC_SEMAPHORE 1 void fatfs_init(void); /* ---------- Serial ------------------------------------------------------- */ diff --git a/pycardium/meson.build b/pycardium/meson.build index 895be888ee81bdd886b990d12f7c6d63321a6c2e..453fc752e9c4bbe403b117c65d1c4cf992faded1 100644 --- a/pycardium/meson.build +++ b/pycardium/meson.build @@ -7,6 +7,7 @@ modsrc = files( 'modules/utime.c', 'modules/vibra.c', 'modules/light_sensor.c' + 'modules/fat_file.c', ) ################################# diff --git a/pycardium/modules/fat_file.c b/pycardium/modules/fat_file.c new file mode 100644 index 0000000000000000000000000000000000000000..711217b4dfd0ace444d08ab6a6f03d5676fcc5d5 --- /dev/null +++ b/pycardium/modules/fat_file.c @@ -0,0 +1,273 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> + +#include "py/mpconfig.h" +#include "py/runtime.h" +#include "py/builtin.h" +#include "py/stream.h" +#include "py/mperrno.h" +#include "epicardium.h" + +extern const mp_obj_type_t mp_type_fat_textio; +#if MICROPY_PY_IO_FILEIO +extern const mp_obj_type_t mp_type_fat_fileio; +#endif + +typedef struct _pyb_file_obj_t { + mp_obj_base_t base; + int fd; +} pyb_file_obj_t; + +STATIC void +file_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + (void)kind; + mp_printf( + print, + "<io.%s %p>", + mp_obj_get_type_str(self_in), + MP_OBJ_TO_PTR(self_in) + ); +} + +STATIC mp_uint_t +file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) +{ + pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); + int res = epic_read(self->fd, buf, size); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return res; +} + +STATIC mp_uint_t +file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) +{ + pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); + int res = epic_write(self->fd, buf, size); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return res; +} + +STATIC mp_obj_t file_obj___exit__(size_t n_args, const mp_obj_t *args) +{ + (void)n_args; + return mp_stream_close(args[0]); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + file_obj___exit___obj, 4, 4, file_obj___exit__ +); + +STATIC mp_uint_t +file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) +{ + pyb_file_obj_t *self = MP_OBJ_TO_PTR(o_in); + int res; + switch (request) { + case MP_STREAM_FLUSH: + res = epic_flush(self->fd); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return 0; + case MP_STREAM_CLOSE: + res = epic_close(self->fd); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return 0; + } + //every valid case returns either success or error, so this is EINVAL land: + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + // if (request == MP_STREAM_SEEK) { + // struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)(uintptr_t)arg; + + // switch (s->whence) { + // case 0: // SEEK_SET + // f_lseek(&self->fp, s->offset); + // break; + + // case 1: // SEEK_CUR + // f_lseek(&self->fp, f_tell(&self->fp) + s->offset); + // break; + + // case 2: // SEEK_END + // f_lseek(&self->fp, f_size(&self->fp) + s->offset); + // break; + // } + + // s->offset = f_tell(&self->fp); + // return 0; +} + +// Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO, +// but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor +STATIC const mp_arg_t file_open_args[] = { + { MP_QSTR_file, + MP_ARG_OBJ | MP_ARG_REQUIRED, + { .u_rom_obj = MP_ROM_PTR(&mp_const_none_obj) } }, + { MP_QSTR_mode, MP_ARG_OBJ, { .u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r) } }, + { MP_QSTR_encoding, + MP_ARG_OBJ | MP_ARG_KW_ONLY, + { .u_rom_obj = MP_ROM_PTR(&mp_const_none_obj) } }, +}; +#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args) + +STATIC mp_obj_t file_open(const mp_obj_type_t *type, mp_arg_val_t *args) +{ + const char *modeString = mp_obj_str_get_str(args[1].u_obj); + const char *mode_s = modeString; + // modes r w x a + are handled on epicardium side, binary / text + // is relevant for python type so look for these here + while (*mode_s) { + switch (*mode_s++) { +#if MICROPY_PY_IO_FILEIO + case 'b': + type = &mp_type_fat_fileio; + break; +#endif + case 't': + type = &mp_type_fat_textio; + break; + } + } + + pyb_file_obj_t *o = m_new_obj_with_finaliser(pyb_file_obj_t); + o->base.type = type; + + const char *fname = mp_obj_str_get_str(args[0].u_obj); + int res = epic_open(fname, modeString); + if (res < 0) { + m_del_obj(pyb_file_obj_t, o); + mp_raise_OSError(-res); + } + o->fd = res; + + return MP_OBJ_FROM_PTR(o); +} + +STATIC mp_obj_t file_obj_make_new( + const mp_obj_type_t *type, + size_t n_args, + size_t n_kw, + const mp_obj_t *args +) { + mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; + mp_arg_parse_all_kw_array( + n_args, + n_kw, + args, + FILE_OPEN_NUM_ARGS, + file_open_args, + arg_vals + ); + return file_open(type, arg_vals); +} + +// TODO gc hook to close the file if not already closed + +STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), + MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readlines), + MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, + { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); + +#if MICROPY_PY_IO_FILEIO +STATIC const mp_stream_p_t fileio_stream_p = { + .read = file_obj_read, + .write = file_obj_write, + .ioctl = file_obj_ioctl, +}; + +const mp_obj_type_t mp_type_fat_fileio = { + { &mp_type_type }, + .name = MP_QSTR_FileIO, + .print = file_obj_print, + .make_new = file_obj_make_new, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &fileio_stream_p, + .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict, +}; +#endif + +STATIC const mp_stream_p_t textio_stream_p = { + .read = file_obj_read, + .write = file_obj_write, + .ioctl = file_obj_ioctl, + .is_text = true, +}; + +const mp_obj_type_t mp_type_fat_textio = { + { &mp_type_type }, + .name = MP_QSTR_TextIOWrapper, + .print = file_obj_print, + .make_new = file_obj_make_new, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &textio_stream_p, + .locals_dict = (mp_obj_dict_t *)&rawfile_locals_dict, +}; + +// Factory function for I/O stream classes +mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) +{ + // TODO: analyze buffering args and instantiate appropriate type + mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS]; + mp_arg_parse_all( + n_args, + args, + kwargs, + FILE_OPEN_NUM_ARGS, + file_open_args, + arg_vals + ); + return file_open(&mp_type_fat_textio, arg_vals); +} +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h index 3dda54d667557f66d39978788fbde813f8e39390..e8ac9dac50a12c6a1566c07626050358940587fc 100644 --- a/pycardium/modules/qstrdefs.h +++ b/pycardium/modules/qstrdefs.h @@ -46,3 +46,24 @@ Q(light_sensor) Q(start) Q(get_reading) Q(stop) + +/* file */ +Q(__del__) +Q(__enter__) +Q(__exit__) +Q(close) +Q(encoding) +Q(file) +Q(FileIO) +Q(flush) +Q(mode) +Q(r) +Q(read) +Q(readinto) +Q(readline) +Q(readlines) +Q(seek) +Q(tell) +Q(TextIOWrapper) +Q(write) + diff --git a/pycardium/mpconfigport.h b/pycardium/mpconfigport.h index 6bfb2c6717fcddb0bfcd585fb13c401b5df86bb9..9bed1f600fd79535f4f53d6792f0ded869cf99d0 100644 --- a/pycardium/mpconfigport.h +++ b/pycardium/mpconfigport.h @@ -76,3 +76,4 @@ typedef long mp_off_t; /* For some reason, we need to define readline history manually */ #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[16]; + diff --git a/pycardium/mphalport.c b/pycardium/mphalport.c index 95d4bffa90089570d4e26ab5f098345b646c8dab..7c14df44e3ef09bbc6972b1a442cae8240fe7b36 100644 --- a/pycardium/mphalport.c +++ b/pycardium/mphalport.c @@ -132,10 +132,3 @@ mp_import_stat_t mp_import_stat(const char *path) return MP_IMPORT_STAT_NO_EXIST; } -mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) -{ - /* TODO: Once fs is implemented, get this working as well */ - mp_raise_NotImplementedError("FS is not yet implemented"); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);