Skip to content

Commit d80ee8b

Browse files
committed
Added memzip filesystem support for teensy
You can now append a zipfile (containining uncomressed python sources) to the micropython.hex file. Use MEMZIP_DIR=directory when you call make, or set that in your environment to include a different tree of source files. Added sample /boot.py, /src/main.py, /test.py and /src/test.py files. Added run command so that you can execute scripts from REPL (until import is implemented). Added build directory to .gitignore
1 parent c698d26 commit d80ee8b

File tree

14 files changed

+285
-47
lines changed

14 files changed

+285
-47
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@
1919
######################
2020
*.swp
2121

22+
# Build directory
23+
######################
24+
build/

stm/printf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,12 @@ void stdout_print_strn(void *data, const char *str, unsigned int len) {
221221
bool any = false;
222222

223223
// TODO should have a setting for which USART port to send to
224+
#if 0 // if 0'd out so that we're not calling functions with the wrong arguments
224225
if (usart_is_enabled()) {
225226
usart_tx_strn_cooked(str, len);
226227
any = true;
227228
}
229+
#endif
228230

229231
if (usb_vcp_is_enabled()) {
230232
usb_vcp_send_strn_cooked(str, len);

teensy/Makefile

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ SRC_C = \
3333
lcd.c \
3434
led.c \
3535
lexerfatfs.c \
36-
usart.c \
36+
lexermemzip.c \
37+
memzip.c \
3738
usb.c \
3839

3940
STM_SRC_C = \
@@ -60,9 +61,9 @@ OBJ = $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(STM_SRC_S:.s=.o
6061
#LIB += -ltermcap
6162

6263
all2: $(BUILD) hex
63-
hex: $(BUILD)/flash.hex
64+
hex: $(BUILD)/micropython-mz.hex
6465

65-
post_compile: $(BUILD)/flash.hex
66+
post_compile: $(BUILD)/micropython-mz.hex
6667
$(ECHO) "Preparing $@ for upload"
6768
$(Q)$(TOOLS_PATH)/teensy_post_compile -file="$(basename $(<F))" -path="$(<D)" -tools="$(TOOLS_PATH)"
6869

@@ -72,11 +73,19 @@ reboot:
7273

7374
upload: post_compile reboot
7475

75-
$(BUILD)/flash.elf: $(OBJ)
76+
$(BUILD)/micropython.elf: $(OBJ)
7677
$(ECHO) "LINK $<"
7778
$(Q)$(CC) $(LDFLAGS) -o "$@" -Wl,-Map,$(@:.elf=.map) $(OBJ) $(LIBS)
7879
$(Q)$(SIZE) $@
7980

81+
ifeq ($(MEMZIP_DIR),)
82+
MEMZIP_DIR = memzip_files
83+
endif
84+
85+
$(BUILD)/micropython-mz.hex: $(BUILD)/micropython.hex $(shell find ${MEMZIP_DIR} -type f)
86+
@$(ECHO) "Creating $@"
87+
$(Q)./add-memzip.sh $< $@ ${MEMZIP_DIR}
88+
8089
$(BUILD)/%.hex: $(BUILD)/%.elf
8190
$(ECHO) "HEX $<"
8291
$(Q)$(OBJCOPY) -O ihex -R .eeprom "$<" "$@"

teensy/add-memzip.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/bash
2+
3+
if [ "$#" != 3 ]; then
4+
echo "Usage: add-memzip.sh input.hex output.hex file-directory"
5+
exit 1
6+
fi
7+
8+
#set -x
9+
10+
input_hex=$1
11+
output_hex=$2
12+
memzip_src_dir=$3
13+
14+
input_bin=${input_hex}.bin
15+
output_bin=${output_hex}.bin
16+
zip_file=${output_hex}.zip
17+
zip_base=$(basename ${zip_file})
18+
zip_dir=$(dirname ${zip_file})
19+
abs_zip_dir=$(realpath ${zip_dir})
20+
21+
rm -f ${zip_file}
22+
(cd ${memzip_src_dir}; zip -0 -r -D ${abs_zip_dir}/${zip_base} .)
23+
objcopy -I ihex -O binary ${input_hex} ${input_bin}
24+
cat ${input_bin} ${zip_file} > ${output_bin}
25+
objcopy -I binary -O ihex ${output_bin} ${output_hex}
26+
echo "Added ${memzip_src_dir} to ${input_hex} creating ${output_hex}"
27+

teensy/lexermemzip.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
4+
#include "misc.h"
5+
#include "lexer.h"
6+
#include "memzip.h"
7+
8+
mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename)
9+
{
10+
void *data;
11+
size_t len;
12+
13+
if (memzip_locate(filename, &data, &len) != MZ_OK) {
14+
return NULL;
15+
}
16+
return mp_lexer_new_from_str_len(filename, (const char *)data, (uint)len, 0);
17+
}
18+

teensy/lexermemzip.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename);
2+

teensy/main.c

Lines changed: 90 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "mpconfig.h"
99
#include "mpqstr.h"
1010
#include "lexer.h"
11+
#include "lexermemzip.h"
1112
#include "parse.h"
1213
#include "obj.h"
1314
#include "compile.h"
@@ -22,52 +23,17 @@
2223

2324
extern uint32_t _heap_start;
2425

25-
#ifdef USE_READLINE
26-
#include <readline/readline.h>
27-
#include <readline/history.h>
28-
#endif
26+
bool do_file(const char *filename);
2927

30-
#if 0
31-
static char *str_join(const char *s1, int sep_char, const char *s2) {
32-
int l1 = strlen(s1);
33-
int l2 = strlen(s2);
34-
char *s = m_new(char, l1 + l2 + 2);
35-
memcpy(s, s1, l1);
36-
if (sep_char != 0) {
37-
s[l1] = sep_char;
38-
l1 += 1;
28+
void flash_error(int n) {
29+
for (int i = 0; i < n; i++) {
30+
led_state(PYB_LED_BUILTIN, 1);
31+
delay(250);
32+
led_state(PYB_LED_BUILTIN, 0);
33+
delay(250);
3934
}
40-
memcpy(s + l1, s2, l2);
41-
s[l1 + l2] = 0;
42-
return s;
4335
}
4436

45-
static char *prompt(char *p) {
46-
#ifdef USE_READLINE
47-
char *line = readline(p);
48-
if (line) {
49-
add_history(line);
50-
}
51-
#else
52-
static char buf[256];
53-
fputs(p, stdout);
54-
char *s = fgets(buf, sizeof(buf), stdin);
55-
if (!s) {
56-
return NULL;
57-
}
58-
int l = strlen(buf);
59-
if (buf[l - 1] == '\n') {
60-
buf[l - 1] = 0;
61-
} else {
62-
l++;
63-
}
64-
char *line = m_new(char, l);
65-
memcpy(line, buf, l);
66-
#endif
67-
return line;
68-
}
69-
#endif
70-
7137
static const char *help_text =
7238
"Welcome to Micro Python!\n\n"
7339
"This is a *very* early version of Micro Python and has minimal functionality.\n\n"
@@ -215,6 +181,19 @@ mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
215181
}
216182
#endif
217183

184+
static qstr pyb_config_source_dir = 0;
185+
static qstr pyb_config_main = 0;
186+
187+
mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
188+
pyb_config_source_dir = mp_obj_get_qstr(source_dir);
189+
return mp_const_none;
190+
}
191+
192+
mp_obj_t pyb_main(mp_obj_t main) {
193+
pyb_config_main = mp_obj_get_qstr(main);
194+
return mp_const_none;
195+
}
196+
218197
mp_obj_t pyb_delay(mp_obj_t count) {
219198
delay(mp_obj_get_int(count));
220199
return mp_const_none;
@@ -225,6 +204,12 @@ mp_obj_t pyb_led(mp_obj_t state) {
225204
return state;
226205
}
227206

207+
mp_obj_t pyb_run(mp_obj_t filename_obj) {
208+
const char *filename = qstr_str(mp_obj_get_qstr(filename_obj));
209+
do_file(filename);
210+
return mp_const_none;
211+
}
212+
228213
char *strdup(const char *str) {
229214
uint32_t len = strlen(str);
230215
char *s2 = m_new(char, len + 1);
@@ -316,6 +301,39 @@ int readline(vstr_t *line, const char *prompt) {
316301
}
317302
}
318303

304+
bool do_file(const char *filename) {
305+
mp_lexer_t *lex = mp_lexer_new_from_memzip_file(filename);
306+
307+
if (lex == NULL) {
308+
printf("could not open file '%s' for reading\n", filename);
309+
return false;
310+
}
311+
312+
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
313+
mp_lexer_free(lex);
314+
315+
if (pn == MP_PARSE_NODE_NULL) {
316+
return false;
317+
}
318+
319+
mp_obj_t module_fun = mp_compile(pn, false);
320+
if (module_fun == mp_const_none) {
321+
return false;
322+
}
323+
324+
nlr_buf_t nlr;
325+
if (nlr_push(&nlr) == 0) {
326+
rt_call_function_0(module_fun);
327+
nlr_pop();
328+
return true;
329+
} else {
330+
// uncaught exception
331+
mp_obj_print((mp_obj_t)nlr.ret_val);
332+
printf("\n");
333+
return false;
334+
}
335+
}
336+
319337
void do_repl(void) {
320338
stdout_tx_str("Micro Python for Teensy 3.1\r\n");
321339
stdout_tx_str("Type \"help()\" for more information.\r\n");
@@ -397,24 +415,53 @@ int main(void) {
397415
rt_init();
398416

399417
#if 1
400-
printf("About to add functions()\n");
401418
// add some functions to the python namespace
402419
{
403420
rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help));
404421
mp_obj_t m = mp_obj_new_module(qstr_from_str_static("pyb"));
405422
rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_0(pyb_info));
423+
rt_store_attr(m, qstr_from_str_static("source_dir"), rt_make_function_1(pyb_source_dir));
424+
rt_store_attr(m, qstr_from_str_static("main"), rt_make_function_1(pyb_main));
406425
rt_store_attr(m, qstr_from_str_static("gc"), rt_make_function_0(pyb_gc));
407426
rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay));
408427
rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led));
409428
rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_1(pyb_Led));
410429
rt_store_attr(m, qstr_from_str_static("gpio"), (mp_obj_t)&pyb_gpio_obj);
411430
rt_store_name(qstr_from_str_static("pyb"), m);
431+
rt_store_name(qstr_from_str_static("run"), rt_make_function_1(pyb_run));
412432
}
413433
#endif
414434

435+
if (!do_file("/boot.py")) {
436+
printf("Unable to open '/boot.py'\n");
437+
flash_error(4);
438+
}
439+
415440
// Turn bootup LED off
416441
led_state(PYB_LED_BUILTIN, 0);
417442

443+
// run main script
444+
{
445+
vstr_t *vstr = vstr_new();
446+
vstr_add_str(vstr, "/");
447+
if (pyb_config_source_dir == 0) {
448+
vstr_add_str(vstr, "src");
449+
} else {
450+
vstr_add_str(vstr, qstr_str(pyb_config_source_dir));
451+
}
452+
vstr_add_char(vstr, '/');
453+
if (pyb_config_main == 0) {
454+
vstr_add_str(vstr, "main.py");
455+
} else {
456+
vstr_add_str(vstr, qstr_str(pyb_config_main));
457+
}
458+
if (!do_file(vstr_str(vstr))) {
459+
printf("Unable to open '%s'\n", vstr_str(vstr));
460+
flash_error(3);
461+
}
462+
vstr_free(vstr);
463+
}
464+
418465
do_repl();
419466

420467
printf("PYB: soft reboot\n");

teensy/memzip.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include "memzip.h"
5+
6+
extern uint8_t _staticfs[];
7+
8+
MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len)
9+
{
10+
const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)_staticfs;
11+
uint8_t *mem_data;
12+
13+
/* Zip file filenames don't have a leading /, so we strip it off */
14+
15+
if (*filename == '/') {
16+
filename++;
17+
}
18+
while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) {
19+
const char *file_hdr_filename = (const char *)&file_hdr[1];
20+
mem_data = (uint8_t *)file_hdr_filename;
21+
mem_data += file_hdr->filename_len;
22+
mem_data += file_hdr->extra_len;
23+
if (!strncmp(file_hdr_filename, filename, file_hdr->filename_len)) {
24+
/* We found a match */
25+
if (file_hdr->compression_method != 0) {
26+
return MZ_FILE_COMPRESSED;
27+
}
28+
29+
*data = mem_data;
30+
*len = file_hdr->uncompressed_size;
31+
return MZ_OK;
32+
}
33+
mem_data += file_hdr->uncompressed_size;
34+
file_hdr = (const MEMZIP_FILE_HDR *)mem_data;
35+
}
36+
return MZ_NO_FILE;
37+
}

0 commit comments

Comments
 (0)