Skip to content

Commit 5130b81

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

File tree

11 files changed

+1632
-0
lines changed

11 files changed

+1632
-0
lines changed

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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy