Ich dachte plötzlich daran, also versuchte ich es.
Bringen Sie, was Sie auf GitHub gegabelt haben, und machen Sie sogar einen Zweig.
git clone [email protected]:ysat0/micropython.git
cd micropython
git checkout -b rx
Verschaffen Sie sich einen groben Überblick. Suchen Sie zunächst den CPU-abhängigen Teil, da dieser vorerst funktionieren sollte.
$ ls
ACKNOWLEDGEMENTS CONTRIBUTING.md docs/ extmod/ mpy-cross/ tests/
CODECONVENTIONS.md LICENSE drivers/ lib/ ports/ tools/
CODEOFCONDUCT.md README.md examples/ logo/ py/
Wilde Intuition sagte mir, ich solle mir Häfen ansehen, also werde ich dort nachsehen.
$ ls ports
bare-arm/ esp8266/ nrf/ qemu-arm/ teensy/ zephyr/
cc3200/ javascript/ pic16bit/ samd/ unix/
esp32/ minimal/ powerpc/ stm32/ windows/
Es scheint gut, minimal als Vorlage zu verwenden, also kopieren Sie es.
$ mkdir ports/rx
$ cp -R ports/minimal/* ports/rx
Also konnte ich es auf ein Schneidebrett legen.
Nachdem wir eine Vorlage vorbereitet haben, werden wir ernsthaft untersuchen, was mit den CPU-abhängigen Teilen passiert.
$ ls ports/rx
Makefile frozentest.mpy main.c mphalport.h stm32f405.ld
README.md frozentest.py mpconfigport.h qstrdefsport.h uart_core.c
Einige können anhand des Dateinamens erraten werden, aber ich weiß nicht, wo ich das Problem beheben soll. Schauen Sie also hinein und überprüfen Sie den Zweck.
Dateiname | Verwenden | Fix |
---|---|---|
Makefil | Datei erstellen | Machen |
README.md | Erläuterung | Macht nichts |
frozentest.mpy | Ergebnis der Bytekompilierung von ↓ | TU es nicht |
frozentest.py | Testskript | TU es nicht |
main.c | Initialisieren+main | Machen |
mpconfigport.h | Verschiedene Einstellungen | Machen |
mphalport.h | Definition hardwareabhängiger Funktionen | Das musst du nicht |
qstrdefsport.h | Spezielle Definition des qstr-Typs | TU es nicht |
stm32f405.ld | LD-Skript | Machen |
uart_core.c | UART-Ein- / Ausgang | Machen |
Sie müssen es nicht so sehr reparieren.
Als ich darüber nachdachte, es zu beheben, bemerkte ich ein ernstes Problem, dass ich keine Entwicklungsumgebung vorbereitet habe (weil es normalerweise nicht für Baremetall ist), also werde ich es zuerst vorbereiten. Es verwendet eine normale RX-Elf-Toolchain (binutils + gcc + newlib). Erstellen Sie sie also selbst oder verwenden Sie KPITs.
Ich möchte es vorerst mit qemu ausführen, daher werde ich es mit der Hardware abgleichen, die qemu emuliert. Die Spezifikationen von Qemu sind
Dieses Mal werde ich jedoch nicht den externen Speicher verwenden, sondern nur den in die CPU integrierten Speicher.
Beheben Sie das Problem wie in der obigen Tabelle gezeigt. main.c Der ursprüngliche Code ist auch in main.c enthalten, z. B. beim Zurücksetzen. Da es jedoch einfacher ist, den vom Assembler geschriebenen Teil gehorsam in .s einzufügen, wird er in crt0.s und main.c. zerlegt.
crt0.s
.global _start
.section ".vector","ax"
.long _start
.text
_start:
mov #_estack, r0
mov #_sdata,r1
mov #_edata,r3
sub r1,r3
mov #_etext,r2
smovf
mov #_sbss,r1
mov #_ebss,r3
sub r1,r3
mov #0,r2
sstr
bsr _rx62n_init
sub r1,r1
sub r2,r2
bsr _main
bra .
.end
Es ist einfach der Ablauf der DATA / BSS-Initialisierung → Hardware-Initialisierung → main. Es gibt viel mehr Vektortabellen, aber da sie nicht aufgerufen werden sollten, wenn nichts vorhanden ist, wird nur der Rücksetzteil registriert.
main.c
(Abkürzung)
#define SCKCR 0x00080020
#define MSTPCRB 0x00080014
#define SCR0 0x00088242
#define SMR0 0x00088240
#define BRR0 0x00088241
void rx62n_init(void) {
/* CPG Initialize */
/* XTAL:12MHz, ICLK:96MHz (x8), PCLK:48MHz (x4) */
*((volatile unsigned long *)SCKCR) = 0x00010100;
/* SCI0 enable */
*((volatile unsigned long *)MSTPCRB) &= ~0x80000000;
/* SCI0 Initialize */
*((volatile unsigned char *)SCR0) = 0x00;
*((volatile unsigned char *)SMR0) = 0x01;
*((volatile unsigned char *)BRR0) = 39; /* 9600 bps */
*((volatile unsigned char *)SCR0) = 0x30;
}
Entspricht der ursprünglichen main.c mit Ausnahme der Hardware-Initialisierung. Dies ist auch die minimale Initialisierung. Aus irgendeinem Grund hat uart_core keine Initialisierung, daher initialisiere ich sie hier. Das Schreiben in C ist übrigens der Grund, warum das Schreiben in einem Assembler problematisch ist.
mpconfigport Geeignet, da ich nicht sicher bin, welche Einstellung wo wirkt. Dies ist auch die minimal notwendige Änderung.
mpconfigport.h
(Abkürzung)
#define MICROPY_HW_BOARD_NAME "minimal"
#define MICROPY_HW_MCU_NAME "Renesas RX"
#ifdef __linux__
#define MICROPY_MIN_USE_STDOUT (1)
#endif
#ifdef __RX__
#define MICROPY_MIN_USE_RX_CPU (1)
#endif
Es gibt ~ THUMB auf der Oberseite, aber es scheint ungültig zu sein, also lasse ich es so wie es ist.
uart_core.c Verantwortlich für die Eingabe / Ausgabe auf niedriger Ebene für den Dialog. Wie ich oben geschrieben habe, gibt es aus irgendeinem Grund keinen Initialisierungsteil, und es gibt nur einen Ort, an dem tatsächlich eingegeben und ausgegeben werden kann.
uart_core.c
#include <unistd.h>
#include "py/mpconfig.h"
/*
* Core UART functions to implement for a port
*/
#if MICROPY_MIN_USE_RX_CPU
#define TDR0 0x00088243
#define SSR0 0x00088244
#define RDR0 0x00088245
#define SSR_TDRE (1 << 7)
#define SSR_RDRF (1 << 6)
#endif
// Receive single character
int mp_hal_stdin_rx_chr(void) {
unsigned char c = 0;
#if MICROPY_MIN_USE_STDOUT
int r = read(0, &c, 1);
(void)r;
#elif MICROPY_MIN_USE_RX_CPU
// wait for RDRF
while ((*(volatile unsigned char *)SSR0 & SSR_RDRF) == 0) {
}
c = *(volatile unsigned char *)RDR0;
#endif
return c;
}
// Send string of given length
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
#if MICROPY_MIN_USE_STDOUT
int r = write(1, str, len);
(void)r;
#elif MICROPY_MIN_USE_RX_CPU
while (len--) {
// wait for TDRE
while ((*(volatile unsigned char *)SSR0 & SSR_TDRE) == 0) {
}
*(volatile unsigned char *)TDR0 = *str++;
}
#endif
}
Dies ist hardwareabhängig, daher schreibe ich es neu. Die Verwendung von UART ist jedoch nahezu identisch, sodass sich nicht viel ändert.
ldscript Wie erwartet ist stm32 ~ verwirrend, daher werde ich den Namen ändern. Dies ist auch hardwareabhängig, daher werde ich es beheben. Das heißt, es ist kein allzu großer Aufwand, da nur Text / Daten / BSS dem internen Speicher ordnungsgemäß zugewiesen werden. Wenn Sie es mit R5F562N7 ausführen möchten, das weltweit verfügbar ist, sollten Sie FLASH und RAM entsprechend reparieren.
rx62n.ld
/*
GNU linker script for RX62N
*/
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0xfff80000, LENGTH = 0x00080000 - 0x4 /* 512 KiB
*/
VECTOR (r) : ORIGIN = 0xfffffffc, LENGTH = 0x0000004
RAM (xrw) : ORIGIN = 0x00000000, LENGTH = 0x00018000 /* 96 KiB */
}
/* top end of the stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);
/* define output sections */
SECTIONS
{
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text.startup)
*(P)
*(C)
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
_etext = .; /* define a global symbol at end of code */
_sidata = _etext; /* This is used by the startup in order to initialize the .data secion */
} >FLASH
.vector :
{
*(.vector)
} > VECTOR
/* This is the initialized data section
The program executes knowing that the data is in the RAM
but the loader puts the initial values in the FLASH (inidata).
It is one task of the startup to copy the initial values from FLASH to RAM.
*/
.data : AT ( _sidata )
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
*(D*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
} >RAM
/* Uninitialized data section */
.bss :
{
. = ALIGN(4);
_sbss = .; /* define a global symbol at bss start; used by startup code */
*(B*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end; used by startup code */
} >RAM
}
Der eindeutige Abschnittsname ist übrigens die RX-Elf-Spezifikation. Die Tatsache, dass die Antwort auf halbem Weg ist, ist jedoch problematisch.
Makefile Ändern Sie die Build-Optionen oder fügen Sie crt0 hinzu. Ich dachte, ich würde es tun, aber ich wurde nach setjmp / longjmp gefragt, also habe ich libc einfach verlinkt. Wenn es um setjmp ging, hätte ich es selbst vorbereiten können, aber es war mühsam, die Definition von jmpbuf nachzuschlagen, also geschah dies.
include ../../py/mkenv.mk
CROSS = 0
TARGET = mpython
# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h
# include py core make definitions
include $(TOP)/py/py.mk
ifeq ($(CROSS), 1)
CROSS_COMPILE ?= rx-elf-
endif
INC += -I.
INC += -I$(TOP)
INC += -I$(BUILD)
ifeq ($(CROSS), 1)
CFLAGS_RX = -fsingle-precision-constant -Wdouble-promotion
CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_RX) $(COPT)
LIBC = $(shell $(CROSS_COMPILE)gcc -print-file-name=libc.a)
LDFLAGS = -T rx62n.ld [email protected] -L $(dir $(LIBC))
else
CFLAGS = -m32 $(INC) -Wall -Werror -std=c99 $(COPT)
LDFLAGS = -m32 -Wl,[email protected],--cref -Wl,--gc-sections
endif
CSUPEROPT = -Os # save some code space
# Tune for Debugging or Optimization
ifeq ($(DEBUG), 1)
CFLAGS += -O0 -ggdb
else
CFLAGS += -Os -DNDEBUG
endif
LIBS = -l c
SRC_C = \
main.c \
uart_core.c \
lib/utils/printf.c \
lib/utils/stdout_helpers.c \
lib/utils/pyexec.c \
lib/libc/string0.c \
lib/mp-readline/readline.c \
$(BUILD)/_frozen_mpy.c
SRC_S = crt0.s
OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
ifeq ($(CROSS), 1)
all: $(BUILD)/$(TARGET).bin
else
all: $(BUILD)/$(TARGET).elf
endif
$(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h
$(ECHO) "MISC freezing bytecode"
$(Q)$(TOP)/tools/mpy-tool.py -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=none $< > $@
$(BUILD)/$(TARGET).elf: $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
$(Q)$(SIZE) $@
$(BUILD)/$(TARGET).bin: $(BUILD)/$(TARGET).elf
$(Q)$(OBJCOPY) -O binary -j .vector -j .text -j .data $^ $@
$(BUILD)/$(TARGET).srec: $(BUILD)/$(TARGET).elf
$(Q)$(OBJCOPY) -O srec -j .vector -j .text -j .data $^ $@
include $(TOP)/py/mkrules.mk
Danach dachte ich, dass die Bereitstellung übrig bleiben würde, aber ich brauchte sie nicht separat für qemu und löschte sie, weil es kein geeignetes Schreibprogramm von make gab. Ich habe mich daran erinnert, aber es gibt dies. Wenn Sie es also wirklich verwenden möchten, verwenden Sie es bitte (machen Sie Werbung). Behalte es).
Gehorsam
make cross=1
Du kannst es schaffen mit.
Jetzt, wo es fertig ist, lass es uns bewegen.
qemu-system-rx -bios build/mpyton.bin
Beginnen Sie mit und schalten Sie den Bildschirm auf die serielle Schnittstelle![Start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316355/1e891cb0-37a4-f9e6 -639a-5dc4a33328b5.png)
Etwas funktioniert, und wenn Sie es richtig eingeben, wird es sein![Print.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316355/076e4079-0cd8-8495 -7206-9a2098799ad2.png)
Ich werde eine richtige Antwort bekommen, also wird es vielleicht so funktionieren, wie es sollte.
# Ende
Wenn Sie es also vorerst verschieben, ist es ziemlich einfach.
Vielleicht Zeit, den Code zu reparieren <Zeit, um die Entwicklungsumgebung vorzubereiten.
Ich denke, ich muss mehr Treiber vorbereiten, damit ich es richtig verwenden kann, aber ich war zufrieden mit dem Ort, an dem es mit qemu funktioniert hat, so dass der zukünftige Zeitplan unentschlossen ist.