From 152568bcb61e65b700ca2b963534f2632d080345 Mon Sep 17 00:00:00 2001 From: Damien Date: Wed, 16 Oct 2013 00:46:39 +0100 Subject: [PATCH] NLR and Python exceptions work on the board. --- py/nlr.h | 10 +++--- py/nlrthumb.s | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ stm/Makefile | 13 ++++--- stm/main.c | 96 +++++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 182 insertions(+), 28 deletions(-) create mode 100644 py/nlrthumb.s diff --git a/py/nlr.h b/py/nlr.h index b824e4a63..fa4e2f45f 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -3,9 +3,9 @@ #include -#ifndef __WORDSIZE -#error __WORDSIZE needs to be defined -#endif +//#ifndef __WORDSIZE +//#error __WORDSIZE needs to be defined +//#endif typedef struct _nlr_buf_t nlr_buf_t; struct _nlr_buf_t { @@ -17,7 +17,9 @@ struct _nlr_buf_t { #elif __WORDSIZE == 64 void *regs[8]; #else -#error Unsupported __WORDSIZE + // hack for thumb + void *regs[10]; +//#error Unsupported __WORDSIZE #endif }; diff --git a/py/nlrthumb.s b/py/nlrthumb.s new file mode 100644 index 000000000..d4d1bff23 --- /dev/null +++ b/py/nlrthumb.s @@ -0,0 +1,91 @@ +@ thumb callee save: bx, bp, sp, r12, r14, r14, r15 + + .syntax unified + .cpu cortex-m4 + .thumb + .text + .align 2 + +@ uint nlr_push(r0=nlr_buf_t *nlr) + .global nlr_push + .thumb + .thumb_func + .type nlr_push, %function +nlr_push: + str lr, [r0, #8] @ store lr into nlr_buf + str r4, [r0, #12] @ store r4 into nlr_buf + str r5, [r0, #16] @ store r5 into nlr_buf + str r6, [r0, #20] @ store r6 into nlr_buf + str r7, [r0, #24] @ store r7 into nlr_buf + str r8, [r0, #28] @ store r8 into nlr_buf + str r9, [r0, #32] @ store r9 into nlr_buf + str r10, [r0, #36] @ store r10 into nlr_buf + str r11, [r0, #40] @ store r11 into nlr_buf + str r13, [r0, #44] @ store r13=sp into nlr_buf + + ldr r3, .L2 @ load addr of nlr_top + ldr r2, [r3] @ load nlr_top + str r2, [r0] @ store nlr_top into nlr_buf + str r0, [r3] @ store nlr_buf into nlr_top (to link list) + + movs r0, #0 @ return 0, normal return + bx lr @ return + .align 2 +.L2: + .word .LANCHOR0 + .size nlr_push, .-nlr_push + +@ void nlr_pop() + .global nlr_pop + .thumb + .thumb_func + .type nlr_pop, %function +nlr_pop: + ldr r3, .L5 @ load addr of nlr_top + ldr r2, [r3] @ load nlr_top + ldr r2, [r2] @ load prev nlr_buf + str r2, [r3] @ store prev nlr_buf to nlr_top (to unlink list) + bx lr @ return + .align 2 +.L5: + .word .LANCHOR0 + .size nlr_pop, .-nlr_pop + +@ void nlr_jump(r0=uint val) + .global nlr_jump + .thumb + .thumb_func + .type nlr_jump, %function +nlr_jump: + ldr r3, .L2 @ load addr of nlr_top + ldr r2, [r3] @ load nlr_top + str r0, [r2, #4] @ store return value + ldr r0, [r2] @ load prev nlr_buf + str r0, [r3] @ store prev nol_buf into nlr_top (to unlink list) + + ldr lr, [r2, #8] @ load lr from nlr_buf + ldr r4, [r2, #12] @ load r4 from nlr_buf + ldr r5, [r2, #16] @ load r5 from nlr_buf + ldr r6, [r2, #20] @ load r6 from nlr_buf + ldr r7, [r2, #24] @ load r7 from nlr_buf + ldr r8, [r2, #28] @ load r8 from nlr_buf + ldr r9, [r2, #32] @ load r9 from nlr_buf + ldr r10, [r2, #36] @ load r10 from nlr_buf + ldr r11, [r2, #40] @ load r11 from nlr_buf + ldr r13, [r2, #44] @ load r13=sp from nlr_buf + + movs r0, #1 @ return 1, non-local return + bx lr @ return + .align 2 +.L6: + .word .LANCHOR0 + .size nlr_jump, .-nlr_jump + +@ local variable nlr_top + .bss + .align 2 + .set .LANCHOR0,. + 0 + .type nlr_top, %object + .size nlr_top, 4 +nlr_top: + .space 4 diff --git a/stm/Makefile b/stm/Makefile index 23bcffc13..ee1453da6 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -8,7 +8,6 @@ CC = arm-none-eabi-gcc LD = arm-none-eabi-ld CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfloat-abi=hard -DSTM32F40XX -DHSE_VALUE=8000000 CFLAGS = -I. -I$(PYSRC) -I$(FATFSSRC) -I$(STMSRC) -Wall -ansi -std=gnu99 -Os -DNDEBUG $(CFLAGS_CORTEX_M4) -CFLAGS_PY = -DEMIT_ENABLE_THUMB LDFLAGS = --nostdlib -T stm32f405.ld SRC_C = \ @@ -27,7 +26,8 @@ SRC_S = \ startup_stm32f40xx.s \ PY_O = \ -# malloc.o \ + nlrthumb.o \ + malloc.o \ qstr.o \ misc.o \ lexer.o \ @@ -109,15 +109,18 @@ $(BUILD)/%.o: $(FATFSSRC)/%.c $(BUILD)/%.o: $(STMSRC)/%.c $(CC) $(CFLAGS) -c -o $@ $< +$(BUILD)/%.o: $(PYSRC)/%.s + $(AS) -c -o $@ $< + $(BUILD)/%.o: $(PYSRC)/%.c mpyconfig.h - $(CC) $(CFLAGS) $(CFLAGS_PY) -c -o $@ $< + $(CC) $(CFLAGS) -c -o $@ $< $(BUILD)/emitnthumb.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h - $(CC) $(CFLAGS) $(CFLAGS_PY) -DN_THUMB -c -o $@ $< + $(CC) $(CFLAGS) -DN_THUMB -c -o $@ $< # optimising vm for speed, adds only a small amount to code size but makes a huge difference to speed (20% faster) $(BUILD)/vm.o: $(PYSRC)/vm.c - $(CC) $(CFLAGS) $(CFLAGS_PY) -O3 -c -o $@ $< + $(CC) $(CFLAGS) -O3 -c -o $@ $< $(BUILD)/parse.o: $(PYSRC)/grammar.h $(BUILD)/compile.o: $(PYSRC)/grammar.h diff --git a/stm/main.c b/stm/main.c index 0d761b8cb..9eb31db53 100644 --- a/stm/main.c +++ b/stm/main.c @@ -418,7 +418,6 @@ void __fatal_error(const char *msg) { #include "compile.h" #include "runtime.h" -/* py_obj_t pyb_delay(py_obj_t count) { delay_ms(rt_get_int(count)); return py_const_none; @@ -436,19 +435,44 @@ py_obj_t pyb_sw() { return py_const_false; } } -*/ - -#include "asmthumb.h" -typedef void (*fun_t)(); #include "ff.h" FATFS fatfs0; +#include "nlr.h" +void g(uint i) { + printf("g:%d\n", i); + if (i & 1) { + nlr_jump((void*)(42 + i)); + } +} +void f() { + nlr_buf_t nlr; + int i; + for (i = 0; i < 4; i++) { + printf("f:loop:%d:%p\n", i, &nlr); + if (nlr_push(&nlr) == 0) { + // normal + //printf("a:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val); + g(i); + printf("f:lp:%d:nrm\n", i); + nlr_pop(); + } else { + // nlr + //printf("b:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val); + printf("f:lp:%d:nlr:%d\n", i, (int)nlr.ret_val); + } + } +} +void nlr_test() { + f(1); +} + int main() { // should disable JTAG - //qstr_init(); - //rt_init(); + qstr_init(); + rt_init(); gpio_init(); led_init(); @@ -503,9 +527,11 @@ int main() { //printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init //delay_ms(1000); - #if 0 + nlr_test(); + + #if 1 // Python! - if (0) { + if (1) { //const char *pysrc = "def f():\n x=x+1\nprint(42)\n"; const char *pysrc = // impl01.py @@ -521,6 +547,7 @@ int main() { " x = x + 1\n"; */ // impl02.py + /* "#@micropython.native\n" "def f():\n" " x = 0\n" @@ -533,6 +560,7 @@ int main() { " y = y + 1\n" " x = x + 1\n" "f()\n"; + */ /* "print('in python!')\n" "x = 0\n" @@ -573,6 +601,23 @@ int main() { " x = x + 1\n" "flash(20)\n"; */ + // impl18.py + /* + "# basic exceptions\n" + "x = 1\n" + "try:\n" + " x.a()\n" + "except:\n" + " print(x)\n"; + */ + // impl19.py + "# for loop\n" + "def f():\n" + " for x in range(400):\n" + " for y in range(400):\n" + " for z in range(400):\n" + " pass\n" + "f()\n"; py_lexer_t *lex = py_lexer_from_str_len("<>", pysrc, strlen(pysrc), false); @@ -605,17 +650,30 @@ int main() { py_obj_t module_fun = rt_make_function_from_id(1); - led_state(PYB_LEDG1_PORT_NUM, 1); - delay_ms(100); - led_state(PYB_LEDG1_PORT_NUM, 0); - py_obj_t ret = rt_call_function_0(module_fun); + // flash once + led_state(PYB_LEDG1_PORT_NUM, 1); + delay_ms(100); + led_state(PYB_LEDG1_PORT_NUM, 0); + + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + py_obj_t ret = rt_call_function_0(module_fun); + printf("done! got: "); + py_obj_print(ret); + printf("\n"); + nlr_pop(); + } else { + // uncaught exception + printf("exception: "); + py_obj_print((py_obj_t)nlr.ret_val); + printf("\n"); + } + + // flash once led_state(PYB_LEDG1_PORT_NUM, 1); delay_ms(100); led_state(PYB_LEDG1_PORT_NUM, 0); - printf("done! got: "); - py_obj_print(ret); - printf("\n"); delay_ms(1000); printf("nalloc=%u\n", m_get_total_bytes_allocated()); delay_ms(1000); @@ -690,7 +748,7 @@ int main() { } // fatfs testing - if (1) { + if (0) { FRESULT res = f_mount(&fatfs0, "0:", 1); if (res == FR_OK) { printf("mount success\n"); @@ -730,7 +788,7 @@ int main() { DWORD nclst; FATFS *fatfs; f_getfree("0:", &nclst, &fatfs); - printf("free=%d\n", nclst * fatfs->csize * 512); + printf("free=%u\n", (uint)(nclst * fatfs->csize * 512)); } @@ -745,7 +803,7 @@ int main() { } // USB testing - if (1) { + if (0) { void usb_init(); usb_init(); }