@@ -8,13 +8,59 @@ QSTR_DEFS = qstrdefsport.h
88# MicroPython feature configurations
99MICROPY_ROM_TEXT_COMPRESSION ?= 1
1010
11+ # Mode selection (default to REPL_SYSCALL for backwards compatibility)
12+ # Valid values: REPL_SYSCALL, HEADLESS, UART
13+ MODE ?= REPL_SYSCALL
14+
15+ # Script to embed (for HEADLESS and UART modes)
16+ FROZEN_SCRIPT ?= startup.py
17+
18+ # Frozen module support for HEADLESS and UART modes
19+ # HEADLESS mode requires a frozen script
20+ # UART mode optionally accepts a frozen script
21+ ifeq ($(MODE ) ,HEADLESS)
22+ ifeq ($(FROZEN_SCRIPT),)
23+ $(error HEADLESS mode requires FROZEN_SCRIPT to be set)
24+ endif
25+ FROZEN_ENABLED = 1
26+ else ifeq ($(MODE),UART)
27+ ifneq ($(FROZEN_SCRIPT),)
28+ FROZEN_ENABLED = 1
29+ else
30+ FROZEN_ENABLED = 0
31+ endif
32+ else ifeq ($(MODE),REPL_SYSCALL)
33+ FROZEN_ENABLED = 0
34+ else
35+ $(error Invalid MODE=$(MODE ) . Valid values : REPL_SYSCALL, HEADLESS, UART)
36+ endif
37+
38+ ifeq ($(FROZEN_ENABLED ) ,1)
39+ # Module name includes .py extension (manifest system registers with full filename)
40+ FROZEN_MODULE_NAME = $(FROZEN_SCRIPT )
41+
42+ # Use manifest.py for freezing (idiomatic MicroPython approach)
43+ # The manifest file will handle compilation via makemanifest.py
44+ FROZEN_MANIFEST = $(CURDIR ) /manifest.py
45+
46+ # Pass FROZEN_SCRIPT to manifest as a variable
47+ MICROPY_MANIFEST_FROZEN_SCRIPT = $(FROZEN_SCRIPT )
48+ endif
49+
1150# include py core make definitions
1251include $(TOP ) /py/py.mk
1352
1453ifeq ($(CROSS ) , 1)
1554CROSS_COMPILE ?= riscv64-unknown-elf-
1655endif
1756
57+ # MicroPython build tools
58+ MPY_CROSS ?= $(TOP ) /mpy-cross/build/mpy-cross
59+ MPY_TOOL ?= $(PYTHON ) $(TOP ) /tools/mpy-tool.py
60+ # Flags for mpy-cross and mpy-tool to match port configuration
61+ MPY_CROSS_FLAGS += -msmall-int-bits=31
62+ MPY_TOOL_FLAGS += -mlongint-impl=longlong
63+
1864# Extension options - set to 1 to enable, 0 to disable
1965# Note: the toolchain might not support all combinations
2066RVM ?= 1 # Multiply/Divide (M extension)
@@ -34,12 +80,12 @@ ifeq ($(CROSS), 1)
3480DFU = $(TOP ) /tools/dfu.py
3581PYDFU = $(TOP ) /tools/pydfu.py
3682CFLAGS_RISCV = -march=$(MARCH ) -mabi=ilp32 -D_REENT_SMALL
37- CFLAGS += $(INC ) -Wall -Werror -std=c99 $(CFLAGS_RISCV ) $(COPT ) # -O2
83+ CFLAGS += $(INC ) -Wall -Werror -std=c99 $(CFLAGS_RISCV ) $(COPT ) -DMICROPY_PORT_MODE=MODE_ $( MODE )
3884LDFLAGS += -nostartfiles -static -Tlinker_newlib.ld --specs=nosys.specs
3985else
4086UNAME_S := $(shell uname -s)
4187LD = $(CC )
42- CFLAGS += $(INC ) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT )
88+ CFLAGS += $(INC ) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT ) -DMICROPY_PORT_MODE=MODE_ $( MODE )
4389ifeq ($(UNAME_S ) ,Linux)
4490LDFLAGS += -nostartfiles -Wl,--gc-sections -static -Tlinker_newlib.ld --specs=nano.specs -Wl,-map,$@ .map -Wl,-dead_strip
4591else ifeq ($(UNAME_S),Darwin)
@@ -58,17 +104,23 @@ CFLAGS += -O2 -DNDEBUG
58104CFLAGS += -fdata-sections -ffunction-sections
59105endif
60106
107+ # Add frozen module defines when frozen modules are enabled
108+ ifeq ($(FROZEN_ENABLED ) ,1)
109+ CFLAGS += -DFROZEN_MODULE_NAME=\"$(FROZEN_MODULE_NAME ) \"
110+ CFLAGS += -DMICROPY_HAS_FROZEN_MODULES=1
111+ endif
112+
61113# Flags for optional C++ source code
62114CXXFLAGS += $(filter-out -std=c99,$(CFLAGS ) )
63115
64116LIBS = -lm
65117
118+ # Common source files for all build modes
66119SRC_C = \
67120 main.c \
68- minimal_stubs.c \
69121 gccollect.c \
70- mphalport .c \
71- shared/libc/printf.c \
122+ minimal_stubs .c \
123+ shared/libc/printf.c \
72124 shared/readline/readline.c \
73125 shared/runtime/pyexec.c \
74126 shared/runtime/gchelper_native.c \
@@ -77,18 +129,30 @@ SRC_C = \
77129 extmod/machine_mem.c \
78130 extmod/moductypes.c
79131
132+ SRC_S = \
133+ start_newlib.S \
134+ syscalls_newlib.S \
135+ gchelper_rv32i.S
136+
137+ # Select HAL based on build mode
138+ ifeq ($(MODE ) ,REPL_SYSCALL)
139+ # Mode 1: syscall-based I/O
140+ SRC_C += mphalport.c
141+ else ifeq ($(MODE),HEADLESS)
142+ # Mode 2: headless (no stdio)
143+ SRC_C += mphalport_headless.c
144+ else ifeq ($(MODE),UART)
145+ # Mode 3: UART MMIO I/O
146+ SRC_C += mphalport_uart.c
147+ endif
148+
80149ifeq ($(CROSS ) , 1)
81150SRC_C += shared/libc/string0.c
82151endif
83152
84153SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c extmod/modmachine.c extmod/machine_mem.c extmod/moductypes.c
85154
86- SRC_S = \
87- start_newlib.S \
88- syscalls_newlib.S \
89- gchelper_rv32i.S
90-
91- OBJ += $(PY_CORE_O )
155+ OBJ += $(PY_O )
92156OBJ += $(addprefix $(BUILD ) /, $(SRC_C:.c=.o ) )
93157OBJ += $(addprefix $(BUILD ) /, $(SRC_S:.S=.o ) )
94158OBJ += $(addprefix $(BUILD ) /, $(SRC_CXX:.cpp=.o ) )
99163all : $(BUILD ) /firmware.elf
100164endif
101165
102- $( BUILD ) /_frozen_mpy.c : $( TOP ) /tests/frozen/frozentest.mpy $( BUILD ) /genhdr/qstrdefs.generated.h
103- $( ECHO ) " MISC freezing bytecode "
104- $( Q )$( TOP ) /tools/mpy-tool.py -f -q $( BUILD ) /genhdr/qstrdefs.preprocessed.h -mlongint-impl=none $< > $@
166+ # Print build configuration
167+ $(info Building MicroPython port in MODE=$(MODE))
168+
105169
106170$(BUILD ) /firmware.elf : $(OBJ )
107171 $(ECHO ) " LINK $@ "
0 commit comments