2021-01-20 13:34:08 +00:00
|
|
|
/*
|
|
|
|
* 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"
|
2021-03-17 06:57:27 +00:00
|
|
|
#include "py/mphal.h"
|
2021-01-20 13:34:08 +00:00
|
|
|
#include "py/stackctrl.h"
|
2021-07-22 12:42:52 +00:00
|
|
|
#include "extmod/modbluetooth.h"
|
2021-08-15 16:30:18 +00:00
|
|
|
#include "extmod/modnetwork.h"
|
2021-07-09 04:19:15 +00:00
|
|
|
#include "shared/readline/readline.h"
|
|
|
|
#include "shared/runtime/gchelper.h"
|
|
|
|
#include "shared/runtime/pyexec.h"
|
2023-11-14 02:21:13 +00:00
|
|
|
#include "shared/runtime/softtimer.h"
|
2024-01-17 21:52:16 +00:00
|
|
|
#include "shared/tinyusb/mp_usbd.h"
|
2021-01-20 13:34:08 +00:00
|
|
|
#include "uart.h"
|
|
|
|
#include "modmachine.h"
|
|
|
|
#include "modrp2.h"
|
2021-07-22 12:42:52 +00:00
|
|
|
#include "mpbthciport.h"
|
2023-02-01 03:24:46 +00:00
|
|
|
#include "mpnetworkport.h"
|
2021-01-20 13:34:08 +00:00
|
|
|
#include "genhdr/mpversion.h"
|
2022-10-03 23:25:56 +00:00
|
|
|
#include "mp_usbd.h"
|
2021-01-20 13:34:08 +00:00
|
|
|
|
|
|
|
#include "pico/stdlib.h"
|
|
|
|
#include "pico/binary_info.h"
|
2022-06-30 06:01:02 +00:00
|
|
|
#include "pico/unique_id.h"
|
2021-01-20 13:34:08 +00:00
|
|
|
#include "hardware/rtc.h"
|
|
|
|
#include "hardware/structs/rosc.h"
|
2022-05-05 02:32:22 +00:00
|
|
|
#if MICROPY_PY_LWIP
|
|
|
|
#include "lwip/init.h"
|
|
|
|
#include "lwip/apps/mdns.h"
|
|
|
|
#endif
|
2022-06-30 06:01:02 +00:00
|
|
|
#if MICROPY_PY_NETWORK_CYW43
|
|
|
|
#include "lib/cyw43-driver/src/cyw43.h"
|
|
|
|
#endif
|
2022-05-05 02:32:22 +00:00
|
|
|
|
2021-01-20 13:34:08 +00:00
|
|
|
extern uint8_t __StackTop, __StackBottom;
|
2023-03-07 23:24:36 +00:00
|
|
|
extern uint8_t __GcHeapStart, __GcHeapEnd;
|
2021-01-20 13:34:08 +00:00
|
|
|
|
|
|
|
// 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) {
|
2023-11-30 05:45:11 +00:00
|
|
|
// This is a tickless port, interrupts should always trigger SEV.
|
|
|
|
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
|
|
|
|
|
2021-01-20 13:34:08 +00:00
|
|
|
#if MICROPY_HW_ENABLE_UART_REPL
|
|
|
|
bi_decl(bi_program_feature("UART REPL"))
|
|
|
|
setup_default_uart();
|
|
|
|
mp_uart_init();
|
2023-03-18 07:06:43 +00:00
|
|
|
#else
|
|
|
|
#ifndef NDEBUG
|
|
|
|
stdio_init_all();
|
|
|
|
#endif
|
2021-01-20 13:34:08 +00:00
|
|
|
#endif
|
|
|
|
|
2024-01-17 21:52:16 +00:00
|
|
|
#if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_USB_CDC
|
2021-01-20 13:34:08 +00:00
|
|
|
bi_decl(bi_program_feature("USB REPL"))
|
2022-11-02 04:21:21 +00:00
|
|
|
#endif
|
2021-01-20 13:34:08 +00:00
|
|
|
|
|
|
|
#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,
|
2021-06-20 09:44:16 +00:00
|
|
|
.dotw = 4, // 0 is Monday, so 4 is Friday
|
2021-01-20 13:34:08 +00:00
|
|
|
.hour = 0,
|
|
|
|
.min = 0,
|
|
|
|
.sec = 0,
|
|
|
|
};
|
|
|
|
rtc_init();
|
|
|
|
rtc_set_datetime(&t);
|
2023-10-05 05:32:19 +00:00
|
|
|
mp_hal_time_ns_set_from_rtc();
|
2021-01-20 13:34:08 +00:00
|
|
|
|
|
|
|
// Initialise stack extents and GC heap.
|
|
|
|
mp_stack_set_top(&__StackTop);
|
|
|
|
mp_stack_set_limit(&__StackTop - &__StackBottom - 256);
|
2023-03-07 23:24:36 +00:00
|
|
|
gc_init(&__GcHeapStart, &__GcHeapEnd);
|
2021-01-20 13:34:08 +00:00
|
|
|
|
2022-05-05 02:32:22 +00:00
|
|
|
#if MICROPY_PY_LWIP
|
|
|
|
// lwIP doesn't allow to reinitialise itself by subsequent calls to this function
|
|
|
|
// because the system timeout list (next_timeout) is only ever reset by BSS clearing.
|
|
|
|
// So for now we only init the lwIP stack once on power-up.
|
|
|
|
lwip_init();
|
|
|
|
#if LWIP_MDNS_RESPONDER
|
|
|
|
mdns_resp_init();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2022-07-13 12:08:09 +00:00
|
|
|
#if MICROPY_PY_NETWORK_CYW43 || MICROPY_PY_BLUETOOTH_CYW43
|
2022-06-30 06:01:02 +00:00
|
|
|
{
|
|
|
|
cyw43_init(&cyw43_state);
|
|
|
|
cyw43_irq_init();
|
|
|
|
cyw43_post_poll_hook(); // enable the irq
|
|
|
|
uint8_t buf[8];
|
|
|
|
memcpy(&buf[0], "PICO", 4);
|
|
|
|
|
|
|
|
// MAC isn't loaded from OTP yet, so use unique id to generate the default AP ssid.
|
|
|
|
const char hexchr[16] = "0123456789ABCDEF";
|
|
|
|
pico_unique_board_id_t pid;
|
|
|
|
pico_get_unique_board_id(&pid);
|
|
|
|
buf[4] = hexchr[pid.id[7] >> 4];
|
|
|
|
buf[5] = hexchr[pid.id[6] & 0xf];
|
|
|
|
buf[6] = hexchr[pid.id[5] >> 4];
|
|
|
|
buf[7] = hexchr[pid.id[4] & 0xf];
|
|
|
|
cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf);
|
2022-07-05 01:07:16 +00:00
|
|
|
cyw43_wifi_ap_set_auth(&cyw43_state, CYW43_AUTH_WPA2_AES_PSK);
|
2022-06-30 06:01:02 +00:00
|
|
|
cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t *)"picoW123");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-01-20 13:34:08 +00:00
|
|
|
for (;;) {
|
|
|
|
|
|
|
|
// Initialise MicroPython runtime.
|
|
|
|
mp_init();
|
|
|
|
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
|
|
|
|
|
|
|
|
// Initialise sub-systems.
|
|
|
|
readline_init0();
|
|
|
|
machine_pin_init();
|
|
|
|
rp2_pio_init();
|
rp2/rp2_dma: Introduce a new rp2.DMA class for control over DMA xfers.
This commit implements fairly complete support for the DMA controller in
the rp2 series of microcontrollers. It provides a class for accessing the
DMA channels through a high-level, Pythonic interface, and functions for
setting and manipulating the DMA channel configurations.
Creating an instance of the rp2.DMA class claims one of the processor's DMA
channels. A sensible, per-channel default value for the ctrl register can
be fetched from the DMA.pack_ctrl() function, and the components of this
register can be set via keyword arguments to pack_ctrl().
The read, write, count and ctrl attributes of the DMA class provide
read/write access to the respective registers of the DMA controller. The
config() method allows any or all of these values to be set simultaneously
and adds a trigger keyword argument to allow the setup to immediately be
triggered. The read and write attributes (or keywords in config()) accept
either actual addresses or any object that supports the buffer interface.
The active() method provides read/write control of the channel's activity,
allowing the user to start and stop the channel and test if it is running.
Standard MicroPython interrupt handlers are supported through the irq()
method and the channel can be released either by deleting it and allowing
it to be garbage-collected or with the explicit close() method.
Direct, unfettered access to the DMA controllers registers is provided
through a proxy memoryview() object returned by the DMA.registers attribute
that maps directly onto the memory-mapped registers. This is necessary for
more fine-grained control and is helpful for allowing chaining of DMA
channels.
As a simple example, using DMA to do a fast memory copy just needs:
src = bytearray(32*1024)
dest = bytearray(32*1024)
dma = rp2.DMA()
dma.config(read=src, write=dest, count=len(src) // 4,
ctrl=dma.pack_ctrl(), trigger=True)
# Wait for completion
while dma.active():
pass
This API aims to strike a balance between simplicity and comprehensiveness.
Signed-off-by: Nicko van Someren <nicko@nicko.org>
Signed-off-by: Damien George <damien@micropython.org>
2023-09-30 22:54:47 +00:00
|
|
|
rp2_dma_init();
|
2021-09-04 03:34:53 +00:00
|
|
|
machine_i2s_init0();
|
2021-01-20 13:34:08 +00:00
|
|
|
|
2021-07-22 12:42:52 +00:00
|
|
|
#if MICROPY_PY_BLUETOOTH
|
|
|
|
mp_bluetooth_hci_init();
|
|
|
|
#endif
|
2021-08-15 16:30:18 +00:00
|
|
|
#if MICROPY_PY_NETWORK
|
|
|
|
mod_network_init();
|
|
|
|
#endif
|
2022-05-05 02:32:22 +00:00
|
|
|
#if MICROPY_PY_LWIP
|
|
|
|
mod_network_lwip_init();
|
|
|
|
#endif
|
2021-07-22 12:42:52 +00:00
|
|
|
|
2021-01-20 13:34:08 +00:00
|
|
|
// Execute _boot.py to set up the filesystem.
|
2021-06-15 22:55:09 +00:00
|
|
|
#if MICROPY_VFS_FAT && MICROPY_HW_USB_MSC
|
2023-04-04 19:05:45 +00:00
|
|
|
pyexec_frozen_module("_boot_fat.py", false);
|
2021-06-15 22:55:09 +00:00
|
|
|
#else
|
2023-04-04 19:05:45 +00:00
|
|
|
pyexec_frozen_module("_boot.py", false);
|
2021-06-15 22:55:09 +00:00
|
|
|
#endif
|
2021-01-20 13:34:08 +00:00
|
|
|
|
|
|
|
// Execute user scripts.
|
2021-02-02 01:55:11 +00:00
|
|
|
int ret = pyexec_file_if_exists("boot.py");
|
2024-01-17 21:52:16 +00:00
|
|
|
|
|
|
|
#if MICROPY_HW_ENABLE_USBDEV
|
|
|
|
mp_usbd_init();
|
|
|
|
#endif
|
|
|
|
|
2021-02-02 01:55:11 +00:00
|
|
|
if (ret & PYEXEC_FORCED_EXIT) {
|
|
|
|
goto soft_reset_exit;
|
|
|
|
}
|
2023-10-11 07:55:14 +00:00
|
|
|
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL && ret != 0) {
|
2021-02-02 01:55:11 +00:00
|
|
|
ret = pyexec_file_if_exists("main.py");
|
|
|
|
if (ret & PYEXEC_FORCED_EXIT) {
|
|
|
|
goto soft_reset_exit;
|
|
|
|
}
|
2021-01-20 13:34:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
|
|
|
|
if (pyexec_raw_repl() != 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (pyexec_friendly_repl() != 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-02 01:55:11 +00:00
|
|
|
soft_reset_exit:
|
2021-01-20 13:34:08 +00:00
|
|
|
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
|
2021-08-15 16:30:18 +00:00
|
|
|
#if MICROPY_PY_NETWORK
|
|
|
|
mod_network_deinit();
|
|
|
|
#endif
|
rp2/rp2_dma: Introduce a new rp2.DMA class for control over DMA xfers.
This commit implements fairly complete support for the DMA controller in
the rp2 series of microcontrollers. It provides a class for accessing the
DMA channels through a high-level, Pythonic interface, and functions for
setting and manipulating the DMA channel configurations.
Creating an instance of the rp2.DMA class claims one of the processor's DMA
channels. A sensible, per-channel default value for the ctrl register can
be fetched from the DMA.pack_ctrl() function, and the components of this
register can be set via keyword arguments to pack_ctrl().
The read, write, count and ctrl attributes of the DMA class provide
read/write access to the respective registers of the DMA controller. The
config() method allows any or all of these values to be set simultaneously
and adds a trigger keyword argument to allow the setup to immediately be
triggered. The read and write attributes (or keywords in config()) accept
either actual addresses or any object that supports the buffer interface.
The active() method provides read/write control of the channel's activity,
allowing the user to start and stop the channel and test if it is running.
Standard MicroPython interrupt handlers are supported through the irq()
method and the channel can be released either by deleting it and allowing
it to be garbage-collected or with the explicit close() method.
Direct, unfettered access to the DMA controllers registers is provided
through a proxy memoryview() object returned by the DMA.registers attribute
that maps directly onto the memory-mapped registers. This is necessary for
more fine-grained control and is helpful for allowing chaining of DMA
channels.
As a simple example, using DMA to do a fast memory copy just needs:
src = bytearray(32*1024)
dest = bytearray(32*1024)
dma = rp2.DMA()
dma.config(read=src, write=dest, count=len(src) // 4,
ctrl=dma.pack_ctrl(), trigger=True)
# Wait for completion
while dma.active():
pass
This API aims to strike a balance between simplicity and comprehensiveness.
Signed-off-by: Nicko van Someren <nicko@nicko.org>
Signed-off-by: Damien George <damien@micropython.org>
2023-09-30 22:54:47 +00:00
|
|
|
rp2_dma_deinit();
|
2021-01-20 13:34:08 +00:00
|
|
|
rp2_pio_deinit();
|
2021-07-22 12:42:52 +00:00
|
|
|
#if MICROPY_PY_BLUETOOTH
|
|
|
|
mp_bluetooth_deinit();
|
|
|
|
#endif
|
2023-02-24 16:06:34 +00:00
|
|
|
machine_pwm_deinit_all();
|
2021-01-20 13:34:08 +00:00
|
|
|
machine_pin_deinit();
|
2021-05-08 14:08:30 +00:00
|
|
|
#if MICROPY_PY_THREAD
|
|
|
|
mp_thread_deinit();
|
|
|
|
#endif
|
2023-11-14 02:21:13 +00:00
|
|
|
soft_timer_deinit();
|
2024-03-12 23:38:05 +00:00
|
|
|
#if MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE
|
|
|
|
mp_usbd_deinit();
|
|
|
|
#endif
|
|
|
|
|
2021-01-20 13:34:08 +00:00
|
|
|
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) {
|
2023-01-24 05:58:29 +00:00
|
|
|
mp_printf(&mp_plat_print, "FATAL: uncaught exception %p\n", val);
|
2021-01-20 13:34:08 +00:00
|
|
|
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
|
|
|
|
|
2021-03-17 06:57:27 +00:00
|
|
|
#define POLY (0xD5)
|
|
|
|
|
|
|
|
uint8_t rosc_random_u8(size_t cycles) {
|
|
|
|
static uint8_t r;
|
|
|
|
for (size_t i = 0; i < cycles; ++i) {
|
|
|
|
r = ((r << 1) | rosc_hw->randombit) ^ (r & 0x80 ? POLY : 0);
|
|
|
|
mp_hal_delay_us_fast(1);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2021-01-20 13:34:08 +00:00
|
|
|
uint32_t rosc_random_u32(void) {
|
|
|
|
uint32_t value = 0;
|
2021-03-17 06:57:27 +00:00
|
|
|
for (size_t i = 0; i < 4; ++i) {
|
|
|
|
value = value << 8 | rosc_random_u8(32);
|
2021-01-20 13:34:08 +00:00
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|