Browse Source

powerpc: Add initial port to bare metal PowerPC arch.

Runs in microwatt (GHDL and FPGA) and qemu.

Port done initially by Michael Neuling, with help from Anton Blanchard and
Jordan Niethe.
pull/5252/head
Michael Neuling 5 years ago
committed by Damien George
parent
commit
079cc940a6
  1. 9
      .travis.yml
  2. 64
      ports/powerpc/Makefile
  3. 40
      ports/powerpc/README.md
  4. BIN
      ports/powerpc/frozentest.mpy
  5. 7
      ports/powerpc/frozentest.py
  6. 121
      ports/powerpc/head.S
  7. 139
      ports/powerpc/main.c
  8. 123
      ports/powerpc/mpconfigport.h
  9. 45
      ports/powerpc/mphalport.h
  10. 13
      ports/powerpc/powerpc.lds
  11. 1
      ports/powerpc/qstrdefsport.h
  12. 73
      ports/powerpc/uart_core.c
  13. 111
      ports/powerpc/uart_lpc_serial.c
  14. 29
      ports/powerpc/uart_lpc_serial.h
  15. 121
      ports/powerpc/uart_potato.c
  16. 29
      ports/powerpc/uart_potato.h
  17. 36
      ports/powerpc/unistd.h
  18. 4
      py/nlr.h
  19. 121
      py/nlrpowerpc.c
  20. 1
      py/py.mk

9
.travis.yml

@ -232,3 +232,12 @@ jobs:
- sudo apt-get install libnewlib-arm-none-eabi
script:
- make ${MAKEOPTS} -C ports/teensy
# powerpc port
- stage: test
env: NAME="powerpc port build"
install:
- sudo apt-get install gcc-powerpc64le-linux-gnu
- sudo apt-get install libc6-dev-ppc64el-cross
script:
- make ${MAKEOPTS} -C ports/powerpc CROSS_COMPILE=powerpc64le-linux-gnu-

64
ports/powerpc/Makefile

@ -0,0 +1,64 @@
include ../../py/mkenv.mk
# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h
# include py core make definitions
include $(TOP)/py/py.mk
ARCH = $(shell uname -m)
ifneq ("$(ARCH)", "ppc64")
ifneq ("$(ARCH)", "ppc64le")
CROSS_COMPILE = powerpc64le-linux-
endif
endif
INC += -I.
INC += -I$(TOP)
INC += -I$(BUILD)
CFLAGS = $(INC) -g -Wall -std=c99 $(COPT)
CFLAGS += -mno-string -mno-multiple -mno-vsx -mno-altivec -nostdlib
CFLAGS += -mlittle-endian -mstrict-align -msoft-float
CFLAGS += -Os
CFLAGS += -fdata-sections -ffunction-sections -fno-stack-protector -ffreestanding
CFLAGS += -U_FORTIFY_SOURCE
LDFLAGS = -N -T powerpc.lds -nostdlib
LIBS =
SRC_C = \
main.c \
uart_core.c \
uart_potato.c \
uart_lpc_serial.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 \
OBJ = $(PY_CORE_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(BUILD)/head.o
all: $(BUILD)/firmware.elf $(BUILD)/firmware.map $(BUILD)/firmware.bin
$(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h
$(ECHO) "MISC freezing bytecode"
$(Q)$(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=mpz $< > $@
$(BUILD)/firmware.elf: $(OBJ) powerpc.lds
$(ECHO) "LINK $@"
$(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
$(Q)$(SIZE) $@
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(Q)$(OBJCOPY) -O binary $^ $(BUILD)/firmware.bin
$(BUILD)/firmware.map: $(BUILD)/firmware.elf
$(Q)nm $^ | sort > $(BUILD)/firmware.map
include $(TOP)/py/mkrules.mk

40
ports/powerpc/README.md

@ -0,0 +1,40 @@
# The PowerPC port that runs on microwatt and qemu
This port is intended to be a minimal MicroPython port that runs in
QEMU, microwatt simulator with ghdl or microwatt on Xilinx FPGA with
potato UART.
## Building
By default the port will be built for the host machine:
$ make
## Cross compilation for POWERPC
If you need to cross compilers you'll want to grab a powerpc64le
compiler (not powerpc or powerpc64).
On Ubuntu (18.04) you'll want:
$ apt install gcc-powerpc64le-linux-gnu
*(Use CROSS_COMPILE=powerpc64le-linux-gnu-)*
If your distro doesn't have cross compilers, you can get cross compilers here:
- https://toolchains.bootlin.com/
*(use CROSS_COMPILE=powerpc64le-buildroot-linux-gnu-)*
(Avoid musl libc as it defines __assert_fail() differently to glibc
which breaks the micropython powerpc code)
Then do:
$ make CROSS_COMPILE=<compiler prefix>
Building will produce the build/firmware.bin file which can be used
QEMU or [microwatt](https://github.com/antonblanchard/microwatt).
To run in QEMU use:
$ ./qemu-system-ppc64 -M powernv -cpu POWER9 -nographic -bios build/firmware.bin

BIN
ports/powerpc/frozentest.mpy

Binary file not shown.

7
ports/powerpc/frozentest.py

@ -0,0 +1,7 @@
print('uPy')
print('a long string that is not interned')
print('a string that has unicode αβγ chars')
print(b'bytes 1234\x01')
print(123456789)
for i in range(4):
print(i)

121
ports/powerpc/head.S

@ -0,0 +1,121 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#define STACK_TOP 0x60000
#define FIXUP_ENDIAN \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
b 191f; /* Skip trampoline if endian is good */ \
.long 0xa600607d; /* mfmsr r11 */ \
.long 0x01006b69; /* xori r11,r11,1 */ \
.long 0x05009f42; /* bcl 20,31,$+4 */ \
.long 0xa602487d; /* mflr r10 */ \
.long 0x14004a39; /* addi r10,r10,20 */ \
.long 0xa64b5a7d; /* mthsrr0 r10 */ \
.long 0xa64b7b7d; /* mthsrr1 r11 */ \
.long 0x2402004c; /* hrfid */ \
191:
/* Load an immediate 64-bit value into a register */
#define LOAD_IMM64(r, e) \
lis r,(e)@highest; \
ori r,r,(e)@higher; \
rldicr r,r, 32, 31; \
oris r,r, (e)@h; \
ori r,r, (e)@l;
.section ".head","ax"
/*
* Microwatt comes in at 0 as little endian so we do not need to worry up
* FIXUP_ENDIAN.
*/
. = 0
.global _start
_start:
b boot_entry
/* QEMU comes in at 0x10. Put a value in argc/r3 to distingush from
* microwatt. */
. = 0x10
FIXUP_ENDIAN
LOAD_IMM64(%r3, 1)
b boot_entry
.global boot_entry
boot_entry:
/* Save R3 to non-volatile register */
mr %r14, %r3
restart:
/*
* setup stack with a safety gap, since we might write to the
* previous frame.
*/
LOAD_IMM64(%r1, STACK_TOP - 0x100)
LOAD_IMM64(%r12, main)
mtctr %r12
bctrl
/* On exit, restart */
mr %r3, %r14
b restart
#define EXCEPTION(nr) \
.= nr; \
b .
/* More exception stubs */
EXCEPTION(0x300)
EXCEPTION(0x380)
EXCEPTION(0x400)
EXCEPTION(0x480)
EXCEPTION(0x500)
EXCEPTION(0x600)
EXCEPTION(0x700)
EXCEPTION(0x800)
EXCEPTION(0x900)
EXCEPTION(0x980)
EXCEPTION(0xa00)
EXCEPTION(0xb00)
EXCEPTION(0xc00)
EXCEPTION(0xd00)
EXCEPTION(0xe00)
EXCEPTION(0xe20)
EXCEPTION(0xe40)
EXCEPTION(0xe60)
EXCEPTION(0xe80)
EXCEPTION(0xf00)
EXCEPTION(0xf20)
EXCEPTION(0xf40)
EXCEPTION(0xf60)
EXCEPTION(0xf80)
EXCEPTION(0x1000)
EXCEPTION(0x1100)
EXCEPTION(0x1200)
EXCEPTION(0x1300)
EXCEPTION(0x1400)
EXCEPTION(0x1500)
EXCEPTION(0x1600)

139
ports/powerpc/main.c

@ -0,0 +1,139 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include "py/compile.h"
#include "py/runtime.h"
#include "py/repl.h"
#include "py/gc.h"
#include "py/mperrno.h"
#include "py/stackctrl.h"
#include "lib/utils/pyexec.h"
void __stack_chk_fail(void);
void __stack_chk_fail(void) {
static bool failed_once;
if (failed_once) {
return;
}
failed_once = true;
printf("Stack corruption detected !\n");
assert(0);
}
/* fill in __assert_fail for libc */
void __assert_fail(const char *__assertion, const char *__file,
unsigned int __line, const char *__function) {
printf("Assert at %s:%d:%s() \"%s\" failed\n", __file, __line, __function, __assertion);
for (;;) ;
}
static char *stack_top;
#if MICROPY_ENABLE_GC
static char heap[32 * 1024];
#endif
extern void uart_init_ppc(int qemu);
int main(int argc, char **argv) {
int stack_dummy;
stack_top = (char*)&stack_dummy;
// microwatt has argc/r3 = 0 whereas QEMU has r3 set in head.S
uart_init_ppc(argc);
#if MICROPY_ENABLE_PYSTACK
static mp_obj_t pystack[1024];
mp_pystack_init(pystack, &pystack[1024]);
#endif
#if MICROPY_STACK_CHECK
mp_stack_ctrl_init();
mp_stack_set_limit(48 * 1024);
#endif
#if MICROPY_ENABLE_GC
gc_init(heap, heap + sizeof(heap));
#endif
mp_init();
#if MICROPY_ENABLE_COMPILER
#if MICROPY_REPL_EVENT_DRIVEN
pyexec_event_repl_init();
for (;;) {
int c = mp_hal_stdin_rx_chr();
if (pyexec_event_repl_process_char(c)) {
break;
}
}
#else
pyexec_friendly_repl();
#endif
#else
pyexec_frozen_module("frozentest.py");
#endif
mp_deinit();
return 0;
}
void gc_collect(void) {
// WARNING: This gc_collect implementation doesn't try to get root
// pointers from CPU registers, and thus may function incorrectly.
void *dummy;
gc_collect_start();
gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t));
gc_collect_end();
gc_dump_info();
}
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
mp_raise_OSError(MP_ENOENT);
}
mp_import_stat_t mp_import_stat(const char *path) {
return MP_IMPORT_STAT_NO_EXIST;
}
mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
void nlr_jump_fail(void *val) {
while (1);
}
void NORETURN __fatal_error(const char *msg) {
while (1);
}
#ifndef NDEBUG
void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
__fatal_error("Assertion failed");
}
#endif

123
ports/powerpc/mpconfigport.h

@ -0,0 +1,123 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdint.h>
// options to control how MicroPython is built
// You can disable the built-in MicroPython compiler by setting the following
// config option to 0. If you do this then you won't get a REPL prompt, but you
// will still be able to execute pre-compiled scripts, compiled with mpy-cross.
#define MICROPY_ENABLE_COMPILER (1)
//#define MICROPY_DEBUG_VERBOSE (1)
#define MICROPY_QSTR_BYTES_IN_HASH (1)
#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool
#define MICROPY_ALLOC_PATH_MAX (256)
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16)
#define MICROPY_EMIT_X64 (0)
#define MICROPY_EMIT_THUMB (0)
#define MICROPY_EMIT_INLINE_THUMB (0)
#define MICROPY_COMP_MODULE_CONST (0)
#define MICROPY_COMP_CONST (0)
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0)
#define MICROPY_MEM_STATS (0)
#define MICROPY_DEBUG_PRINTERS (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_STACK_CHECK (1)
#define MICROPY_GC_ALLOC_THRESHOLD (0)
#define MICROPY_REPL_EVENT_DRIVEN (0)
#define MICROPY_HELPER_REPL (1)
#define MICROPY_HELPER_LEXER_UNIX (0)
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_ENABLE_DOC_STRING (0)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0)
#define MICROPY_PY_ASYNC_AWAIT (0)
#define MICROPY_MODULE_BUILTIN_INIT (1)
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
#define MICROPY_PY_BUILTINS_DICT_FROMKEYS (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_ENUMERATE (1)
#define MICROPY_PY_BUILTINS_FILTER (1)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_REVERSED (1)
#define MICROPY_PY_BUILTINS_SET (1)
#define MICROPY_PY_BUILTINS_SLICE (1)
#define MICROPY_PY_BUILTINS_PROPERTY (1)
#define MICROPY_PY_BUILTINS_MIN_MAX (1)
#define MICROPY_PY_BUILTINS_STR_COUNT (1)
#define MICROPY_PY_BUILTINS_STR_OP_MODULO (1)
#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
#define MICROPY_PY___FILE__ (0)
#define MICROPY_PY_GC (1)
#define MICROPY_PY_ARRAY (1)
#define MICROPY_PY_COLLECTIONS (1)
#define MICROPY_PY_MATH (0)
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_IO (0)
#define MICROPY_PY_STRUCT (1)
#define MICROPY_PY_SYS (1)
#define MICROPY_MODULE_FROZEN_MPY (1)
#define MICROPY_CPYTHON_COMPAT (0)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
#define MICROPY_ENABLE_PYSTACK (1)
#define MICROPY_USE_INTERNAL_PRINTF (1)
// type definitions for the specific machine
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
// This port is 64-bit
#define UINT_FMT "%lu"
#define INT_FMT "%ld"
typedef signed long mp_int_t; // must be pointer size
typedef unsigned long mp_uint_t; // must be pointer size
typedef long mp_off_t;
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
// extra built in names to add to the global namespace
#define MICROPY_PORT_BUILTINS \
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) },
#define MICROPY_HW_BOARD_NAME "bare-metal"
#define MICROPY_HW_MCU_NAME "POWERPC"
#define MP_STATE_PORT MP_STATE_VM
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[8];
// powerpc64 gcc doesn't seem to define these
// These are pointers, so make them 64 bit types
typedef long intptr_t;
typedef unsigned long uintptr_t;

45
ports/powerpc/mphalport.h

@ -0,0 +1,45 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#define mftb() ({unsigned long rval; \
__asm__ volatile("mftb %0" : "=r" (rval)); rval;})
#define TBFREQ 512000000
static inline mp_uint_t mp_hal_ticks_ms(void) {
unsigned long tb = mftb();
return tb * 1000 / TBFREQ;
}
static inline mp_uint_t mp_hal_ticks_us(void) {
unsigned long tb = mftb();
return tb * 1000000 / TBFREQ;
}
static inline void mp_hal_set_interrupt_char(char c) {
}

13
ports/powerpc/powerpc.lds

@ -0,0 +1,13 @@
SECTIONS
{
. = 0;
_start = .;
.head : {
KEEP(*(.head))
}
/* Put this at 0x1700 which is right after our execption
* vectors in head.S.
*/
. = 0x1700;
}

1
ports/powerpc/qstrdefsport.h

@ -0,0 +1 @@
// qstrs specific to this port

73
ports/powerpc/uart_core.c

@ -0,0 +1,73 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <unistd.h>
#include <stdbool.h>
#include "py/mpconfig.h"
#include "uart_potato.h"
#include "uart_lpc_serial.h"
static int lpc_console;
static int potato_console;
void uart_init_ppc(int lpc) {
lpc_console = lpc;
if (!lpc_console) {
potato_console = 1;
potato_uart_init();
} else {
lpc_uart_init();
}
}
// Receive single character
int mp_hal_stdin_rx_chr(void) {
unsigned char c = 0;
if (lpc_console) {
c = lpc_uart_read();
} else if (potato_console) {
c = potato_uart_read();
}
return c;
}
// Send string of given length
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
if (lpc_console) {
int i;
for (i = 0; i < len; i++) {
lpc_uart_write(str[i]);
}
} else if (potato_console) {
int i;
for (i = 0; i < len; i++) {
potato_uart_write(str[i]);
}
}
}

111
ports/powerpc/uart_lpc_serial.c

@ -0,0 +1,111 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This is the LPC serial UART used by POWER9 boxes. This is modelled
* in the qemu POWER9 machine.
*/
#include <unistd.h>
#include <stdbool.h>
#include "py/mpconfig.h"
#define PROC_FREQ 50000000
#define UART_FREQ 115200
#define UART_BASE 0xc0002000
#define LPC_UART_BASE 0x60300d00103f8
/* Taken from skiboot */
#define REG_RBR 0
#define REG_THR 0
#define REG_DLL 0
#define REG_IER 1
#define REG_DLM 1
#define REG_FCR 2
#define REG_IIR 2
#define REG_LCR 3
#define REG_MCR 4
#define REG_LSR 5
#define REG_MSR 6
#define REG_SCR 7
#define LSR_DR 0x01 /* Data ready */
#define LSR_OE 0x02 /* Overrun */
#define LSR_PE 0x04 /* Parity error */
#define LSR_FE 0x08 /* Framing error */
#define LSR_BI 0x10 /* Break */
#define LSR_THRE 0x20 /* Xmit holding register empty */
#define LSR_TEMT 0x40 /* Xmitter empty */
#define LSR_ERR 0x80 /* Error */
#define LCR_DLAB 0x80 /* DLL access */
#define IER_RX 0x01
#define IER_THRE 0x02
#define IER_ALL 0x0f
static uint64_t lpc_uart_base;
static void lpc_uart_reg_write(uint64_t offset, uint8_t val) {
uint64_t addr;
addr = lpc_uart_base + offset;
*(volatile uint8_t *)addr = val;
}
static uint8_t lpc_uart_reg_read(uint64_t offset) {
uint64_t addr;
uint8_t val;
addr = lpc_uart_base + offset;
val = *(volatile uint8_t *)addr;
return val;
}
static int lpc_uart_tx_full(void) {
return !(lpc_uart_reg_read(REG_LSR) & LSR_THRE);
}
static int lpc_uart_rx_empty(void) {
return !(lpc_uart_reg_read(REG_LSR) & LSR_DR);
}
void lpc_uart_init(void) {
lpc_uart_base = LPC_UART_BASE;
}
char lpc_uart_read(void) {
while (lpc_uart_rx_empty()) ;
return lpc_uart_reg_read(REG_THR);
}
void lpc_uart_write(char c) {
while (lpc_uart_tx_full());
lpc_uart_reg_write(REG_RBR, c);
}

29
ports/powerpc/uart_lpc_serial.h

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
void lpc_uart_init(void);
char lpc_uart_read(void);
void lpc_uart_write(char c);

121
ports/powerpc/uart_potato.c

@ -0,0 +1,121 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* This is a driver for the potato UART used by the microwatt core.
* The original potato UART came from here
* https://github.com/skordal/potato
*/
#include <unistd.h>
#include <stdbool.h>
#include "py/mpconfig.h"
#define PROC_FREQ 50000000
#define UART_FREQ 115200
#define POTATO_UART_BASE 0xc0002000
uint64_t potato_uart_base;
#define POTATO_CONSOLE_TX 0x00
#define POTATO_CONSOLE_RX 0x08
#define POTATO_CONSOLE_STATUS 0x10
#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01
#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02
#define POTATO_CONSOLE_STATUS_RX_FULL 0x04
#define POTATO_CONSOLE_STATUS_TX_FULL 0x08
#define POTATO_CONSOLE_CLOCK_DIV 0x18
#define POTATO_CONSOLE_IRQ_EN 0x20
static uint64_t potato_uart_reg_read(int offset) {
uint64_t addr;
uint64_t val;
addr = potato_uart_base + offset;
val = *(volatile uint64_t *)addr;
return val;
}
void potato_uart_reg_write(int offset, uint64_t val) {
uint64_t addr;
addr = potato_uart_base + offset;
*(volatile uint64_t *)addr = val;
}
static int potato_uart_rx_empty(void) {
uint64_t val;
val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
if (val & POTATO_CONSOLE_STATUS_RX_EMPTY) {
return 1;
}
return 0;
}
static int potato_uart_tx_full(void) {
uint64_t val;
val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
if (val & POTATO_CONSOLE_STATUS_TX_FULL) {
return 1;
}
return 0;
}
static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq) {
return proc_freq / (uart_freq * 16) - 1;
}
void potato_uart_init(void) {
potato_uart_base = POTATO_UART_BASE;
potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(PROC_FREQ, UART_FREQ));
}
char potato_uart_read(void) {
uint64_t val;
while (potato_uart_rx_empty());
val = potato_uart_reg_read(POTATO_CONSOLE_RX);
return (char)(val & 0x000000ff);
}
void potato_uart_write(char c) {
uint64_t val;
val = c;
while (potato_uart_tx_full());
potato_uart_reg_write(POTATO_CONSOLE_TX, val);
}

29
ports/powerpc/uart_potato.h

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
void potato_uart_init(void);
char potato_uart_read(void);
void potato_uart_write(char c);

36
ports/powerpc/unistd.h

@ -0,0 +1,36 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_POWERPC_UNISTD_H
#define MICROPY_INCLUDED_POWERPC_UNISTD_H
// powerpc gcc compiler doesn't seem to have unistd.h file
#define SEEK_SET 0
#define SEEK_CUR 1
typedef int ssize_t;
#endif // MICROPY_INCLUDED_POWERPC_UNISTD_H

4
py/nlr.h

@ -73,6 +73,10 @@
#elif defined(__xtensa__)
#define MICROPY_NLR_XTENSA (1)
#define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_XTENSA)
#elif defined(__powerpc__)
#define MICROPY_NLR_POWERPC (1)
// this could be less but using 128 for safety
#define MICROPY_NLR_NUM_REGS (128)
#else
#define MICROPY_NLR_SETJMP (1)
//#warning "No native NLR support for this arch, using setjmp implementation"

121
py/nlrpowerpc.c

@ -0,0 +1,121 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019, Michael Neuling, IBM Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/mpstate.h"
#if MICROPY_NLR_POWERPC
#undef nlr_push
// Saving all ABI non-vol registers here
unsigned int nlr_push(nlr_buf_t *nlr) {
__asm__ volatile(
"li 4, 0x4eed ; " // Store canary
"std 4, 0x00(%0) ;"
"std 0, 0x08(%0) ;"
"std 1, 0x10(%0) ;"
"std 2, 0x18(%0) ;"
"std 14, 0x20(%0) ;"
"std 15, 0x28(%0) ;"
"std 16, 0x30(%0) ;"
"std 17, 0x38(%0) ;"
"std 18, 0x40(%0) ;"
"std 19, 0x48(%0) ;"
"std 20, 0x50(%0) ;"
"std 21, 0x58(%0) ;"
"std 22, 0x60(%0) ;"
"std 23, 0x68(%0) ;"
"std 24, 0x70(%0) ;"
"std 25, 0x78(%0) ;"
"std 26, 0x80(%0) ;"
"std 27, 0x88(%0) ;"
"std 28, 0x90(%0) ;"
"std 29, 0x98(%0) ;"
"std 30, 0xA0(%0) ;"
"std 31, 0xA8(%0) ;"
"mfcr 4 ; "
"std 4, 0xB0(%0) ;"
"mflr 4 ;"
"std 4, 0xB8(%0) ;"
"li 4, nlr_push_tail@l ;"
"oris 4, 4, nlr_push_tail@h ;"
"mtctr 4 ;"
"mr 3, %1 ; "
"bctr ;"
:
: "r"(&nlr->regs), "r"(nlr)
:
);
return 0;
}
NORETURN void nlr_jump(void *val) {
MP_NLR_JUMP_HEAD(val, top)
__asm__ volatile(
"ld 3, 0x0(%0) ;"
"cmpdi 3, 0x4eed ; " // Check canary
"bne . ; "
"ld 0, 0x08(%0) ;"
"ld 1, 0x10(%0) ;"
"ld 2, 0x18(%0) ;"
"ld 14, 0x20(%0) ;"
"ld 15, 0x28(%0) ;"
"ld 16, 0x30(%0) ;"
"ld 17, 0x38(%0) ;"
"ld 18, 0x40(%0) ;"
"ld 19, 0x48(%0) ;"
"ld 20, 0x50(%0) ;"
"ld 21, 0x58(%0) ;"
"ld 22, 0x60(%0) ;"
"ld 23, 0x68(%0) ;"
"ld 24, 0x70(%0) ;"
"ld 25, 0x78(%0) ;"
"ld 26, 0x80(%0) ;"
"ld 27, 0x88(%0) ;"
"ld 28, 0x90(%0) ;"
"ld 29, 0x98(%0) ;"
"ld 30, 0xA0(%0) ;"
"ld 31, 0xA8(%0) ;"
"ld 3, 0xB0(%0) ;"
"mtcr 3 ;"
"ld 3, 0xB8(%0) ;"
"mtlr 3 ; "
"li 3, 1;"
"blr ;"
:
: "r"(&top->regs)
:
);
MP_UNREACHABLE;
}
#endif // MICROPY_NLR_POWERPC

1
py/py.mk

@ -46,6 +46,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\
nlrx86.o \
nlrx64.o \
nlrthumb.o \
nlrpowerpc.o \
nlrxtensa.o \
nlrsetjmp.o \
malloc.o \

Loading…
Cancel
Save