J'y ai soudainement pensé, alors j'ai essayé.
Apportez ce que vous avez fourché sur GitHub et créez même une branche.
git clone [email protected]:ysat0/micropython.git
cd micropython
git checkout -b rx
Obtenez un aperçu approximatif. Tout d'abord, trouvez la partie dépendante du processeur car elle devrait fonctionner pour le moment.
$ ls
ACKNOWLEDGEMENTS CONTRIBUTING.md docs/ extmod/ mpy-cross/ tests/
CODECONVENTIONS.md LICENSE drivers/ lib/ ports/ tools/
CODEOFCONDUCT.md README.md examples/ logo/ py/
Une intuition sauvage m'a dit de regarder les ports, alors je vais y regarder.
$ ls ports
bare-arm/ esp8266/ nrf/ qemu-arm/ teensy/ zephyr/
cc3200/ javascript/ pic16bit/ samd/ unix/
esp32/ minimal/ powerpc/ stm32/ windows/
Il semble bon d'utiliser minimal comme modèle, alors copiez-le.
$ mkdir ports/rx
$ cp -R ports/minimal/* ports/rx
J'ai donc pu le mettre sur une planche à découper.
Maintenant que nous avons préparé un modèle, nous allons étudier sérieusement ce qui arrive aux parties dépendant du processeur.
$ ls ports/rx
Makefile frozentest.mpy main.c mphalport.h stm32f405.ld
README.md frozentest.py mpconfigport.h qstrdefsport.h uart_core.c
Certains peuvent être devinés par le nom du fichier, mais je ne sais pas où le réparer, alors regardez à l'intérieur et vérifiez le but.
nom de fichier | Utilisation | Réparer |
---|---|---|
Makefil | Créer un fichier | Faire |
README.md | La description | N'a pas d'importance |
frozentest.mpy | Résultat de la compilation d'octets de ↓ | ne pas faire |
frozentest.py | Script de test | ne pas faire |
main.c | Initialisation+main | Faire |
mpconfigport.h | Divers réglages | Faire |
mphalport.h | Définition des fonctions dépendant du matériel | Tu n'as pas à |
qstrdefsport.h | Définition spéciale du type qstr | ne pas faire |
stm32f405.ld | Script LD | Faire |
uart_core.c | Entrée / sortie UART | Faire |
Vous n'êtes pas obligé de le réparer autant.
Donc, quand j'ai pensé à le réparer, j'ai remarqué un problème sérieux que je n'avais pas préparé d'environnement de développement (car ce n'est généralement pas pour baremetal), donc je vais le préparer en premier. Il utilise une chaîne d'outils rx-elf normale (binutils + gcc + newlib), alors construisez-la vous-même ou utilisez KPIT.
Je veux l'exécuter avec qemu pour le moment, donc je vais le faire correspondre avec le matériel qui émule qemu. Les spécifications de qemu sont
Cependant, cette fois, je n'utiliserai pas la mémoire externe, mais uniquement la mémoire intégrée du processeur.
Fixez-le comme indiqué dans le tableau ci-dessus. main.c Le code d'origine est également inclus dans main.c comme le traitement de réinitialisation, mais comme il est plus facile de mettre la pièce écrite dans l'assembleur directement dans .s, il est décomposé en crt0.s et main.c.
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
C'est simplement le flux d'initialisation DATA / BSS → initialisation matérielle → main. Il y a beaucoup plus de tables vectorielles, mais comme elles ne devraient pas être appelées s'il n'y a rien, seule la partie réinitialisée est enregistrée.
main.c
(Abréviation)
#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;
}
Identique au main.c d'origine, sauf pour l'initialisation matérielle. C'est également l'initialisation minimale. Pour une raison quelconque, uart_core n'a pas d'initialisation, donc je l'initialise ici. D'ailleurs, écrire en C est la raison pour laquelle écrire dans un assembleur est gênant.
mpconfigport Approprié car je ne sais pas quel paramètre affecte où. C'est aussi la modification minimale nécessaire.
mpconfigport.h
(Abréviation)
#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
Il y a ~ THUMB sur le côté supérieur, mais il semble être invalide, donc je le laisse tel quel.
uart_core.c Responsable des entrées / sorties de bas niveau pour le dialogue. Comme je l'ai écrit ci-dessus, il n'y a pas de partie d'initialisation pour une raison quelconque, et il n'y a qu'un endroit pour entrer et sortir.
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
}
Cela dépend du matériel, donc je le réécris. Cependant, l'utilisation d'UART est presque la même, donc cela ne change pas beaucoup.
ldscript Comme prévu, stm32 ~ est déroutant, je vais donc changer le nom. Cela dépend également du matériel, je vais donc le réparer. Cela dit, ce n'est pas trop compliqué car il alloue simplement text / data / bss à la mémoire interne correctement. Si vous voulez l'exécuter avec R5F562N7, qui est largement disponible dans le monde, vous devez corriger FLASH et RAM de manière appropriée.
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
}
Au fait, le nom de section unique est la spécification rx-elf. Cependant, le fait que la réponse soit à mi-chemin est gênant.
Makefile Modifiez les options de construction ou ajoutez crt0. J'ai pensé que je le ferais, mais on m'a demandé setjmp / longjmp, donc j'ai lié libc facilement. S'il s'agissait de setjmp, j'aurais pu le préparer moi-même, mais il était difficile de chercher la définition de jmpbuf, alors c'est arrivé.
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
Après cela, j'ai pensé que le déploiement serait laissé, mais je n'en avais pas besoin séparément pour qemu, et je l'ai supprimé car il n'y avait pas de programme d'écriture approprié de make. Je m'en suis souvenu, mais il y a ceci, donc si vous voulez vraiment l'utiliser, veuillez l'utiliser (en faire la publicité) Garde le).
Docilement
make cross=1
Vous pouvez le faire avec.
Maintenant que c'est fait, déplaçons-le.
qemu-system-rx -bios build/mpyton.bin
Commencez par et basculez l'écran sur le port série![Start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316355/1e891cb0-37a4-f9e6 -639a-5dc4a33328b5.png)
Quelque chose fonctionne, et si vous le saisissez correctement, vous pouvez le saisir![Print.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316355/076e4079-0cd8-8495 -7206-9a2098799ad2.png)
J'obtiendrai une réponse appropriée, alors peut-être que cela fonctionnera comme il se doit.
# fin
Donc, si vous le déplacez pour le moment, c'est assez facile à faire.
Peut-être qu'il est temps de corriger le code <temps de préparer l'environnement de développement.
Je pense que je dois préparer plus de pilotes pour pouvoir l'utiliser correctement, mais j'étais satisfait de l'endroit où cela fonctionnait avec qemu, donc le calendrier futur est indécis.