Skip to content

Commit c1039cd

Browse files
markshannonMark Shannon
authored andcommitted
Add file sytem and relevant methods to os module. Allows files to written to and read. Files can be uploaded, including script to be run on reset. Modules can be imported.
1 parent bc60294 commit c1039cd

File tree

14 files changed

+1386
-17
lines changed

14 files changed

+1386
-17
lines changed

inc/genhdr/qstrdefs.generated.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,4 +679,9 @@ QDEF(MP_QSTR_uname, (const byte*)"\xb7\x05" "uname")
679679
QDEF(MP_QSTR_sysname, (const byte*)"\x9b\x07" "sysname")
680680
QDEF(MP_QSTR_nodename, (const byte*)"\x62\x08" "nodename")
681681
QDEF(MP_QSTR_release, (const byte*)"\xec\x07" "release")
682+
QDEF(MP_QSTR_BytesIO, (const byte*)"\x1a\x07" "BytesIO")
683+
QDEF(MP_QSTR_TextIO, (const byte*)"\x1e\x06" "TextIO")
684+
QDEF(MP_QSTR_writable, (const byte*)"\xf7\x08" "writable")
685+
QDEF(MP_QSTR_listdir, (const byte*)"\x98\x07" "listdir")
682686
QDEF(MP_QSTR_machine, (const byte*)"\x60\x07" "machine")
687+
QDEF(MP_QSTR_size, (const byte*)"\x20\x04" "size")

inc/microbit/filesystem.h

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Mark Shannon
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
#ifndef __MICROPY_INCLUDED_FILESYSTEM_H__
27+
#define __MICROPY_INCLUDED_FILESYSTEM_H__
28+
29+
#include "nrf51.h"
30+
#include "nrf_nvmc.h"
31+
#include "py/lexer.h"
32+
33+
inline uint32_t persistent_page_size(void) {
34+
return NRF_FICR->CODEPAGESIZE;
35+
}
36+
37+
bool is_persistent_page_aligned(const void *ptr);
38+
39+
/** WARNING: This function may require 1k of heap space in order to hold data when erasing a page.
40+
* Returns -1 if it cannot allocate sufficient memory.
41+
*/
42+
int persistent_write(const void *dest, const void *src, uint32_t byte_count);
43+
/** WARNING: This function may require 1k of heap space in order to hold data when erasing a page.
44+
* Returns -1 if it cannot allocate sufficient memory.
45+
*/
46+
int persistent_write_byte(const uint8_t *dest, const uint8_t val);
47+
48+
void persistent_write_unchecked(const void *dest, const void *src, uint32_t byte_count);
49+
void persistent_write_byte_unchecked(const uint8_t *dest, const uint8_t val);
50+
51+
void persistent_erase_page(const void *page);
52+
53+
typedef struct _file_descriptor_obj {
54+
mp_obj_base_t base;
55+
uint8_t start_chunk;
56+
uint8_t seek_chunk;
57+
uint8_t seek_offset;
58+
bool writable;
59+
bool open;
60+
bool binary;
61+
} file_descriptor_obj;
62+
63+
#define LOG_CHUNK_SIZE 7
64+
#define CHUNK_SIZE (1<<LOG_CHUNK_SIZE)
65+
#define DATA_PER_CHUNK (CHUNK_SIZE-2)
66+
67+
#define UNUSED_CHUNK 255
68+
#define FREED_CHUNK 0
69+
#define FILE_START 254
70+
#define PERSISTENT_DATA_MARKER 253
71+
72+
/** Must be such that sizeof(file_header) < DATA_PER_CHUNK */
73+
#define MAX_FILENAME_LENGTH 120
74+
75+
//Minimum number of free chunks to justify sweeping.
76+
//If this is too low it may cause excessive wear
77+
#define MIN_CHUNKS_FOR_SWEEP 8
78+
79+
typedef struct _file_header {
80+
uint8_t end_offset;
81+
uint8_t name_len;
82+
char filename[MAX_FILENAME_LENGTH];
83+
} file_header;
84+
85+
typedef struct _file_chunk {
86+
uint8_t marker;
87+
union {
88+
char data[DATA_PER_CHUNK];
89+
file_header header;
90+
};
91+
uint8_t next_chunk;
92+
} file_chunk;
93+
94+
typedef struct _persistent_config_t {
95+
// Must start with a marker, so that we can identify it.
96+
uint8_t marker; // Should always be PERSISTENT_DATA_MARKER
97+
} persistent_config_t;
98+
99+
#define FILE_NOT_FOUND ((uint8_t)-1)
100+
101+
/** Maximum number of chunks allowed in filesystem. 240 chunks is 30kb */
102+
#define MAX_CHUNKS_IN_FILE_SYSTEM 240
103+
104+
#define STATIC_ASSERT(e) extern char static_assert_failed[(e) ? 1 : -1]
105+
106+
uint8_t microbit_find_file(const char *name, int name_len);
107+
file_descriptor_obj *microbit_file_open(const char *name, uint32_t name_len, bool write, bool binary);
108+
void microbit_file_close(file_descriptor_obj *fd);
109+
mp_uint_t microbit_file_read(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
110+
mp_uint_t microbit_file_write(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode);
111+
mp_obj_t microbit_file_name(file_descriptor_obj *fd);
112+
113+
mp_obj_t microbit_remove(mp_obj_t filename);
114+
mp_obj_t microbit_file_list(void);
115+
mp_obj_t microbit_file_size(mp_obj_t filename);
116+
117+
mp_lexer_t *microbit_file_lexer(qstr src_name, file_descriptor_obj *fd);
118+
119+
void microbit_filesystem_init(void);
120+
121+
extern const mp_obj_type_t microbit_bytesio_type;
122+
extern const mp_obj_type_t microbit_textio_type;
123+
124+
#define min(a,b) (((a)<(b))?(a):(b))
125+
126+
#endif // __MICROPY_INCLUDED_FILESYSTEM_H__

inc/microbit/memory.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Mark Shannon
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef __MICROPY_INCLUDED_MEMORY_H__
28+
#define __MICROPY_INCLUDED_MEMORY_H__
29+
30+
extern uint32_t __data_end__;
31+
extern uint32_t __data_start__;
32+
extern uint32_t __etext;
33+
34+
inline char *rounddown(char *addr, uint32_t align) {
35+
return (char *)(((uint32_t)addr)&(-align));
36+
}
37+
38+
inline char *roundup(char *addr, uint32_t align) {
39+
return (char *)((((uint32_t)addr)+align-1)&(-align));
40+
}
41+
42+
/** The end of the code area in flash ROM (text plus read-only copy of data area) */
43+
inline char *microbit_end_of_code() {
44+
return (char *)(&__etext + (&__data_end__ - &__data_start__));
45+
}
46+
47+
inline char *microbit_end_of_rom() {
48+
return (char *)0x40000;
49+
}
50+
51+
inline char *microbit_mp_appended_script() {
52+
return (char *)0x3e000;
53+
}
54+
55+
#endif // __MICROPY_INCLUDED_MEMORY_H__

inc/microbit/qstrdefsport.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ Q(choice)
386386
Q(uniform)
387387

388388
Q(name)
389+
Q(os)
389390

390391
Q(os)
391392
Q(uname)
@@ -394,4 +395,13 @@ Q(sysname)
394395
Q(nodename)
395396
Q(release)
396397
Q(version)
398+
Q(BytesIO)
399+
Q(TextIO)
400+
Q(read)
401+
Q(write)
402+
Q(writable)
403+
Q(readall)
404+
Q(name)
405+
Q(listdir)
397406
Q(machine)
407+
Q(size)

source/microbit/fileobj.c

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Mark Shannon
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
28+
29+
30+
#include "py/nlr.h"
31+
#include "py/obj.h"
32+
#include "filesystem.h"
33+
#include "py/stream.h"
34+
35+
36+
static mp_obj_t microbit_file_writable(mp_obj_t self) {
37+
return mp_obj_new_bool(((file_descriptor_obj *)self)->writable);
38+
}
39+
MP_DEFINE_CONST_FUN_OBJ_1(microbit_file_writable_obj, microbit_file_writable);
40+
41+
MP_DEFINE_CONST_FUN_OBJ_1(microbit_file_name_obj, (mp_fun_1_t)microbit_file_name);
42+
43+
static mp_obj_t microbit_file_close_func(mp_obj_t self_in) {
44+
microbit_file_close((file_descriptor_obj *)self_in);
45+
return mp_const_none;
46+
}
47+
MP_DEFINE_CONST_FUN_OBJ_1(microbit_file_close_obj, microbit_file_close_func);
48+
49+
STATIC mp_obj_t file___exit__(size_t n_args, const mp_obj_t *args) {
50+
(void)n_args;
51+
return microbit_file_close_func(args[0]);
52+
}
53+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(file___exit___obj, 4, 4, file___exit__);
54+
55+
static const mp_map_elem_t microbit_bytesio_locals_dict_table[] = {
56+
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&microbit_file_close_obj },
57+
{ MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&microbit_file_name_obj },
58+
{ MP_ROM_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
59+
{ MP_ROM_QSTR(MP_QSTR___exit__), (mp_obj_t)&file___exit___obj },
60+
{ MP_OBJ_NEW_QSTR(MP_QSTR_writable), (mp_obj_t)&microbit_file_writable_obj },
61+
/* Stream methods */
62+
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
63+
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
64+
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
65+
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
66+
};
67+
static MP_DEFINE_CONST_DICT(microbit_bytesio_locals_dict, microbit_bytesio_locals_dict_table);
68+
69+
STATIC const mp_stream_p_t bytesio_stream_p = {
70+
.read = microbit_file_read,
71+
.write = microbit_file_write,
72+
};
73+
74+
const mp_obj_type_t microbit_bytesio_type = {
75+
{ &mp_type_type },
76+
.name = MP_QSTR_BytesIO,
77+
.print = NULL,
78+
.make_new = NULL,
79+
.call = NULL,
80+
.unary_op = NULL,
81+
.binary_op = NULL,
82+
.attr = NULL,
83+
.subscr = NULL,
84+
.getiter = NULL,
85+
.iternext = NULL,
86+
.buffer_p = {NULL},
87+
.stream_p = &bytesio_stream_p,
88+
.bases_tuple = NULL,
89+
.locals_dict = (mp_obj_dict_t*)&microbit_bytesio_locals_dict,
90+
};
91+
92+
static const mp_map_elem_t microbit_textio_locals_dict_table[] = {
93+
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&microbit_file_close_obj },
94+
{ MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&microbit_file_name_obj },
95+
{ MP_ROM_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
96+
{ MP_ROM_QSTR(MP_QSTR___exit__), (mp_obj_t)&file___exit___obj },
97+
{ MP_OBJ_NEW_QSTR(MP_QSTR_writable), (mp_obj_t)&microbit_file_writable_obj },
98+
/* Stream methods */
99+
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
100+
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
101+
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
102+
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
103+
};
104+
static MP_DEFINE_CONST_DICT(microbit_textio_locals_dict, microbit_textio_locals_dict_table);
105+
106+
107+
STATIC const mp_stream_p_t textio_stream_p = {
108+
.read = microbit_file_read,
109+
.write = microbit_file_write,
110+
.is_text = true,
111+
};
112+
113+
const mp_obj_type_t microbit_textio_type = {
114+
{ &mp_type_type },
115+
.name = MP_QSTR_TextIO,
116+
.print = NULL,
117+
.make_new = NULL,
118+
.call = NULL,
119+
.unary_op = NULL,
120+
.binary_op = NULL,
121+
.attr = NULL,
122+
.subscr = NULL,
123+
.getiter = NULL,
124+
.iternext = NULL,
125+
.buffer_p = {NULL},
126+
.stream_p = &textio_stream_p,
127+
.bases_tuple = NULL,
128+
.locals_dict = (mp_obj_dict_t*)&microbit_textio_locals_dict,
129+
};
130+
131+
132+
static mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args) {
133+
/// -1 means default; 0 explicitly false; 1 explicitly true.
134+
int read = -1;
135+
int text = -1;
136+
if (n_args == 2) {
137+
mp_uint_t len;
138+
const char *mode = mp_obj_str_get_data(args[1], &len);
139+
for (mp_uint_t i = 0; i < len; i++) {
140+
if (mode[i] == 'r' || mode[i] == 'w') {
141+
if (read >= 0) {
142+
goto mode_error;
143+
}
144+
read = (mode[i] == 'r');
145+
} else if (mode[i] == 'b' || mode[i] == 't') {
146+
if (text >= 0) {
147+
goto mode_error;
148+
}
149+
text = (mode[i] == 't');
150+
} else {
151+
goto mode_error;
152+
}
153+
}
154+
}
155+
mp_uint_t name_len;
156+
const char *filename = mp_obj_str_get_data(args[0], &name_len);
157+
file_descriptor_obj *res = microbit_file_open(filename, name_len, read == 0, text == 0);
158+
if (res == NULL) {
159+
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "file not found"));
160+
}
161+
return res;
162+
mode_error:
163+
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "illegal mode"));
164+
}
165+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy