Skip to content

Commit e17e4da

Browse files
committed
bricks/nxt: Run an .mpy file from flash.
Similar to how it is done on the other hubs. Allow basic debugging in one step: Make, flash, boot, run mpy, reset, repeat.
1 parent a8e5372 commit e17e4da

File tree

5 files changed

+79
-14
lines changed

5 files changed

+79
-14
lines changed

bricks/nxt/Makefile

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ QSTR_GLOBAL_DEPENDENCIES =
3939
# MicroPython feature configurations
4040
MICROPY_ROM_TEXT_COMPRESSION ?= 1
4141

42+
MPY_CROSS_FLAGS += -mno-unicode
43+
4244
# include py core make definitions
4345
include $(TOP)/py/py.mk
4446

@@ -230,6 +232,16 @@ OBJ += $(addprefix $(BUILD)/, $(PBIO_SRC_C:.c=.o))
230232
OBJ += $(addprefix $(BUILD)/, $(PYBRICKS_PYBRICKS_SRC_C:.c=.o))
231233
OBJ += $(addprefix $(BUILD)/, $(CONTIKI_SRC_C:.c=.o))
232234
OBJ += $(addprefix $(BUILD)/, $(LIBFIXMATH_SRC_C:.c=.o))
235+
OBJ += $(BUILD)/main.mpy.o
236+
237+
$(BUILD)/main.mpy: main.py
238+
$(ECHO) "MPY $<"
239+
$(Q)$(MPY_CROSS) -o $@ $(MPY_CROSS_FLAGS) $<
240+
$(ECHO) "`wc -c < $@` bytes"
241+
242+
$(BUILD)/main.mpy.o: $(BUILD)/main.mpy
243+
$(Q)$(OBJCOPY) -I binary -O elf32-littlearm -B arm \
244+
--rename-section .data=.mpy,alloc,load,readonly,data,contents $^ $@
233245

234246
# List of sources for qstr extraction
235247
SRC_QSTR += $(SRC_C) $(PYBRICKS_PYBRICKS_SRC_C)
@@ -242,9 +254,10 @@ $(BUILD)/firmware.elf: $(LDSCRIPT) $(OBJ)
242254
$(ECHO) "LINK $@"
243255
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
244256

257+
# firmware blob with main.mpy - can be flashed to hub
245258
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
246259
$(ECHO) "BIN creating firmware file"
247-
$(Q)$(OBJCOPY) -O binary $< $@
260+
$(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data -j .name -j .user $^ $@
248261
$(ECHO) "`wc -c < $@` bytes"
249262

250263
include $(TOP)/py/mkrules.mk

bricks/nxt/main.c

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "py/gc.h"
2121
#include "py/mperrno.h"
2222
#include "py/persistentcode.h"
23+
#include "py/stackctrl.h"
2324
#include "lib/utils/pyexec.h"
2425
#include "lib/utils/interrupt_char.h"
2526

@@ -80,7 +81,7 @@ void nxt_init() {
8081
udp_init();
8182
systick_wait_ms(100);
8283
sound_freq(500, 100, 30);
83-
systick_wait_ms(1000);
84+
systick_wait_ms(100);
8485
display_init();
8586
sp_init();
8687
display_set_auto_update_period(DEFAULT_UPDATE_PERIOD);
@@ -102,7 +103,10 @@ void nxt_deinit() {
102103
shutdown(1);
103104
}
104105

105-
static char *stack_top;
106+
// defined in linker script
107+
extern uint32_t _estack;
108+
extern uint32_t __bss_end__;
109+
106110
#if MICROPY_ENABLE_GC
107111
static char heap[PYBRICKS_HEAP_KB * 1024];
108112
#endif
@@ -143,20 +147,21 @@ static const pbsys_user_program_callbacks_t user_program_callbacks = {
143147
.stdin_event = user_program_stdin_event_func,
144148
};
145149

150+
// Defined in linker script
151+
extern uint32_t _pb_user_mpy_size;
152+
extern uint8_t _pb_user_mpy_data;
153+
146154
int main(int argc, char **argv) {
147-
int stack_dummy;
148-
stack_top = (char *)&stack_dummy;
149155

150156
pbio_init();
151157
nxt_init();
152158

159+
mp_stack_set_top(&_estack);
160+
mp_stack_set_limit((char *)&_estack - (char *)&__bss_end__ - 1024);
161+
153162
#if MICROPY_ENABLE_GC
154163
gc_init(heap, heap + sizeof(heap));
155164
#endif
156-
157-
// (re)boot message
158-
mp_print_str(&mp_plat_print, "Pybricks\n");
159-
160165
// Get system hardware ready
161166
pbsys_user_program_prepare(&user_program_callbacks);
162167
// make sure any pending events are handled before starting MicroPython
@@ -167,11 +172,29 @@ int main(int argc, char **argv) {
167172
mp_init();
168173

169174
// Run a program
170-
// TODO
175+
nlr_buf_t nlr;
176+
if (nlr_push(&nlr) == 0) {
177+
// run user .mpy file
178+
mp_reader_t reader;
179+
mp_reader_new_mem(&reader, &_pb_user_mpy_data, _pb_user_mpy_size, 0);
180+
mp_raw_code_t *raw_code = mp_raw_code_load(&reader);
181+
mp_obj_t module_fun = mp_make_function_from_raw_code(raw_code, MP_OBJ_NULL, MP_OBJ_NULL);
182+
mp_hal_set_interrupt_char(3);
183+
mp_call_function_0(module_fun);
184+
mp_hal_set_interrupt_char(-1);
185+
mp_handle_pending(true);
186+
nlr_pop();
187+
} else {
188+
// uncaught exception
189+
mp_hal_set_interrupt_char(-1); // disable interrupt
190+
mp_handle_pending(false); // clear any pending exceptions (and run any callbacks)
191+
192+
pbsys_user_program_unprepare();
193+
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
194+
}
171195

172196
// Uninitialize MicroPython and the system hardware
173197
mp_deinit();
174-
pbsys_user_program_unprepare();
175198

176199
nxt_deinit();
177200
return 0;

bricks/nxt/main.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from pybricks.tools import wait
2+
from pybricks.nxtdevices import Motor
3+
from pybricks.parameters import Port
4+
5+
motor = Motor(Port.A)
6+
7+
print("1")
8+
9+
motor.dc(50)
10+
wait(1000)
11+
motor.stop()
12+
13+
print("2")

bricks/nxt/mpconfigport.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#define PYBRICKS_PY_COMMON_SYSTEM (1)
2020
#define PYBRICKS_PY_EXPERIMENTAL (0)
2121
#define PYBRICKS_PY_GEOMETRY (0)
22-
#define PYBRICKS_PY_HUBS (1)
22+
#define PYBRICKS_PY_HUBS (0)
2323
#define PYBRICKS_PY_MEDIA (0)
2424
#define PYBRICKS_PY_NXTDEVICES (1)
2525
#define PYBRICKS_PY_PARAMETERS (1)
@@ -49,6 +49,7 @@
4949
#define MICROPY_DEBUG_PRINTERS (0)
5050
#define MICROPY_ENABLE_GC (1)
5151
#define MICROPY_GC_ALLOC_THRESHOLD (0)
52+
#define MICROPY_STACK_CHECK (1)
5253
#define MICROPY_REPL_EVENT_DRIVEN (0)
5354
#define MICROPY_HELPER_REPL (1)
5455
#define MICROPY_HELPER_LEXER_UNIX (0)
@@ -89,6 +90,9 @@
8990
#define MICROPY_ENABLE_SCHEDULER (0)
9091
#define MICROPY_PY_INSTANCE_ATTRS (1)
9192

93+
#define MICROPY_PERSISTENT_CODE_LOAD (1)
94+
#define MICROPY_ENABLE_EXTERNAL_IMPORT (0)
95+
9296
// type definitions for the specific machine
9397

9498
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))

bricks/nxt/nxt.ld

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,24 @@ SECTIONS {
5151
__bss_start__ = ADDR(.bss);
5252
__bss_end__ = ADDR(.bss) + SIZEOF(.bss);
5353

54-
.stack (NOLOAD) : {
55-
*(.stack .stack.*)
54+
.stack :
55+
{
56+
. = ALIGN(4);
57+
. = . + 4K; /* will cause linker error if there is not enough space for stack. */
58+
. = ALIGN(4);
5659
} >RAM
5760

5861
_estack = ADDR(.stack) + SIZEOF(.stack);
5962

63+
.user :
64+
{
65+
. = ALIGN(4);
66+
_pb_user_mpy_size = .;
67+
LONG(SIZEOF(.user) - (. + 4 - LOADADDR(.user))); /* Size of compiled main.mpy file in bytes */
68+
_pb_user_mpy_data = .;
69+
KEEP(*(.mpy)); /* Compiled main.mpy file */
70+
} >ROM
71+
6072
__free_ram_start__ = ALIGN(ADDR(.stack) + SIZEOF(.stack), 16);
6173
__free_ram_end__ = ORIGIN(RAM) + LENGTH(RAM);
6274
}

0 commit comments

Comments
 (0)