Add initial RP2040 support

The RP2040 is new microcontroller from Raspberry Pi that features
two Cortex M0s and eight PIO state machines that are good for
crunching lots of data. It has 264k RAM and a built in UF2
bootloader too.

Datasheet: https://pico.raspberrypi.org/files/rp2040_datasheet.pdf
This commit is contained in:
Scott Shawcroft 2021-01-20 16:47:18 -08:00
parent eff68b0d9f
commit 733094aead
No known key found for this signature in database
GPG Key ID: 9349BC7E64B1921E
87 changed files with 5676 additions and 18 deletions

View File

@ -177,6 +177,7 @@ jobs:
- "8086_commander"
- "ADM_B_NRF52840_1"
- "TG-Watch"
- "adafruit_feather_rp2040"
- "aloriumtech_evo_m51"
- "aramcon_badge_2019"
- "arduino_mkr1300"
@ -294,6 +295,7 @@ jobs:
- "pyruler"
- "qtpy_m0"
- "qtpy_m0_haxpress"
- "raspberry_pi_pico"
- "raytac_mdbt50q-db-40"
- "robohatmm1_m4"
- "sam32"

5
.gitmodules vendored
View File

@ -75,7 +75,7 @@
url = https://github.com/adafruit/nrfx.git
[submodule "lib/tinyusb"]
path = lib/tinyusb
url = https://github.com/hathach/tinyusb.git
url = https://github.com/tannewt/tinyusb.git
branch = master
fetchRecurseSubmodules = false
[submodule "tools/huffman"]
@ -171,3 +171,6 @@
[submodule "frozen/Adafruit_CircuitPython_LC709203F"]
path = frozen/Adafruit_CircuitPython_LC709203F
url = https://github.com/adafruit/Adafruit_CircuitPython_LC709203F
[submodule "ports/raspberrypi/sdk"]
path = ports/raspberrypi/sdk
url = https://github.com/raspberrypi/pico-sdk.git

View File

@ -255,6 +255,7 @@ stubs:
@$(PYTHON) tools/extract_pyi.py shared-bindings/ $(STUBDIR)
@$(PYTHON) tools/extract_pyi.py extmod/ulab/code/ $(STUBDIR)/ulab
@$(PYTHON) tools/extract_pyi.py ports/atmel-samd/bindings $(STUBDIR)
@$(PYTHON) tools/extract_pyi.py ports/raspberrypi/bindings $(STUBDIR)
@$(PYTHON) setup.py -q sdist
.PHONY: check-stubs

View File

@ -189,6 +189,7 @@ exclude_patterns = ["**/build*",
"ports/nrf/nrfx",
"ports/nrf/peripherals",
"ports/nrf/usb",
"ports/raspberrypi/sdk",
"ports/stm/st_driver",
"ports/stm/packages",
"ports/stm/peripherals",

View File

@ -13,8 +13,9 @@ is limited.
../ports/atmel-samd/README
../ports/cxd56/README
../ports/esp32s2/README
../ports/litex/README
../ports/mimxrt10xx/README
../ports/nrf/README
../ports/raspberrypi/README
../ports/stm/README
../ports/esp32s2/README

@ -1 +1 @@
Subproject commit cfcffe94ce62f5ef1fb5aef4641924d64dc4b1c0
Subproject commit b68e4e9d70ddef442c4d95412414c4221eef59eb

1
ports/raspberrypi/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build-*/

273
ports/raspberrypi/Makefile Normal file
View File

@ -0,0 +1,273 @@
# This file is part of the MicroPython project, http://micropython.org/
#
# The MIT License (MIT)
#
# SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
#
# 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.
# Select the board to build for.
ifeq ($(BOARD),)
$(error You must provide a BOARD parameter)
else
ifeq ($(wildcard boards/$(BOARD)/.),)
$(error Invalid BOARD specified)
endif
endif
# If the build directory is not given, make it reflect the board name.
BUILD ?= build-$(BOARD)
include ../../py/mkenv.mk
# Board-specific
include boards/$(BOARD)/mpconfigboard.mk
# Port-specific
include mpconfigport.mk
# CircuitPython-specific
include $(TOP)/py/circuitpy_mpconfig.mk
# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h
# include py core make definitions
include $(TOP)/py/py.mk
include $(TOP)/supervisor/supervisor.mk
# Include make rules and variables common across CircuitPython builds.
include $(TOP)/py/circuitpy_defns.mk
CROSS_COMPILE = arm-none-eabi-
HAL_DIR=hal/$(MCU_SERIES)
INC += -I. \
-I../.. \
-I../lib/mp-readline \
-I../lib/timeutils \
-Iboards/$(BOARD) \
-Iboards/ \
-isystem sdk/ \
-isystem sdk/src/common/pico_base/include/ \
-isystem sdk/src/common/pico_binary_info/include/ \
-isystem sdk/src/common/pico_stdlib/include/ \
-isystem sdk/src/common/pico_sync/include/ \
-isystem sdk/src/common/pico_time/include/ \
-isystem sdk/src/common/pico_util/include/ \
-isystem sdk/src/rp2040/hardware_regs/include/ \
-isystem sdk/src/rp2040/hardware_structs/include/ \
-isystem sdk/src/rp2_common/hardware_adc/include/ \
-isystem sdk/src/rp2_common/hardware_base/include/ \
-isystem sdk/src/rp2_common/hardware_claim/include/ \
-isystem sdk/src/rp2_common/hardware_clocks/include/ \
-isystem sdk/src/rp2_common/hardware_dma/include/ \
-isystem sdk/src/rp2_common/hardware_flash/include/ \
-isystem sdk/src/rp2_common/hardware_gpio/include/ \
-isystem sdk/src/rp2_common/hardware_irq/include/ \
-isystem sdk/src/rp2_common/hardware_i2c/include/ \
-isystem sdk/src/rp2_common/hardware_pio/include/ \
-isystem sdk/src/rp2_common/hardware_pll/include/ \
-isystem sdk/src/rp2_common/hardware_resets/include/ \
-isystem sdk/src/rp2_common/hardware_spi/include/ \
-isystem sdk/src/rp2_common/hardware_sync/include/ \
-isystem sdk/src/rp2_common/hardware_timer/include/ \
-isystem sdk/src/rp2_common/hardware_uart/include/ \
-isystem sdk/src/rp2_common/hardware_watchdog/include/ \
-isystem sdk/src/rp2_common/hardware_xosc/include/ \
-isystem sdk/src/rp2_common/pico_multicore/include/ \
-isystem sdk/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/include/ \
-isystem sdk/src/rp2_common/pico_stdio/include/ \
-isystem sdk/src/rp2_common/pico_printf/include/ \
-isystem sdk/src/rp2_common/pico_float/include/ \
-isystem sdk/src/rp2_common/pico_platform/include/ \
-isystem sdk/src/rp2_common/pico_runtime/printf/include/ \
-isystem sdk/src/rp2_common/pico_bootrom/include/ \
-Isdk_config \
-I../../lib/tinyusb/src \
-I../../supervisor/shared/usb \
-I$(BUILD)
# Pico specific configuration
CFLAGS += -DPICO_ON_DEVICE=1 -DPICO_NO_BINARY_INFO=0 -DPICO_TIME_DEFAULT_ALARM_POOL_DISABLED=1 -DPICO_DIVIDER_CALL_IDIV0=0 -DPICO_DIVIDER_CALL_LDIV0=0 -DPICO_DIVIDER_HARDWARE=1 -DPICO_DOUBLE_ROM=1 -DPICO_FLOAT_ROM=1 -DPICO_MULTICORE=1 -DPICO_BITS_IN_RAM=0 -DPICO_DIVIDER_IN_RAM=0 -DPICO_DOUBLE_PROPAGATE_NANS=0 -DPICO_DOUBLE_IN_RAM=0 -DPICO_MEM_IN_RAM=0 -DPICO_FLOAT_IN_RAM=0 -DPICO_FLOAT_PROPAGATE_NANS=1 -DPICO_NO_FLASH=0 -DPICO_COPY_TO_RAM=0 -DPICO_DISABLE_SHARED_IRQ_HANDLERS=0
OPTIMIZATION_FLAGS ?= -O3
# TinyUSB defines
CFLAGS += -DTUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX=1 -DCFG_TUSB_MCU=OPT_MCU_RP2040 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
# option to override default optimization level, set in boards/$(BOARD)/mpconfigboard.mk
CFLAGS += $(OPTIMIZATION_FLAGS)
#Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS += -ggdb3 -Og
# No LTO because we may place some functions in RAM instead of flash.
else
CFLAGS += -DNDEBUG
# No LTO because we may place some functions in RAM instead of flash.
ifdef CFLAGS_BOARD
CFLAGS += $(CFLAGS_BOARD)
endif
endif
DISABLE_WARNINGS = -Wno-unused-function -Wno-unused-variable -Wno-strict-overflow -Wno-cast-align -Wno-strict-prototypes -Wno-nested-externs -Wno-double-promotion -Wno-sign-compare
CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) $(DISABLE_WARNINGS)
CFLAGS += \
-march=armv6-m \
-mthumb \
-mabi=aapcs-linux \
-mcpu=cortex-m0plus \
-msoft-float \
-mfloat-abi=soft
PICO_LDFLAGS = --specs=nosys.specs -Wl,--wrap=__aeabi_ldiv0 -Wl,--wrap=__aeabi_idiv0 -Wl,--wrap=__aeabi_lmul -Wl,--wrap=__clzsi2 -Wl,--wrap=__clzdi2 -Wl,--wrap=__ctzsi2 -Wl,--wrap=__ctzdi2 -Wl,--wrap=__popcountsi2 -Wl,--wrap=__popcountdi2 -Wl,--wrap=__clz -Wl,--wrap=__clzl -Wl,--wrap=__clzll -Wl,--wrap=__aeabi_idiv -Wl,--wrap=__aeabi_idivmod -Wl,--wrap=__aeabi_ldivmod -Wl,--wrap=__aeabi_uidiv -Wl,--wrap=__aeabi_uidivmod -Wl,--wrap=__aeabi_uldivmod -Wl,--wrap=__aeabi_dadd -Wl,--wrap=__aeabi_ddiv -Wl,--wrap=__aeabi_dmul -Wl,--wrap=__aeabi_drsub -Wl,--wrap=__aeabi_dsub -Wl,--wrap=__aeabi_cdcmpeq -Wl,--wrap=__aeabi_cdrcmple -Wl,--wrap=__aeabi_cdcmple -Wl,--wrap=__aeabi_dcmpeq -Wl,--wrap=__aeabi_dcmplt -Wl,--wrap=__aeabi_dcmple -Wl,--wrap=__aeabi_dcmpge -Wl,--wrap=__aeabi_dcmpgt -Wl,--wrap=__aeabi_dcmpun -Wl,--wrap=__aeabi_i2d -Wl,--wrap=__aeabi_l2d -Wl,--wrap=__aeabi_ui2d -Wl,--wrap=__aeabi_ul2d -Wl,--wrap=__aeabi_d2iz -Wl,--wrap=__aeabi_d2lz -Wl,--wrap=__aeabi_d2uiz -Wl,--wrap=__aeabi_d2ulz -Wl,--wrap=__aeabi_d2f -Wl,--wrap=sqrt -Wl,--wrap=cos -Wl,--wrap=sin -Wl,--wrap=tan -Wl,--wrap=atan2 -Wl,--wrap=exp -Wl,--wrap=log -Wl,--wrap=ldexp -Wl,--wrap=copysign -Wl,--wrap=trunc -Wl,--wrap=floor -Wl,--wrap=ceil -Wl,--wrap=round -Wl,--wrap=sincos -Wl,--wrap=asin -Wl,--wrap=acos -Wl,--wrap=atan -Wl,--wrap=sinh -Wl,--wrap=cosh -Wl,--wrap=tanh -Wl,--wrap=asinh -Wl,--wrap=acosh -Wl,--wrap=atanh -Wl,--wrap=exp2 -Wl,--wrap=log2 -Wl,--wrap=exp10 -Wl,--wrap=log10 -Wl,--wrap=pow -Wl,--wrap=powint -Wl,--wrap=hypot -Wl,--wrap=cbrt -Wl,--wrap=fmod -Wl,--wrap=drem -Wl,--wrap=remainder -Wl,--wrap=remquo -Wl,--wrap=expm1 -Wl,--wrap=log1p -Wl,--wrap=fma -Wl,--wrap=__aeabi_fadd -Wl,--wrap=__aeabi_fdiv -Wl,--wrap=__aeabi_fmul -Wl,--wrap=__aeabi_frsub -Wl,--wrap=__aeabi_fsub -Wl,--wrap=__aeabi_cfcmpeq -Wl,--wrap=__aeabi_cfrcmple -Wl,--wrap=__aeabi_cfcmple -Wl,--wrap=__aeabi_fcmpeq -Wl,--wrap=__aeabi_fcmplt -Wl,--wrap=__aeabi_fcmple -Wl,--wrap=__aeabi_fcmpge -Wl,--wrap=__aeabi_fcmpgt -Wl,--wrap=__aeabi_fcmpun -Wl,--wrap=__aeabi_i2f -Wl,--wrap=__aeabi_l2f -Wl,--wrap=__aeabi_ui2f -Wl,--wrap=__aeabi_ul2f -Wl,--wrap=__aeabi_f2iz -Wl,--wrap=__aeabi_f2lz -Wl,--wrap=__aeabi_f2uiz -Wl,--wrap=__aeabi_f2ulz -Wl,--wrap=__aeabi_f2d -Wl,--wrap=sqrtf -Wl,--wrap=cosf -Wl,--wrap=sinf -Wl,--wrap=tanf -Wl,--wrap=atan2f -Wl,--wrap=expf -Wl,--wrap=logf -Wl,--wrap=ldexpf -Wl,--wrap=copysignf -Wl,--wrap=truncf -Wl,--wrap=floorf -Wl,--wrap=ceilf -Wl,--wrap=roundf -Wl,--wrap=sincosf -Wl,--wrap=asinf -Wl,--wrap=acosf -Wl,--wrap=atanf -Wl,--wrap=sinhf -Wl,--wrap=coshf -Wl,--wrap=tanhf -Wl,--wrap=asinhf -Wl,--wrap=acoshf -Wl,--wrap=atanhf -Wl,--wrap=exp2f -Wl,--wrap=log2f -Wl,--wrap=exp10f -Wl,--wrap=log10f -Wl,--wrap=powf -Wl,--wrap=powintf -Wl,--wrap=hypotf -Wl,--wrap=cbrtf -Wl,--wrap=fmodf -Wl,--wrap=dremf -Wl,--wrap=remainderf -Wl,--wrap=remquof -Wl,--wrap=expm1f -Wl,--wrap=log1pf -Wl,--wrap=fmaf -Wl,--wrap=memcpy -Wl,--wrap=memset -Wl,--wrap=__aeabi_memcpy -Wl,--wrap=__aeabi_memset -Wl,--wrap=__aeabi_memcpy4 -Wl,--wrap=__aeabi_memset4 -Wl,--wrap=__aeabi_memcpy8 -Wl,--wrap=__aeabi_memset8
LDFLAGS = $(CFLAGS) $(PICO_LDFLAGS) -Wl,-T,link.ld -Wl,-Map=$@.map -Wl,-cref -Wl,--gc-sections
# Use toolchain libm if we're not using our own.
ifndef INTERNAL_LIBM
LIBS += -lm
endif
LDFLAGS += -mthumb -mcpu=cortex-m0plus
SRC_SDK := \
src/common/pico_sync/critical_section.c \
src/common/pico_sync/lock_core.c \
src/common/pico_sync/mutex.c \
src/common/pico_time/time.c \
src/common/pico_util/pheap.c \
src/rp2_common/hardware_adc/adc.c \
src/rp2_common/hardware_claim/claim.c \
src/rp2_common/hardware_clocks/clocks.c \
src/rp2_common/hardware_dma/dma.c \
src/rp2_common/hardware_flash/flash.c \
src/rp2_common/hardware_gpio/gpio.c \
src/rp2_common/hardware_i2c/i2c.c \
src/rp2_common/hardware_irq/irq.c \
src/rp2_common/hardware_pio/pio.c \
src/rp2_common/hardware_pll/pll.c \
src/rp2_common/hardware_spi/spi.c \
src/rp2_common/hardware_sync/sync.c \
src/rp2_common/hardware_timer/timer.c \
src/rp2_common/hardware_uart/uart.c \
src/rp2_common/hardware_watchdog/watchdog.c \
src/rp2_common/hardware_xosc/xosc.c \
src/rp2_common/pico_bootrom/bootrom.c \
src/rp2_common/pico_double/double_init_rom.c \
src/rp2_common/pico_fix/rp2040_usb_device_enumeration/rp2040_usb_device_enumeration.c \
src/rp2_common/pico_float/float_init_rom.c \
src/rp2_common/pico_float/float_math.c \
src/rp2_common/pico_multicore/multicore.c \
src/rp2_common/pico_platform/platform.c \
src/rp2_common/pico_printf/printf.c \
src/rp2_common/pico_runtime/runtime.c \
src/rp2_common/pico_stdio/stdio.c \
SRC_SDK := $(addprefix sdk/, $(SRC_SDK))
SRC_C += \
boards/$(BOARD)/board.c \
boards/$(BOARD)/pins.c \
bindings/rp2pio/StateMachine.c \
bindings/rp2pio/__init__.c \
common-hal/rp2pio/StateMachine.c \
common-hal/rp2pio/__init__.c \
background.c \
peripherals/pins.c \
fatfs_port.c \
lib/libc/string0.c \
lib/mp-readline/readline.c \
lib/oofatfs/ff.c \
lib/oofatfs/option/ccsbcs.c \
lib/timeutils/timeutils.c \
lib/tinyusb/src/portable/raspberrypi/rp2040/dcd_rp2040.c \
lib/tinyusb/src/portable/raspberrypi/rp2040/rp2040_usb.c \
lib/utils/buffer_helper.c \
lib/utils/context_manager_helpers.c \
lib/utils/interrupt_char.c \
lib/utils/pyexec.c \
lib/utils/stdout_helpers.c \
lib/utils/sys_stdio_mphal.c \
mphalport.c \
supervisor/shared/memory.c \
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
$(addprefix common-hal/, $(SRC_COMMON_HAL))
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
$(addprefix shared-module/, $(SRC_SHARED_MODULE)) \
$(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL))
# There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED,
# because a few modules have files both in common-hal/ and shared-modules/.
# Doing a $(sort ...) removes duplicates as part of sorting.
SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED))
SRC_S = supervisor/$(CHIP_FAMILY)_cpu.s
SRC_S_UPPER = bs2_default_padded_checksummed.S \
sdk/src/rp2_common/hardware_divider/divider.S \
sdk/src/rp2_common/hardware_irq/irq_handler_chain.S \
sdk/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S \
sdk/src/rp2_common/pico_double/double_aeabi.S \
sdk/src/rp2_common/pico_double/double_v1_rom_shim.S \
sdk/src/rp2_common/pico_divider/divider.S \
sdk/src/rp2_common/pico_float/float_aeabi.S \
sdk/src/rp2_common/pico_float/float_v1_rom_shim.S \
sdk/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S \
sdk/src/rp2_common/pico_mem_ops/mem_ops_aeabi.S \
sdk/src/rp2_common/pico_standard_link/crt0.S \
OBJ = $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_SDK:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o))
ifeq ($(INTERNAL_LIBM),1)
OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o))
endif
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S_UPPER:.S=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)
all: $(BUILD)/firmware.uf2
$(BUILD)/firmware.elf: $(OBJ) link.ld
$(STEPECHO) "LINK $@"
$(Q)$(CC) -o $@ $(LDFLAGS) $(OBJ)
$(Q)$(SIZE) $@ | $(PYTHON3) $(TOP)/tools/build_memory_info.py link.ld
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(STEPECHO) "Create $@"
$(Q)$(OBJCOPY) -O binary $^ $@
$(BUILD)/firmware.uf2: $(BUILD)/firmware.bin
$(STEPECHO) "Create $@"
$(Q)$(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xe48bff56 -b 0x10000000 -c -o $@ $^
include $(TOP)/py/mkrules.mk
# Print out the value of a make variable.
# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile
print-%:
@echo $* = $($*)

View File

@ -0,0 +1,18 @@
RP2040
==================
This port supports many development boards that utilize RP2040 chips. See
https://circuitpython.org/downloads for all supported boards.
Building
--------
For build instructions see this guide: https://learn.adafruit.com/building-circuitpython/
Port Specific modules
---------------------
.. toctree::
../../shared-bindings/rp2pio/index

View File

@ -0,0 +1,44 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "background.h"
#include "supervisor/filesystem.h"
#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include "py/runtime.h"
#include "shared-module/network/__init__.h"
#include "supervisor/shared/stack.h"
#include "supervisor/port.h"
#if CIRCUITPY_DISPLAYIO
#include "shared-module/displayio/__init__.h"
#endif
void port_start_background_task(void) {}
void port_finish_background_task(void) {}
void port_background_task(void) {}

View File

@ -0,0 +1,32 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_BACKGROUND_H
#define MICROPY_INCLUDED_RASPBERRYPI_BACKGROUND_H
#include <stdbool.h>
#endif // MICROPY_INCLUDED_RASPBERRYPI_BACKGROUND_H

View File

@ -0,0 +1,449 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 file contains all of the Python API definitions for the
// rp2pio.StateMachine class.
#include <string.h>
#include "shared-bindings/microcontroller/Pin.h"
#include "bindings/rp2pio/StateMachine.h"
#include "shared-bindings/util.h"
#include "lib/utils/buffer_helper.h"
#include "lib/utils/context_manager_helpers.h"
#include "lib/utils/interrupt_char.h"
#include "py/mperrno.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
//| class StateMachine:
//| """A single PIO StateMachine
//|
//| The programmable I/O peripheral on the RP2 series of microcontrollers is
//| unique. It is a collection of generic state machines that can be
//| used for a variety of protocols. State machines may be independent or
//| coordinated. Program memory and IRQs are shared between the state machines
//| in a particular PIO instance. They are independent otherwise.
//|
//| This class is designed to facilitate sharing of PIO resources. By default,
//| it is assumed that the state machine is used on it's own and can be placed
//| in either PIO. State machines with the same program will be placed in the
//| same PIO if possible. To ensure multiple state machines share a PIO use
//| the ``colocate`` kwarg during construction and create them one after another."""
//|
//| def __init__(self,
//| program: ReadableBuffer,
//| frequency: int,
//| *,
//| init: Optional[ReadableBuffer] = None,
//| first_out_pin: Optional[microcontroller.Pin] = None,
//| out_pin_count: int = 1,
//| first_in_pin: Optional[microcontroller.Pin] = None,
//| in_pin_count: int = 1,
//| first_set_pin: Optional[microcontroller.Pin] = None,
//| set_pin_count: int = 1,
//| first_sideset_pin: Optional[microcontroller.Pin] = None,
//| sideset_pin_count: int = 1,
//| exclusive_pin_use: bool = True,
//| auto_pull: bool = False,
//| pull_threshold : int = 32,
//| out_shift_right : bool = True,
//| auto_push: bool = False,
//| push_threshold : int = 32,
//| in_shift_right : bool = True) -> None:
// //| colocate: Union[int, StateMachine, None] = None
//|
//| """Construct a StateMachine object on the given pins with the given program.
//|
//| :param ReadableBuffer program: the program to run with the state machine
//| :param int frequency: the target clock frequency of the state machine. Actual may be less.
//| :param ReadableBuffer init: a program to run once at start up. This is run after program
//| is started so instructions may be intermingled
//| :param ~microcontroller.Pin first_out_pin: the first pin to use with the OUT instruction
//| :param int out_pin_count: the count of consecutive pins to use with OUT starting at first_out_pin
//| :param ~microcontroller.Pin first_in_pin: the first pin to use with the IN instruction
//| :param int in_pin_count: the count of consecutive pins to use with IN starting at first_in_pin
//| :param ~microcontroller.Pin first_set_pin: the first pin to use with the SET instruction
//| :param int set_pin_count: the count of consecutive pins to use with SET starting at first_set_pin
//| :param ~microcontroller.Pin first_sideset_pin: the first pin to use with a side set
//| :param int sideset_pin_count: the count of consecutive pins to use with a side set starting at first_sideset_pin
//| :param bool exclusive_pin_use: When True, do not share any pins with other state machines. Pins are never shared with other peripherals
//| :param bool auto_pull: When True, automatically load data from the tx FIFO into the
//| output shift register (OSR) when an OUT instruction shifts more than pull_threshold bits
//| :param int pull_threshold: Number of bits to shift before loading a new value into the OSR from the tx FIFO
//| :param bool out_shift_right: When True, data is shifted out the right side (LSB) of the
//| OSR. It is shifted out the left (MSB) otherwise. NOTE! This impacts data alignment
//| when the number of bytes is not a power of two (1, 2 or 4 bytes).
//| :param bool auto_push: When True, automatically save data from input shift register
//| (ISR) into the rx FIFO when an IN instruction shifts more than push_threshold bits
//| :param int push_threshold: Number of bits to shift before saving the ISR value to the RX FIFO
//| :param bool in_shift_right: When True, data is shifted into the right side (LSB) of the
//| ISR. It is shifted into the left (MSB) otherwise. NOTE! This impacts data alignment
//| when the number of bytes is not a power of two (1, 2 or 4 bytes)."""
//| ...
//|
STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
rp2pio_statemachine_obj_t *self = m_new_obj(rp2pio_statemachine_obj_t);
self->base.type = &rp2pio_statemachine_type;
enum { ARG_program, ARG_frequency, ARG_init,
ARG_first_out_pin, ARG_out_pin_count,
ARG_first_in_pin, ARG_in_pin_count,
ARG_first_set_pin, ARG_set_pin_count,
ARG_first_sideset_pin, ARG_sideset_pin_count,
ARG_exclusive_pin_use,
ARG_auto_pull, ARG_pull_threshold, ARG_out_shift_right,
ARG_auto_push, ARG_push_threshold, ARG_in_shift_right};
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_program, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_init, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_first_out_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_out_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_first_in_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_in_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_first_set_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_set_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_first_sideset_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_sideset_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_exclusive_pin_use, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
{ MP_QSTR_auto_pull, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_pull_threshold, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
{ MP_QSTR_out_shift_right, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
{ MP_QSTR_auto_push, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_push_threshold, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
{ MP_QSTR_in_shift_right, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_program].u_obj, &bufinfo, MP_BUFFER_READ);
mp_buffer_info_t init_bufinfo;
init_bufinfo.len = 0;
mp_get_buffer(args[ARG_init].u_obj, &init_bufinfo, MP_BUFFER_READ);
// We don't validate pin in use here because we may be ok sharing them within a PIO.
mcu_pin_obj_t *first_out_pin = validate_obj_is_pin_or_none(args[ARG_first_out_pin].u_obj);
if (args[ARG_out_pin_count].u_int < 1) {
mp_raise_ValueError(translate("Pin count must be at least 1"));
}
mcu_pin_obj_t *first_in_pin = validate_obj_is_pin_or_none(args[ARG_first_in_pin].u_obj);
if (args[ARG_in_pin_count].u_int < 1) {
mp_raise_ValueError(translate("Pin count must be at least 1"));
}
mcu_pin_obj_t *first_set_pin = validate_obj_is_pin_or_none(args[ARG_first_set_pin].u_obj);
if (args[ARG_set_pin_count].u_int < 1) {
mp_raise_ValueError(translate("Pin count must be at least 1"));
}
if (args[ARG_set_pin_count].u_int > 5) {
mp_raise_ValueError(translate("Set pin count must be between 1 and 5"));
}
mcu_pin_obj_t *first_sideset_pin = validate_obj_is_pin_or_none(args[ARG_first_sideset_pin].u_obj);
if (args[ARG_sideset_pin_count].u_int < 1) {
mp_raise_ValueError(translate("Pin count must be at least 1"));
}
if (args[ARG_sideset_pin_count].u_int > 5) {
mp_raise_ValueError(translate("Side set pin count must be between 1 and 5"));
}
mp_int_t pull_threshold = args[ARG_pull_threshold].u_int;
mp_int_t push_threshold = args[ARG_push_threshold].u_int;
if (pull_threshold < 1 || pull_threshold > 32) {
mp_raise_ValueError(translate("pull_threshold must be between 1 and 32"));
}
if (push_threshold < 1 || push_threshold > 32) {
mp_raise_ValueError(translate("push_threshold must be between 1 and 32"));
}
if (bufinfo.len < 2) {
mp_raise_ValueError(translate("Program must contain at least one 16-bit instruction."));
}
if (bufinfo.len % 2 != 0) {
mp_raise_ValueError(translate("Program size invalid"));
}
if (bufinfo.len > 32) {
mp_raise_ValueError(translate("Program too large"));
}
if (init_bufinfo.len % 2 != 0) {
mp_raise_ValueError(translate("Init program size invalid"));
}
common_hal_rp2pio_statemachine_construct(self,
bufinfo.buf, bufinfo.len / 2,
args[ARG_frequency].u_int,
init_bufinfo.buf, init_bufinfo.len / 2,
first_out_pin, args[ARG_out_pin_count].u_int,
first_in_pin, args[ARG_in_pin_count].u_int,
first_set_pin, args[ARG_set_pin_count].u_int,
first_sideset_pin, args[ARG_sideset_pin_count].u_int,
args[ARG_exclusive_pin_use].u_bool,
args[ARG_auto_pull].u_bool, pull_threshold, args[ARG_out_shift_right].u_bool,
args[ARG_auto_push].u_bool, push_threshold, args[ARG_in_shift_right].u_bool);
return MP_OBJ_FROM_PTR(self);
}
//| def deinit(self) -> None:
//| """Turn off the state machine and release it's resources."""
//| ...
//|
STATIC mp_obj_t rp2pio_statemachine_obj_deinit(mp_obj_t self_in) {
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_rp2pio_statemachine_deinit(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_deinit_obj, rp2pio_statemachine_obj_deinit);
//| def __enter__(self) -> SPI:
//| """No-op used by Context Managers.
//| Provided by context manager helper."""
//| ...
//|
//| def __exit__(self) -> None:
//| """Automatically deinitializes the hardware when exiting a context. See
//| :ref:`lifetime-and-contextmanagers` for more info."""
//| ...
//|
STATIC mp_obj_t rp2pio_statemachine_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
common_hal_rp2pio_statemachine_deinit(args[0]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2pio_statemachine_obj___exit___obj, 4, 4, rp2pio_statemachine_obj___exit__);
STATIC void check_for_deinit(rp2pio_statemachine_obj_t *self) {
if (common_hal_rp2pio_statemachine_deinited(self)) {
raise_deinited_error();
}
}
// // | def restart(self, *other_state_machines) -> None:
// // | """Restarts this state machine and any others given. They must share
// // | an underlying PIO. An exception will be raised otherwise."""
// // | ...
// // |
//| def write(self, buffer: ReadableBuffer, *, start: int = 0, end: Optional[int] = None) -> None:
//| """Write the data contained in ``buffer`` to the state machine. If the buffer is empty, nothing happens.
//|
//| :param ~_typing.ReadableBuffer buffer: Write out the data in this buffer
//| :param int start: Start of the slice of ``buffer`` to write out: ``buffer[start:end]``
//| :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)``"""
//| ...
//|
STATIC mp_obj_t rp2pio_statemachine_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_start, ARG_end };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
};
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
int32_t start = args[ARG_start].u_int;
size_t length = bufinfo.len;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
if (length == 0) {
return mp_const_none;
}
bool ok = common_hal_rp2pio_statemachine_write(self, ((uint8_t*)bufinfo.buf) + start, length);
if (mp_hal_is_interrupted()) {
return mp_const_none;
}
if (!ok) {
mp_raise_OSError(MP_EIO);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine_write);
// // | def readinto(self, buffer: WriteableBuffer, *, start: int = 0, end: Optional[int] = None) -> None:
// // | """Read into ``buffer``. If the number of bytes to read is 0, nothing happens.
// // |
// // | :param ~_typing.WriteableBuffer buffer: Read data into this buffer
// // | :param int start: Start of the slice of ``buffer`` to read into: ``buffer[start:end]``
// // | :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)``
// // | :param int write_value: Value to write while reading. (Usually ignored.)"""
// // | ...
// // |
// STATIC mp_obj_t rp2pio_statemachine_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value };
// static const mp_arg_t allowed_args[] = {
// { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
// { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
// { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
// { MP_QSTR_write_value,MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
// };
// rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
// check_for_deinit(self);
// check_lock(self);
// mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
// mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// mp_buffer_info_t bufinfo;
// mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
// int32_t start = args[ARG_start].u_int;
// size_t length = bufinfo.len;
// normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
// if (length == 0) {
// return mp_const_none;
// }
// bool ok = common_hal_rp2pio_statemachine_read(self, ((uint8_t*)bufinfo.buf) + start, length, args[ARG_write_value].u_int);
// if (!ok) {
// mp_raise_OSError(MP_EIO);
// }
// return mp_const_none;
// }
// MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_readinto_obj, 2, rp2pio_statemachine_readinto);
// //| def write_readinto(self, buffer_out: ReadableBuffer, buffer_in: WriteableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None) -> None:
// //| """Write out the data in ``buffer_out`` while simultaneously reading data into ``buffer_in``.
// //| The SPI object must be locked.
// //| The lengths of the slices defined by ``buffer_out[out_start:out_end]`` and ``buffer_in[in_start:in_end]``
// //| must be equal.
// //| If buffer slice lengths are both 0, nothing happens.
// //|
// //| :param ~_typing.ReadableBuffer buffer_out: Write out the data in this buffer
// //| :param ~_typing.WriteableBuffer buffer_in: Read data into this buffer
// //| :param int out_start: Start of the slice of buffer_out to write out: ``buffer_out[out_start:out_end]``
// //| :param int out_end: End of the slice; this index is not included. Defaults to ``len(buffer_out)``
// //| :param int in_start: Start of the slice of ``buffer_in`` to read into: ``buffer_in[in_start:in_end]``
// //| :param int in_end: End of the slice; this index is not included. Defaults to ``len(buffer_in)``"""
// //| ...
// //|
// STATIC mp_obj_t rp2pio_statemachine_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
// static const mp_arg_t allowed_args[] = {
// { MP_QSTR_buffer_out, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
// { MP_QSTR_buffer_in, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
// { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
// { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
// { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
// { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
// };
// rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
// check_for_deinit(self);
// check_lock(self);
// mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
// mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// mp_buffer_info_t buf_out_info;
// mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ);
// int32_t out_start = args[ARG_out_start].u_int;
// size_t out_length = buf_out_info.len;
// normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length);
// mp_buffer_info_t buf_in_info;
// mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE);
// int32_t in_start = args[ARG_in_start].u_int;
// size_t in_length = buf_in_info.len;
// normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length);
// if (out_length != in_length) {
// mp_raise_ValueError(translate("buffer slices must be of equal length"));
// }
// if (out_length == 0) {
// return mp_const_none;
// }
// bool ok = common_hal_rp2pio_statemachine_transfer(self,
// ((uint8_t*)buf_out_info.buf) + out_start,
// ((uint8_t*)buf_in_info.buf) + in_start,
// out_length);
// if (!ok) {
// mp_raise_OSError(MP_EIO);
// }
// return mp_const_none;
// }
// MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_readinto_obj, 2, rp2pio_statemachine_write_readinto);
//| frequency: int
//| """The actual state machine frequency. This may not match the frequency requested
//| due to internal limitations."""
//|
STATIC mp_obj_t rp2pio_statemachine_obj_get_frequency(mp_obj_t self_in) {
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_rp2pio_statemachine_get_frequency(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_frequency_obj, rp2pio_statemachine_obj_get_frequency);
const mp_obj_property_t rp2pio_statemachine_frequency_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&rp2pio_statemachine_get_frequency_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
STATIC const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rp2pio_statemachine_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&rp2pio_statemachine_obj___exit___obj) },
// { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&rp2pio_statemachine_configure_obj) },
// { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&rp2pio_statemachine_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&rp2pio_statemachine_write_obj) },
// { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&rp2pio_statemachine_write_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&rp2pio_statemachine_frequency_obj) }
};
STATIC MP_DEFINE_CONST_DICT(rp2pio_statemachine_locals_dict, rp2pio_statemachine_locals_dict_table);
const mp_obj_type_t rp2pio_statemachine_type = {
{ &mp_type_type },
.name = MP_QSTR_StateMachine,
.make_new = rp2pio_statemachine_make_new,
.locals_dict = (mp_obj_dict_t*)&rp2pio_statemachine_locals_dict,
};
rp2pio_statemachine_obj_t *validate_obj_is_statemachine(mp_obj_t obj) {
if (!MP_OBJ_IS_TYPE(obj, &rp2pio_statemachine_type)) {
mp_raise_TypeError_varg(translate("Expected a %q"), rp2pio_statemachine_type.name);
}
return MP_OBJ_TO_PTR(obj);
}

View File

@ -0,0 +1,71 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_BINDINGS_RP2PIO_STATEMACHINE_H
#define MICROPY_INCLUDED_RASPBERRYPI_BINDINGS_RP2PIO_STATEMACHINE_H
#include "py/obj.h"
#include "common-hal/microcontroller/Pin.h"
#include "common-hal/rp2pio/StateMachine.h"
// Type object used in Python. Should be shared between ports.
extern const mp_obj_type_t rp2pio_statemachine_type;
// Construct an underlying SPI object.
extern void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
const uint16_t* program, size_t program_len,
size_t frequency,
const uint16_t* init, size_t init_len,
const mcu_pin_obj_t * first_out_pin, uint8_t out_pin_count,
const mcu_pin_obj_t * first_in_pin, uint8_t in_pin_count,
const mcu_pin_obj_t * first_set_pin, uint8_t set_pin_count,
const mcu_pin_obj_t * first_sideset_pin, uint8_t sideset_pin_count,
bool exclusive_pin_use,
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
bool auto_push, uint8_t push_threshold, bool in_shift_right);
extern void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self);
extern bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self);
// Writes out the given data.
extern bool common_hal_rp2pio_statemachine_write(rp2pio_statemachine_obj_t *self, const uint8_t *data, size_t len);
// // Reads in len bytes while outputting zeroes.
// extern bool common_hal_rp2pio_statemachine_read(rp2pio_statemachine_obj_t *self, uint8_t *data, size_t len, uint8_t write_value);
// // Reads and write len bytes simultaneously.
// extern bool common_hal_rp2pio_statemachine_transfer(rp2pio_statemachine_obj_t *self,
// const uint8_t *data_out, size_t out_len,
// uint8_t *data_in, size_t in_len);
// Return actual SPI bus frequency.
uint32_t common_hal_rp2pio_statemachine_get_frequency(rp2pio_statemachine_obj_t* self);
// This is used by the supervisor to claim SPI devices indefinitely.
// extern void common_hal_rp2pio_statemachine_never_reset(rp2pio_statemachine_obj_t *self);
#endif // MICROPY_INCLUDED_RASPBERRYPI_BINDINGS_RP2PIO_STATEMACHINE_H

View File

@ -0,0 +1,45 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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/obj.h"
#include "py/runtime.h"
#include "bindings/rp2pio/StateMachine.h"
//| """Hardware interface to RP2 series' programmable IO (PIO) peripheral."""
//|
STATIC const mp_rom_map_elem_t rp2pio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rp2pio) },
{ MP_ROM_QSTR(MP_QSTR_StateMachine), MP_ROM_PTR(&rp2pio_statemachine_type) },
};
STATIC MP_DEFINE_CONST_DICT(rp2pio_module_globals, rp2pio_module_globals_table);
const mp_obj_module_t rp2pio_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&rp2pio_module_globals,
};

View File

@ -0,0 +1,44 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "supervisor/board.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
void board_init(void) {
common_hal_never_reset_pin(&pin_GPIO17);
gpio_init(17);
gpio_set_dir(17, GPIO_OUT);
gpio_put(17, true);
}
bool board_requests_safe_mode(void) {
return false;
}
void reset_board(void) {
}

View File

@ -0,0 +1,14 @@
#define MICROPY_HW_BOARD_NAME "Adafruit Feather RP2040"
#define MICROPY_HW_MCU_NAME "rp2040"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO16)
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO3)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO2)
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19)
#define DEFAULT_SPI_BUS_MISO (&pin_GPIO20)
// #define DEFAULT_UART_BUS_RX (&pin_PA11)
// #define DEFAULT_UART_BUS_TX (&pin_PA10)

View File

@ -0,0 +1,10 @@
USB_VID = 0x239A
USB_PID = 0x80F2
USB_PRODUCT = "Feather RP2040"
USB_MANUFACTURER = "Adafruit"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2
INTERNAL_FLASH_FILESYSTEM = 1

View File

@ -0,0 +1,36 @@
#include "shared-bindings/board/__init__.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_D24), MP_ROM_PTR(&pin_GPIO24) },
{ MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
// { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);

View File

@ -0,0 +1,38 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "supervisor/board.h"
void board_init(void)
{
}
bool board_requests_safe_mode(void) {
return false;
}
void reset_board(void) {
}

View File

@ -0,0 +1,15 @@
// LEDs
// #define MICROPY_HW_LED_STATUS (&pin_PA17)
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico"
#define MICROPY_HW_MCU_NAME "rp2040"
// #define DEFAULT_I2C_BUS_SCL (&pin_PA23)
// #define DEFAULT_I2C_BUS_SDA (&pin_PA22)
// #define DEFAULT_SPI_BUS_SCK (&pin_PB11)
// #define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
// #define DEFAULT_SPI_BUS_MISO (&pin_PA12)
// #define DEFAULT_UART_BUS_RX (&pin_PA11)
// #define DEFAULT_UART_BUS_TX (&pin_PA10)

View File

@ -0,0 +1,10 @@
USB_VID = 0x239A
USB_PID = 0x80F4
USB_PRODUCT = "Pico"
USB_MANUFACTURER = "Raspberry Pi"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2
INTERNAL_FLASH_FILESYSTEM = 1

View File

@ -0,0 +1,38 @@
#include "shared-bindings/board/__init__.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);

View File

@ -0,0 +1,20 @@
// Padded and checksummed version of: /Users/graham/dev/mu/pico_sdk/cmake-build-debug-mu/src/rp2_common/boot_stage2/bs2_default.bin
.section .boot2, "a"
.byte 0x00, 0xb5, 0x2f, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60
.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2b, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61
.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x28, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20
.byte 0x00, 0xf0, 0x3e, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0
.byte 0x2e, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0
.byte 0x26, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x29, 0xf8, 0x01, 0x21
.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x18, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60
.byte 0x17, 0x49, 0x18, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21
.byte 0x19, 0x66, 0x00, 0xf0, 0x0c, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x13, 0x49, 0x11, 0x48, 0x01, 0x60
.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd1, 0x10, 0x48, 0x00, 0x47, 0x03, 0xb5
.byte 0x99, 0x6a, 0x04, 0x20, 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd
.byte 0x02, 0xb5, 0x18, 0x66, 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd
.byte 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00
.byte 0x21, 0x22, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x01, 0x01, 0x00, 0x10
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x27, 0x2a, 0x60

View File

@ -0,0 +1,73 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "common-hal/analogio/AnalogIn.h"
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
#include "src/rp2_common/hardware_adc/include/hardware/adc.h"
#define ADC_FIRST_PIN_NUMBER 26
#define ADC_PIN_COUNT 4
void common_hal_analogio_analogin_construct(analogio_analogin_obj_t *self, const mcu_pin_obj_t *pin) {
if (pin->number < ADC_FIRST_PIN_NUMBER || pin->number > ADC_FIRST_PIN_NUMBER + ADC_PIN_COUNT) {
mp_raise_ValueError(translate("Pin does not have ADC capabilities"));
}
adc_init();
adc_gpio_init(pin->number);
claim_pin(pin);
self->pin = pin;
}
bool common_hal_analogio_analogin_deinited(analogio_analogin_obj_t *self) {
return self->pin == NULL;
}
void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) {
if (common_hal_analogio_analogin_deinited(self)) {
return;
}
reset_pin_number(self->pin->number);
self->pin = NULL;
}
uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
adc_select_input(self->pin->number - ADC_FIRST_PIN_NUMBER);
uint16_t value = adc_read();
// Map value to from 12 to 16 bits
return (value << 4);
}
float common_hal_analogio_analogin_get_reference_voltage(analogio_analogin_obj_t *self) {
// The nominal VCC voltage
return 3.3f;
}

View File

@ -0,0 +1,41 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_ANALOGIO_ANALOGIN_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ANALOGIO_ANALOGIN_H
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t * pin;
} analogio_analogin_obj_t;
void analogin_init(void);
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ANALOGIO_ANALOGIN_H

View File

@ -0,0 +1,48 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
*
* 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 "shared-bindings/analogio/AnalogOut.h"
#include <stdint.h>
#include <string.h>
#include "py/mperrno.h"
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self, const mcu_pin_obj_t *pin) {
mp_raise_RuntimeError(translate("AnalogOut functionality not supported"));
}
bool common_hal_analogio_analogout_deinited(analogio_analogout_obj_t *self) {
return true;
}
void common_hal_analogio_analogout_deinit(analogio_analogout_obj_t *self) {
}
void common_hal_analogio_analogout_set_value(analogio_analogout_obj_t *self, uint16_t value) {
}

View File

@ -0,0 +1,36 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Scott Shawcroft
*
* 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_RASPBERRYPI_COMMON_HAL_ANALOGIO_ANALOGOUT_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ANALOGIO_ANALOGOUT_H
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
} analogio_analogout_obj_t;
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ANALOGIO_ANALOGOUT_H

View File

@ -0,0 +1 @@
// No analogio module functions.

View File

@ -0,0 +1,34 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 <string.h>
#include "py/runtime.h"
#include "py/mphal.h"
#include "common-hal/microcontroller/Pin.h"
// Pins aren't actually defined here. They are in the board specific directory
// such as boards/arduino_zero/pins.c.

View File

@ -0,0 +1,175 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "shared-bindings/busio/I2C.h"
#include "py/mperrno.h"
#include "py/runtime.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/shared/translate.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
// Synopsys DW_apb_i2c (v2.01) IP
#define NO_PIN 0xff
STATIC bool never_reset_i2c[2];
STATIC i2c_inst_t* i2c[2] = {i2c0, i2c1};
void reset_i2c(void) {
for (size_t i = 0; i < 2; i++) {
if (never_reset_i2c[i]) {
continue;
}
i2c_deinit(i2c[i]);
}
}
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency, uint32_t timeout) {
self->peripheral = NULL;
// I2C pins have a regular pattern. SCL is always odd and SDA is even. They match up in pairs
// so we can divide by two to get the instance. This pattern repeats.
if (scl->number % 2 == 1 && sda->number % 2 == 0 && scl->number / 2 == sda->number / 2) {
size_t instance = (scl->number / 2) % 2;
self->peripheral = i2c[instance];
}
if (self->peripheral == NULL) {
mp_raise_ValueError(translate("Invalid pins"));
}
if ((i2c_get_hw(self->peripheral)->enable & I2C_IC_ENABLE_ENABLE_BITS) != 0) {
mp_raise_ValueError(translate("I2C peripheral in use"));
}
if (frequency > 1000000) {
mp_raise_ValueError(translate("Unsupported baudrate"));
}
#if CIRCUITPY_REQUIRE_I2C_PULLUPS
// Test that the pins are in a high state. (Hopefully indicating they are pulled up.)
gpio_set_function(sda->number, GPIO_FUNC_SIO);
gpio_set_function(scl->number, GPIO_FUNC_SIO);
gpio_set_dir(sda->number, GPIO_IN);
gpio_set_dir(scl->number, GPIO_IN);
gpio_set_pulls(sda->number, false, true);
gpio_set_pulls(scl->number, false, true);
common_hal_mcu_delay_us(10);
gpio_set_pulls(sda->number, false, false);
gpio_set_pulls(scl->number, false, false);
// We must pull up within 3us to achieve 400khz.
common_hal_mcu_delay_us(3);
if (!gpio_get(sda->number) || !gpio_get(scl->number)) {
reset_pin_number(sda->number);
reset_pin_number(scl->number);
mp_raise_RuntimeError(translate("SDA or SCL needs a pull up"));
}
#endif
gpio_set_function(sda->number, GPIO_FUNC_I2C);
gpio_set_function(scl->number, GPIO_FUNC_I2C);
self->baudrate = i2c_init(self->peripheral, frequency);
self->sda_pin = sda->number;
self->scl_pin = scl->number;
claim_pin(sda);
claim_pin(scl);
}
bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
return self->sda_pin == NO_PIN;
}
void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
if (common_hal_busio_i2c_deinited(self)) {
return;
}
never_reset_i2c[i2c_hw_index(self->peripheral)] = false;
i2c_deinit(self->peripheral);
reset_pin_number(self->sda_pin);
reset_pin_number(self->scl_pin);
self->sda_pin = NO_PIN;
self->scl_pin = NO_PIN;
}
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
uint8_t fake_read = 0;
return i2c_read_blocking(self->peripheral, addr, &fake_read, 1, false) != PICO_ERROR_GENERIC;
}
bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
bool grabbed_lock = false;
if (!self->has_lock) {
grabbed_lock = true;
self->has_lock = true;
}
return grabbed_lock;
}
bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) {
return self->has_lock;
}
void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
self->has_lock = false;
}
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
const uint8_t *data, size_t len, bool transmit_stop_bit) {
int result = i2c_write_blocking(self->peripheral, addr, data, len, !transmit_stop_bit);
if (result == len) {
return 0;
} else if (result == PICO_ERROR_GENERIC) {
return MP_ENODEV;
}
return MP_EIO;
}
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr,
uint8_t *data, size_t len) {
int result = i2c_read_blocking(self->peripheral, addr, data, len, false);
if (result == len) {
return 0;
} else if (result == PICO_ERROR_GENERIC) {
return MP_ENODEV;
}
return MP_EIO;
}
void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
never_reset_i2c[i2c_hw_index(self->peripheral)] = true;
never_reset_pin_number(self->scl_pin);
never_reset_pin_number(self->sda_pin);
}

View File

@ -0,0 +1,47 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_BUSIO_I2C_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_I2C_H
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
#include "src/rp2_common/hardware_i2c/include/hardware/i2c.h"
typedef struct {
mp_obj_base_t base;
i2c_inst_t * peripheral;
bool has_lock;
uint baudrate;
uint8_t scl_pin;
uint8_t sda_pin;
} busio_i2c_obj_t;
void reset_i2c(void);
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_I2C_H

View File

@ -0,0 +1,33 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_BUSIO_ONEWIRE_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_ONEWIRE_H
// Use bitbangio.
#include "shared-module/busio/OneWire.h"
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_ONEWIRE_H

View File

@ -0,0 +1,294 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "shared-bindings/busio/SPI.h"
#include "lib/utils/interrupt_char.h"
#include "py/mperrno.h"
#include "py/runtime.h"
#include "supervisor/board.h"
#include "common-hal/microcontroller/Pin.h"
#include "supervisor/shared/rgb_led_status.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "src/rp2_common/hardware_dma/include/hardware/dma.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
#define NO_INSTANCE 0xff
STATIC bool never_reset_spi[2];
STATIC spi_inst_t* spi[2] = {spi0, spi1};
void reset_spi(void) {
for (size_t i = 0; i < 2; i++) {
if (never_reset_spi[i]) {
continue;
}
spi_deinit(spi[i]);
}
}
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi,
const mcu_pin_obj_t * miso) {
size_t instance_index = NO_INSTANCE;
if (clock->number % 4 == 2) {
instance_index = (clock->number / 8) % 2;
}
if (mosi != NULL) {
// Make sure the set MOSI matches the clock settings.
if (mosi->number % 4 != 3 ||
(mosi->number / 8) % 2 != instance_index) {
instance_index = NO_INSTANCE;
}
}
if (miso != NULL) {
// Make sure the set MOSI matches the clock settings.
if (miso->number % 4 != 0 ||
(miso->number / 8) % 2 != instance_index) {
instance_index = NO_INSTANCE;
}
}
// TODO: Check to see if we're sharing the SPI with a native APA102.
if (instance_index > 1) {
mp_raise_ValueError(translate("Invalid pins"));
}
if (instance_index == 0) {
self->peripheral = spi0;
} else if (instance_index == 1) {
self->peripheral = spi1;
}
if ((spi_get_hw(self->peripheral)->cr1 & SPI_SSPCR1_SSE_BITS) != 0) {
mp_raise_ValueError(translate("SPI peripheral in use"));
}
spi_init(self->peripheral, 250000);
gpio_set_function(clock->number, GPIO_FUNC_SPI);
claim_pin(clock);
self->clock = clock;
self->MOSI = mosi;
if (mosi != NULL) {
gpio_set_function(mosi->number, GPIO_FUNC_SPI);
claim_pin(mosi);
}
self->MISO = miso;
if (miso != NULL) {
gpio_set_function(miso->number, GPIO_FUNC_SPI);
claim_pin(miso);
}
}
void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
never_reset_spi[spi_get_index(self->peripheral)] = true;
common_hal_never_reset_pin(self->clock);
common_hal_never_reset_pin(self->MOSI);
common_hal_never_reset_pin(self->MISO);
}
bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
return self->clock == NULL;
}
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
if (common_hal_busio_spi_deinited(self)) {
return;
}
never_reset_spi[spi_get_index(self->peripheral)] = false;
spi_deinit(self->peripheral);
common_hal_reset_pin(self->clock);
common_hal_reset_pin(self->MOSI);
common_hal_reset_pin(self->MISO);
self->clock = NULL;
}
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
if (baudrate == self->target_frequency &&
polarity == self->polarity &&
phase == self->phase &&
bits == self->bits) {
return true;
}
spi_set_format(self->peripheral, bits, polarity, phase, SPI_MSB_FIRST);
self->polarity = polarity;
self->phase = phase;
self->bits = bits;
self->target_frequency = baudrate;
self->real_frequency = spi_set_baudrate(self->peripheral, baudrate);
return true;
}
bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {
bool grabbed_lock = false;
if (!self->has_lock) {
grabbed_lock = true;
self->has_lock = true;
}
return grabbed_lock;
}
bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) {
return self->has_lock;
}
void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
self->has_lock = false;
}
static bool _transfer(busio_spi_obj_t *self,
const uint8_t *data_out, size_t out_len,
uint8_t *data_in, size_t in_len) {
// Use DMA for large transfers if channels are available
const size_t dma_min_size_threshold = 32;
int chan_tx = -1;
int chan_rx = -1;
size_t len = MAX(out_len, in_len);
if (len >= dma_min_size_threshold) {
// Use two DMA channels to service the two FIFOs
chan_tx = dma_claim_unused_channel(false);
chan_rx = dma_claim_unused_channel(false);
}
bool use_dma = chan_rx >= 0 && chan_tx >= 0;
if (use_dma) {
dma_channel_config c = dma_channel_get_default_config(chan_tx);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_dreq(&c, spi_get_index(self->peripheral) ? DREQ_SPI1_TX : DREQ_SPI0_TX);
channel_config_set_read_increment(&c, out_len == len);
channel_config_set_write_increment(&c, false);
dma_channel_configure(chan_tx, &c,
&spi_get_hw(self->peripheral)->dr,
data_out,
len,
false);
c = dma_channel_get_default_config(chan_rx);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_dreq(&c, spi_get_index(self->peripheral) ? DREQ_SPI1_RX : DREQ_SPI0_RX);
channel_config_set_read_increment(&c, false);
channel_config_set_write_increment(&c, in_len == len);
dma_channel_configure(chan_rx, &c,
data_in,
&spi_get_hw(self->peripheral)->dr,
len,
false);
dma_start_channel_mask((1u << chan_rx) | (1u << chan_tx));
while (dma_channel_is_busy(chan_rx) || dma_channel_is_busy(chan_tx)) {
// TODO: We should idle here until we get a DMA interrupt or something else.
RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
if (dma_channel_is_busy(chan_rx)) {
dma_channel_abort(chan_rx);
}
if (dma_channel_is_busy(chan_tx)) {
dma_channel_abort(chan_tx);
}
break;
}
}
}
// If we have claimed only one channel successfully, we should release immediately. This also
// releases the DMA after use_dma has been done.
if (chan_rx >= 0) {
dma_channel_unclaim(chan_rx);
}
if (chan_tx >= 0) {
dma_channel_unclaim(chan_tx);
}
if (!use_dma && !mp_hal_is_interrupted()) {
// Use software for small transfers, or if couldn't claim two DMA channels
// Never have more transfers in flight than will fit into the RX FIFO,
// else FIFO will overflow if this code is heavily interrupted.
const size_t fifo_depth = 8;
size_t rx_remaining = len;
size_t tx_remaining = len;
while (!mp_hal_is_interrupted() && (rx_remaining || tx_remaining)) {
if (tx_remaining && spi_is_writable(self->peripheral) && rx_remaining - tx_remaining < fifo_depth) {
spi_get_hw(self->peripheral)->dr = (uint32_t) *data_out;
// Increment only if the buffer is the transfer length. It's 1 otherwise.
if (out_len == len) {
data_out++;
}
--tx_remaining;
}
if (rx_remaining && spi_is_readable(self->peripheral)) {
*data_in = (uint8_t) spi_get_hw(self->peripheral)->dr;
// Increment only if the buffer is the transfer length. It's 1 otherwise.
if (in_len == len) {
data_in++;
}
--rx_remaining;
}
RUN_BACKGROUND_TASKS;
}
}
return true;
}
bool common_hal_busio_spi_write(busio_spi_obj_t *self,
const uint8_t *data, size_t len) {
uint32_t data_in;
return _transfer(self, data, len, (uint8_t*) &data_in, MIN(len, 4));
}
bool common_hal_busio_spi_read(busio_spi_obj_t *self,
uint8_t *data, size_t len, uint8_t write_value) {
uint32_t data_out = write_value << 24 | write_value << 16 | write_value << 8 | write_value;
return _transfer(self, (const uint8_t*) &data_out, MIN(4, len), data, len);
}
bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) {
return _transfer(self, data_out, len, data_in, len);
}
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
return self->real_frequency;
}
uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t* self) {
return self->phase;
}
uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t* self) {
return self->polarity;
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_BUSIO_SPI_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_SPI_H
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
#include "src/rp2_common/hardware_spi/include/hardware/spi.h"
typedef struct {
mp_obj_base_t base;
spi_inst_t * peripheral;
bool has_lock;
const mcu_pin_obj_t* clock;
const mcu_pin_obj_t* MOSI;
const mcu_pin_obj_t* MISO;
uint32_t target_frequency;
int32_t real_frequency;
uint8_t polarity;
uint8_t phase;
uint8_t bits;
} busio_spi_obj_t;
void reset_spi(void);
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_SPI_H

View File

@ -0,0 +1,403 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/busio/UART.h"
#include "mpconfigport.h"
#include "lib/utils/interrupt_char.h"
#include "py/gc.h"
#include "py/mperrno.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/tick.h"
#define UART_DEBUG(...) (void)0
// #define UART_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
// Do-nothing callback needed so that usart_async code will enable rx interrupts.
// See comment below re usart_async_register_callback()
// static void usart_async_rxc_callback(const struct usart_async_descriptor *const descr) {
// // Nothing needs to be done by us.
// }
#define NO_PIN 0xff
void common_hal_busio_uart_construct(busio_uart_obj_t *self,
const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx,
const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
const mcu_pin_obj_t * rs485_dir, bool rs485_invert,
uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop,
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
bool sigint_enabled) {
// Sercom* sercom = NULL;
// uint8_t sercom_index = 255; // Unset index
// uint32_t rx_pinmux = 0;
// uint8_t rx_pad = 255; // Unset pad
// uint32_t tx_pinmux = 0;
// uint8_t tx_pad = 255; // Unset pad
// if ((rts != NULL) || (cts != NULL) || (rs485_dir != NULL) || (rs485_invert)) {
// mp_raise_ValueError(translate("RTS/CTS/RS485 Not yet supported on this device"));
// }
// if (bits > 8) {
// mp_raise_NotImplementedError(translate("bytes > 8 bits not supported"));
// }
// bool have_tx = tx != NULL;
// bool have_rx = rx != NULL;
// if (!have_tx && !have_rx) {
// mp_raise_ValueError(translate("tx and rx cannot both be None"));
// }
// self->baudrate = baudrate;
// self->character_bits = bits;
// self->timeout_ms = timeout * 1000;
// // This assignment is only here because the usart_async routines take a *const argument.
// struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc;
// for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) {
// Sercom* potential_sercom = NULL;
// if (have_tx) {
// sercom_index = tx->sercom[i].index;
// if (sercom_index >= SERCOM_INST_NUM) {
// continue;
// }
// potential_sercom = sercom_insts[sercom_index];
// #ifdef SAMD21
// if (potential_sercom->USART.CTRLA.bit.ENABLE != 0 ||
// !(tx->sercom[i].pad == 0 ||
// tx->sercom[i].pad == 2)) {
// continue;
// }
// #endif
// #ifdef SAM_D5X_E5X
// if (potential_sercom->USART.CTRLA.bit.ENABLE != 0 ||
// !(tx->sercom[i].pad == 0)) {
// continue;
// }
// #endif
// tx_pinmux = PINMUX(tx->number, (i == 0) ? MUX_C : MUX_D);
// tx_pad = tx->sercom[i].pad;
// if (rx == NULL) {
// sercom = potential_sercom;
// break;
// }
// }
// for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) {
// if (((!have_tx && rx->sercom[j].index < SERCOM_INST_NUM &&
// sercom_insts[rx->sercom[j].index]->USART.CTRLA.bit.ENABLE == 0) ||
// sercom_index == rx->sercom[j].index) &&
// rx->sercom[j].pad != tx_pad) {
// rx_pinmux = PINMUX(rx->number, (j == 0) ? MUX_C : MUX_D);
// rx_pad = rx->sercom[j].pad;
// sercom = sercom_insts[rx->sercom[j].index];
// sercom_index = rx->sercom[j].index;
// break;
// }
// }
// if (sercom != NULL) {
// break;
// }
// }
// if (sercom == NULL) {
// mp_raise_ValueError(translate("Invalid pins"));
// }
// if (!have_tx) {
// tx_pad = 0;
// if (rx_pad == 0) {
// tx_pad = 2;
// }
// }
// if (!have_rx) {
// rx_pad = (tx_pad + 1) % 4;
// }
// // Set up clocks on SERCOM.
// samd_peripherals_sercom_clock_init(sercom, sercom_index);
// if (rx && receiver_buffer_size > 0) {
// self->buffer_length = receiver_buffer_size;
// // Initially allocate the UART's buffer in the long-lived part of the
// // heap. UARTs are generally long-lived objects, but the "make long-
// // lived" machinery is incapable of moving internal pointers like
// // self->buffer, so do it manually. (However, as long as internal
// // pointers like this are NOT moved, allocating the buffer
// // in the long-lived pool is not strictly necessary)
// self->buffer = (uint8_t *) gc_alloc(self->buffer_length * sizeof(uint8_t), false, true);
// if (self->buffer == NULL) {
// common_hal_busio_uart_deinit(self);
// mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), self->buffer_length * sizeof(uint8_t));
// }
// } else {
// self->buffer_length = 0;
// self->buffer = NULL;
// }
// if (usart_async_init(usart_desc_p, sercom, self->buffer, self->buffer_length, NULL) != ERR_NONE) {
// mp_raise_ValueError(translate("Could not initialize UART"));
// }
// // usart_async_init() sets a number of defaults based on a prototypical SERCOM
// // which don't necessarily match what we need. After calling it, set the values
// // specific to this instantiation of UART.
// // Set pads computed for this SERCOM.
// // TXPO:
// // 0x0: TX pad 0; no RTS/CTS
// // 0x1: TX pad 2; no RTS/CTS
// // 0x2: TX pad 0; RTS: pad 2, CTS: pad 3 (not used by us right now)
// // So divide by 2 to map pad to value.
// // RXPO:
// // 0x0: RX pad 0
// // 0x1: RX pad 1
// // 0x2: RX pad 2
// // 0x3: RX pad 3
// // Doing a group mask and set of the registers saves 60 bytes over setting the bitfields individually.
// sercom->USART.CTRLA.reg &= ~(SERCOM_USART_CTRLA_TXPO_Msk |
// SERCOM_USART_CTRLA_RXPO_Msk |
// SERCOM_USART_CTRLA_FORM_Msk);
// sercom->USART.CTRLA.reg |= SERCOM_USART_CTRLA_TXPO(tx_pad / 2) |
// SERCOM_USART_CTRLA_RXPO(rx_pad) |
// (parity == BUSIO_UART_PARITY_NONE ? 0 : SERCOM_USART_CTRLA_FORM(1));
// // Enable tx and/or rx based on whether the pins were specified.
// // CHSIZE is 0 for 8 bits, 5, 6, 7 for 5, 6, 7 bits. 1 for 9 bits, but we don't support that.
// sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_TXEN |
// SERCOM_USART_CTRLB_RXEN |
// SERCOM_USART_CTRLB_PMODE |
// SERCOM_USART_CTRLB_SBMODE |
// SERCOM_USART_CTRLB_CHSIZE_Msk);
// sercom->USART.CTRLB.reg |= (have_tx ? SERCOM_USART_CTRLB_TXEN : 0) |
// (have_rx ? SERCOM_USART_CTRLB_RXEN : 0) |
// (parity == BUSIO_UART_PARITY_ODD ? SERCOM_USART_CTRLB_PMODE : 0) |
// (stop > 1 ? SERCOM_USART_CTRLB_SBMODE : 0) |
// SERCOM_USART_CTRLB_CHSIZE(bits % 8);
// // Set baud rate
// common_hal_busio_uart_set_baudrate(self, baudrate);
// // Turn on rx interrupt handling. The UART async driver has its own set of internal callbacks,
// // which are set up by uart_async_init(). These in turn can call user-specified callbacks.
// // In fact, the actual interrupts are not enabled unless we set up a user-specified callback.
// // This is confusing. It's explained in the Atmel START User Guide -> Implementation Description ->
// // Different read function behavior in some asynchronous drivers. As of this writing:
// // http://start.atmel.com/static/help/index.html?GUID-79201A5A-226F-4FBB-B0B8-AB0BE0554836
// // Look at the ASFv4 code example for async USART.
// usart_async_register_callback(usart_desc_p, USART_ASYNC_RXC_CB, usart_async_rxc_callback);
// if (have_tx) {
// gpio_set_pin_direction(tx->number, GPIO_DIRECTION_OUT);
// gpio_set_pin_pull_mode(tx->number, GPIO_PULL_OFF);
// gpio_set_pin_function(tx->number, tx_pinmux);
// self->tx_pin = tx->number;
// claim_pin(tx);
// } else {
// self->tx_pin = NO_PIN;
// }
// if (have_rx) {
// gpio_set_pin_direction(rx->number, GPIO_DIRECTION_IN);
// gpio_set_pin_pull_mode(rx->number, GPIO_PULL_OFF);
// gpio_set_pin_function(rx->number, rx_pinmux);
// self->rx_pin = rx->number;
// claim_pin(rx);
// } else {
// self->rx_pin = NO_PIN;
// }
// usart_async_enable(usart_desc_p);
}
bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) {
return self->rx_pin == NO_PIN && self->tx_pin == NO_PIN;
}
void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
if (common_hal_busio_uart_deinited(self)) {
return;
}
// This assignment is only here because the usart_async routines take a *const argument.
// struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc;
// usart_async_disable(usart_desc_p);
// usart_async_deinit(usart_desc_p);
reset_pin_number(self->rx_pin);
reset_pin_number(self->tx_pin);
self->rx_pin = NO_PIN;
self->tx_pin = NO_PIN;
}
// Read characters.
size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) {
if (self->rx_pin == NO_PIN) {
mp_raise_ValueError(translate("No RX pin"));
}
// This assignment is only here because the usart_async routines take a *const argument.
// struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc;
if (len == 0) {
// Nothing to read.
return 0;
}
// struct io_descriptor *io;
// usart_async_get_io_descriptor(usart_desc_p, &io);
size_t total_read = 0;
// uint64_t start_ticks = supervisor_ticks_ms64();
// // Busy-wait until timeout or until we've read enough chars.
// while (supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) {
// // Read as many chars as we can right now, up to len.
// size_t num_read = io_read(io, data, len);
// // Advance pointer in data buffer, and decrease how many chars left to read.
// data += num_read;
// len -= num_read;
// total_read += num_read;
// if (len == 0) {
// // Don't need to read any more: data buf is full.
// break;
// }
// if (num_read > 0) {
// // Reset the timeout on every character read.
// start_ticks = supervisor_ticks_ms64();
// }
// RUN_BACKGROUND_TASKS;
// // Allow user to break out of a timeout with a KeyboardInterrupt.
// if (mp_hal_is_interrupted()) {
// break;
// }
// // If we are zero timeout, make sure we don't loop again (in the event
// // we read in under 1ms)
// if (self->timeout_ms == 0) {
// break;
// }
// }
// if (total_read == 0) {
// *errcode = EAGAIN;
// return MP_STREAM_ERROR;
// }
return total_read;
}
// Write characters.
size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) {
if (self->tx_pin == NO_PIN) {
mp_raise_ValueError(translate("No TX pin"));
}
// This assignment is only here because the usart_async routines take a *const argument.
// struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc;
// struct io_descriptor *io;
// usart_async_get_io_descriptor(usart_desc_p, &io);
// // Start writing characters. This is non-blocking and will
// // return immediately after setting up the write.
// if (io_write(io, data, len) < 0) {
// *errcode = MP_EAGAIN;
// return MP_STREAM_ERROR;
// }
// // Busy-wait until all characters transmitted.
// struct usart_async_status async_status;
// while (true) {
// usart_async_get_status(usart_desc_p, &async_status);
// if (async_status.txcnt >= len) {
// break;
// }
// RUN_BACKGROUND_TASKS;
// }
return len;
}
uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) {
return self->baudrate;
}
void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) {
// This assignment is only here because the usart_async routines take a *const argument.
// struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc;
// usart_async_set_baud_rate(usart_desc_p,
// // Samples and ARITHMETIC vs FRACTIONAL must correspond to USART_SAMPR in
// // hpl_sercom_config.h.
// _usart_async_calculate_baud_rate(baudrate, // e.g. 9600 baud
// PROTOTYPE_SERCOM_USART_ASYNC_CLOCK_FREQUENCY,
// 16, // samples
// USART_BAUDRATE_ASYNCH_ARITHMETIC,
// 0 // fraction - not used for ARITHMETIC
// ));
self->baudrate = baudrate;
}
mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) {
return (mp_float_t) (self->timeout_ms / 1000.0f);
}
void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) {
self->timeout_ms = timeout * 1000;
}
uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
// This assignment is only here because the usart_async routines take a *const argument.
// struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc;
// struct usart_async_status async_status;
// usart_async_get_status(usart_desc_p, &async_status);
// return async_status.rxcnt;
return 0;
}
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
// This assignment is only here because the usart_async routines take a *const argument.
// struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc;
// usart_async_flush_rx_buffer(usart_desc_p);
}
// True if there are no characters still to be written.
bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {
if (self->tx_pin == NO_PIN) {
return false;
}
return false;
// // This assignment is only here because the usart_async routines take a *const argument.
// struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc;
// struct usart_async_status async_status;
// usart_async_get_status(usart_desc_p, &async_status);
// return !(async_status.flags & USART_ASYNC_STATUS_BUSY);
}

View File

@ -0,0 +1,47 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_BUSIO_UART_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_UART_H
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
// struct usart_async_descriptor usart_desc;
uint8_t rx_pin;
uint8_t tx_pin;
uint8_t character_bits;
bool rx_error;
uint32_t baudrate;
uint32_t timeout_ms;
uint32_t buffer_length;
uint8_t* buffer;
} busio_uart_obj_t;
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_BUSIO_UART_H

View File

@ -0,0 +1 @@
// No busio module functions.

View File

@ -0,0 +1,157 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
*
* 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>
#include <string.h>
#include "py/runtime.h"
#include "py/mphal.h"
#include "common-hal/microcontroller/Pin.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "supervisor/shared/translate.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
digitalinout_result_t common_hal_digitalio_digitalinout_construct(
digitalio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin) {
claim_pin(pin);
self->pin = pin;
self->output = false;
self->open_drain = false;
gpio_init(pin->number);
return DIGITALINOUT_OK;
}
void common_hal_digitalio_digitalinout_never_reset(
digitalio_digitalinout_obj_t *self) {
never_reset_pin_number(self->pin->number);
}
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t* self) {
return self->pin == NULL;
}
void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self) {
if (common_hal_digitalio_digitalinout_deinited(self)) {
return;
}
reset_pin_number(self->pin->number);
self->pin = NULL;
}
void common_hal_digitalio_digitalinout_switch_to_input(
digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
self->output = false;
// This also sets direction to input.
common_hal_digitalio_digitalinout_set_pull(self, pull);
}
digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output(
digitalio_digitalinout_obj_t* self, bool value,
digitalio_drive_mode_t drive_mode) {
const uint8_t pin = self->pin->number;
gpio_set_dir(pin, GPIO_OUT);
// Turn on "strong" pin driving (more current available). See DRVSTR doc in datasheet.
// hri_port_set_PINCFG_DRVSTR_bit(PORT, (enum gpio_port)GPIO_PORT(pin), GPIO_PIN(pin));
self->output = true;
common_hal_digitalio_digitalinout_set_drive_mode(self, drive_mode);
common_hal_digitalio_digitalinout_set_value(self, value);
return DIGITALINOUT_OK;
}
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
digitalio_digitalinout_obj_t* self) {
return self->output ? DIRECTION_OUTPUT : DIRECTION_INPUT;
}
void common_hal_digitalio_digitalinout_set_value(
digitalio_digitalinout_obj_t* self, bool value) {
const uint8_t pin = self->pin->number;
if (self->open_drain) {
gpio_set_dir(pin, value ? GPIO_IN : GPIO_OUT);
} else {
gpio_put(pin, value);
}
}
bool common_hal_digitalio_digitalinout_get_value(
digitalio_digitalinout_obj_t* self) {
return gpio_get(self->pin->number);
}
digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode(
digitalio_digitalinout_obj_t* self,
digitalio_drive_mode_t drive_mode) {
const uint8_t pin = self->pin->number;
bool value = common_hal_digitalio_digitalinout_get_value(self);
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
if (self->open_drain) {
gpio_put(pin, false);
}
// True is implemented differently between modes so reset the value to make
// sure it's correct for the new mode.
if (value) {
common_hal_digitalio_digitalinout_set_value(self, value);
}
return DIGITALINOUT_OK;
}
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
digitalio_digitalinout_obj_t* self) {
if (self->open_drain) {
return DRIVE_MODE_OPEN_DRAIN;
} else {
return DRIVE_MODE_PUSH_PULL;
}
}
void common_hal_digitalio_digitalinout_set_pull(
digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
const uint8_t pin = self->pin->number;
gpio_set_pulls(pin, pull == PULL_UP, pull == PULL_DOWN);
gpio_set_dir(pin, GPIO_IN);
}
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
digitalio_digitalinout_obj_t* self) {
// uint32_t pin = self->pin->number;
// if (self->output) {
// mp_raise_AttributeError(translate("Cannot get pull while in output mode"));
// return PULL_NONE;
// } else {
// if (hri_port_get_PINCFG_PULLEN_bit(PORT, GPIO_PORT(pin), GPIO_PIN(pin)) == 0) {
// return PULL_NONE;
// } if (hri_port_get_OUT_reg(PORT, GPIO_PORT(pin), 1U << GPIO_PIN(pin)) > 0) {
// return PULL_UP;
// } else {
// return PULL_DOWN;
// }
// }
return PULL_NONE;
}

View File

@ -0,0 +1,40 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t * pin;
bool output;
bool open_drain;
} digitalio_digitalinout_obj_t;
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_DIGITALIO_DIGITALINOUT_H

View File

@ -0,0 +1 @@
// No digitalio module functions.

View File

@ -0,0 +1,68 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "shared-bindings/displayio/ParallelBus.h"
#include <stdint.h>
#include "common-hal/microcontroller/Pin.h"
#include "py/runtime.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/microcontroller/__init__.h"
void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* self,
const mcu_pin_obj_t* data0, const mcu_pin_obj_t* command, const mcu_pin_obj_t* chip_select,
const mcu_pin_obj_t* write, const mcu_pin_obj_t* read, const mcu_pin_obj_t* reset) {
mp_raise_NotImplementedError(translate("ParallelBus not yet supported"));
// TODO: Implement with PIO and DMA.
}
void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self) {
}
bool common_hal_displayio_parallelbus_reset(mp_obj_t obj) {
return false;
}
bool common_hal_displayio_parallelbus_bus_free(mp_obj_t obj) {
return false;
}
bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {
return false;
}
void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {
}
void common_hal_displayio_parallelbus_end_transaction(mp_obj_t obj) {
}

View File

@ -0,0 +1,36 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
#include "common-hal/digitalio/DigitalInOut.h"
typedef struct {
mp_obj_base_t base;
} displayio_parallelbus_obj_t;
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_DISPLAYIO_PARALLELBUS_H

View File

@ -0,0 +1,190 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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/runtime.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/shared/rgb_led_status.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
#ifdef MICROPY_HW_NEOPIXEL
bool neopixel_in_use;
#endif
#ifdef MICROPY_HW_APA102_MOSI
bool apa102_sck_in_use;
bool apa102_mosi_in_use;
#endif
#ifdef SPEAKER_ENABLE_PIN
bool speaker_enable_in_use;
#endif
STATIC uint32_t never_reset_pins;
void reset_all_pins(void) {
for (size_t i = 0; i < 30; i++) {
if ((never_reset_pins & (1 << i)) != 0) {
continue;
}
reset_pin_number(i);
}
}
void never_reset_pin_number(uint8_t pin_number) {
if (pin_number >= 32) {
return;
}
never_reset_pins |= 1 << pin_number;
}
void reset_pin_number(uint8_t pin_number) {
if (pin_number >= 32
#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
// Pin 15 is used for Errata so we don't mess with it.
|| pin_number == 15
#endif
) {
return;
}
never_reset_pins &= ~(1 << pin_number);
// We are very aggressive in shutting down the pad fully. Both pulls are
// disabled and both buffers are as well.
gpio_init(pin_number);
hw_clear_bits(&padsbank0_hw->io[pin_number], PADS_BANK0_GPIO0_IE_BITS |
PADS_BANK0_GPIO0_PUE_BITS |
PADS_BANK0_GPIO0_PDE_BITS);
hw_set_bits(&padsbank0_hw->io[pin_number], PADS_BANK0_GPIO0_OD_BITS);
#ifdef MICROPY_HW_NEOPIXEL
if (pin_number == MICROPY_HW_NEOPIXEL->number) {
neopixel_in_use = false;
rgb_led_status_init();
return;
}
#endif
#ifdef MICROPY_HW_APA102_MOSI
if (pin_number == MICROPY_HW_APA102_MOSI->number ||
pin_number == MICROPY_HW_APA102_SCK->number) {
apa102_mosi_in_use = apa102_mosi_in_use && pin_number != MICROPY_HW_APA102_MOSI->number;
apa102_sck_in_use = apa102_sck_in_use && pin_number != MICROPY_HW_APA102_SCK->number;
if (!apa102_sck_in_use && !apa102_mosi_in_use) {
rgb_led_status_init();
}
return;
}
#endif
#ifdef SPEAKER_ENABLE_PIN
if (pin_number == SPEAKER_ENABLE_PIN->number) {
speaker_enable_in_use = false;
}
#endif
}
void common_hal_never_reset_pin(const mcu_pin_obj_t* pin) {
never_reset_pin_number(pin->number);
}
void common_hal_reset_pin(const mcu_pin_obj_t* pin) {
reset_pin_number(pin->number);
}
void claim_pin(const mcu_pin_obj_t* pin) {
#ifdef MICROPY_HW_NEOPIXEL
if (pin == MICROPY_HW_NEOPIXEL) {
neopixel_in_use = true;
}
#endif
#ifdef MICROPY_HW_APA102_MOSI
if (pin == MICROPY_HW_APA102_MOSI) {
apa102_mosi_in_use = true;
}
if (pin == MICROPY_HW_APA102_SCK) {
apa102_sck_in_use = true;
}
#endif
#ifdef SPEAKER_ENABLE_PIN
if (pin == SPEAKER_ENABLE_PIN) {
speaker_enable_in_use = true;
}
#endif
}
bool pin_number_is_free(uint8_t pin_number) {
if (pin_number >= 30) {
return false;
}
#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
// Pin 15 is used for Errata so we don't mess with it.
if (pin_number == 15) {
return true;
}
#endif
uint32_t pad_state = padsbank0_hw->io[pin_number];
return (pad_state & PADS_BANK0_GPIO0_IE_BITS) == 0 &&
(pad_state & PADS_BANK0_GPIO0_OD_BITS) != 0;
}
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin) {
#ifdef MICROPY_HW_NEOPIXEL
if (pin == MICROPY_HW_NEOPIXEL) {
return !neopixel_in_use;
}
#endif
#ifdef MICROPY_HW_APA102_MOSI
if (pin == MICROPY_HW_APA102_MOSI) {
return !apa102_mosi_in_use;
}
if (pin == MICROPY_HW_APA102_SCK) {
return !apa102_sck_in_use;
}
#endif
#ifdef SPEAKER_ENABLE_PIN
if (pin == SPEAKER_ENABLE_PIN) {
return !speaker_enable_in_use;
}
#endif
return pin_number_is_free(pin->number);
}
uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t* pin) {
return pin->number;
}
void common_hal_mcu_pin_claim(const mcu_pin_obj_t* pin) {
return claim_pin(pin);
}
void common_hal_mcu_pin_reset_number(uint8_t pin_no) {
reset_pin_number(pin_no);
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER_PIN_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER_PIN_H
#include <assert.h>
#include <stdint.h>
#include <py/obj.h>
#include "peripherals/pins.h"
#ifdef MICROPY_HW_NEOPIXEL
extern bool neopixel_in_use;
#endif
#ifdef MICROPY_HW_APA102_MOSI
extern bool apa102_sck_in_use;
extern bool apa102_mosi_in_use;
#endif
void reset_all_pins(void);
// reset_pin_number takes the pin number instead of the pointer so that objects don't
// need to store a full pointer.
void reset_pin_number(uint8_t pin_number);
void never_reset_pin_number(uint8_t pin_number);
void claim_pin(const mcu_pin_obj_t* pin);
bool pin_number_is_free(uint8_t pin_number);
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER_PIN_H

View File

@ -0,0 +1,66 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 <math.h>
#include "py/mphal.h"
#include "common-hal/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/ResetReason.h"
#include "src/rp2_common/hardware_adc/include/hardware/adc.h"
#include "src/rp2_common/hardware_clocks/include/hardware/clocks.h"
float common_hal_mcu_processor_get_temperature(void) {
adc_init();
adc_set_temp_sensor_enabled(true);
adc_select_input(4);
uint16_t value = adc_read();
adc_set_temp_sensor_enabled(false);
float voltage = value * 3.3 / (1 << 12);
// TODO: turn the ADC back off
return 27 - (voltage - 0.706) / 0.001721;
}
float common_hal_mcu_processor_get_voltage(void) {
return 3.3f;
}
uint32_t common_hal_mcu_processor_get_frequency(void) {
return clock_get_hz(clk_sys);
}
void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
// TODO: get the unique id from the flash. The chip itself doesn't have one.
// for (int i=0; i<4; i++) {
// for (int k=0; k<4; k++) {
// raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff;
// }
// }
}
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
return RESET_REASON_UNKNOWN;
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 16
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
// Stores no state currently.
} mcu_processor_obj_t;
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H

View File

@ -0,0 +1,148 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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/mphal.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "common-hal/microcontroller/__init__.h"
#if CIRCUITPY_NVM
#include "shared-bindings/nvm/ByteArray.h"
#endif
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "supervisor/shared/safe_mode.h"
#include "supervisor/shared/translate.h"
#include "src/rp2040/hardware_structs/include/hardware/structs/sio.h"
#include "src/rp2_common/hardware_sync/include/hardware/sync.h"
void common_hal_mcu_delay_us(uint32_t delay) {
mp_hal_delay_us(delay);
}
volatile uint32_t nesting_count = 0;
void common_hal_mcu_disable_interrupts(void) {
// We don't use save_and_disable_interrupts() from the sdk because we don't want to worry about PRIMASK.
// This is what we do on the SAMD21 via CMSIS.
asm volatile ("cpsid i" : : : "memory");
__dmb();
nesting_count++;
}
void common_hal_mcu_enable_interrupts(void) {
if (nesting_count == 0) {
// reset_into_safe_mode(LOCKING_ERROR);
}
nesting_count--;
if (nesting_count > 0) {
return;
}
__dmb();
asm volatile ("cpsie i" : : : "memory");
}
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
if (runmode == RUNMODE_BOOTLOADER) {
} else {
}
if (runmode == RUNMODE_SAFE_MODE) {
safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
}
}
void common_hal_mcu_reset(void) {
}
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
// It currently only has properties, and no state.
static const mcu_processor_obj_t processor0 = {
.base = {
.type = &mcu_processor_type,
},
};
static const mcu_processor_obj_t processor1 = {
.base = {
.type = &mcu_processor_type,
},
};
const mp_rom_obj_tuple_t common_hal_mcu_processor_obj = {
{&mp_type_tuple},
CIRCUITPY_PROCESSOR_COUNT,
{
MP_ROM_PTR(&processor0),
MP_ROM_PTR(&processor1)
}
};
#if CIRCUITPY_NVM && CIRCUITPY_INTERNAL_NVM_SIZE > 0
// The singleton nvm.ByteArray object.
const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
.base = {
.type = &nvm_bytearray_type,
},
.len = CIRCUITPY_INTERNAL_NVM_SIZE,
.start_address = (uint8_t*) (CIRCUITPY_INTERNAL_NVM_START_ADDR)
};
#endif
// This maps MCU pin names to pin objects.
const mp_rom_map_elem_t mcu_pin_global_dict_table[TOTAL_GPIO_COUNT] = {
{ MP_ROM_QSTR(MP_QSTR_GPIO0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_GPIO4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_GPIO5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_GPIO6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_GPIO7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_GPIO9), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_GPIO10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_GPIO11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_GPIO12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_GPIO13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_GPIO14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_GPIO15), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_GPIO16), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_GPIO18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_GPIO21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_GPIO22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_GPIO24), MP_ROM_PTR(&pin_GPIO24) },
{ MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_GPIO26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GPIO27), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GPIO28), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_GPIO29), MP_ROM_PTR(&pin_GPIO29) },
};
MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table);

View File

@ -0,0 +1,36 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER___INIT___H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER___INIT___H
#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h"
#define TOTAL_GPIO_COUNT NUM_BANK0_GPIOS
extern const mp_rom_map_elem_t mcu_pin_global_dict_table[TOTAL_GPIO_COUNT];
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER___INIT___H

View File

@ -0,0 +1,95 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "shared-bindings/neopixel_write/__init__.h"
#include "bindings/rp2pio/StateMachine.h"
#include "common-hal/rp2pio/StateMachine.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/port.h"
uint64_t next_start_raw_ticks = 0;
// NeoPixels are 800khz bit streams. Zeroes are 1/3 duty cycle (~416ns) and ones
// are 2/3 duty cycle (~833ns). Each of the instructions below take 1/3 duty
// cycle. The first two instructions always run while only one of the two final
// instructions run per bit. We start with the low period because it can be
// longer than 1/3 period while waiting for more data.
const uint16_t neopixel_program[] = {
// bitloop:
// out x 1 side 0 [1]; Side-set still takes place before instruction stalls
0x6121,
// jmp !x do_zero side 1 [1]; Branch on the bit we shifted out after 1/3 duty delay. Positive pulse
0x1123,
// do_one:
// jmp bitloop side 1 [1]; Continue driving high, for a long pulse
0x1100,
// do_zero:
// nop side 0 [1]; Or drive low, for a short pulse
0xa142
};
const uint16_t init_program[] = {
0xe081
};
void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t num_bytes) {
// Set everything up.
rp2pio_statemachine_obj_t state_machine;
// TODO: Cache the state machine after we create it once. We'll need a way to
// change the pins then though.
uint8_t pin_number = digitalinout->pin->number;
bool ok = rp2pio_statemachine_construct(&state_machine,
neopixel_program, sizeof(neopixel_program) / sizeof(neopixel_program[0]),
800000 * 6, // 800 khz * 6 cycles per bit
init_program, 1,
NULL, 1,
NULL, 1,
digitalinout->pin, 1,
digitalinout->pin, 1,
1 << pin_number, true, false,
true, 8, false, // TX, auto pull every 8 bits. shift left to output msb first
false, 32, true, // RX setting we don't use
false); // claim pins
if (!ok) {
// Do nothing. Maybe bitbang?
return;
}
// Wait to make sure we don't append onto the last transmission. This should only be a tick or
// two.
while (port_get_raw_ticks(NULL) < next_start_raw_ticks) {}
common_hal_rp2pio_statemachine_write(&state_machine, pixels, num_bytes);
// Use a private deinit of the state machine that doesn't reset the pin.
rp2pio_statemachine_deinit(&state_machine, true);
gpio_init(digitalinout->pin->number);
// Update the next start.
next_start_raw_ticks = port_get_raw_ticks(NULL) + 1;
}

View File

@ -0,0 +1,62 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "genhdr/mpversion.h"
#include "py/mpconfig.h"
#include "py/objstr.h"
#include "py/objtuple.h"
#include "py/qstr.h"
STATIC const qstr os_uname_info_fields[] = {
MP_QSTR_sysname, MP_QSTR_nodename,
MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
};
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "rp2040");
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "rp2040");
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
STATIC MP_DEFINE_ATTRTUPLE(
os_uname_info_obj,
os_uname_info_fields,
5,
(mp_obj_t)&os_uname_info_sysname_obj,
(mp_obj_t)&os_uname_info_nodename_obj,
(mp_obj_t)&os_uname_info_release_obj,
(mp_obj_t)&os_uname_info_version_obj,
(mp_obj_t)&os_uname_info_machine_obj
);
mp_obj_t common_hal_os_uname(void) {
return (mp_obj_t)&os_uname_info_obj;
}
bool common_hal_os_urandom(uint8_t* buffer, uint32_t length) {
return false;
}

View File

@ -0,0 +1,216 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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>
#include "py/runtime.h"
#include "common-hal/pwmio/PWMOut.h"
#include "shared-bindings/pwmio/PWMOut.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "supervisor/shared/translate.h"
#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h"
#include "src/rp2_common/hardware_clocks/include/hardware/clocks.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h"
uint32_t target_slice_frequencies[NUM_PWM_SLICES];
uint32_t slice_fixed_frequency;
#define CHANNELS_PER_SLICE 2
static uint32_t channel_use;
static uint32_t never_reset_channel;
static uint32_t _mask(uint8_t slice, uint8_t channel) {
return 1 << (slice * CHANNELS_PER_SLICE + channel);
}
void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) {
never_reset_channel |= _mask(self->slice, self->channel);
never_reset_pin_number(self->pin->number);
}
void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) {
never_reset_channel &= ~_mask(self->slice, self->channel);
}
void pwmout_reset(void) {
// Reset all slices
for (size_t slice = 0; slice < NUM_PWM_SLICES; slice++) {
bool reset = true;
for (size_t channel = 0; channel < CHANNELS_PER_SLICE; channel++) {
uint32_t channel_use_mask = _mask(slice, channel);
if ((never_reset_channel & channel_use_mask) != 0) {
reset = false;
continue;
}
channel_use &= ~channel_use_mask;
}
if (!reset) {
continue;
}
pwm_set_enabled(slice, false);
target_slice_frequencies[slice] = 0;
slice_fixed_frequency &= ~(1 << slice);
}
}
pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
const mcu_pin_obj_t* pin,
uint16_t duty,
uint32_t frequency,
bool variable_frequency) {
self->pin = pin;
self->variable_frequency = variable_frequency;
self->duty_cycle = duty;
if (frequency == 0 || frequency > (common_hal_mcu_processor_get_frequency() / 2)) {
return PWMOUT_INVALID_FREQUENCY;
}
uint8_t slice = pwm_gpio_to_slice_num(pin->number);
uint8_t channel = pwm_gpio_to_channel(pin->number);
uint32_t channel_use_mask = _mask(slice, channel);
// Check the channel first.
if ((channel_use & channel_use_mask) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
// Now check if the slice is in use and if we can share with it.
if (target_slice_frequencies[slice] > 0) {
// If we want to change frequency then we can't share.
if (variable_frequency) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
// If the other user wants to change frequency then we can't share either.
if ((slice_fixed_frequency & (1 << slice)) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
// If we're both fixed frequency but we don't match target frequencies then we can't share.
if (target_slice_frequencies[slice] != frequency) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
}
self->slice = slice;
self->channel = channel;
channel_use |= channel_use_mask;
if (!variable_frequency) {
slice_fixed_frequency |= 1 << slice;
}
if (target_slice_frequencies[slice] != frequency) {
// Reset the counter and compare values.
pwm_hw->slice[slice].ctr = PWM_CH0_CTR_RESET;
common_hal_pwmio_pwmout_set_duty_cycle(self, duty);
common_hal_pwmio_pwmout_set_frequency(self, frequency);
pwm_set_enabled(slice, true);
} else {
common_hal_pwmio_pwmout_set_duty_cycle(self, duty);
}
// Connect to the pad last to avoid any glitches from changing settings.
gpio_set_function(pin->number, GPIO_FUNC_PWM);
return PWMOUT_OK;
}
bool common_hal_pwmio_pwmout_deinited(pwmio_pwmout_obj_t* self) {
return self->pin == NULL;
}
void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self) {
if (common_hal_pwmio_pwmout_deinited(self)) {
return;
}
uint32_t channel_mask = _mask(self->slice, self->channel);
channel_use &= ~channel_mask;
never_reset_channel &= ~channel_mask;
uint32_t slice_mask = ((1 << CHANNELS_PER_SLICE) - 1) << (self->slice * CHANNELS_PER_SLICE + self->channel);
if ((channel_use & slice_mask) == 0) {
target_slice_frequencies[self->slice] = 0;
slice_fixed_frequency &= ~(1 << self->slice);
pwm_set_enabled(self->slice, false);
}
reset_pin_number(self->pin->number);
self->pin = NULL;
}
extern void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t* self, uint16_t duty) {
self->duty_cycle = duty;
uint16_t actual_duty = duty * self->top / ((1 << 16) - 1);
pwm_set_chan_level(self->slice, self->channel, actual_duty);
}
uint16_t common_hal_pwmio_pwmout_get_duty_cycle(pwmio_pwmout_obj_t* self) {
return self->duty_cycle;
}
void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t frequency) {
if (frequency == 0 || frequency > (common_hal_mcu_processor_get_frequency() / 2)) {
mp_raise_ValueError(translate("Invalid PWM frequency"));
}
target_slice_frequencies[self->slice] = frequency;
// For low frequencies use the divider to give us full resolution duty_cycle.
if (frequency < (common_hal_mcu_processor_get_frequency() / (1 << 16))) {
// Compute the divisor. It's an 8 bit integer and 4 bit fraction. Therefore,
// we compute everything * 16 for the fractional part.
// This is 1 << 12 because 4 bits are the * 16.
uint64_t frequency16 = ((uint64_t) clock_get_hz(clk_sys)) / (1 << 12);
uint64_t div16 = frequency16 / frequency;
// Round the divisor to try and get closest to the target frequency. We could
// also always round up and use TOP to get us closer. We may not need that though.
if (frequency16 % frequency >= frequency / 2) {
div16 += 1;
}
if (div16 >= (1 << 12)) {
div16 = (1 << 12) - 1;
}
self->actual_frequency = frequency16 / div16;
self->top = 1 << 16;
pwm_set_clkdiv_int_frac(self->slice, div16 / 16, div16 % 16);
pwm_set_wrap(self->slice, self->top - 1);
} else {
uint32_t top = common_hal_mcu_processor_get_frequency() / frequency;
self->actual_frequency = common_hal_mcu_processor_get_frequency() / top;
self->top = top;
pwm_set_clkdiv_int_frac(self->slice, 1, 0);
pwm_set_wrap(self->slice, self->top - 1);
}
common_hal_pwmio_pwmout_set_duty_cycle(self, self->duty_cycle);
}
uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t* self) {
return self->actual_frequency;
}
bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t* self) {
return self->variable_frequency;
}

View File

@ -0,0 +1,47 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t *pin;
uint8_t slice;
uint8_t channel;
bool variable_frequency;
uint16_t duty_cycle;
uint32_t actual_frequency;
uint32_t top;
} pwmio_pwmout_obj_t;
void pwmout_reset(void);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H

View File

@ -0,0 +1 @@
// No pwmio module functions.

View File

@ -0,0 +1,586 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "bindings/rp2pio/StateMachine.h"
#include "common-hal/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h"
#include "src/rp2_common/hardware_clocks/include/hardware/clocks.h"
#include "src/rp2_common/hardware_dma/include/hardware/dma.h"
#include "src/rp2_common/hardware_pio/include/hardware/pio_instructions.h"
#include "src/rp2040/hardware_structs/include/hardware/structs/iobank0.h"
#include "lib/utils/interrupt_char.h"
#include "py/obj.h"
#include "py/objproperty.h"
#include "py/runtime.h"
// Count how many state machines are using each pin.
STATIC uint8_t _pin_reference_count[TOTAL_GPIO_COUNT];
STATIC uint32_t _current_program_id[NUM_PIOS][NUM_PIO_STATE_MACHINES];
STATIC uint8_t _current_program_offset[NUM_PIOS][NUM_PIO_STATE_MACHINES];
STATIC uint8_t _current_program_len[NUM_PIOS][NUM_PIO_STATE_MACHINES];
STATIC bool _never_reset[NUM_PIOS][NUM_PIO_STATE_MACHINES];
STATIC uint32_t _current_pins[NUM_PIOS];
STATIC uint32_t _current_sm_pins[NUM_PIOS][NUM_PIO_STATE_MACHINES];
STATIC PIO pio_instances[2] = {pio0, pio1};
void _reset_statemachine(PIO pio, uint8_t sm, bool leave_pins) {
uint8_t pio_index = pio_get_index(pio);
pio_sm_unclaim(pio, sm);
uint32_t program_id = _current_program_id[pio_index][sm];
if (program_id == 0) {
return;
}
_current_program_id[pio_index][sm] = 0;
bool program_in_use = false;
for (size_t i = 0; i < NUM_PIO_STATE_MACHINES; i++) {
if (_current_program_id[pio_index][i] == program_id) {
program_in_use = true;
break;
}
}
if (!program_in_use) {
uint8_t offset = _current_program_offset[pio_index][sm];
pio_program_t program_struct = {
.length = _current_program_len[pio_index][sm]
};
pio_remove_program(pio, &program_struct, offset);
}
uint32_t pins = _current_sm_pins[pio_index][sm];
for (size_t pin_number = 0; pin_number < TOTAL_GPIO_COUNT; pin_number++) {
if ((pins & (1 << pin_number)) == 0) {
continue;
}
_pin_reference_count[pin_number]--;
if (_pin_reference_count[pin_number] == 0) {
if (!leave_pins) {
reset_pin_number(pin_number);
}
_current_pins[pio_index] &= ~(1 << pin_number);
}
}
_current_sm_pins[pio_index][sm] = 0;
}
void reset_rp2pio_statemachine(void) {
for (size_t i = 0; i < NUM_PIOS; i++) {
PIO pio = pio_instances[i];
for (size_t j = 0; j < NUM_PIO_STATE_MACHINES; j++) {
if (_never_reset[i][j]) {
continue;
}
_reset_statemachine(pio, j, false);
}
}
}
STATIC uint32_t _check_pins_free(const mcu_pin_obj_t * first_pin, uint8_t pin_count, bool exclusive_pin_use) {
uint32_t pins_we_use = 0;
if (first_pin != NULL) {
for (size_t i = 0; i < pin_count; i++) {
uint8_t pin_number = first_pin->number + i;
if (pin_number >= TOTAL_GPIO_COUNT) {
mp_raise_ValueError(translate("Pin count too large"));
}
const mcu_pin_obj_t * pin = mcu_pin_global_dict_table[pin_number].value;
if (exclusive_pin_use || _pin_reference_count[pin_number] == 0) {
assert_pin_free(pin);
}
pins_we_use |= 1 << pin_number;
}
}
return pins_we_use;
}
bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
const uint16_t* program, size_t program_len,
size_t frequency,
const uint16_t* init, size_t init_len,
const mcu_pin_obj_t * first_out_pin, uint8_t out_pin_count,
const mcu_pin_obj_t * first_in_pin, uint8_t in_pin_count,
const mcu_pin_obj_t * first_set_pin, uint8_t set_pin_count,
const mcu_pin_obj_t * first_sideset_pin, uint8_t sideset_pin_count,
uint32_t pins_we_use, bool tx_fifo, bool rx_fifo,
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
bool auto_push, uint8_t push_threshold, bool in_shift_right,
bool claim_pins) {
// Create a program id that isn't the pointer so we can store it without storing the original object.
uint32_t program_id = ~((uint32_t) program);
// Next, find a PIO and state machine to use.
size_t pio_index = NUM_PIOS;
uint8_t program_offset = 32;
pio_program_t program_struct = {
.instructions = (uint16_t*) program,
.length = program_len,
.origin = 0
};
for (size_t i = 0; i < NUM_PIOS; i++) {
PIO pio = pio_instances[i];
uint8_t free_count = 0;
for (size_t j = 0; j < NUM_PIO_STATE_MACHINES; j++) {
if (_current_program_id[i][j] == program_id &&
_current_program_len[i][j] == program_len) {
program_offset = _current_program_offset[i][j];
}
int temp_claim = pio_claim_unused_sm(pio, false);
if (temp_claim >= 0) {
pio_sm_unclaim(pio, temp_claim);
free_count++;
}
}
if (free_count > 0 && (program_offset < 32 || pio_can_add_program(pio, &program_struct))) {
pio_index = i;
if (program_offset < 32) {
break;
}
}
// Reset program offset if we weren't able to find a free state machine
// on that PIO. (We would have broken the loop otherwise.)
program_offset = 32;
}
int state_machine = -1;
if (pio_index < NUM_PIOS) {
PIO pio = pio_instances[pio_index];
for (size_t i = 0; i < NUM_PIOS; i++) {
if (i == pio_index) {
continue;
}
if ((_current_pins[i] & pins_we_use) != 0) {
// Pin in use by another PIO already.
return false;
}
}
state_machine = pio_claim_unused_sm(pio, false);
}
if (pio_index == NUM_PIOS || state_machine < 0 || state_machine >= NUM_PIO_STATE_MACHINES) {
return false;
}
self->pio = pio_instances[pio_index];
self->state_machine = state_machine;
if (program_offset == 32) {
program_offset = pio_add_program(self->pio, &program_struct);
}
_current_program_id[pio_index][state_machine] = program_id;
_current_program_len[pio_index][state_machine] = program_len;
_current_program_offset[pio_index][state_machine] = program_offset;
_current_sm_pins[pio_index][state_machine] = pins_we_use;
_current_pins[pio_index] |= pins_we_use;
for (size_t pin_number = 0; pin_number < TOTAL_GPIO_COUNT; pin_number++) {
if ((pins_we_use & (1 << pin_number)) == 0) {
continue;
}
_pin_reference_count[pin_number]++;
const mcu_pin_obj_t * pin = mcu_pin_global_dict_table[pin_number].value;
// Also claim the pin at the top level when we're the first to grab it.
if (_pin_reference_count[pin_number] == 1) {
if (claim_pins) {
claim_pin(pin);
}
pio_gpio_init(self->pio, pin_number);
}
}
pio_sm_config c = {0, 0, 0};
if (frequency == 0) {
frequency = clock_get_hz(clk_sys);
}
uint64_t frequency256 = ((uint64_t) clock_get_hz(clk_sys)) * 256;
uint64_t div256 = frequency256 / frequency;
if (frequency256 % div256 > 0) {
div256 += 1;
}
self->actual_frequency = frequency256 / div256;
sm_config_set_clkdiv_int_frac(&c, div256 / 256, div256 % 256);
if (first_out_pin != NULL) {
sm_config_set_out_pins(&c, first_out_pin->number, out_pin_count);
}
if (first_in_pin != NULL) {
sm_config_set_in_pins(&c, first_in_pin->number);
}
if (first_set_pin != NULL) {
sm_config_set_set_pins(&c, first_set_pin->number, set_pin_count);
}
if (first_sideset_pin != NULL) {
sm_config_set_sideset(&c, sideset_pin_count, false /* optional */, false /* pin direction */);
sm_config_set_sideset_pins(&c, first_sideset_pin->number);
}
sm_config_set_wrap(&c, program_offset, program_offset + program_len - 1);
sm_config_set_in_shift(&c, in_shift_right, auto_push, push_threshold);
sm_config_set_out_shift(&c, out_shift_right, auto_pull, pull_threshold);
enum pio_fifo_join join = PIO_FIFO_JOIN_NONE;
if (!rx_fifo) {
join = PIO_FIFO_JOIN_TX;
} else if (!tx_fifo) {
join = PIO_FIFO_JOIN_RX;
}
if (rx_fifo) {
self->rx_dreq = pio_get_dreq(self->pio, self->state_machine, false);
}
if (tx_fifo) {
self->tx_dreq = pio_get_dreq(self->pio, self->state_machine, true);
}
self->in = rx_fifo;
self->out = tx_fifo;
self->out_shift_right = out_shift_right;
self->in_shift_right = in_shift_right;
sm_config_set_fifo_join(&c, join);
pio_sm_init(self->pio, self->state_machine, program_offset, &c);
pio_sm_set_enabled(self->pio, self->state_machine, true);
for (size_t i = 0; i < init_len; i++) {
pio_sm_exec(self->pio, self->state_machine, init[i]);
}
return true;
}
void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
const uint16_t* program, size_t program_len,
size_t frequency,
const uint16_t* init, size_t init_len,
const mcu_pin_obj_t * first_out_pin, uint8_t out_pin_count,
const mcu_pin_obj_t * first_in_pin, uint8_t in_pin_count,
const mcu_pin_obj_t * first_set_pin, uint8_t set_pin_count,
const mcu_pin_obj_t * first_sideset_pin, uint8_t sideset_pin_count,
bool exclusive_pin_use,
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
bool auto_push, uint8_t push_threshold, bool in_shift_right) {
// First, check that all pins are free OR already in use by any PIO if exclusive_pin_use is false.
uint32_t pins_we_use = 0;
pins_we_use |= _check_pins_free(first_out_pin, out_pin_count, exclusive_pin_use);
pins_we_use |= _check_pins_free(first_in_pin, in_pin_count, exclusive_pin_use);
pins_we_use |= _check_pins_free(first_set_pin, set_pin_count, exclusive_pin_use);
pins_we_use |= _check_pins_free(first_sideset_pin, sideset_pin_count, exclusive_pin_use);
// Look through the program to see what we reference and make sure it was provided.
bool tx_fifo = false;
bool rx_fifo = false;
bool in_loaded = false; // can be loaded in other ways besides the fifo
bool out_loaded = false;
bool in_used = false;
bool out_used = false;
for (size_t i = 0; i < program_len; i++) {
uint16_t full_instruction = program[i];
uint16_t instruction = full_instruction & 0xe000;
if (instruction == 0x8000) {
if ((full_instruction & 0xe080) == pio_instr_bits_push) {
rx_fifo = true;
in_loaded = true;
} else { // pull otherwise.
tx_fifo = true;
out_loaded = true;
}
}
if (instruction == pio_instr_bits_jmp) {
uint16_t condition = (full_instruction & 0x00e0) >> 5;
if (condition == 0x6) { // GPIO
mp_raise_NotImplementedError_varg(translate("Instruction %d jumps on pin"), i);
}
}
if (instruction == pio_instr_bits_wait) {
uint16_t wait_source = (full_instruction & 0x0060) >> 5;
uint16_t wait_index = full_instruction & 0x001f;
if (wait_source == 0 && (pins_we_use & (1 << wait_index)) == 0) { // GPIO
mp_raise_ValueError_varg(translate("Instruction %d uses extra pin"), i);
}
if (wait_source == 1) { // Input pin
if (first_in_pin == NULL) {
mp_raise_ValueError_varg(translate("Missing first_in_pin. Instruction %d waits based on pin"), i);
}
if (wait_index > in_pin_count) {
mp_raise_ValueError_varg(translate("Instruction %d waits on input outside of count"), i);
}
}
}
if (instruction == pio_instr_bits_in) {
uint16_t source = (full_instruction & 0x00e0) >> 5;
uint16_t bit_count = full_instruction & 0x001f;
if (source == 0) {
if (first_in_pin == NULL) {
mp_raise_ValueError_varg(translate("Missing first_in_pin. Instruction %d shifts in from pin(s)"), i);
}
if (bit_count > in_pin_count) {
mp_raise_ValueError_varg(translate("Instruction %d shifts in more bits than pin count"), i);
}
}
if (auto_push) {
in_loaded = true;
rx_fifo = true;
}
in_used = true;
}
if (instruction == pio_instr_bits_out) {
uint16_t bit_count = full_instruction & 0x001f;
uint16_t destination = (full_instruction & 0x00e0) >> 5;
// Check for pins or pindirs destination.
if (destination == 0x0 || destination == 0x4) {
if (first_out_pin == NULL) {
mp_raise_ValueError_varg(translate("Missing first_out_pin. Instruction %d shifts out to pin(s)"), i);
}
if (bit_count > out_pin_count) {
mp_raise_ValueError_varg(translate("Instruction %d shifts out more bits than pin count"), i);
}
}
if (auto_pull) {
out_loaded = true;
tx_fifo = true;
}
out_used = true;
}
if (instruction == pio_instr_bits_set) {
uint16_t destination = (full_instruction & 0x00e0) >> 5;
// Check for pins or pindirs destination.
if ((destination == 0x00 || destination == 0x4) && first_set_pin == NULL) {
mp_raise_ValueError_varg(translate("Missing first_set_pin. Instruction %d sets pin(s)"), i);
}
}
if (instruction == pio_instr_bits_mov) {
uint16_t source = full_instruction & 0x0007;
uint16_t destination = (full_instruction & 0x00e0) >> 5;
// Check for pins or pindirs destination.
if (destination == 0x0 && first_out_pin == NULL) {
mp_raise_ValueError_varg(translate("Missing first_out_pin. Instruction %d writes pin(s)"), i);
}
if (source == 0x0 && first_in_pin == NULL) {
mp_raise_ValueError_varg(translate("Missing first_in_pin. Instruction %d reads pin(s)"), i);
}
if (destination == 0x6) {
in_loaded = true;
} else if (destination == 0x7) {
out_loaded = true;
}
}
}
if (!in_loaded && in_used) {
mp_raise_ValueError_varg(translate("Program does IN without loading ISR"));
}
if (!out_loaded && out_used) {
mp_raise_ValueError_varg(translate("Program does OUT without loading OSR"));
}
if (in_pin_count > 8 || out_pin_count > 8) {
mp_raise_NotImplementedError(translate("Only IN/OUT of up to 8 supported"));
}
bool ok = rp2pio_statemachine_construct(self,
program, program_len,
frequency,
init, init_len,
first_out_pin, out_pin_count,
first_in_pin, in_pin_count,
first_set_pin, set_pin_count,
first_sideset_pin, sideset_pin_count,
pins_we_use, tx_fifo, rx_fifo,
auto_pull, pull_threshold, out_shift_right,
auto_push, push_threshold, in_shift_right,
true /* claim pins */);
if (!ok) {
mp_raise_RuntimeError(translate("All state machines in use"));
}
}
uint32_t common_hal_rp2pio_statemachine_get_frequency(rp2pio_statemachine_obj_t* self) {
return self->actual_frequency;
}
void rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self, bool leave_pins) {
uint8_t sm = self->state_machine;
uint8_t pio_index = pio_get_index(self->pio);
_never_reset[pio_index][sm] = false;
_reset_statemachine(self->pio, sm, leave_pins);
self->state_machine = NUM_PIO_STATE_MACHINES;
}
void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self) {
rp2pio_statemachine_deinit(self, false);
}
void common_hal_rp2pio_statemachine_never_reset(rp2pio_statemachine_obj_t *self) {
uint8_t sm = self->state_machine;
uint8_t pio_index = pio_get_index(self->pio);
_never_reset[pio_index][sm] = true;
// TODO: never reset all the pins
}
bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self) {
return self->state_machine == NUM_PIO_STATE_MACHINES;
}
static bool _transfer(rp2pio_statemachine_obj_t *self,
const uint8_t *data_out, size_t out_len,
uint8_t *data_in, size_t in_len) {
// This implementation is based on SPI but varies because the tx and rx buffers
// may be different lengths and occur at different times or speeds.
// Use DMA for large transfers if channels are available
const size_t dma_min_size_threshold = 32;
int chan_tx = -1;
int chan_rx = -1;
size_t len = MAX(out_len, in_len);
bool tx = data_out != NULL;
bool rx = data_in != NULL;
if (len >= dma_min_size_threshold) {
// Use DMA channels to service the two FIFOs
if (tx) {
chan_tx = dma_claim_unused_channel(false);
}
if (rx) {
chan_rx = dma_claim_unused_channel(false);
}
}
volatile uint8_t* tx_destination = NULL;
const volatile uint8_t* rx_source = NULL;
if (tx) {
tx_destination = (volatile uint8_t*) &self->pio->txf[self->state_machine];
if (!self->out_shift_right) {
tx_destination += 3;
}
}
if (rx) {
rx_source = (const volatile uint8_t*) &self->pio->rxf[self->state_machine];
if (!self->in_shift_right) {
rx_source += 3;
}
}
bool use_dma = (!rx || chan_rx >= 0) && (!tx || chan_tx >= 0);
if (use_dma) {
dma_channel_config c;
uint32_t channel_mask = 0;
if (tx) {
c = dma_channel_get_default_config(chan_tx);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_dreq(&c, self->tx_dreq);
channel_config_set_read_increment(&c, true);
channel_config_set_write_increment(&c, false);
dma_channel_configure(chan_tx, &c,
tx_destination,
data_out,
len,
false);
channel_mask |= 1u << chan_tx;
}
if (rx) {
c = dma_channel_get_default_config(chan_rx);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_dreq(&c, self->rx_dreq);
channel_config_set_read_increment(&c, false);
channel_config_set_write_increment(&c, true);
dma_channel_configure(chan_rx, &c,
data_in,
rx_source,
len,
false);
channel_mask |= 1u << chan_rx;
}
dma_start_channel_mask(channel_mask);
while ((rx && dma_channel_is_busy(chan_rx)) ||
(tx && dma_channel_is_busy(chan_tx))) {
// TODO: We should idle here until we get a DMA interrupt or something else.
RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
if (rx && dma_channel_is_busy(chan_rx)) {
dma_channel_abort(chan_rx);
}
if (tx && dma_channel_is_busy(chan_tx)) {
dma_channel_abort(chan_tx);
}
break;
}
}
// Clear the stall bit so we can detect when the state machine is done transmitting.
self->pio->fdebug = PIO_FDEBUG_TXSTALL_BITS;
}
// If we have claimed only one channel successfully, we should release immediately. This also
// releases the DMA after use_dma has been done.
if (chan_rx >= 0) {
dma_channel_unclaim(chan_rx);
}
if (chan_tx >= 0) {
dma_channel_unclaim(chan_tx);
}
if (!use_dma && !mp_hal_is_interrupted()) {
// Use software for small transfers, or if couldn't claim two DMA channels
size_t rx_remaining = in_len;
size_t tx_remaining = out_len;
while (rx_remaining || tx_remaining) {
if (tx_remaining && !pio_sm_is_tx_fifo_full(self->pio, self->state_machine)) {
*tx_destination = *data_out;
data_out++;
--tx_remaining;
}
if (rx_remaining && !pio_sm_is_rx_fifo_empty(self->pio, self->state_machine)) {
*data_in = (uint8_t) *rx_source;
data_in++;
--rx_remaining;
}
RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
break;
}
}
// Clear the stall bit so we can detect when the state machine is done transmitting.
self->pio->fdebug = PIO_FDEBUG_TXSTALL_BITS;
}
// Wait for the state machine to finish transmitting the data we've queued
// up.
if (tx) {
while (!pio_sm_is_tx_fifo_empty(self->pio, self->state_machine) ||
(self->pio->fdebug & PIO_FDEBUG_TXSTALL_BITS) == 0) {
RUN_BACKGROUND_TASKS;
}
}
return true;
}
// Writes out the given data.
bool common_hal_rp2pio_statemachine_write(rp2pio_statemachine_obj_t *self,
const uint8_t *data, size_t len) {
if (!self->out) {
mp_raise_RuntimeError(translate("No out in program"));
}
return _transfer(self, data, len, NULL, 0);
}

View File

@ -0,0 +1,68 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_COMMON_HAL_RP2PIO_STATEMACHINE_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_RP2PIO_STATEMACHINE_H
#include "py/obj.h"
#include "src/rp2_common/hardware_pio/include/hardware/pio.h"
typedef struct {
mp_obj_base_t base;
uint32_t pins; // Bitmask of what pins this state machine uses.
int state_machine;
PIO pio;
bool in;
bool out;
uint tx_dreq;
uint rx_dreq;
bool out_shift_right;
bool in_shift_right;
uint32_t actual_frequency;
} rp2pio_statemachine_obj_t;
void reset_rp2pio_statemachine(void);
// Minimal internal version that only fails on pin error (not in use) or full PIO.
bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
const uint16_t* program, size_t program_len,
size_t frequency,
const uint16_t* init, size_t init_len,
const mcu_pin_obj_t * first_out_pin, uint8_t out_pin_count,
const mcu_pin_obj_t * first_in_pin, uint8_t in_pin_count,
const mcu_pin_obj_t * first_set_pin, uint8_t set_pin_count,
const mcu_pin_obj_t * first_sideset_pin, uint8_t sideset_pin_count,
uint32_t pins_we_use, bool tx_fifo, bool rx_fifo,
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
bool auto_push, uint8_t push_threshold, bool in_shift_right,
bool claim_pins);
void rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self, bool leave_pins);
extern const mp_obj_type_t rp2pio_statemachine_type;
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_RP2PIO_STATEMACHINE_H

View File

@ -0,0 +1 @@
// Nothing yet.

View File

@ -0,0 +1,37 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Michael Schroeder
*
* 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 <stdbool.h>
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
bool common_hal_get_serial_connected(void) {
return (bool) serial_connected();
}
bool common_hal_get_serial_bytes_available(void) {
return (bool) serial_bytes_available();
}

View File

@ -0,0 +1,37 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Michael Schroeder
*
* 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_RASPBERRYPI_COMMON_HAL_SUPERVISOR_RUNTIME_H
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_SUPERVISOR_RUNTIME_H
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
// Stores no state currently.
} super_runtime_obj_t;
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_SUPERVISOR_RUNTIME_H

View File

@ -0,0 +1,40 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Michael Schroeder
*
* 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/obj.h"
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/Runtime.h"
// The singleton supervisor.Runtime object, bound to supervisor.runtime
// It currently only has properties, and no state.
const super_runtime_obj_t common_hal_supervisor_runtime_obj = {
.base = {
.type = &supervisor_runtime_type,
},
};

View File

@ -0,0 +1,48 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* SPDX-FileCopyrightText: Copyright (c) 2013, 2014 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 "py/mphal.h"
#include "py/runtime.h"
#include "lib/oofatfs/ff.h" /* FatFs lower layer API */
#include "lib/oofatfs/diskio.h" /* FatFs lower layer API */
#include "lib/timeutils/timeutils.h"
#if CIRCUITPY_RTC
#include "shared-bindings/rtc/RTC.h"
#endif
DWORD get_fattime(void) {
#if CIRCUITPY_RTC
timeutils_struct_time_t tm;
common_hal_rtc_get_time(&tm);
return ((tm.tm_year - 1980) << 25) | (tm.tm_mon << 21) | (tm.tm_mday << 16) |
(tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec >> 1);
#else
return ((2016 - 1980) << 25) | ((9) << 21) | ((1) << 16) | ((16) << 11) | ((43) << 5) | (35 / 2);
#endif
}

251
ports/raspberrypi/link.ld Normal file
View File

@ -0,0 +1,251 @@
/* Based on GCC ARM embedded samples.
Defines the following symbols for use by code:
__exidx_start
__exidx_end
__etext
__data_start__
__preinit_array_start
__preinit_array_end
__init_array_start
__init_array_end
__fini_array_start
__fini_array_end
__data_end__
__bss_start__
__bss_end__
__end__
end
__HeapLimit
__StackLimit
__StackTop
__stack (== StackTop)
*/
MEMORY
{
FLASH_FIRMWARE (rx) : ORIGIN = 0x10000000, LENGTH = 1024k
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256k
SCRATCH_X (rwx) : ORIGIN = 0x20040000, LENGTH = 4k
SCRATCH_Y (rwx) : ORIGIN = 0x20041000, LENGTH = 4k
}
ENTRY(_entry_point)
SECTIONS
{
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
and checksummed. It is usually built by the boot_stage2 target
in the Pico SDK
*/
.flash_begin : {
__flash_binary_start = .;
} > FLASH_FIRMWARE
.boot2 : {
__boot2_start__ = .;
KEEP (*(.boot2))
__boot2_end__ = .;
} > FLASH_FIRMWARE
ASSERT(__boot2_end__ - __boot2_start__ == 256,
"ERROR: Pico second stage bootloader must be 256 bytes in size")
/* The second stage will always enter the image at the start of .text.
The debugger will use the ELF entry point, which is the _entry_point
symbol if present, otherwise defaults to start of .text.
This can be used to transfer control back to the bootrom on debugger
launches only, to perform proper flash setup.
*/
.text : {
__reset_start = .;
KEEP (*(.reset))
. = ALIGN(256);
__reset_end = .;
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
KEEP (*(.vectors))
/* TODO revisit this now memset/memcpy/float in ROM */
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
* FLASH ... we will include any thing excluded here in .data below by default */
*(.init)
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
*(.fini)
/* Pull all c'tors into .text */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* Followed by destructors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.eh_frame*)
. = ALIGN(4);
} > FLASH_FIRMWARE
.rodata : {
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
. = ALIGN(4);
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
. = ALIGN(4);
} > FLASH_FIRMWARE
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH_FIRMWARE
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH_FIRMWARE
__exidx_end = .;
/* Machine inspectable binary information */
. = ALIGN(4);
__binary_info_start = .;
.binary_info :
{
KEEP(*(.binary_info.keep.*))
*(.binary_info.*)
} > FLASH_FIRMWARE
__binary_info_end = .;
. = ALIGN(4);
/* End of .text-like segments */
__etext = .;
.ram_vector_table (COPY): {
*(.ram_vector_table)
} > RAM
.data : {
__data_start__ = .;
*(vtable)
*(.time_critical*)
/* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
*(.text*)
. = ALIGN(4);
*(.rodata*)
. = ALIGN(4);
*(.data*)
. = ALIGN(4);
*(.after_data.*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__mutex_array_start = .);
KEEP(*(SORT(.mutex_array.*)))
KEEP(*(.mutex_array))
PROVIDE_HIDDEN (__mutex_array_end = .);
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(SORT(.preinit_array.*)))
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE_HIDDEN (__fini_array_end = .);
*(.jcr)
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM AT> FLASH_FIRMWARE
.uninitialized_data (COPY): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
/* Start and end symbols must be word-aligned */
.scratch_x : {
__scratch_x_start__ = .;
*(.scratch_x.*)
. = ALIGN(4);
__scratch_x_end__ = .;
} > SCRATCH_X AT > FLASH_FIRMWARE
__scratch_x_source__ = LOADADDR(.scratch_x);
.scratch_y : {
__scratch_y_start__ = .;
*(.scratch_y.*)
. = ALIGN(4);
__scratch_y_end__ = .;
} > SCRATCH_Y AT > FLASH_FIRMWARE
__scratch_y_source__ = LOADADDR(.scratch_y);
.bss : {
. = ALIGN(4);
__bss_start__ = .;
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.heap (COPY):
{
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack*_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later
*
* stack1 section may be empty/missing if platform_launch_core1 is not used */
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
* stack is not used then all of SCRATCH_X is free.
*/
.stack1_dummy (COPY):
{
*(.stack1*)
} > SCRATCH_X
.stack_dummy (COPY):
{
*(.stack*)
} > SCRATCH_Y
.flash_end : {
__flash_binary_end = .;
} > FLASH_FIRMWARE
/* stack limit is poorly named, but historically is maximum heap ptr */
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
/* todo assert on extra code */
}

View File

@ -0,0 +1,46 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 __INCLUDED_MPCONFIGPORT_H
#define __INCLUDED_MPCONFIGPORT_H
#define MICROPY_PY_UJSON (1)
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define CIRCUITPY_DEFAULT_STACK_SIZE (24*1024)
#define MICROPY_USE_INTERNAL_PRINTF (1)
#define CIRCUITPY_PROCESSOR_COUNT (2)
// This also includes mpconfigboard.h.
#include "py/circuitpy_mpconfig.h"
#define MICROPY_PORT_ROOT_POINTERS \
CIRCUITPY_COMMON_ROOT_POINTERS;
#endif // __INCLUDED_MPCONFIGPORT_H

View File

@ -0,0 +1,44 @@
# Define an equivalent for MICROPY_LONGINT_IMPL, to pass to $(MPY-TOOL) in py/mkrules.mk
# $(MPY-TOOL) needs to know what kind of longint to use (if any) to freeze long integers.
# This should correspond to the MICROPY_LONGINT_IMPL definition in mpconfigport.h.
ifeq ($(LONGINT_IMPL),NONE)
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=none
endif
ifeq ($(LONGINT_IMPL),MPZ)
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
endif
ifeq ($(LONGINT_IMPL),LONGLONG)
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=longlong
endif
ifndef CIRCUITPY_RP2PIO
CIRCUITPY_RP2PIO = 1
else
CIRCUITPY_NEOPIXEL_WRITE = 0
endif
CIRCUITPY_FULL_BUILD = 1
CIRCUITPY_PWMIO = 1
# Things that need to be implemented.
CIRCUITPY_AUDIOBUSIO = 0 # Use PIO interally for I2S
CIRCUITPY_AUDIOMP3 = 0
CIRCUITPY_COUNTIO = 0 # Use PWM interally
CIRCUITPY_FREQUENCYIO = 0 # Use PWM interally
CIRCUITPY_I2CPERIPHERAL = 0
CIRCUITPY_NVM = 0
CIRCUITPY_PULSEIO = 0 # Use PIO interally
CIRCUITPY_ROTARYIO = 0 # Use PIO interally
CIRCUITPY_RTC = 0
# Things that are unsupported by the hardware.
CIRCUITPY_AUDIOIO = 0
INTERNAL_LIBM = 1
USB_SERIAL_NUMBER_LENGTH = 32
USB_NUM_EP = 8

View File

@ -0,0 +1,57 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 <string.h>
#include "lib/mp-readline/readline.h"
#include "lib/utils/interrupt_char.h"
#include "py/mphal.h"
#include "py/mpstate.h"
#include "py/runtime.h"
#include "py/smallint.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/time/__init__.h"
#include "supervisor/shared/autoreload.h"
#include "mpconfigboard.h"
#include "mphalport.h"
#include "supervisor/shared/tick.h"
#include "src/rp2_common/hardware_timer/include/hardware/timer.h"
extern uint32_t common_hal_mcu_processor_get_frequency(void);
void mp_hal_delay_us(mp_uint_t delay) {
busy_wait_us_32(delay);
}
void mp_hal_disable_all_interrupts(void) {
common_hal_mcu_disable_interrupts();
}
void mp_hal_enable_all_interrupts(void) {
common_hal_mcu_enable_interrupts();
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_MPHALPORT_H
#define MICROPY_INCLUDED_RASPBERRYPI_MPHALPORT_H
#include "py/obj.h"
#include "lib/oofatfs/ff.h"
#include "supervisor/shared/tick.h"
// Global millisecond tick count (driven by SysTick interrupt).
#define mp_hal_ticks_ms() ((mp_uint_t) supervisor_ticks_ms32())
// Number of bytes in receive buffer
extern volatile uint8_t usb_rx_count;
extern volatile bool mp_cdc_enabled;
int receive_usb(void);
void mp_hal_set_interrupt_char(int c);
void mp_hal_disable_all_interrupts(void);
void mp_hal_enable_all_interrupts(void);
#endif // MICROPY_INCLUDED_RASPBERRYPI_MPHALPORT_H

View File

@ -0,0 +1,67 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "pins.h"
#include "shared-bindings/microcontroller/Pin.h"
// This macro is used to simplify pin definition in boards/<board>/pins.c
#define PIN(p_number) \
const mcu_pin_obj_t pin_GPIO## p_number = { \
{ &mcu_pin_type }, \
.number = p_number \
}
PIN(0);
PIN(1);
PIN(2);
PIN(3);
PIN(4);
PIN(5);
PIN(6);
PIN(7);
PIN(8);
PIN(9);
PIN(10);
PIN(11);
PIN(12);
PIN(13);
PIN(14);
PIN(15);
PIN(16);
PIN(17);
PIN(18);
PIN(19);
PIN(20);
PIN(21);
PIN(22);
PIN(23);
PIN(24);
PIN(25);
PIN(26);
PIN(27);
PIN(28);
PIN(29);

View File

@ -0,0 +1,71 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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.
*/
// DO NOT include this file directly. Use shared-bindings/microcontroller/Pin.h instead to ensure
// that all necessary includes are already included.
#ifndef MICROPY_INCLUDED_RASPBERRYPI_PERIPHERALS_PINS_H
#define MICROPY_INCLUDED_RASPBERRYPI_PERIPHERALS_PINS_H
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
uint8_t number;
} mcu_pin_obj_t;
extern const mcu_pin_obj_t pin_GPIO0;
extern const mcu_pin_obj_t pin_GPIO1;
extern const mcu_pin_obj_t pin_GPIO2;
extern const mcu_pin_obj_t pin_GPIO3;
extern const mcu_pin_obj_t pin_GPIO4;
extern const mcu_pin_obj_t pin_GPIO5;
extern const mcu_pin_obj_t pin_GPIO6;
extern const mcu_pin_obj_t pin_GPIO7;
extern const mcu_pin_obj_t pin_GPIO8;
extern const mcu_pin_obj_t pin_GPIO9;
extern const mcu_pin_obj_t pin_GPIO10;
extern const mcu_pin_obj_t pin_GPIO11;
extern const mcu_pin_obj_t pin_GPIO12;
extern const mcu_pin_obj_t pin_GPIO13;
extern const mcu_pin_obj_t pin_GPIO14;
extern const mcu_pin_obj_t pin_GPIO15;
extern const mcu_pin_obj_t pin_GPIO16;
extern const mcu_pin_obj_t pin_GPIO17;
extern const mcu_pin_obj_t pin_GPIO18;
extern const mcu_pin_obj_t pin_GPIO19;
extern const mcu_pin_obj_t pin_GPIO20;
extern const mcu_pin_obj_t pin_GPIO21;
extern const mcu_pin_obj_t pin_GPIO22;
extern const mcu_pin_obj_t pin_GPIO23;
extern const mcu_pin_obj_t pin_GPIO24;
extern const mcu_pin_obj_t pin_GPIO25;
extern const mcu_pin_obj_t pin_GPIO26;
extern const mcu_pin_obj_t pin_GPIO27;
extern const mcu_pin_obj_t pin_GPIO28;
extern const mcu_pin_obj_t pin_GPIO29;
#endif // MICROPY_INCLUDED_RASPBERRYPI_PERIPHERALS_PINS_H

View File

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

1
ports/raspberrypi/sdk Submodule

@ -0,0 +1 @@
Subproject commit 26653ea81e340cacee55025d110c3e014a252a87

View File

@ -0,0 +1,19 @@
#pragma once
#define PICO_IE_26_29_UNCHANGED_ON_RESET (0)
#define PICO_USE_STACK_GUARDS (0)
#define PICO_ENTER_USB_BOOT_ON_EXIT (0)
#define PICO_USE_OPTIMISTIC_SBRK (0)
#define PICO_NO_HARDWARE (0)
#define PICO_ON_DEVICE (1)
#define PICO_USE_CRT_PRINTF (0)
#define PICO_NO_PRINTF (0)
#define PICO_FLOAT_SUPPORT_ROM_V1 (1)
#define PICO_DOUBLE_SUPPORT_ROM_V1 (1)
#define PICO_STDIO_UART (0)
#define PICO_STDIO_USB (0)
#define PICO_STDIO_SEMIHOSTING (0)
#define PICO_STDIO_IGNORE_NESTED_STDOUT (0)
#define PICO_PRINTF_PICO (0)
#define PICO_PRINTF_NONE (0)
#define PICO_PRINTF_ALWAYS_INCLUDED (1)

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// ----------------------------------------------------------
// THIS FILE IS (NOT) AUTOGENERATED; EDIT when updating sdk/
// ----------------------------------------------------------
#ifndef _PICO_VERSION_H
#define _PICO_VERSION_H
#define PICO_SDK_VERSION_MAJOR 1
#define PICO_SDK_VERSION_MINOR 0
#define PICO_SDK_VERSION_REVISION 0
#define PICO_SDK_VERSION_STRING "1.0.0"
#endif

View File

@ -0,0 +1,131 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "supervisor/internal_flash.h"
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "py/mphal.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "lib/oofatfs/ff.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/usb.h"
#include "src/rp2040/hardware_structs/include/hardware/structs/sio.h"
#include "src/rp2_common/hardware_flash/include/hardware/flash.h"
#include "src/common/pico_binary_info/include/pico/binary_info.h"
#define RESERVED_FLASH 1 * 1024 * 1024
// TODO: Parameterize flash size based on the configured flash.
#define TOTAL_FLASH_SIZE 2 * 1024 * 1024
// TODO: Split the caching out of supervisor/shared/external_flash so we can use it.
#define SECTOR_SIZE 4096
#define NO_CACHE 0xffffffff
STATIC uint8_t _cache[SECTOR_SIZE];
STATIC uint32_t _cache_lba = NO_CACHE;
void supervisor_flash_init(void) {
bi_decl_if_func_used(bi_block_device(
BINARY_INFO_MAKE_TAG('C', 'P'),
"CircuitPython",
RESERVED_FLASH,
TOTAL_FLASH_SIZE - RESERVED_FLASH,
NULL,
BINARY_INFO_BLOCK_DEV_FLAG_READ |
BINARY_INFO_BLOCK_DEV_FLAG_WRITE |
BINARY_INFO_BLOCK_DEV_FLAG_PT_UNKNOWN));
}
uint32_t supervisor_flash_get_block_size(void) {
return FILESYSTEM_BLOCK_SIZE;
}
uint32_t supervisor_flash_get_block_count(void) {
return (TOTAL_FLASH_SIZE - RESERVED_FLASH) / FILESYSTEM_BLOCK_SIZE;
}
void port_internal_flash_flush(void) {
if (_cache_lba == NO_CACHE) {
return;
}
common_hal_mcu_disable_interrupts();
flash_range_erase(RESERVED_FLASH + _cache_lba, SECTOR_SIZE);
flash_range_program(RESERVED_FLASH + _cache_lba, _cache, SECTOR_SIZE);
common_hal_mcu_enable_interrupts();
_cache_lba = NO_CACHE;
}
mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {
memcpy(dest,
(void*)(XIP_BASE + RESERVED_FLASH + block * FILESYSTEM_BLOCK_SIZE),
num_blocks * FILESYSTEM_BLOCK_SIZE);
return 0;
}
mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32_t num_blocks) {
uint32_t blocks_per_sector = SECTOR_SIZE / FILESYSTEM_BLOCK_SIZE;
uint32_t block = 0;
while (block < num_blocks) {
uint32_t block_address = lba + block;
uint32_t sector_offset = block_address / blocks_per_sector * SECTOR_SIZE;
uint8_t block_offset = block_address % blocks_per_sector;
if (_cache_lba != block_address) {
memcpy(_cache,
(void*)(XIP_BASE + RESERVED_FLASH + sector_offset),
SECTOR_SIZE);
_cache_lba = sector_offset;
}
for (uint8_t b = block_offset; b < blocks_per_sector; b++) {
// Stop copying after the last block.
if (block >= num_blocks) {
break;
}
memcpy(_cache + b * FILESYSTEM_BLOCK_SIZE,
src + block * FILESYSTEM_BLOCK_SIZE,
FILESYSTEM_BLOCK_SIZE);
block++;
}
// Make sure we don't have an interrupt while we do flash operations.
common_hal_mcu_disable_interrupts();
flash_range_erase(RESERVED_FLASH + sector_offset, SECTOR_SIZE);
flash_range_program(RESERVED_FLASH + sector_offset, _cache, SECTOR_SIZE);
common_hal_mcu_enable_interrupts();
}
return 0; // success
}
void supervisor_flash_release_cache(void) {
}

View File

@ -0,0 +1,38 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_INTERNAL_FLASH_H
#define MICROPY_INCLUDED_RASPBERRYPI_INTERNAL_FLASH_H
#include <stdbool.h>
#include "mpconfigport.h"
// #define INTERNAL_FLASH_PART1_NUM_BLOCKS (CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE)
// #define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms
// #define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2)
#endif // MICROPY_INCLUDED_RASPBERRYPI_INTERNAL_FLASH_H

View File

@ -0,0 +1,31 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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_RASPBERRYPI_INTERNAL_FLASH_ROOT_POINTERS_H
#define MICROPY_INCLUDED_RASPBERRYPI_INTERNAL_FLASH_ROOT_POINTERS_H
#define FLASH_ROOT_POINTERS
#endif // MICROPY_INCLUDED_RASPBERRYPI_INTERNAL_FLASH_ROOT_POINTERS_H

View File

@ -0,0 +1,200 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 <string.h>
#include <stdlib.h>
#include "supervisor/board.h"
#include "supervisor/port.h"
#include "bindings/rp2pio/StateMachine.h"
#include "genhdr/mpversion.h"
#include "shared-bindings/busio/I2C.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/rtc/__init__.h"
#include "shared-bindings/pwmio/PWMOut.h"
#include "supervisor/shared/safe_mode.h"
#include "supervisor/shared/stack.h"
#include "supervisor/shared/tick.h"
#include "src/rp2040/hardware_structs/include/hardware/structs/watchdog.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
#include "src/rp2_common/hardware_uart/include/hardware/uart.h"
#include "src/rp2_common/hardware_sync/include/hardware/sync.h"
#include "src/rp2_common/hardware_timer/include/hardware/timer.h"
#include "src/common/pico_time/include/pico/time.h"
#include "src/common/pico_binary_info/include/pico/binary_info.h"
#include "tusb.h"
extern volatile bool mp_msc_enabled;
STATIC void _tick_callback(uint alarm_num);
STATIC void _binary_info(void) {
// Binary info readable with `picotool`.
bi_decl(bi_program_name("CircuitPython"));
bi_decl(bi_program_version_string(MICROPY_GIT_TAG));
bi_decl(bi_program_build_date_string(MICROPY_BUILD_DATE));
bi_decl(bi_program_url("https://circuitpython.org"));
bi_decl(bi_program_build_attribute("BOARD=" CIRCUITPY_BOARD_ID));
// TODO: Add build attribute for debug builds. Needs newer CircuitPython with CIRCUITPY_DEBUG.
}
safe_mode_t port_init(void) {
_binary_info();
// Set brown out.
// Reset everything into a known state before board_init.
reset_port();
// For the tick.
hardware_alarm_claim(0);
hardware_alarm_set_callback(0, _tick_callback);
// Check brownout.
if (board_requests_safe_mode()) {
return USER_SAFE_MODE;
}
return NO_SAFE_MODE;
}
void reset_port(void) {
#if CIRCUITPY_BUSIO
reset_i2c();
reset_spi();
#endif
#if CIRCUITPY_RP2PIO
reset_rp2pio_statemachine();
#endif
#if CIRCUITPY_PWMIO
pwmout_reset();
#endif
reset_all_pins();
}
void reset_to_bootloader(void) {
// reset();
while (true) {}
}
void reset_cpu(void) {
// reset();
while (true) {}
}
bool port_has_fixed_stack(void) {
return false;
}
// From the linker script
extern uint32_t __HeapLimit;
extern uint32_t __StackTop;
uint32_t *port_stack_get_limit(void) {
return &__HeapLimit;
}
uint32_t *port_stack_get_top(void) {
return &__StackTop;
}
uint32_t *port_heap_get_bottom(void) {
return port_stack_get_limit();
}
uint32_t *port_heap_get_top(void) {
return port_stack_get_top();
}
void port_set_saved_word(uint32_t value) {
// NOTE: This doesn't survive pressing the reset button (aka toggling RUN).
watchdog_hw->scratch[0] = value;
}
uint32_t port_get_saved_word(void) {
return watchdog_hw->scratch[0];
}
uint64_t port_get_raw_ticks(uint8_t* subticks) {
uint64_t microseconds = time_us_64();
return 1024 * (microseconds / 1000000) + (microseconds % 1000000) / 977;
}
STATIC void _tick_callback(uint alarm_num) {
supervisor_tick();
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
}
// Enable 1/1024 second tick.
void port_enable_tick(void) {
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
}
// Disable 1/1024 second tick.
void port_disable_tick(void) {
// hardware_alarm_cancel(0);
}
// This is called by sleep, we ignore it when our ticks are enabled because
// they'll wake us up earlier. If we don't, we'll mess up ticks by overwriting
// the next RTC wake up time.
void port_interrupt_after_ticks(uint32_t ticks) {
}
void port_idle_until_interrupt(void) {
common_hal_mcu_disable_interrupts();
if (!tud_task_event_ready()) {
// asm volatile ("dsb 0xF":::"memory");
// __wfi();
}
common_hal_mcu_enable_interrupts();
}
/**
* \brief Default interrupt handler for unused IRQs.
*/
__attribute__((used)) void HardFault_Handler(void)
{
#ifdef ENABLE_MICRO_TRACE_BUFFER
// Turn off the micro trace buffer so we don't fill it up in the infinite
// loop below.
REG_MTB_MASTER = 0x00000000 + 6;
#endif
reset_into_safe_mode(HARD_CRASH);
while (true) {
asm("nop;");
}
}

View File

@ -0,0 +1,35 @@
.syntax unified
.cpu cortex-m0
.thumb
.text
.align 2
@ uint cpu_get_regs_and_sp(r0=uint regs[10])
.global cpu_get_regs_and_sp
.thumb
.thumb_func
.type cpu_get_regs_and_sp, %function
cpu_get_regs_and_sp:
@ store registers into given array
str r4, [r0, #0]
str r5, [r0, #4]
str r6, [r0, #8]
str r7, [r0, #12]
push {r1}
mov r1, r8
str r1, [r0, #16]
mov r1, r9
str r1, [r0, #20]
mov r1, r10
str r1, [r0, #24]
mov r1, r11
str r1, [r0, #28]
mov r1, r12
str r1, [r0, #32]
mov r1, r13
str r1, [r0, #36]
pop {r1}
@ return the sp
mov r0, sp
bx lr

View File

@ -0,0 +1,38 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
*
* 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 "lib/tinyusb/src/device/usbd.h"
#include "supervisor/background_callback.h"
#include "supervisor/usb.h"
#include "src/rp2_common/pico_platform/include/pico/platform.h"
#include "src/rp2040/hardware_regs/include/hardware/regs/intctrl.h"
void init_usb_hardware(void) {
}
void __isr __used isr_usbctrl(void) {
usb_irq_handler();
}

View File

@ -51,6 +51,7 @@ BASE_CFLAGS = \
-DCIRCUITPY_SOFTWARE_SAFE_MODE=0x0ADABEEF \
-DCIRCUITPY_CANARY_WORD=0xADAF00 \
-DCIRCUITPY_SAFE_RESTART_WORD=0xDEADBEEF \
-DCIRCUITPY_BOARD_ID="\"$(BOARD)\"" \
--param max-inline-insns-single=500
# Use these flags to debug build times and header includes.
@ -234,6 +235,9 @@ endif
ifeq ($(CIRCUITPY_RANDOM),1)
SRC_PATTERNS += random/%
endif
ifeq ($(CIRCUITPY_RP2PIO),1)
SRC_PATTERNS += rp2pio/%
endif
ifeq ($(CIRCUITPY_ROTARYIO),1)
SRC_PATTERNS += rotaryio/%
endif

View File

@ -228,7 +228,7 @@ typedef long mp_off_t;
#endif
#ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (CIRCUITPY_FULL_BUILD)
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (CIRCUITPY_ULAB || CIRCUITPY_FULL_BUILD)
#endif
#if INTERNAL_FLASH_FILESYSTEM == 0 && QSPI_FLASH_FILESYSTEM == 0 && SPI_FLASH_FILESYSTEM == 0 && !DISABLE_FILESYSTEM
@ -581,13 +581,6 @@ extern const struct _mp_obj_module_t pwmio_module;
#define PWMIO_MODULE
#endif
#if CIRCUITPY_RGBMATRIX
extern const struct _mp_obj_module_t rgbmatrix_module;
#define RGBMATRIX_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_rgbmatrix),(mp_obj_t)&rgbmatrix_module },
#else
#define RGBMATRIX_MODULE
#endif
#if CIRCUITPY_RANDOM
extern const struct _mp_obj_module_t random_module;
#define RANDOM_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module },
@ -595,6 +588,20 @@ extern const struct _mp_obj_module_t random_module;
#define RANDOM_MODULE
#endif
#if CIRCUITPY_RP2PIO
extern const struct _mp_obj_module_t rp2pio_module;
#define RP2PIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_rp2pio),(mp_obj_t)&rp2pio_module },
#else
#define RP2PIO_MODULE
#endif
#if CIRCUITPY_RGBMATRIX
extern const struct _mp_obj_module_t rgbmatrix_module;
#define RGBMATRIX_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_rgbmatrix),(mp_obj_t)&rgbmatrix_module },
#else
#define RGBMATRIX_MODULE
#endif
#if CIRCUITPY_ROTARYIO
extern const struct _mp_obj_module_t rotaryio_module;
#define ROTARYIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_rotaryio), (mp_obj_t)&rotaryio_module },
@ -849,6 +856,7 @@ extern const struct _mp_obj_module_t msgpack_module;
PULSEIO_MODULE \
PWMIO_MODULE \
RANDOM_MODULE \
RP2PIO_MODULE \
RE_MODULE \
RGBMATRIX_MODULE \
ROTARYIO_MODULE \
@ -928,12 +936,15 @@ void supervisor_run_background_tasks_if_tick(void);
#define CIRCUITPY_PYSTACK_SIZE 1536
#endif
// Wait this long imediately after startup to see if we are connected to USB.
#ifndef CIRCUITPY_USB_CONNECTED_SLEEP_DELAY
#define CIRCUITPY_USB_CONNECTED_SLEEP_DELAY 5
#endif
#ifndef CIRCUITPY_PROCESSOR_COUNT
#define CIRCUITPY_PROCESSOR_COUNT (1)
#endif
#define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt"
#define CIRCUITPY_VERBOSE_BLE 0

View File

@ -198,12 +198,18 @@ CFLAGS += -DCIRCUITPY_PULSEIO=$(CIRCUITPY_PULSEIO)
# For now we tie PWMIO to PULSEIO so they always both exist. In CircuitPython 7
# we can enable and disable them separately once PWMOut is removed from `pulseio`.
CIRCUITPY_PWMIO = $(CIRCUITPY_PULSEIO)
CIRCUITPY_PWMIO ?= $(CIRCUITPY_PULSEIO)
CFLAGS += -DCIRCUITPY_PWMIO=$(CIRCUITPY_PWMIO)
CIRCUITPY_RANDOM ?= 1
CFLAGS += -DCIRCUITPY_RANDOM=$(CIRCUITPY_RANDOM)
# CIRCUITPY_RP2PIO is handled in the raspberrypi tree.
# Only for rp2 chips.
# Assume not a rp2 build.
CIRCUITPY_RP2PIO ?= 0
CFLAGS += -DCIRCUITPY_RP2PIO=$(CIRCUITPY_RP2PIO)
CIRCUITPY_RGBMATRIX ?= 0
CFLAGS += -DCIRCUITPY_RGBMATRIX=$(CIRCUITPY_RGBMATRIX)

View File

@ -29,6 +29,7 @@
#include "py/obj.h"
#include "py/mpconfig.h"
#include "py/objtuple.h"
#include "common-hal/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/ResetReason.h"
@ -44,7 +45,13 @@ extern void common_hal_mcu_reset(void);
extern const mp_obj_dict_t mcu_pin_globals;
#if CIRCUITPY_PROCESSOR_COUNT == 1
extern const mcu_processor_obj_t common_hal_mcu_processor_obj;
#elif CIRCUITPY_PROCESSOR_COUNT > 1
extern const mp_rom_obj_tuple_t common_hal_mcu_processor_obj;
#else
#error "Invalid processor count"
#endif
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0

View File

@ -375,7 +375,7 @@ int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t
return r;
}
int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) {
STATIC int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) {
wait_for_ready(self);
uint8_t cmd[2];
@ -420,7 +420,7 @@ int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) {
return 0;
}
int writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
STATIC int writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
common_hal_sdcardio_check_for_deinit(self);
uint32_t nblocks = buf->len / 512;
if (nblocks == 1) {

View File

@ -79,6 +79,8 @@ static void make_sample_code_file(FATFS *fatfs) {
f_open(fatfs, &fs, "/code.py", FA_WRITE | FA_CREATE_ALWAYS);
f_write(&fs, buffer, sizeof(buffer) - 1, &char_written);
f_close(&fs);
#else
make_empty_file(fatfs, "/code.py");
#endif
}

View File

@ -28,7 +28,9 @@
#include "mphalport.h"
#if defined(MICROPY_HW_LED_STATUS)
#include "shared-bindings/digitalio/DigitalInOut.h"
#endif
#include "shared-bindings/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/ResetReason.h"

View File

@ -36,7 +36,9 @@ void supervisor_workflow_reset(void) {
// Not that some chips don't notice when USB is unplugged after first being plugged in,
// so this is not perfect, but tud_suspended() check helps.
bool supervisor_workflow_connecting(void) {
return tud_connected() && !tud_suspended();
return true;
// TODO: Use the below once we've updated TinyUSB for the RP2040.
// return tud_connected() && !tud_suspended();
}
// Return true if host has completed connection to us (such as USB enumeration).

View File

@ -26,6 +26,7 @@ SUPPORTED_PORTS = [
"litex",
"mimxrt10xx",
"nrf",
"raspberrypi",
"stm",
]
@ -47,6 +48,7 @@ extension_by_port = {
"mimxrt10xx": HEX_UF2,
"litex": DFU,
"esp32s2": BIN_UF2,
"raspberrypi": UF2,
}
# Per board overrides

View File

@ -9,10 +9,10 @@ import re
import sys
# Handle size constants with K or M suffixes (allowed in .ld but not in Python).
K_PATTERN = re.compile(r'([0-9]+)K')
K_PATTERN = re.compile(r'([0-9]+)[kK]')
K_REPLACE = r'(\1*1024)'
M_PATTERN = re.compile(r'([0-9]+)M')
M_PATTERN = re.compile(r'([0-9]+)[mM]')
M_REPLACE = r'(\1*1024*1024)'
print()