Skip to content

Commit 5ebabcd

Browse files
committed
minimal: Convert "bare-arm" port to "minimal" port.
This enable libc functions, GC, and line-editing function. Also, UART emulation for POSIX systems is added. Emulation build is set as default.
1 parent d511a20 commit 5ebabcd

File tree

5 files changed

+121
-47
lines changed

5 files changed

+121
-47
lines changed

minimal/Makefile

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
include ../py/mkenv.mk
22

3+
CROSS = 0
4+
35
# qstr definitions (must come before including py.mk)
46
QSTR_DEFS = qstrdefsport.h
57

68
# include py core make definitions
79
include ../py/py.mk
810

11+
ifeq ($(CROSS), 1)
912
CROSS_COMPILE = arm-none-eabi-
13+
endif
1014

1115
INC = -I.
1216
INC += -I..
17+
INC += -I../lib/mp-readline
18+
INC += -I$(PY_SRC) -I../stmhal
1319
INC += -I$(BUILD)
1420

21+
ifeq ($(CROSS), 1)
1522
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
1623
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
24+
else
25+
CFLAGS = -m32 $(INC) -Wall -Werror -ansi -std=gnu99 $(COPT)
26+
endif
1727

1828
#Debugging/Optimization
1929
ifeq ($(DEBUG), 1)
@@ -22,15 +32,22 @@ else
2232
CFLAGS += -Os -DNDEBUG
2333
endif
2434

35+
ifeq ($(CROSS), 1)
2536
LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref
37+
else
38+
LD = gcc
39+
LDFLAGS = -m32 -Wl,-Map=$@.map,--cref
40+
endif
2641
LIBS =
2742

2843
SRC_C = \
2944
main.c \
30-
# printf.c \
31-
string0.c \
32-
malloc0.c \
33-
gccollect.c \
45+
uart_core.c \
46+
uart_extra.c \
47+
stmhal/printf.c \
48+
stmhal/string0.c \
49+
stmhal/pyexec.c \
50+
lib/mp-readline/readline.c \
3451

3552
SRC_S = \
3653
# startup_stm32f40xx.s \

minimal/main.c

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include "py/runtime.h"
99
#include "py/repl.h"
1010
#include "py/pfenv.h"
11+
#include "py/gc.h"
12+
#include "pyexec.h"
13+
#include "pybstdio.h"
1114

1215
void do_str(const char *src) {
1316
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
@@ -46,14 +49,31 @@ void do_str(const char *src) {
4649
}
4750
}
4851

52+
static char *stack_top;
53+
static char heap[2048];
54+
4955
int main(int argc, char **argv) {
56+
int stack_dummy;
57+
stack_top = (char*)&stack_dummy;
58+
59+
#if MICROPY_ENABLE_GC
60+
gc_init(heap, heap + sizeof(heap));
61+
#endif
5062
mp_init();
51-
do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\n')");
63+
pyexec_friendly_repl();
64+
//do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')");
5265
mp_deinit();
5366
return 0;
5467
}
5568

5669
void gc_collect(void) {
70+
// WARNING: This gc_collect implementation doesn't try to get root
71+
// pointers from CPU registers, and thus may function incorrectly.
72+
void *dummy;
73+
gc_collect_start();
74+
gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t));
75+
gc_collect_end();
76+
gc_dump_info();
5777
}
5878

5979
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
@@ -83,39 +103,6 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c
83103
}
84104
#endif
85105

86-
/*
87-
int _lseek() {return 0;}
88-
int _read() {return 0;}
89-
int _write() {return 0;}
90-
int _close() {return 0;}
91-
void _exit(int x) {for(;;){}}
92-
int _sbrk() {return 0;}
93-
int _kill() {return 0;}
94-
int _getpid() {return 0;}
95-
int _fstat() {return 0;}
96-
int _isatty() {return 0;}
97-
*/
98-
99-
void *malloc(size_t n) {return NULL;}
100-
void *calloc(size_t nmemb, size_t size) {return NULL;}
101-
void *realloc(void *ptr, size_t size) {return NULL;}
102-
void free(void *p) {}
103-
int printf(const char *m, ...) {return 0;}
104-
void *memcpy(void *dest, const void *src, size_t n) {return NULL;}
105-
int memcmp(const void *s1, const void *s2, size_t n) {return 0;}
106-
void *memmove(void *dest, const void *src, size_t n) {return NULL;}
107-
void *memset(void *s, int c, size_t n) {return NULL;}
108-
int strcmp(const char *s1, const char* s2) {return 0;}
109-
int strncmp(const char *s1, const char* s2, size_t n) {return 0;}
110-
size_t strlen(const char *s) {return 0;}
111-
char *strcat(char *dest, const char *src) {return NULL;}
112-
char *strchr(const char *dest, int c) {return NULL;}
113-
#include <stdarg.h>
114-
int vprintf(const char *format, va_list ap) {return 0;}
115-
int vsnprintf(char *str, size_t size, const char *format, va_list ap) {return 0;}
116-
117-
#undef putchar
118-
int putchar(int c) {return 0;}
119-
int puts(const char *s) {return 0;}
120-
106+
#if !MICROPY_MIN_USE_STDOUT
121107
void _start(void) {main(0, NULL);}
108+
#endif

minimal/mpconfigport.h

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
// options to control how Micro Python is built
44

5-
#define MICROPY_ALLOC_PATH_MAX (512)
5+
#define MICROPY_ALLOC_PATH_MAX (256)
66
#define MICROPY_EMIT_X64 (0)
77
#define MICROPY_EMIT_THUMB (0)
88
#define MICROPY_EMIT_INLINE_THUMB (0)
99
#define MICROPY_COMP_MODULE_CONST (0)
1010
#define MICROPY_COMP_CONST (0)
1111
#define MICROPY_MEM_STATS (0)
1212
#define MICROPY_DEBUG_PRINTERS (0)
13-
#define MICROPY_ENABLE_GC (0)
14-
#define MICROPY_HELPER_REPL (0)
13+
#define MICROPY_ENABLE_GC (1)
14+
#define MICROPY_HELPER_REPL (1)
1515
#define MICROPY_HELPER_LEXER_UNIX (0)
1616
#define MICROPY_ENABLE_SOURCE_LINE (0)
1717
#define MICROPY_ENABLE_DOC_STRING (0)
@@ -41,11 +41,15 @@
4141

4242
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
4343

44-
#define UINT_FMT "%lu"
45-
#define INT_FMT "%ld"
44+
// This port is intended to be 32-bit, but unfortunately, int32_t for
45+
// different targets may be defined in different ways - either as int
46+
// or as long. This requires different printf formatting specifiers
47+
// to print such value. So, we avoid int32_t and use int directly.
48+
#define UINT_FMT "%u"
49+
#define INT_FMT "%d"
50+
typedef int mp_int_t; // must be pointer size
51+
typedef unsigned mp_uint_t; // must be pointer size
4652

47-
typedef int32_t mp_int_t; // must be pointer size
48-
typedef uint32_t mp_uint_t; // must be pointer size
4953
typedef void *machine_ptr_t; // must be of pointer size
5054
typedef const void *machine_const_ptr_t; // must be of pointer size
5155
typedef long mp_off_t;
@@ -57,3 +61,19 @@ extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
5761

5862
// We need to provide a declaration/definition of alloca()
5963
#include <alloca.h>
64+
65+
#define HAL_GetTick() 0
66+
67+
static inline void mp_hal_set_interrupt_char(char c) {}
68+
69+
#define MICROPY_HW_BOARD_NAME "minimal"
70+
#define MICROPY_HW_MCU_NAME "unknown-cpu"
71+
72+
#ifdef __linux__
73+
#define MICROPY_MIN_USE_STDOUT (1)
74+
#endif
75+
76+
#define MP_STATE_PORT MP_STATE_VM
77+
78+
#define MICROPY_PORT_ROOT_POINTERS \
79+
const char *readline_hist[8];

minimal/uart_core.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <unistd.h>
2+
#include "py/mpconfig.h"
3+
4+
/*
5+
* Core UART functions to implement for a port
6+
*/
7+
8+
// Receive single character
9+
int stdin_rx_chr(void) {
10+
unsigned char c = 0;
11+
#if MICROPY_MIN_USE_STDOUT
12+
int r = read(0, &c, 1);
13+
(void)r;
14+
#endif
15+
return c;
16+
}
17+
18+
// Send string of given length
19+
void stdout_tx_strn(const char *str, mp_uint_t len) {
20+
#if MICROPY_MIN_USE_STDOUT
21+
int r = write(1, str, len);
22+
(void)r;
23+
#endif
24+
}

minimal/uart_extra.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <string.h>
2+
#include <unistd.h>
3+
#include "py/mpconfig.h"
4+
#include "pybstdio.h"
5+
6+
/*
7+
* Extra UART functions
8+
* These can be either optimized for a particular port, or reference,
9+
* not very optimal implementation below can be used.
10+
*/
11+
12+
// Send "cooked" string of length, where every occurance of
13+
// LF character is replaced with CR LF.
14+
void stdout_tx_strn_cooked(const char *str, mp_uint_t len) {
15+
while (len--) {
16+
if (*str == '\n') {
17+
stdout_tx_strn("\r", 1);
18+
}
19+
stdout_tx_strn(str++, 1);
20+
}
21+
}
22+
23+
// Send zero-terminated string
24+
void stdout_tx_str(const char *str) {
25+
stdout_tx_strn(str, strlen(str));
26+
}

0 commit comments

Comments
 (0)