Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
François Revol
firmware
Commits
287ae82e
Commit
287ae82e
authored
Jul 18, 2019
by
swym
Browse files
First implementation of file IO via libff in epicardium & pycarddium
parent
f54e3c0e
Changes
8
Hide whitespace changes
Inline
Side-by-side
epicardium/epicardium.h
View file @
287ae82e
...
...
@@ -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 */
epicardium/modules/fatfs.c
View file @
287ae82e
...
...
@@ -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
\0
DISK_ERR
\0
INT_ERR
\0
NOT_READY
\0
NO_FILE
\0
NO_PATH
\0
INVALID_NAME
\0
"
)
_T
(
"DENIED
\0
EXIST
\0
INVALID_OBJECT
\0
WRITE_PROTECTED
\0
INVALID_DRIVE
\0
"
)
_T
(
"NOT_ENABLED
\0
NO_FILESYSTEM
\0
MKFS_ABORTED
\0
TIMEOUT
\0
LOCKED
\0
"
)
_T
(
"NOT_ENOUGH_CORE
\0
TOO_MANY_OPEN_FILES
\0
INVALID_PARAMETER
\0
"
);
_T
(
"OK
\0
DISK_ERR
\0
INT_ERR
\0
NOT_READY
\0
NO_FILE
\0
NO_PATH
\0
INVALID_NAME
\0
"
)
_T
(
"DENIED
\0
EXIST
\0
INVALID_OBJECT
\0
WRITE_PROTECTED
\0
INVALID_DRIVE
\0
"
)
_T
(
"NOT_ENABLED
\0
NO_FILESYSTEM
\0
MKFS_ABORTED
\0
TIMEOUT
\0
LOCKED
\0
"
)
_T
(
"NOT_ENOUGH_CORE
\0
TOO_MANY_OPEN_FILES
\0
INVALID_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
;
}
epicardium/modules/modules.h
View file @
287ae82e
#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 ------------------------------------------------------- */
...
...
pycardium/meson.build
View file @
287ae82e
...
...
@@ -7,6 +7,7 @@ modsrc = files(
'modules/utime.c'
,
'modules/vibra.c'
,
'modules/light_sensor.c'
'modules/fat_file.c'
,
)
#################################
...
...
pycardium/modules/fat_file.c
0 → 100644
View file @
287ae82e
/*
* 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
,