Skip to content

Commit 5130b81

Browse files
author
Ilya Dmitrichenko
committed
cortex-m3-qemu: a working port
1 parent ca045d9 commit 5130b81

11 files changed

Lines changed: 1632 additions & 0 deletions

File tree

cortex-m3-qemu/Makefile

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
include ../py/mkenv.mk
2+
-include mpconfigport.mk
3+
4+
# qstr definitions (must come before including py.mk)
5+
QSTR_DEFS = qstrdefsport.h
6+
7+
# include py core make definitions
8+
include ../py/py.mk
9+
10+
CROSS_COMPILE = arm-none-eabi-
11+
12+
CFLAGS_CORTEX_M3 = -mthumb -mcpu=cortex-m3
13+
CFLAGS = -I. -I$(PY_SRC) -Wall -ansi -std=gnu99 $(CFLAGS_CORTEX_M3) $(COPT)
14+
15+
#Debugging/Optimization
16+
ifeq ($(DEBUG), 1)
17+
CFLAGS += -g -DPENDSV_DEBUG
18+
COPT = -O0
19+
else
20+
COPT += -Os -DNDEBUG
21+
endif
22+
23+
#LDFLAGS = --nostdlib -T stm32f405.ld -Map=$(@:.elf=.map) --cref
24+
LDFLAGS = -lm -T generic-m-hosted.ld # -Map=$(@:.elf=.map) --cref
25+
LIBS =
26+
27+
# uncomment this if you want libgcc
28+
#LIBS += $(shell $(CC) -print-libgcc-file-name)
29+
30+
SRC_C = \
31+
help.c \
32+
math.c \
33+
34+
#gccollect.c \
35+
#pyexec.c \
36+
37+
SRC_S = \
38+
gchelper.s \
39+
40+
OBJ =
41+
OBJ += $(PY_O)
42+
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
43+
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
44+
45+
all: $(BUILD)/flash.elf
46+
47+
run:
48+
qemu-system-arm -cpu cortex-m3 -nographic -monitor null -serial null -semihosting -kernel $(BUILD)/flash.elf
49+
50+
$(BUILD)/flash.elf: $(OBJ)
51+
$(Q)$(CC) $(CFLAGS) $(LDFLAGS) main.c -o $@ $(OBJ) $(LIBS)
52+
$(Q)$(SIZE) $@
53+
54+
include ../py/mkrules.mk

cortex-m3-qemu/gccollect.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include <stdio.h>
2+
3+
//#include <stm32f4xx_hal.h>
4+
5+
#include "misc.h"
6+
#include "mpconfig.h"
7+
#include "qstr.h"
8+
#include "obj.h"
9+
#include "gc.h"
10+
#include "gccollect.h"
11+
12+
machine_uint_t gc_helper_get_regs_and_sp(machine_uint_t *regs);
13+
14+
// obsolete
15+
// void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
16+
17+
void gc_collect(void) {
18+
// get current time, in case we want to time the GC
19+
uint32_t start = HAL_GetTick();
20+
21+
// start the GC
22+
gc_collect_start();
23+
24+
// scan everything in RAM before the heap
25+
// this includes the data and bss segments
26+
// TODO possibly don't need to scan data, since all pointers should start out NULL and be in bss
27+
gc_collect_root((void**)&_ram_start, ((uint32_t)&_ebss - (uint32_t)&_ram_start) / sizeof(uint32_t));
28+
29+
// get the registers and the sp
30+
machine_uint_t regs[10];
31+
machine_uint_t sp = gc_helper_get_regs_and_sp(regs);
32+
33+
// trace the stack, including the registers (since they live on the stack in this function)
34+
gc_collect_root((void**)sp, ((uint32_t)&_ram_end - sp) / sizeof(uint32_t));
35+
36+
// end the GC
37+
gc_collect_end();
38+
39+
if (0) {
40+
// print GC info
41+
uint32_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly
42+
gc_info_t info;
43+
gc_info(&info);
44+
printf("GC@%lu %lums\n", start, ticks);
45+
printf(" %lu total\n", info.total);
46+
printf(" %lu : %lu\n", info.used, info.free);
47+
printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
48+
}
49+
}
50+
51+
static mp_obj_t pyb_gc(void) {
52+
gc_collect();
53+
return mp_const_none;
54+
}
55+
56+
MP_DEFINE_CONST_FUN_OBJ_0(pyb_gc_obj, pyb_gc);

cortex-m3-qemu/gccollect.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// variables defining memory layout
2+
// (these probably belong somewhere else...)
3+
extern uint32_t _etext;
4+
extern uint32_t _sidata;
5+
extern uint32_t _ram_start;
6+
extern uint32_t _sdata;
7+
extern uint32_t _edata;
8+
extern uint32_t _sbss;
9+
extern uint32_t _ebss;
10+
extern uint32_t _heap_start;
11+
extern uint32_t _heap_end;
12+
extern uint32_t _estack;
13+
extern uint32_t _ram_end;
14+
15+
void gc_collect(void);
16+
17+
MP_DECLARE_CONST_FUN_OBJ(pyb_gc_obj);

cortex-m3-qemu/gchelper.s

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
.syntax unified
2+
.cpu cortex-m4
3+
.thumb
4+
.text
5+
.align 2
6+
7+
@ uint gc_helper_get_regs_and_sp(r0=uint regs[10])
8+
.global gc_helper_get_regs_and_sp
9+
.thumb
10+
.thumb_func
11+
.type gc_helper_get_regs_and_sp, %function
12+
gc_helper_get_regs_and_sp:
13+
@ store registers into given array
14+
str r4, [r0], #4
15+
str r5, [r0], #4
16+
str r6, [r0], #4
17+
str r7, [r0], #4
18+
str r8, [r0], #4
19+
str r9, [r0], #4
20+
str r10, [r0], #4
21+
str r11, [r0], #4
22+
str r12, [r0], #4
23+
str r13, [r0], #4
24+
25+
@ return the sp
26+
mov r0, sp
27+
bx lr
28+
29+
30+
@ this next function is now obsolete
31+
32+
.size gc_helper_get_regs_and_clean_stack, .-gc_helper_get_regs_and_clean_stack
33+
@ void gc_helper_get_regs_and_clean_stack(r0=uint regs[10], r1=heap_end)
34+
.global gc_helper_get_regs_and_clean_stack
35+
.thumb
36+
.thumb_func
37+
.type gc_helper_get_regs_and_clean_stack, %function
38+
gc_helper_get_regs_and_clean_stack:
39+
@ store registers into given array
40+
str r4, [r0], #4
41+
str r5, [r0], #4
42+
str r6, [r0], #4
43+
str r7, [r0], #4
44+
str r8, [r0], #4
45+
str r9, [r0], #4
46+
str r10, [r0], #4
47+
str r11, [r0], #4
48+
str r12, [r0], #4
49+
str r13, [r0], #4
50+
51+
@ clean the stack from given pointer up to current sp
52+
movs r0, #0
53+
mov r2, sp
54+
b.n .entry
55+
.loop:
56+
str r0, [r1], #4
57+
.entry:
58+
cmp r1, r2
59+
bcc.n .loop
60+
bx lr
61+
62+
.size gc_helper_get_regs_and_clean_stack, .-gc_helper_get_regs_and_clean_stack

cortex-m3-qemu/help.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include <stdio.h>
2+
3+
#include "nlr.h"
4+
#include "misc.h"
5+
#include "mpconfig.h"
6+
#include "qstr.h"
7+
#include "obj.h"
8+
9+
STATIC const char *help_text =
10+
"Welcome to Micro Python!\n"
11+
"\n"
12+
"For online help please visit http://micropython.org/help/.\n"
13+
"\n"
14+
"Specific commands for the board:\n"
15+
" pyb.info() -- print some general information\n"
16+
" pyb.gc() -- run the garbage collector\n"
17+
" pyb.repl_info(val) -- enable/disable printing of info after each command\n"
18+
" pyb.delay(n) -- wait for n milliseconds\n"
19+
" pyb.udelay(n) -- wait for n microseconds\n"
20+
" pyb.switch() -- return True/False if switch pressed or not\n"
21+
" pyb.switch(f) -- call the given function when the switch is pressed\n"
22+
" pyb.Led(n) -- create Led object for LED n (n=1,2,3,4)\n"
23+
" Led methods: on(), off(), toggle(), intensity(<n>)\n"
24+
" pyb.Servo(n) -- create Servo object for servo n (n=1,2,3,4)\n"
25+
" Servo methods: calibrate(...), pulse_width([p]), angle([x, [t]]), speed([x, [t]])\n"
26+
" pyb.Accel() -- create an Accelerometer object\n"
27+
" Accelerometer methods: x(), y(), z(), tilt(), filtered_xyz()\n"
28+
" pyb.rng() -- get a 30-bit hardware random number\n"
29+
" pyb.gpio_in(port, [m]) -- set IO port to input, mode m\n"
30+
" pyb.gpio_out(port, [m]) -- set IO port to output, mode m\n"
31+
" pyb.gpio(port) -- get digital port value\n"
32+
" pyb.gpio(port, val) -- set digital port value, True or False, 1 or 0\n"
33+
" pyb.ADC(port) -- make an analog port object\n"
34+
" ADC methods: read()\n"
35+
"\n"
36+
"Ports are numbered X1-X12, X17-X22, Y1-Y12, or by their MCU name\n"
37+
"Port input modes are: pyb.PULL_NONE, pyb.PULL_UP, pyb.PULL_DOWN\n"
38+
"Port output modes are: pyb.PUSH_PULL, pyb.OPEN_DRAIN\n"
39+
"\n"
40+
"Control commands:\n"
41+
" CTRL-A -- on a blank line, enter raw REPL mode\n"
42+
" CTRL-B -- on a blank line, enter normal REPL mode\n"
43+
" CTRL-C -- interrupt a running program\n"
44+
" CTRL-D -- on a blank line, do a soft reset of the board\n"
45+
"\n"
46+
"For further help on a specific object, type help(obj)\n"
47+
;
48+
49+
STATIC void pyb_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) {
50+
printf(" ");
51+
mp_obj_print(name_o, PRINT_STR);
52+
printf(" -- ");
53+
mp_obj_print(value, PRINT_STR);
54+
printf("\n");
55+
}
56+
57+
STATIC mp_obj_t pyb_help(uint n_args, const mp_obj_t *args) {
58+
if (n_args == 0) {
59+
// print a general help message
60+
printf("%s", help_text);
61+
62+
} else {
63+
// try to print something sensible about the given object
64+
65+
printf("object ");
66+
mp_obj_print(args[0], PRINT_STR);
67+
printf(" is of type %s\n", mp_obj_get_type_str(args[0]));
68+
69+
mp_map_t *map = NULL;
70+
if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) {
71+
map = mp_obj_dict_get_map(mp_obj_module_get_globals(args[0]));
72+
} else {
73+
mp_obj_type_t *type;
74+
if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {
75+
type = args[0];
76+
} else {
77+
type = mp_obj_get_type(args[0]);
78+
}
79+
if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
80+
map = mp_obj_dict_get_map(type->locals_dict);
81+
}
82+
}
83+
if (map != NULL) {
84+
for (uint i = 0; i < map->alloc; i++) {
85+
if (map->table[i].key != MP_OBJ_NULL) {
86+
pyb_help_print_info_about_object(map->table[i].key, map->table[i].value);
87+
}
88+
}
89+
}
90+
}
91+
92+
return mp_const_none;
93+
}
94+
95+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, pyb_help);

0 commit comments

Comments
 (0)