diff options
| author | Damien George | 2021-01-21 00:34:08 +1100 |
|---|---|---|
| committer | Damien George | 2021-01-30 00:42:29 +1100 |
| commit | 469345e7285128739e2934e7934e107ffda79fc1 (patch) | |
| tree | a410ce2d427770a01d5b6f4d1b3ff2fb342cd94b /ports/rp2/main.c | |
| parent | ef3ee7aa1005cd1f15c2144d4b46feb792ab3185 (diff) | |
rp2: Add new port to Raspberry Pi RP2 microcontroller.
This commit adds a new port "rp2" which targets the new Raspberry Pi RP2040
microcontroller.
The build system uses pure cmake (with a small Makefile wrapper for
convenience). The USB driver is TinyUSB, and there is a machine module
with most of the standard classes implemented. Some examples are provided
in the examples/rp2/ directory.
Work done in collaboration with Graham Sanderson.
Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'ports/rp2/main.c')
| -rw-r--r-- | ports/rp2/main.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/ports/rp2/main.c b/ports/rp2/main.c new file mode 100644 index 000000000..3e956ae78 --- /dev/null +++ b/ports/rp2/main.c @@ -0,0 +1,208 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * + * 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/gc.h" +#include "py/mperrno.h" +#include "py/stackctrl.h" +#include "lib/mp-readline/readline.h" +#include "lib/utils/gchelper.h" +#include "lib/utils/pyexec.h" +#include "tusb.h" +#include "uart.h" +#include "modmachine.h" +#include "modrp2.h" +#include "genhdr/mpversion.h" + +#include "pico/stdlib.h" +#include "pico/binary_info.h" +#include "hardware/rtc.h" +#include "hardware/structs/rosc.h" + +extern uint8_t __StackTop, __StackBottom; +static char gc_heap[192 * 1024]; + +// Embed version info in the binary in machine readable form +bi_decl(bi_program_version_string(MICROPY_GIT_TAG)); + +// Add a section to the picotool output similar to program features, but for frozen modules +// (it will aggregate BINARY_INFO_ID_MP_FROZEN binary info) +bi_decl(bi_program_feature_group_with_flags(BINARY_INFO_TAG_MICROPYTHON, + BINARY_INFO_ID_MP_FROZEN, "frozen modules", + BI_NAMED_GROUP_SEPARATE_COMMAS | BI_NAMED_GROUP_SORT_ALPHA)); + +int main(int argc, char **argv) { + #if MICROPY_HW_ENABLE_UART_REPL + bi_decl(bi_program_feature("UART REPL")) + setup_default_uart(); + mp_uart_init(); + #endif + + #if MICROPY_HW_ENABLE_USBDEV + bi_decl(bi_program_feature("USB REPL")) + tusb_init(); + #endif + + #if MICROPY_PY_THREAD + bi_decl(bi_program_feature("thread support")) + mp_thread_init(); + #endif + + // Start and initialise the RTC + datetime_t t = { + .year = 2021, + .month = 1, + .day = 1, + .dotw = 5, // 0 is Sunday, so 5 is Friday + .hour = 0, + .min = 0, + .sec = 0, + }; + rtc_init(); + rtc_set_datetime(&t); + + // Initialise stack extents and GC heap. + mp_stack_set_top(&__StackTop); + mp_stack_set_limit(&__StackTop - &__StackBottom - 256); + gc_init(&gc_heap[0], &gc_heap[MP_ARRAY_SIZE(gc_heap)]); + + for (;;) { + + // Initialise MicroPython runtime. + mp_init(); + mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); + mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); + + // Initialise sub-systems. + readline_init0(); + machine_pin_init(); + rp2_pio_init(); + + // Execute _boot.py to set up the filesystem. + pyexec_frozen_module("_boot.py"); + + // Execute user scripts. + pyexec_file_if_exists("boot.py"); + if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { + pyexec_file_if_exists("main.py"); + } + + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if (pyexec_raw_repl() != 0) { + break; + } + } else { + if (pyexec_friendly_repl() != 0) { + break; + } + } + } + + mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); + rp2_pio_deinit(); + machine_pin_deinit(); + gc_sweep_all(); + mp_deinit(); + } + + return 0; +} + +void gc_collect(void) { + gc_collect_start(); + gc_helper_collect_regs_and_stack(); + #if MICROPY_PY_THREAD + mp_thread_gc_others(); + #endif + gc_collect_end(); +} + +void nlr_jump_fail(void *val) { + printf("FATAL: uncaught exception %p\n", val); + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val)); + for (;;) { + __breakpoint(); + } +} + +#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); + panic("Assertion failed"); +} +#endif + +uint32_t rosc_random_u32(void) { + uint32_t value = 0; + for (size_t i = 0; i < 32; ++i) { + value = value << 1 | rosc_hw->randombit; + } + return value; +} + +const char rp2_help_text[] = + "Welcome to MicroPython!\n" + "\n" + "For online help please visit https://micropython.org/help/.\n" + "\n" + "For access to the hardware use the 'machine' module. RP2 specific commands\n" + "are in the 'rp2' module.\n" + "\n" + "Quick overview of some objects:\n" + " machine.Pin(pin) -- get a pin, eg machine.Pin(0)\n" + " machine.Pin(pin, m, [p]) -- get a pin and configure it for IO mode m, pull mode p\n" + " methods: init(..), value([v]), high(), low(), irq(handler)\n" + " machine.ADC(pin) -- make an analog object from a pin\n" + " methods: read_u16()\n" + " machine.PWM(pin) -- make a PWM object from a pin\n" + " methods: deinit(), freq([f]), duty_u16([d]), duty_ns([d])\n" + " machine.I2C(id) -- create an I2C object (id=0,1)\n" + " methods: readfrom(addr, buf, stop=True), writeto(addr, buf, stop=True)\n" + " readfrom_mem(addr, memaddr, arg), writeto_mem(addr, memaddr, arg)\n" + " machine.SPI(id, baudrate=1000000) -- create an SPI object (id=0,1)\n" + " methods: read(nbytes, write=0x00), write(buf), write_readinto(wr_buf, rd_buf)\n" + " machine.Timer(freq, callback) -- create a software timer object\n" + " eg: machine.Timer(freq=1, callback=lambda t:print(t))\n" + "\n" + "Pins are numbered 0-29, and 26-29 have ADC capabilities\n" + "Pin IO modes are: Pin.IN, Pin.OUT, Pin.ALT\n" + "Pin pull modes are: Pin.PULL_UP, Pin.PULL_DOWN\n" + "\n" + "Useful control commands:\n" + " CTRL-C -- interrupt a running program\n" + " CTRL-D -- on a blank line, do a soft reset of the board\n" + " CTRL-E -- on a blank line, enter paste mode\n" + "\n" + "For further help on a specific object, type help(obj)\n" + "For a list of available modules, type help('modules')\n" +; + |
