From c9d2437cc8c9f93ca647e1790f5598eff9b4d996 Mon Sep 17 00:00:00 2001 From: Yilin Sun Date: Tue, 19 Mar 2024 18:30:20 +0800 Subject: [PATCH 1/2] ports: mcx: Initial port for MCXN947 series MCU. Signed-off-by: Yilin Sun --- lib/nxp_driver | 2 +- ports/mcx/Makefile | 321 +++ ports/mcx/board.h | 77 + .../mcx/boards/FRDM_MCXA153/mpconfigboard.mk | 4 + ports/mcx/boards/FRDM_MCXN947/board.c | 529 +++++ ports/mcx/boards/FRDM_MCXN947/clock_config.c | 162 ++ ports/mcx/boards/FRDM_MCXN947/clock_config.h | 86 + ports/mcx/boards/FRDM_MCXN947/interrupts.c | 103 + ports/mcx/boards/FRDM_MCXN947/manifest.py | 1 + ports/mcx/boards/FRDM_MCXN947/mpconfigboard.h | 12 + .../mcx/boards/FRDM_MCXN947/mpconfigboard.mk | 12 + ports/mcx/boards/FRDM_MCXN947/pin_mux.c | 102 + ports/mcx/boards/FRDM_MCXN947/pin_mux.h | 72 + ports/mcx/boards/FRDM_MCXN947/pins.csv | 124 ++ ports/mcx/boards/make-pins.py | 161 ++ ports/mcx/boards/manifest.py | 7 + ports/mcx/boards/mcx_pin_prefix.c | 37 + ports/mcx/boards/mcxn947_af.csv | 125 ++ .../MCXN947/MCXN947_cm33_core0_flash.ld | 249 +++ .../MCXN947/startup_MCXN947_cm33_core0.S | 1948 +++++++++++++++++ .../MCXN947/system_MCXN947_cm33_core0.c | 129 ++ .../MCXN947/system_MCXN947_cm33_core0.h | 108 + ports/mcx/drv_adc.c | 108 + ports/mcx/drv_adc.h | 45 + ports/mcx/drv_i2c.c | 96 + ports/mcx/drv_i2c.h | 50 + ports/mcx/drv_iflash.c | 95 + ports/mcx/drv_iflash.h | 49 + ports/mcx/drv_pin.c | 351 +++ ports/mcx/drv_pin.h | 83 + ports/mcx/drv_pwm.c | 307 +++ ports/mcx/drv_pwm.h | 51 + ports/mcx/drv_spi.c | 79 + ports/mcx/drv_spi.h | 54 + ports/mcx/drv_uart.c | 299 +++ ports/mcx/drv_uart.h | 90 + ports/mcx/hal_pin.c | 227 ++ ports/mcx/hal_pin.h | 84 + ports/mcx/hal_stdio.c | 154 ++ ports/mcx/hal_systick.c | 76 + ports/mcx/machine_adc.c | 107 + ports/mcx/machine_i2c.c | 153 ++ ports/mcx/machine_pin.c | 349 +++ ports/mcx/machine_pin.h | 71 + ports/mcx/machine_pin_defs.h | 106 + ports/mcx/machine_pwm.c | 180 ++ ports/mcx/machine_spi.c | 185 ++ ports/mcx/machine_uart.c | 320 +++ ports/mcx/main.c | 184 ++ ports/mcx/mcx.mk | 31 + ports/mcx/mcx_flash.c | 230 ++ ports/mcx/modmachine.c | 43 + ports/mcx/modmachine.h | 6 + ports/mcx/modmcx.c | 46 + ports/mcx/modmcx.h | 34 + ports/mcx/modos.c | 34 + ports/mcx/modules/_boot.py | 15 + ports/mcx/mpconfigboard_common.h | 38 + ports/mcx/mpconfigport.h | 207 ++ ports/mcx/mphalport.c | 53 + ports/mcx/mphalport.h | 79 + ports/mcx/pendsv.c | 146 ++ ports/mcx/pendsv.h | 44 + ports/mcx/qstrdefsport.h | 2 + ports/mcx/tusb_config.h | 36 + ports/mcx/tusb_port.c | 138 ++ 66 files changed, 9505 insertions(+), 1 deletion(-) create mode 100644 ports/mcx/Makefile create mode 100644 ports/mcx/board.h create mode 100644 ports/mcx/boards/FRDM_MCXA153/mpconfigboard.mk create mode 100644 ports/mcx/boards/FRDM_MCXN947/board.c create mode 100644 ports/mcx/boards/FRDM_MCXN947/clock_config.c create mode 100644 ports/mcx/boards/FRDM_MCXN947/clock_config.h create mode 100644 ports/mcx/boards/FRDM_MCXN947/interrupts.c create mode 100644 ports/mcx/boards/FRDM_MCXN947/manifest.py create mode 100644 ports/mcx/boards/FRDM_MCXN947/mpconfigboard.h create mode 100644 ports/mcx/boards/FRDM_MCXN947/mpconfigboard.mk create mode 100644 ports/mcx/boards/FRDM_MCXN947/pin_mux.c create mode 100644 ports/mcx/boards/FRDM_MCXN947/pin_mux.h create mode 100644 ports/mcx/boards/FRDM_MCXN947/pins.csv create mode 100644 ports/mcx/boards/make-pins.py create mode 100644 ports/mcx/boards/manifest.py create mode 100644 ports/mcx/boards/mcx_pin_prefix.c create mode 100644 ports/mcx/boards/mcxn947_af.csv create mode 100644 ports/mcx/devices/MCXN947/MCXN947_cm33_core0_flash.ld create mode 100644 ports/mcx/devices/MCXN947/startup_MCXN947_cm33_core0.S create mode 100644 ports/mcx/devices/MCXN947/system_MCXN947_cm33_core0.c create mode 100644 ports/mcx/devices/MCXN947/system_MCXN947_cm33_core0.h create mode 100644 ports/mcx/drv_adc.c create mode 100644 ports/mcx/drv_adc.h create mode 100644 ports/mcx/drv_i2c.c create mode 100644 ports/mcx/drv_i2c.h create mode 100644 ports/mcx/drv_iflash.c create mode 100644 ports/mcx/drv_iflash.h create mode 100644 ports/mcx/drv_pin.c create mode 100644 ports/mcx/drv_pin.h create mode 100644 ports/mcx/drv_pwm.c create mode 100644 ports/mcx/drv_pwm.h create mode 100644 ports/mcx/drv_spi.c create mode 100644 ports/mcx/drv_spi.h create mode 100644 ports/mcx/drv_uart.c create mode 100644 ports/mcx/drv_uart.h create mode 100644 ports/mcx/hal_pin.c create mode 100644 ports/mcx/hal_pin.h create mode 100644 ports/mcx/hal_stdio.c create mode 100644 ports/mcx/hal_systick.c create mode 100644 ports/mcx/machine_adc.c create mode 100644 ports/mcx/machine_i2c.c create mode 100644 ports/mcx/machine_pin.c create mode 100644 ports/mcx/machine_pin.h create mode 100644 ports/mcx/machine_pin_defs.h create mode 100644 ports/mcx/machine_pwm.c create mode 100644 ports/mcx/machine_spi.c create mode 100644 ports/mcx/machine_uart.c create mode 100644 ports/mcx/main.c create mode 100644 ports/mcx/mcx.mk create mode 100644 ports/mcx/mcx_flash.c create mode 100644 ports/mcx/modmachine.c create mode 100644 ports/mcx/modmachine.h create mode 100644 ports/mcx/modmcx.c create mode 100644 ports/mcx/modmcx.h create mode 100644 ports/mcx/modos.c create mode 100644 ports/mcx/modules/_boot.py create mode 100644 ports/mcx/mpconfigboard_common.h create mode 100644 ports/mcx/mpconfigport.h create mode 100644 ports/mcx/mphalport.c create mode 100644 ports/mcx/mphalport.h create mode 100644 ports/mcx/pendsv.c create mode 100644 ports/mcx/pendsv.h create mode 100644 ports/mcx/qstrdefsport.h create mode 100644 ports/mcx/tusb_config.h create mode 100644 ports/mcx/tusb_port.c diff --git a/lib/nxp_driver b/lib/nxp_driver index fa5a554c79..485ff6db37 160000 --- a/lib/nxp_driver +++ b/lib/nxp_driver @@ -1 +1 @@ -Subproject commit fa5a554c7944d2a196626f8d3631e44943f9abcc +Subproject commit 485ff6db37e9bc288d33d8c252cbb9dbd48678d3 diff --git a/ports/mcx/Makefile b/ports/mcx/Makefile new file mode 100644 index 0000000000..e56ca803b0 --- /dev/null +++ b/ports/mcx/Makefile @@ -0,0 +1,321 @@ +# Determine which board we are compiling for... +ifdef BOARD_DIR +BOARD ?= $(notdir $(BOARD_DIR:/=)) +else +BOARD ?= FRDM_MCXN947 +BOARD_DIR ?= boards/$(BOARD) +endif + +ifeq ($(wildcard $(BOARD_DIR)/.),) + $(error Invalid BOARD specified: $(BOARD_DIR)) +endif + +BUILD ?= build-$(BOARD) +GIT_SUBMODULES += lib/nxp_driver + +include ../../py/mkenv.mk + +# qstr definitions (must come before including py.mk) +QSTR_DEFS = qstrdefsport.h + +include $(BOARD_DIR)/mpconfigboard.mk + +# MicroPython feature configurations +MICROPY_ROM_TEXT_COMPRESSION ?= 1 + +# File containing description of content to be frozen into firmware. +FROZEN_MANIFEST ?= boards/manifest.py + +# include py core make definitions +include $(TOP)/py/py.mk +include $(TOP)/extmod/extmod.mk + +include mcx.mk + +CROSS_COMPILE ?= arm-none-eabi- + +INC += -I. +INC += -I$(TOP) +INC += -I$(BUILD) + +CFLAGS += $(INC) -Wall -Werror -std=gnu99 -nostdlib $(TARGET_CFLAGS_CPU) $(COPT) + +CFLAGS_BUILTIN ?= -ffreestanding -fno-builtin -fno-lto + +ASFLAGS += $(TARGET_CFLAGS_CPU) + +# Configure floating point support +ifeq ($(MICROPY_FLOAT_IMPL),single) +CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT +CFLAGS += -fsingle-precision-constant +else ifeq ($(MICROPY_FLOAT_IMPL),none) +CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE +endif + +LDFLAGS += -nostdlib \ + $(addprefix -T,devices/$(TARGET_MCU_SERIES)/$(TARGET_MCU_VARIANT)_flash.ld) \ + -Wl,-Map=$(@:.elf=.map) -Wl,--cref -Wl,--gc-sections + +ifneq ($(TARGET_STACK_SIZE),) +LDFLAGS += -Wl,--defsym=__stack_size__=$(TARGET_STACK_SIZE) +endif + +ifneq ($(TARGET_HEAP_SIZE),) +LDFLAGS += -Wl,--defsym=__heap_size__=$(TARGET_HEAP_SIZE) +endif + +CSUPEROPT = -Os # save some code space + +# PIN Generator +AF_FILE = $(TARGET_MCU_AF_FILE) +MAKE_PINS = boards/make-pins.py +PREFIX_FILE = boards/mcx_pin_prefix.c +BOARD_PINS = $(BOARD_DIR)/pins.csv +GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c +GEN_PINS_HDR = $(HEADER_BUILD)/pins.h + +# SDK +SDK_DIR = lib/nxp_driver/sdk +MCUX_DIR = $(SDK_DIR)/devices/$(TARGET_MCU_SERIES) + +TARGET_STARTUP_S = devices/$(TARGET_MCU_SERIES)/startup_$(TARGET_MCU_VARIANT) +TARGET_SYSTEM_C = devices/$(TARGET_MCU_SERIES)/system_$(TARGET_MCU_VARIANT) + +# Tune for Debugging or Optimization +CFLAGS += -g # always include debug info in the ELF +ifeq ($(DEBUG), 1) +CFLAGS += -O0 -DDEBUG +else +CFLAGS += -Os -DNDEBUG +CFLAGS += -fdata-sections -ffunction-sections +endif + +# Hardware & SDK C defines +CFLAGS += \ + -D__START=main \ + -D$(TARGET_MCU_DEF) \ + -DMCUXPRESSO_SDK \ + -D__STARTUP_CLEAR_BSS + +# Hardware & SDK C includes +CFLAGS += \ + -I$(BOARD_DIR) \ + -I$(TOP)/$(SDK_DIR)/CMSIS/Include \ + -I$(TOP)/$(MCUX_DIR) \ + -I$(TOP)/$(MCUX_DIR)/drivers \ + -I$(TOP)/$(MCUX_DIR)/drivers/romapi/flash \ + + +# Flags for optional C++ source code +CXXFLAGS += $(filter-out -std=c99,$(CFLAGS)) + +LIBS = \ + "$(shell $(CC) $(CFLAGS) -print-libgcc-file-name)" + +SRC_C = \ + drv_adc.c \ + drv_i2c.c \ + drv_iflash.c \ + drv_pin.c \ + drv_pwm.c \ + drv_spi.c \ + drv_uart.c \ + hal_pin.c \ + hal_stdio.c \ + hal_systick.c \ + machine_i2c.c \ + machine_pin.c \ + machine_spi.c \ + main.c \ + mcx_flash.c \ + modmcx.c \ + mphalport.c \ + pendsv.c \ + tusb_port.c \ + +SRC_BOARD_C = $(addprefix $(BOARD_DIR)/, \ + board.c \ + clock_config.c \ + interrupts.c \ + pin_mux.c \ + ) + +SRC_SDK_C = $(addprefix $(MCUX_DIR)/, \ + drivers/romapi/flash/src/fsl_flash.c \ + drivers/fsl_clock.c \ + drivers/fsl_common.c \ + drivers/fsl_common_arm.c \ + drivers/fsl_ctimer.c \ + drivers/fsl_gpio.c \ + drivers/fsl_lpadc.c \ + drivers/fsl_lpi2c.c \ + drivers/fsl_lpspi.c \ + drivers/fsl_lpuart.c \ + drivers/fsl_power.c \ + drivers/fsl_reset.c \ + drivers/fsl_spc.c \ + drivers/fsl_vref.c \ + ) + +SRC_DRIVERS_C = $(addprefix drivers/, \ + bus/softspi.c \ + bus/softqspi.c \ + memory/spiflash.c \ + dht/dht.c \ + ) + +# TinyUSB Stack source +SRC_TINYUSB_C += \ + lib/tinyusb/src/class/cdc/cdc_device.c \ + lib/tinyusb/src/class/dfu/dfu_rt_device.c \ + lib/tinyusb/src/class/hid/hid_device.c \ + lib/tinyusb/src/class/midi/midi_device.c \ + lib/tinyusb/src/class/msc/msc_device.c \ + lib/tinyusb/src/class/usbtmc/usbtmc_device.c \ + lib/tinyusb/src/class/vendor/vendor_device.c \ + lib/tinyusb/src/common/tusb_fifo.c \ + lib/tinyusb/src/device/usbd.c \ + lib/tinyusb/src/device/usbd_control.c \ + lib/tinyusb/src/tusb.c + +CFLAGS += \ + -I$(TOP)/lib/tinyusb/hw \ + -I$(TOP)/lib/tinyusb/hw/bsp/mcx \ + -I$(TOP)/lib/tinyusb/src \ + +SRC_C += $(TARGET_SYSTEM_C).c +SRC_O += $(TARGET_STARTUP_S).o + +ifeq ($(TARGET_MCU_HAS_LPFLEXCOMM), 1) +SRC_SDK_C += $(MCUX_DIR)/drivers/fsl_lpflexcomm.c +CFLAGS += -DMICROPY_HW_HAS_LPFLEXCOMM +endif + +ifeq ($(TARGET_MCU_HAS_OSTIMER), 1) +SRC_SDK_C += $(MCUX_DIR)/drivers/fsl_ostimer.c +CFLAGS += -DMICROPY_HW_HAS_OSTIMER +endif + +ifeq ($(TARGET_MCU_HAS_USB_HS), 1) +SRC_TINYUSB_C += lib/tinyusb/src/portable/chipidea/ci_hs/dcd_ci_hs.c +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_MCXN9 +CFLAGS += -DMICROPY_HW_HAS_USB_HS +endif + +ifeq ($(TARGET_MCU_HAS_FLEXSPI), 1) +SRC_SDK_C += $(MCUX_DIR)/drivers/fsl_flexspi.c +CFLAGS += -DMICROPY_HW_HAS_FLEXSPI +endif + +SRC_SHARED_C = $(addprefix shared/,\ + libc/printf.c \ + readline/readline.c \ + runtime/interrupt_char.c \ + runtime/gchelper_native.c \ + runtime/mpirq.c \ + runtime/pyexec.c \ + runtime/stdout_helpers.c \ + runtime/sys_stdio_mphal.c \ + ) + + +$(BUILD)/shared/libc/string0.o: CFLAGS += $(CFLAGS_BUILTIN) + +# LibC sources +SRC_LIBC_C = \ + shared/libc/string0.c + +# LibM sources +SRC_LIBM_C = $(addprefix lib/libm/,\ + acoshf.c \ + asinfacosf.c \ + asinhf.c \ + atan2f.c \ + atanf.c \ + atanhf.c \ + ef_rem_pio2.c \ + erf_lgamma.c \ + fmodf.c \ + kf_cos.c \ + kf_rem_pio2.c \ + kf_sin.c \ + kf_tan.c \ + log1pf.c \ + math.c \ + nearbyintf.c \ + roundf.c \ + sf_cos.c \ + sf_erf.c \ + sf_frexp.c \ + sf_ldexp.c \ + sf_modf.c \ + sf_sin.c \ + sf_tan.c \ + wf_lgamma.c \ + wf_tgamma.c \ + ) + +ifeq ($(SUPPORTS_HARDWARE_FP_SINGLE),1) +SRC_LIBM_C += lib/libm/thumb_vfp_sqrtf.c +else +SRC_LIBM_C += lib/libm/ef_sqrt.c +endif + +SRC_O += \ + shared/runtime/gchelper_thumb2.o + +SRC_QSTR += $(SRC_C) $(SRC_SHARED_C) $(GEN_PINS_SRC) + +# Making OBJ use an order-only dependency on the generated pins.h file +# has the side effect of making the pins.h file before we actually compile +# any of the objects. The normal dependency generation will deal with the +# case when pins.h is modified. But when it doesn't exist, we don't know +# which source files might need it. +$(OBJ): | $(GEN_PINS_HDR) + +OBJ += $(PY_O) +OBJ += $(addprefix $(BUILD)/, $(SRC_O)) +OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_BOARD_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_SDK_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_DRIVERS_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_TINYUSB_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_LIBC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM_C:.c=.o)) +OBJ += $(GEN_PINS_SRC:.c=.o) + +all: $(BUILD)/firmware.hex $(BUILD)/firmware.bin + +# Need correct CPU flags to assemble this file. +$(BUILD)/shared/runtime/gchelper_thumb2.o: $(TOP)/shared/runtime/gchelper_thumb2.s + $(ECHO) "AS $<" + $(Q)$(AS) $(ASFLAGS) -o $@ $< + +# Startup file requires CPP support. +$(BUILD)/$(TARGET_STARTUP_S).o: $(TARGET_STARTUP_S).S + $(ECHO) "AS $<" + $(Q)$(CC) $(CFLAGS) -c -xassembler-with-cpp -o $@ $< + +$(BUILD)/firmware.elf: $(OBJ) + $(ECHO) "LINK $@" + $(Q)$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + $(Q)$(SIZE) $@ + +$(BUILD)/firmware.hex: $(BUILD)/firmware.elf + $(ECHO) "COPY $@" + $(Q)$(OBJCOPY) -Oihex $^ $@ + +$(BUILD)/firmware.bin: $(BUILD)/firmware.elf + $(ECHO) "COPY $@" + $(Q)$(OBJCOPY) -Obinary $^ $@ + +# Use a pattern rule here so that make will only call make-pins.py once to make +# both pins_$(BOARD).c and pins.h +$(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h: $(BOARD_PINS) $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD) + $(ECHO) "GEN $@" + $(Q)$(PYTHON) $(MAKE_PINS) --board-csv $(BOARD_PINS) --af-csv $(AF_FILE) --prefix $(PREFIX_FILE) \ + --output-source $(GEN_PINS_SRC) --output-header $(GEN_PINS_HDR) + +include $(TOP)/py/mkrules.mk diff --git a/ports/mcx/board.h b/ports/mcx/board.h new file mode 100644 index 0000000000..d11c2937b5 --- /dev/null +++ b/ports/mcx/board.h @@ -0,0 +1,77 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_BOARD_H +#define MP_PORT_MCX_BOARD_H + +#include "py/mphal.h" + +typedef void (*mcx_board_isr_t)(void *param); + +void MCX_BoardEarlyInit(void); + +/* UUID */ +int MCX_BoardGetUniqueID(uint64_t *uuid); + +/* GPIO and Port */ +void *MCX_BoardGetPORTInstance(uint8_t id); +void *MCX_BoardGetGPIOInstance(uint8_t id); +int MCX_BoardConfigurePORTClock(uint8_t id); +int MCX_BoardConfigureGPIOClock(uint8_t id); + +/* ADC */ +void *MCX_BoardGetADCInstance(uint8_t id); +int MCX_BoardConfigureADCClock(uint8_t id); + +/* UART */ +void *MCX_BoardGetUARTInstance(uint8_t id); +int MCX_BoardConfigureUARTClock(uint8_t id); +int MCX_BoardConfigureUARTISR(uint8_t id, mcx_board_isr_t isr, void *param); + +/* I2C */ +void *MCX_BoardGetI2CInstance(uint8_t id); +int MCX_BoardConfigureI2CClock(uint8_t id); + +/* SPI */ +void *MCX_BoardGetSPIInstance(uint8_t id); +int MCX_BoardConfigureSPIClock(uint8_t id); + +/* CT32 */ +void *MCX_BoardGetCT32Instance(uint8_t id); +int MCX_BoardConfigureCT32Clock(uint8_t id); + +/* USB HS */ +int MCX_BoardConfigureUSBClock(uint8_t id); +int MCX_BoardConfigureUSBPHY(uint8_t id); +int MCX_BoardConfigureUSBISR(uint8_t id, mcx_board_isr_t isr, void *param); + +/* OSTimer */ +#ifdef MICROPY_HW_HAS_OSTIMER +void *MCX_BoardGetOSTimerInstance(uint8_t id); +int MCX_BoardConfigureOSTimerClock(uint8_t id); +#endif + +#endif diff --git a/ports/mcx/boards/FRDM_MCXA153/mpconfigboard.mk b/ports/mcx/boards/FRDM_MCXA153/mpconfigboard.mk new file mode 100644 index 0000000000..383e49a936 --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXA153/mpconfigboard.mk @@ -0,0 +1,4 @@ +TARGET_MCU_SERIES = MCXA153 +TARGET_MCU_PART = MCXA153VLH +TARGET_MCU_CORE_HAS_DSP = 0 +TARGET_MCU_CORE_HAS_FPU = 0 \ No newline at end of file diff --git a/ports/mcx/boards/FRDM_MCXN947/board.c b/ports/mcx/boards/FRDM_MCXN947/board.c new file mode 100644 index 0000000000..fec9b66398 --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/board.c @@ -0,0 +1,529 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 + +#include "board.h" + +#include "fsl_spc.h" + +#include "clock_config.h" +#include "pin_mux.h" + +typedef struct mcxn947_irq_table_type { + mcx_board_isr_t irq_gpio[5]; + void *irq_gpio_params[5]; + mcx_board_isr_t irq_uart[10]; + void *irq_uart_params[10]; + mcx_board_isr_t irq_ostimer[1]; + void *irq_ostimer_params[1]; + mcx_board_isr_t irq_usb[2]; + void *irq_usb_params[2]; +} mcxn947_irq_table_t; + +typedef struct mcxn947_irqn_prio_type { + IRQn_Type irqn; + uint8_t priority; +} mcxn947_irqn_prio_t; + +static volatile mcxn947_irq_table_t s_mcxn947_irq_table; + +static ADC_Type *const s_mcxn947_adc_inst_map[] = ADC_BASE_PTRS; + +static LPUART_Type *const s_mcxn947_uart_inst_map[] = LPUART_BASE_PTRS; +static LPI2C_Type *const s_mcxn947_i2c_inst_map[] = LPI2C_BASE_PTRS; +static LPSPI_Type *const s_mcxn947_spi_inst_map[] = LPSPI_BASE_PTRS; + +static CTIMER_Type *const s_mcxn947_ctimer_inst_map[] = CTIMER_BASE_PTRS; + +static OSTIMER_Type *const s_mcxn947_ostimer_inst_map[] = OSTIMER_BASE_PTRS; + +static PORT_Type *const s_mcxn947_port_inst_map[] = PORT_BASE_PTRS; +static GPIO_Type *const s_mcxn947_gpio_inst_map[] = GPIO_BASE_PTRS; + +static clock_ip_name_t const s_mcxn947_port_clk_map[] = { + kCLOCK_Port0, + kCLOCK_Port1, + kCLOCK_Port2, + kCLOCK_Port3, + kCLOCK_Port4, + kCLOCK_None, /* Special: PORT5 is in VBAT domain */ +}; + +static clock_ip_name_t const s_mcxn947_gpio_clk_map[] = { + kCLOCK_Gpio0, + kCLOCK_Gpio1, + kCLOCK_Gpio2, + kCLOCK_Gpio3, + kCLOCK_Gpio4, + kCLOCK_None, /* Special: GPIO is in VBAT domain */ +}; + +static clock_attach_id_t const s_mcxn947_adc_clk_att_map[] = { + kFRO12M_to_ADC0, + kFRO12M_to_ADC1, +}; + +static clock_div_name_t const s_mcxn947_adc_clk_div_map[] = { + kCLOCK_DivAdc0Clk, + kCLOCK_DivAdc1Clk, +}; + +static clock_attach_id_t const s_mcxn947_flexcomm_clk_att_map[] = { + kPLL_DIV_to_FLEXCOMM0, + kPLL_DIV_to_FLEXCOMM1, + kPLL_DIV_to_FLEXCOMM2, + kPLL_DIV_to_FLEXCOMM3, + kPLL_DIV_to_FLEXCOMM4, + kPLL_DIV_to_FLEXCOMM5, + kPLL_DIV_to_FLEXCOMM6, + kPLL_DIV_to_FLEXCOMM7, + kPLL_DIV_to_FLEXCOMM8, + kPLL_DIV_to_FLEXCOMM9, +}; + +static clock_div_name_t const s_mcxn947_flexcomm_clk_div_map[] = { + kCLOCK_DivFlexcom0Clk, + kCLOCK_DivFlexcom1Clk, + kCLOCK_DivFlexcom2Clk, + kCLOCK_DivFlexcom3Clk, + kCLOCK_DivFlexcom4Clk, + kCLOCK_DivFlexcom5Clk, + kCLOCK_DivFlexcom6Clk, + kCLOCK_DivFlexcom7Clk, + kCLOCK_DivFlexcom8Clk, + kCLOCK_DivFlexcom9Clk, +}; + +static clock_attach_id_t const s_mcxn947_ctimer_clk_att_map[] = { + kPLL0_to_CTIMER0, + kPLL0_to_CTIMER1, + kPLL0_to_CTIMER2, + kPLL0_to_CTIMER3, + kPLL0_to_CTIMER4, +}; + +static clock_div_name_t const s_mcxn947_ctimer_clk_div_map[] = { + kCLOCK_DivCtimer0Clk, + kCLOCK_DivCtimer1Clk, + kCLOCK_DivCtimer2Clk, + kCLOCK_DivCtimer3Clk, + kCLOCK_DivCtimer4Clk, +}; + +static clock_attach_id_t const s_mcxn947_ostimer_clk_att_map[] = { + kCLK_1M_to_OSTIMER, +}; + +static mcxn947_irqn_prio_t const s_mcxn947_gpio_irqn_map[] = { + {.irqn = GPIO00_IRQn, .priority = 3}, /* TODO: Only IRQ A in use for now. */ + {.irqn = GPIO10_IRQn, .priority = 3}, + {.irqn = GPIO20_IRQn, .priority = 3}, + {.irqn = GPIO30_IRQn, .priority = 3}, + {.irqn = GPIO40_IRQn, .priority = 3}, + {.irqn = GPIO50_IRQn, .priority = 3}, +}; + +static mcxn947_irqn_prio_t const s_mcxn947_flexcomm_irqn_map[] = { + {.irqn = LP_FLEXCOMM0_IRQn, .priority = 3}, + {.irqn = LP_FLEXCOMM1_IRQn, .priority = 3}, + {.irqn = LP_FLEXCOMM2_IRQn, .priority = 3}, + {.irqn = LP_FLEXCOMM3_IRQn, .priority = 3}, + {.irqn = LP_FLEXCOMM4_IRQn, .priority = 3}, + {.irqn = LP_FLEXCOMM5_IRQn, .priority = 3}, + {.irqn = LP_FLEXCOMM6_IRQn, .priority = 3}, + {.irqn = LP_FLEXCOMM7_IRQn, .priority = 3}, + {.irqn = LP_FLEXCOMM8_IRQn, .priority = 3}, + {.irqn = LP_FLEXCOMM9_IRQn, .priority = 3}, +}; + +static mcxn947_irqn_prio_t const s_mcxn947_usb_irqn_map[] = { + {.irqn = USB0_FS_IRQn, .priority = 2}, + {.irqn = USB1_HS_IRQn, .priority = 2}, +}; + +void MCX_BoardEarlyInit(void) { + BOARD_InitBootClocks(); + BOARD_InitBootPins(); + + /* Use PLLDIV clock (50MHz) to clock most of the peripherals. */ + CLOCK_AttachClk(kPLL0_to_PLLCLKDIV); + CLOCK_SetClkDiv(kCLOCK_DivPllClk, 3U); +} + +int MCX_BoardGetUniqueID(uint64_t *uuid) { + /* TODO: Implement this */ + + *uuid = 0xAA55BEEF0066CCFF; + + return 0; +} + +void *MCX_BoardGetPORTInstance(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_port_inst_map)) { + return s_mcxn947_port_inst_map[id]; + } + + return NULL; +} + +void *MCX_BoardGetGPIOInstance(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_gpio_inst_map)) { + return s_mcxn947_gpio_inst_map[id]; + } + + return NULL; +} + +int MCX_BoardConfigurePORTClock(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_port_inst_map)) { + CLOCK_EnableClock(s_mcxn947_port_clk_map[id]); + + return 0; + } + + return -1; +} + +int MCX_BoardConfigureGPIOClock(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_gpio_inst_map)) { + CLOCK_EnableClock(s_mcxn947_gpio_clk_map[id]); + + return 0; + } + + return -1; +} + +int MCX_BoardConfigureGPIOISR(uint8_t id, mcx_board_isr_t isr, void *param) { + if (id >= ARRAY_SIZE(s_mcxn947_irq_table.irq_gpio)) { + return -1; + } + + s_mcxn947_irq_table.irq_gpio[id] = isr; + s_mcxn947_irq_table.irq_gpio_params[id] = param; + + if (isr == NULL) { + DisableIRQ(s_mcxn947_gpio_irqn_map[id].irqn); + } else { + NVIC_SetPriority(s_mcxn947_gpio_irqn_map[id].irqn, s_mcxn947_gpio_irqn_map[id].priority); + EnableIRQ(s_mcxn947_gpio_irqn_map[id].irqn); + } + + return 0; +} + +void MCX_BoardGenericGPIOISR(uint8_t id) { + if (id >= ARRAY_SIZE(s_mcxn947_irq_table.irq_gpio)) { + return; + } + + mcx_board_isr_t isr = s_mcxn947_irq_table.irq_gpio[id]; + + if (isr == NULL) { + return; + } + + isr(s_mcxn947_irq_table.irq_gpio_params[id]); +} + +void *MCX_BoardGetADCInstance(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_adc_inst_map)) { + return s_mcxn947_adc_inst_map[id]; + } + + return NULL; +} + +int MCX_BoardConfigureADCClock(uint8_t id) { + clock_attach_id_t attach_id = kNONE_to_NONE; + clock_div_name_t div_name; + + if (id >= ARRAY_SIZE(s_mcxn947_adc_clk_att_map)) { + return -1; + } + + attach_id = s_mcxn947_adc_clk_att_map[id]; + div_name = s_mcxn947_adc_clk_div_map[id]; + + CLOCK_AttachClk(attach_id); + CLOCK_SetClkDiv(div_name, 1U); + + return CLOCK_GetAdcClkFreq(id); +} + +void *MCX_BoardGetUARTInstance(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_uart_inst_map)) { + return s_mcxn947_uart_inst_map[id]; + } + + /* No such UART */ + return NULL; +} + +void *MCX_BoardGetI2CInstance(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_i2c_inst_map)) { + return s_mcxn947_i2c_inst_map[id]; + } + + /* No such I2C */ + return NULL; +} + +void *MCX_BoardGetSPIInstance(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_spi_inst_map)) { + return s_mcxn947_spi_inst_map[id]; + } + + /* No such SPI */ + return NULL; +} + +static int MCX_BoardConfigureLPFCClock(uint8_t id) { + clock_attach_id_t attach_id = kNONE_to_NONE; + clock_div_name_t div_name; + + if (id >= ARRAY_SIZE(s_mcxn947_flexcomm_clk_att_map)) { + return -1; + } + + attach_id = s_mcxn947_flexcomm_clk_att_map[id]; + div_name = s_mcxn947_flexcomm_clk_div_map[id]; + + CLOCK_AttachClk(attach_id); + CLOCK_SetClkDiv(div_name, 1U); + + return CLOCK_GetLPFlexCommClkFreq(id); +} + +int MCX_BoardConfigureUARTClock(uint8_t id) { + return MCX_BoardConfigureLPFCClock(id); +} + +int MCX_BoardConfigureI2CClock(uint8_t id) { + return MCX_BoardConfigureLPFCClock(id); +} + +int MCX_BoardConfigureSPIClock(uint8_t id) { + return MCX_BoardConfigureLPFCClock(id); +} + +int MCX_BoardConfigureUARTISR(uint8_t id, mcx_board_isr_t isr, void *param) { + if (id >= ARRAY_SIZE(s_mcxn947_irq_table.irq_uart)) { + return -1; + } + + s_mcxn947_irq_table.irq_uart[id] = isr; + s_mcxn947_irq_table.irq_uart_params[id] = param; + + /* Pass NULL as ISR to disable IRQ. */ + if (isr == NULL) { + DisableIRQ(s_mcxn947_flexcomm_irqn_map[id].irqn); + } else { + NVIC_SetPriority(s_mcxn947_flexcomm_irqn_map[id].irqn, s_mcxn947_flexcomm_irqn_map[id].priority); + EnableIRQ(s_mcxn947_flexcomm_irqn_map[id].irqn); + } + + return 0; +} + +void MCX_BoardGenericUARTISR(uint8_t id) { + if (id >= ARRAY_SIZE(s_mcxn947_irq_table.irq_uart)) { + return; + } + + mcx_board_isr_t isr = s_mcxn947_irq_table.irq_uart[id]; + + if (isr == NULL) { + return; + } + + isr(s_mcxn947_irq_table.irq_uart_params[id]); +} + +void *MCX_BoardGetCT32Instance(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_ctimer_inst_map)) { + return s_mcxn947_ctimer_inst_map[id]; + } + + /* No such CTIMER */ + return NULL; +} + +int MCX_BoardConfigureCT32Clock(uint8_t id) { + clock_attach_id_t attach_id = kNONE_to_NONE; + clock_div_name_t div_name; + + if (id >= ARRAY_SIZE(s_mcxn947_ctimer_clk_att_map)) { + return -1; + } + + attach_id = s_mcxn947_ctimer_clk_att_map[id]; + div_name = s_mcxn947_ctimer_clk_div_map[id]; + + CLOCK_AttachClk(attach_id); + CLOCK_SetClkDiv(div_name, 1U); + + return CLOCK_GetCTimerClkFreq(id); +} + +void *MCX_BoardGetOSTimerInstance(uint8_t id) { + if (id < ARRAY_SIZE(s_mcxn947_ostimer_inst_map)) { + return s_mcxn947_ostimer_inst_map[id]; + } + + /* No such OSTimer */ + return NULL; +} + +int MCX_BoardConfigureUSBClock(uint8_t id) { + if (id >= ARRAY_SIZE(s_mcxn947_usb_irqn_map)) { + return -1; + } + + switch (id) { + case 0: { + /* TODO: Configure FS USB here. */ + break; + } + + case 1: { + CLOCK_SetupExtClocking(24000000); + + CLOCK_SetupClockCtrl(kCLOCK_CLKIN_ENA_FM_USBH_LPT); + + CLOCK_EnableClock(kCLOCK_UsbHs); + CLOCK_EnableClock(kCLOCK_UsbHsPhy); + + CLOCK_EnableUsbhsPhyPllClock(kCLOCK_Usbphy480M, 24000000); + CLOCK_EnableUsbhsClock(); + + break; + } + + default: + break; + } + + return 0; +} + +int MCX_BoardConfigureUSBPHY(uint8_t id) { + if (id >= ARRAY_SIZE(s_mcxn947_gpio_irqn_map)) { + return -1; + } + + switch (id) { + case 0: { + /* TODO: Implement this */ + break; + } + + case 1: { + USBPHY->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK | USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; + USBPHY->PWD = 0; + + break; + } + + default: + break; + } + + return 0; +} + +int MCX_BoardConfigureUSBISR(uint8_t id, mcx_board_isr_t isr, void *param) { + if (id >= ARRAY_SIZE(s_mcxn947_irq_table.irq_usb)) { + return -1; + } + + s_mcxn947_irq_table.irq_usb[id] = isr; + s_mcxn947_irq_table.irq_usb_params[id] = param; + + /* Pass NULL as ISR to disable IRQ. */ + if (isr == NULL) { + DisableIRQ(s_mcxn947_usb_irqn_map[id].irqn); + } else { + NVIC_SetPriority(s_mcxn947_usb_irqn_map[id].irqn, s_mcxn947_usb_irqn_map[id].priority); + EnableIRQ(s_mcxn947_usb_irqn_map[id].irqn); + } + + return 0; +} + +void MCX_BoardGenericUSBISR(uint8_t id) { + if (id >= ARRAY_SIZE(s_mcxn947_irq_table.irq_usb)) { + return; + } + + mcx_board_isr_t isr = s_mcxn947_irq_table.irq_usb[id]; + + if (isr == NULL) { + return; + } + + isr(s_mcxn947_irq_table.irq_usb_params[id]); +} + +int MCX_BoardConfigureOSTimerClock(uint8_t id) { + clock_attach_id_t attach_id = kNONE_to_NONE; + + if (id >= ARRAY_SIZE(s_mcxn947_ostimer_clk_att_map)) { + return -1; + } + + attach_id = s_mcxn947_ostimer_clk_att_map[id]; + + CLOCK_AttachClk(attach_id); + + return CLOCK_GetOstimerClkFreq(); +} + +int MCX_BoardConfigureOSTimerISR(uint8_t id, mcx_board_isr_t isr, void *param) { + if (id >= ARRAY_SIZE(s_mcxn947_irq_table.irq_ostimer)) { + return -1; + } + + s_mcxn947_irq_table.irq_ostimer[id] = isr; + s_mcxn947_irq_table.irq_ostimer_params[id] = param; + + return 0; +} + +void MCX_BoardGenericOSTimerISR(uint8_t id) { + if (id >= ARRAY_SIZE(s_mcxn947_irq_table.irq_ostimer)) { + return; + } + + mcx_board_isr_t isr = s_mcxn947_irq_table.irq_ostimer[id]; + + if (isr == NULL) { + return; + } + + isr(s_mcxn947_irq_table.irq_ostimer_params[id]); +} diff --git a/ports/mcx/boards/FRDM_MCXN947/clock_config.c b/ports/mcx/boards/FRDM_MCXN947/clock_config.c new file mode 100644 index 0000000000..0075efff29 --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/clock_config.c @@ -0,0 +1,162 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 NXP + * + * 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 was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ +/* + * How to setup clock using clock driver functions: + * + * 1. Setup clock sources. + * + * 2. Set up wait states of the flash. + * + * 3. Set up all dividers. + * + * 4. Set up all selectors to provide selected clocks. + * + */ + +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Clocks v12.0 +processor: MCXN947 +package_id: MCXN947VDF +mcu_data: ksdk2_0 +processor_version: 0.14.14 + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ + +#include "fsl_clock.h" +#include "clock_config.h" +#include "fsl_spc.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ +/* System clock frequency. */ +extern uint32_t SystemCoreClock; + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ +void BOARD_InitBootClocks(void) { + BOARD_BootClockPLL150M(); +} + + +/******************************************************************************* + ******************** Configuration BOARD_BootClockPLL150M ********************* + ******************************************************************************/ +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!Configuration +name: BOARD_BootClockPLL150M +called_from_default_init: true +outputs: +- {id: CLK_144M_clock.outFreq, value: 144 MHz} +- {id: CLK_48M_clock.outFreq, value: 48 MHz} +- {id: FRO_12M_clock.outFreq, value: 12 MHz} +- {id: FRO_HF_clock.outFreq, value: 48 MHz} +- {id: MAIN_clock.outFreq, value: 150 MHz} +- {id: PLL0_CLK_clock.outFreq, value: 150 MHz} +- {id: Slow_clock.outFreq, value: 37.5 MHz} +- {id: System_clock.outFreq, value: 150 MHz} +- {id: gdet_clock.outFreq, value: 48 MHz} +- {id: trng_clock.outFreq, value: 48 MHz} +settings: +- {id: PLL0_Mode, value: Normal} +- {id: RunPowerMode, value: OD} +- {id: SCGMode, value: PLL0} +- {id: SCG.PLL0M_MULT.scale, value: '50', locked: true} +- {id: SCG.PLL0SRCSEL.sel, value: SCG.FIRC_48M} +- {id: SCG.PLL0_NDIV.scale, value: '8', locked: true} +- {id: SCG.SCSSEL.sel, value: SCG.PLL0_CLK} +- {id: SYSCON.FLEXSPICLKSEL.sel, value: NO_CLOCK} +- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} +- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ + +/******************************************************************************* + * Variables for BOARD_BootClockPLL150M configuration + ******************************************************************************/ +/******************************************************************************* + * Code for BOARD_BootClockPLL150M configuration + ******************************************************************************/ +void BOARD_BootClockPLL150M(void) { + CLOCK_EnableClock(kCLOCK_Scg); /*!< Enable SCG clock */ + + /* FRO OSC setup - begin, attach FRO12M to MainClock for safety switching */ + CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch to FRO 12M first to ensure we can change the clock setting */ + + /* Set the DCDC VDD regulator to 1.2 V voltage level */ + spc_active_mode_dcdc_option_t dcdcOpt = { + .DCDCVoltage = kSPC_DCDC_OverdriveVoltage, + .DCDCDriveStrength = kSPC_DCDC_NormalDriveStrength, + }; + SPC_SetActiveModeDCDCRegulatorConfig(SPC0, &dcdcOpt); + /* Set the LDO_CORE VDD regulator to 1.2 V voltage level */ + spc_active_mode_core_ldo_option_t ldoOpt = { + .CoreLDOVoltage = kSPC_CoreLDO_OverDriveVoltage, + .CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength, + }; + SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOpt); + /* Configure Flash wait-states to support 1.2V voltage level and 150000000Hz frequency */; + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x3U)); + /* Specifies the 1.2V operating voltage for the SRAM's read/write timing margin */ + spc_sram_voltage_config_t sramCfg = { + .operateVoltage = kSPC_sramOperateAt1P2V, + .requestVoltageUpdate = true, + }; + SPC_SetSRAMOperateVoltage(SPC0, &sramCfg); + + CLOCK_SetupFROHFClocking(48000000U); /*!< Enable FRO HF(48MHz) output */ + /*!< Set up PLL0 */ + const pll_setup_t pll0Setup = { + .pllctrl = SCG_APLLCTRL_SOURCE(1U) | SCG_APLLCTRL_SELI(27U) | SCG_APLLCTRL_SELP(13U), + .pllndiv = SCG_APLLNDIV_NDIV(8U), + .pllpdiv = SCG_APLLPDIV_PDIV(1U), + .pllmdiv = SCG_APLLMDIV_MDIV(50U), + .pllRate = 150000000U + }; + CLOCK_SetPLL0Freq(&pll0Setup); /*!< Configure PLL0 to the desired values */ + CLOCK_SetPll0MonitorMode(kSCG_Pll0MonitorDisable); /* Pll0 Monitor is disabled */ + + /*!< Set up clock selectors */ + CLOCK_AttachClk(kPLL0_to_MAIN_CLK); + + /*!< Set up dividers */ + CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); /*!< Set AHBCLKDIV divider to value 1 */ + + /* Set SystemCoreClock variable */ + SystemCoreClock = BOARD_BOOTCLOCKPLL150M_CORE_CLOCK; +} diff --git a/ports/mcx/boards/FRDM_MCXN947/clock_config.h b/ports/mcx/boards/FRDM_MCXN947/clock_config.h new file mode 100644 index 0000000000..601d284078 --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/clock_config.h @@ -0,0 +1,86 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 NXP + * + * 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 was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +#ifndef _CLOCK_CONFIG_H_ +#define _CLOCK_CONFIG_H_ + +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define BOARD_XTAL0_CLK_HZ 24000000U /*!< Board xtal0 frequency in Hz */ + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes default configuration of clocks. + * + */ +void BOARD_InitBootClocks(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockPLL150M ********************* + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockPLL150M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKPLL150M_CORE_CLOCK 150000000U /*!< Core clock frequency: 150000000Hz */ +#define BOARD_BOOTCLOCKPLL150M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ + + +/******************************************************************************* + * API for BOARD_BootClockPLL150M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockPLL150M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +#endif /* _CLOCK_CONFIG_H_ */ diff --git a/ports/mcx/boards/FRDM_MCXN947/interrupts.c b/ports/mcx/boards/FRDM_MCXN947/interrupts.c new file mode 100644 index 0000000000..a4fd51de24 --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/interrupts.c @@ -0,0 +1,103 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "board.h" + +void MCX_BoardGenericGPIOISR(uint8_t id); +void MCX_BoardGenericUARTISR(uint8_t id); +void MCX_BoardGenericUSBISR(uint8_t id); + +void GPIO00_IRQHandler(void) { + MCX_BoardGenericGPIOISR(0); +} + +void GPIO10_IRQHandler(void) { + MCX_BoardGenericGPIOISR(1); +} + +void GPIO20_IRQHandler(void) { + MCX_BoardGenericGPIOISR(2); +} + +void GPIO30_IRQHandler(void) { + MCX_BoardGenericGPIOISR(3); +} + +void GPIO40_IRQHandler(void) { + MCX_BoardGenericGPIOISR(4); +} + +void GPIO50_IRQHandler(void) { + MCX_BoardGenericGPIOISR(5); +} + +void LP_FLEXCOMM0_IRQHandler(void) { + MCX_BoardGenericUARTISR(0); +} + +void LP_FLEXCOMM1_IRQHandler(void) { + MCX_BoardGenericUARTISR(1); +} + +void LP_FLEXCOMM2_IRQHandler(void) { + MCX_BoardGenericUARTISR(2); +} + +void LP_FLEXCOMM3_IRQHandler(void) { + MCX_BoardGenericUARTISR(3); +} + +void LP_FLEXCOMM4_IRQHandler(void) { + MCX_BoardGenericUARTISR(4); +} + +void LP_FLEXCOMM5_IRQHandler(void) { + MCX_BoardGenericUARTISR(5); +} + +void LP_FLEXCOMM6_IRQHandler(void) { + MCX_BoardGenericUARTISR(6); +} + +void LP_FLEXCOMM7_IRQHandler(void) { + MCX_BoardGenericUARTISR(7); +} + +void LP_FLEXCOMM8_IRQHandler(void) { + MCX_BoardGenericUARTISR(8); +} + +void LP_FLEXCOMM9_IRQHandler(void) { + MCX_BoardGenericUARTISR(9); +} + +void USB0_FS_IRQHandler(void) { + MCX_BoardGenericUSBISR(0); +} + +void USB1_HS_IRQHandler(void) { + MCX_BoardGenericUSBISR(1); +} diff --git a/ports/mcx/boards/FRDM_MCXN947/manifest.py b/ports/mcx/boards/FRDM_MCXN947/manifest.py new file mode 100644 index 0000000000..35f4f40b46 --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/manifest.py @@ -0,0 +1 @@ +include("$(BOARD_DIR)/manifest.py") diff --git a/ports/mcx/boards/FRDM_MCXN947/mpconfigboard.h b/ports/mcx/boards/FRDM_MCXN947/mpconfigboard.h new file mode 100644 index 0000000000..1ad35b5849 --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/mpconfigboard.h @@ -0,0 +1,12 @@ +#define MICROPY_HW_BOARD_NAME "FRDM_MCXN947" +#define MICROPY_HW_MCU_NAME "MCXN947VDF" + +#define MICROPY_HW_ENABLE_UART_REPL (1) +#define MICROPY_HW_UART_REPL (4) + +#define MICROPY_HW_ENABLE_USBDEV (1) +#define MICROPY_HW_USBDEV (1) + +#define MICROPY_HW_ENABLE_IFS (1) +#define MICROPY_HW_IFS_START (0x100000U) +#define MICROPY_HW_IFS_LENGTH (0x100000U) diff --git a/ports/mcx/boards/FRDM_MCXN947/mpconfigboard.mk b/ports/mcx/boards/FRDM_MCXN947/mpconfigboard.mk new file mode 100644 index 0000000000..7c83d3641b --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/mpconfigboard.mk @@ -0,0 +1,12 @@ +TARGET_MCU_SERIES = MCXN947 +TARGET_MCU_PART = MCXN947VDF +TARGET_MCU_CORE = cm33_core0 +TARGET_MCU_CORE_HAS_DSP = 1 +TARGET_MCU_CORE_HAS_FPU = 1 +TARGET_MCU_AF_FILE = boards/mcxn947_af.csv + +TARGET_HEAP_SIZE = 0x20000 +TARGET_STACK_SIZE = 0x8000 + +# Extmod settings +MICROPY_VFS_LFS2 = 1 \ No newline at end of file diff --git a/ports/mcx/boards/FRDM_MCXN947/pin_mux.c b/ports/mcx/boards/FRDM_MCXN947/pin_mux.c new file mode 100644 index 0000000000..f65796ddb9 --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/pin_mux.c @@ -0,0 +1,102 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 NXP + * + * 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 was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Pins v14.0 +processor: MCXN947 +package_id: MCXN947VDF +mcu_data: ksdk2_0 +processor_version: 0.14.14 + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +#include "fsl_common.h" +#include "fsl_port.h" +#include "pin_mux.h" + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitBootPins + * Description : Calls initialization functions. + * + * END ****************************************************************************************************************/ +void BOARD_InitBootPins(void) { + BOARD_InitUartConsolePins(); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitUartConsolePins: +- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {pin_num: A1, peripheral: LP_FLEXCOMM4, signal: LPFLEXCOMM_P0, pin_signal: PIO1_8/WUU0_IN10/LPTMR1_ALT3/TRACE_DATA0/FC4_P0/FC5_P4/CT_INP8/SCT0_OUT2/FLEXIO0_D16/PLU_OUT0/ENET0_TXD2/I3C1_SDA/TSI0_CH17/ADC1_A8} + - {pin_num: B1, peripheral: LP_FLEXCOMM4, signal: LPFLEXCOMM_P1, pin_signal: PIO1_9/TRACE_DATA1/FC4_P1/FC5_P5/CT_INP9/SCT0_OUT3/FLEXIO0_D17/PLU_OUT1/ENET0_TXD3/I3C1_SCL/TSI0_CH18/ADC1_A9} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitUartConsolePins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitUartConsolePins(void) { + /* Enables the clock for PORT1: Enables clock */ + CLOCK_EnableClock(kCLOCK_Port1); + + /* PORT1_8 (pin A1) is configured as FC4_P0 */ + PORT_SetPinMux(PORT1, 8U, kPORT_MuxAlt2); + + PORT1->PCR[8] = ((PORT1->PCR[8] & + /* Mask bits to zero which are setting */ + (~(PORT_PCR_IBE_MASK))) + + /* Input Buffer Enable: Enables. */ + | PORT_PCR_IBE(PCR_IBE_ibe1)); + + /* PORT1_9 (pin B1) is configured as FC4_P1 */ + PORT_SetPinMux(PORT1, 9U, kPORT_MuxAlt2); + + PORT1->PCR[9] = ((PORT1->PCR[9] & + /* Mask bits to zero which are setting */ + (~(PORT_PCR_IBE_MASK))) + + /* Input Buffer Enable: Enables. */ + | PORT_PCR_IBE(PCR_IBE_ibe1)); +} +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/ports/mcx/boards/FRDM_MCXN947/pin_mux.h b/ports/mcx/boards/FRDM_MCXN947/pin_mux.h new file mode 100644 index 0000000000..b3a47ac914 --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/pin_mux.h @@ -0,0 +1,72 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 NXP + * + * 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 was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +#ifndef _PIN_MUX_H_ +#define _PIN_MUX_H_ + +/*! + * @addtogroup pin_mux + * @{ + */ + +/*********************************************************************************************************************** + * API + **********************************************************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Calls initialization functions. + * + */ +void BOARD_InitBootPins(void); + +#define PCR_IBE_ibe1 0x01u /*!<@brief Input Buffer Enable: Enables */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitUartConsolePins(void); + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ +#endif /* _PIN_MUX_H_ */ + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/ports/mcx/boards/FRDM_MCXN947/pins.csv b/ports/mcx/boards/FRDM_MCXN947/pins.csv new file mode 100644 index 0000000000..547f29659e --- /dev/null +++ b/ports/mcx/boards/FRDM_MCXN947/pins.csv @@ -0,0 +1,124 @@ +P0_0 ,P0_0 +P0_1 ,P0_1 +P0_2 ,P0_2 +P0_3 ,P0_3 +P0_4 ,P0_4 +P0_5 ,P0_5 +P0_6 ,P0_6 +P0_7 ,P0_7 +P0_8 ,P0_8 +P0_9 ,P0_9 +D9 ,P0_10 +P0_11 ,P0_11 +P0_12 ,P0_12 +P0_13 ,P0_13 +A2 ,P0_14 +A4 ,P0_15 +P0_16 ,P0_16 +P0_17 ,P0_17 +P0_18 ,P0_18 +P0_19 ,P0_19 +P0_20 ,P0_20 +P0_21 ,P0_21 +A3 ,P0_22 +A5 ,P0_23 +D11 ,P0_24 +D13 ,P0_25 +D12 ,P0_26 +D10 ,P0_27 +D8 ,P0_28 +D2 ,P0_29 +D4 ,P0_30 +D7 ,P0_31 +P1_0 ,P1_0 +P1_1 ,P1_1 +D6 ,P1_2 +P1_3 ,P1_3 +P1_4 ,P1_4 +P1_5 ,P1_5 +P1_6 ,P1_6 +P1_7 ,P1_7 +P1_8 ,P1_8 +P1_9 ,P1_9 +P1_10 ,P1_10 +P1_11 ,P1_11 +P1_12 ,P1_12 +P1_13 ,P1_13 +P1_14 ,P1_14 +P1_15 ,P1_15 +P1_16 ,P1_16 +P1_17 ,P1_17 +P1_18 ,P1_18 +P1_19 ,P1_19 +P1_20 ,P1_20 +D5 ,P1_21 +P1_22 ,P1_22 +D3 ,P1_23 +P1_30 ,P1_30 +P1_31 ,P1_31 +P2_0 ,P2_0 +P2_1 ,P2_1 +P2_2 ,P2_2 +P2_3 ,P2_3 +P2_4 ,P2_4 +P2_5 ,P2_5 +P2_6 ,P2_6 +P2_7 ,P2_7 +P2_8 ,P2_8 +P2_9 ,P2_9 +P2_10 ,P2_10 +P2_11 ,P2_11 +P3_0 ,P3_0 +P3_1 ,P3_1 +P3_2 ,P3_2 +P3_3 ,P3_3 +P3_4 ,P3_4 +P3_5 ,P3_5 +P3_6 ,P3_6 +P3_7 ,P3_7 +P3_8 ,P3_8 +P3_9 ,P3_9 +P3_10 ,P3_10 +P3_11 ,P3_11 +P3_12 ,P3_12 +P3_13 ,P3_13 +P3_14 ,P3_14 +P3_15 ,P3_15 +P3_16 ,P3_16 +P3_17 ,P3_17 +P3_18 ,P3_18 +P3_19 ,P3_19 +P3_20 ,P3_20 +P3_21 ,P3_21 +P3_22 ,P3_22 +P3_23 ,P3_23 +D18 ,P4_0 +D19 ,P4_1 +D1 ,P4_2 +D0 ,P4_3 +P4_4 ,P4_4 +P4_5 ,P4_5 +P4_6 ,P4_6 +P4_7 ,P4_7 +P4_12 ,P4_12 +P4_13 ,P4_13 +P4_14 ,P4_14 +P4_15 ,P4_15 +P4_16 ,P4_16 +P4_17 ,P4_17 +P4_18 ,P4_18 +P4_19 ,P4_19 +P4_20 ,P4_20 +P4_21 ,P4_21 +P4_22 ,P4_22 +P4_23 ,P4_23 +P5_0 ,P5_0 +P5_1 ,P5_1 +P5_2 ,P5_2 +P5_3 ,P5_3 +P5_4 ,P5_4 +P5_5 ,P5_5 +P5_6 ,P5_6 +P5_7 ,P5_7 +P5_8 ,P5_8 +P5_9 ,P5_9 diff --git a/ports/mcx/boards/make-pins.py b/ports/mcx/boards/make-pins.py new file mode 100644 index 0000000000..ff03a6afcd --- /dev/null +++ b/ports/mcx/boards/make-pins.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python +"""Creates the pin file for MCX series""" + +import os +import re +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../../tools")) +import boardgen + +# Dictionary contains the supported AF and its regexp to select one +SUPPORTED_AF = { + "GPIO": "P([0-9]+)_([0-9]+)", + "LPFC": "FC([0-9]+)_P([0-9]+)", + "CT32": "CT([0-9]*)_(MAT|INP)([0-9]+)", +} + +ADC_RE = "ADC([0-9]+)_([A-B])([0-9]+)" + + +class MCXPin(boardgen.Pin): + def __init__(self, cpu_pin_name): + super().__init__(cpu_pin_name) + self.__af_table = [] + self.__adc_table = [] + + def add_af(self, af_idx, af_name, af): + if af_name == "ADC": + m = re.match(ADC_RE, af) + if not m: + print("Unable to detect ADC parameter from AF {:s}".format(af)) + else: + self.__af_add_adc(int(m.group(1)), m.group(2), int(m.group(3))) + else: + for k, v in SUPPORTED_AF.items(): + m = re.match(v, af) + if m: + match k: + case "GPIO": + self.__af_add_gpio(af_idx, int(m.group(1)), int(m.group(2))) + case "LPFC": + self.__af_add_flexcomm(af_idx, int(m.group(1)), int(m.group(2))) + case "CT32": + # Instance may be None. + instance = m.group(1) + if instance == "": + instance = "0" + + attribute = "{:s}{:s}".format(m.group(2), m.group(3)) + + self.__af_add_ctimer(af_idx, int(instance), attribute) + case _: + # Simply does not exist. + print("??") + + def definition(self): + port, pin = self.__get_pin_id() + + af_name = "pin_{:d}_{:d}_af".format(port, pin) + + adc_name = "NULL" + if len(self.__adc_table): + adc_name = "&pin_{:d}_{:d}_adc".format(port, pin) + + pin_def = "PIN({:s}, {:d}, {:d}, {:s}, {:s})".format( + self.name(), port, pin, af_name, adc_name + ) + + return pin_def + + def print_source(self, out_source): + port, pin = self.__get_pin_id() + + print("const machine_pin_af_t pin_{:d}_{:d}_af[] = {{".format(port, pin), file=out_source) + for af_item in self.__af_table: + print( + " AF({:d}, {:s}, {:d}, {:s}),".format( + af_item["index"], af_item["type"], af_item["instance"], af_item["attribute"] + ), + file=out_source, + ) + + print("};", file=out_source) + + for adc_item in self.__adc_table: + # Add ADC item entries. + print( + "const machine_pin_adc_t pin_{:d}_{:d}_adc = ADC({:d}, '{:s}', {:d});".format( + port, pin, adc_item["instance"], adc_item["side"], adc_item["channel"] + ), + file=out_source, + ) + + print("", file=out_source) + + def __af_add_adc(self, instance, side, channel): + self.__adc_table.append({"instance": instance, "side": side, "channel": channel}) + + def __af_add_gpio(self, af_idx, instance, attribute): + self.__af_table.append( + { + "type": "GPIO", + "index": af_idx, + "instance": instance, + "attribute": "GPIO_P{:d}".format(attribute), + } + ) + + def __af_add_flexcomm(self, af_idx, instance, attribute): + self.__af_table.append( + { + "type": "LPFC", + "index": af_idx, + "instance": instance, + "attribute": "LPFC_P{:d}".format(attribute), + } + ) + + def __af_add_ctimer(self, af_idx, instance, attribute): + self.__af_table.append( + { + "type": "CT32", + "index": af_idx, + "instance": instance, + "attribute": "CT32_{:s}".format(attribute), + } + ) + + def __get_pin_id(self): + m = re.match("P([0-9]+)_([0-9]+)", self.name()) + if not m: + raise boardgen.PinGeneratorError( + "Port ID not found for given pin {:s}".format(self.name()) + ) + + return int(m.group(1)), int(m.group(2)) + + +class MCXPinGenerator(boardgen.PinGenerator): + def __init__(self): + # Use custom pin type above, and also enable the --af-csv argument. + super().__init__( + pin_type=MCXPin, + enable_af=True, + ) + + def board_name_define_prefix(self): + return "pyb_" + + def parse_af_csv(self, filename): + return super().parse_af_csv(filename, header_rows=1, pin_col=1, af_col=2) + + def print_source(self, out_source): + super().print_source(out_source) + + def print_header(self, out_header): + super().print_header(out_header) + + +if __name__ == "__main__": + MCXPinGenerator().main() diff --git a/ports/mcx/boards/manifest.py b/ports/mcx/boards/manifest.py new file mode 100644 index 0000000000..b7ea74f82e --- /dev/null +++ b/ports/mcx/boards/manifest.py @@ -0,0 +1,7 @@ +include("$(MPY_DIR)/extmod/asyncio") + +require("onewire") +require("ds18x20") +require("dht") + +freeze("$(PORT_DIR)/modules") diff --git a/ports/mcx/boards/mcx_pin_prefix.c b/ports/mcx/boards/mcx_pin_prefix.c new file mode 100644 index 0000000000..fdeb624958 --- /dev/null +++ b/ports/mcx/boards/mcx_pin_prefix.c @@ -0,0 +1,37 @@ +// mcx_pin_prefix.c becomes the initial portion of the generated pins file. + +#include + +#include "py/obj.h" +#include "py/mphal.h" + +#include "extmod/modmachine.h" + +/* Struct definitions */ +#include "machine_pin.h" + +#define AF(p_af_id, p_af_type, p_af_inst, p_af_attr) \ + { \ + .af_id = p_af_id, \ + .af_type = MACHINE_PIN_AF_TYPE_##p_af_type, \ + .af_instance_id = p_af_inst, \ + .af_attribute = MACHINE_PIN_AF_ATTR_##p_af_attr, \ + } + +#define ADC(p_adc_id, p_adc_side, p_adc_channel) \ + { \ + .adc_id = p_adc_id, \ + .adc_side = p_adc_side, \ + .adc_channel = p_adc_channel, \ + } + +#define PIN(p_name, p_port, p_pin, p_af, p_adc) \ + { \ + { &machine_pin_type }, \ + .name = MP_QSTR_##p_name, \ + .port = p_port, \ + .pin = p_pin, \ + .af_count = sizeof(p_af) / sizeof(p_af[0]), \ + .af = p_af, \ + .adc = p_adc, \ + } diff --git a/ports/mcx/boards/mcxn947_af.csv b/ports/mcx/boards/mcxn947_af.csv new file mode 100644 index 0000000000..968563d54d --- /dev/null +++ b/ports/mcx/boards/mcxn947_af.csv @@ -0,0 +1,125 @@ +Port ,Pin ,AF0 ,AF1 ,AF2 ,AF3 ,AF4 ,AF5 ,AF6 ,AF7 ,AF8 ,AF9 ,AF10 ,AF11 ,AF12 ,AF13 ,AF14 ,AF15 ,ADC +PORT1 ,P1_8 ,P1_8 ,TRACE_DATA0 ,FC4_P0 ,FC5_P4 ,CT_INP8 ,SCT0_OUT2 ,FLEXIO0_D16 ,EZH_PIO4 ,PLU_OUT0 ,ENET0_TXD2 ,I3C1_SDA , , , , , ,ADC1_A8 +PORT1 ,P1_9 ,P1_9 ,TRACE_DATA1 ,FC4_P1 ,FC5_P5 ,CT_INP9 ,SCT0_OUT3 ,FLEXIO0_D17 ,EZH_PIO5 ,PLU_OUT1 ,ENET0_TXD3 ,I3C1_SCL , , , , , ,ADC1_A9 +PORT1 ,P1_10 ,P1_10 ,TRACE_DATA2 ,FC4_P2 ,FC5_P6 ,CT2_MAT0 ,SCT0_IN2 ,FLEXIO0_D18 ,EZH_PIO6 ,PLU_IN0 ,ENET0_TXER , ,CAN0_TXD , , , , ,ADC1_A10 +PORT1 ,P1_11 ,P1_11 ,TRACE_DATA3 ,FC4_P3 , ,CT2_MAT1 ,SCT0_IN3 ,FLEXIO0_D19 ,EZH_PIO7 ,PLU_IN1 ,ENET0_RX_CLK ,I3C1_PUR ,CAN0_RXD , , , , ,ADC1_A11 +PORT1 ,P1_12 ,P1_12 ,TRACE_CLK ,FC4_P4 ,FC3_P0 ,CT2_MAT2 ,SCT0_OUT4 ,FLEXIO0_D20 ,EZH_PIO8 ,PLU_OUT2 ,ENET0_RXER , ,CAN1_RXD , , , , ,ADC1_A12 +PORT1 ,P1_13 ,P1_13 ,TRIG_IN3 ,FC4_P5 ,FC3_P1 ,CT2_MAT3 ,SCT0_OUT5 ,FLEXIO0_D21 ,EZH_PIO9 ,PLU_OUT3 ,ENET0_RXDV , ,CAN1_TXD , , , , ,ADC1_A13 +PORT1 ,P1_14 ,P1_14 , ,FC4_P6 ,FC3_P2 ,CT_INP10 ,SCT0_IN4 ,FLEXIO0_D22 ,EZH_PIO10 ,PLU_IN2 ,ENET0_RXD0 , , , , , , ,ADC1_A14 +PORT1 ,P1_15 ,P1_15 , , ,FC3_P3 ,CT_INP11 ,SCT0_IN5 ,FLEXIO0_D23 ,EZH_PIO11 ,PLU_IN3 ,ENET0_RXD1 ,I3C1_PUR , , , , , ,ADC1_A15 +PORT1 ,P1_16 ,P1_16 , ,FC5_P0 ,FC3_P4 ,CT_INP12 ,SCT0_OUT6 ,FLEXIO0_D24 ,EZH_PIO12 ,PLU_OUT4 ,ENET0_RXD2 ,I3C1_SDA , , , , , ,ADC1_A16 +PORT1 ,P1_17 ,P1_17 , ,FC5_P1 ,FC3_P5 ,CT_INP13 ,SCT0_OUT7 ,FLEXIO0_D25 ,EZH_PIO13 ,PLU_OUT5 ,ENET0_RXD3 ,I3C1_SCL , , , , , ,ADC1_A17 +PORT1 ,P1_18 ,P1_18 ,FREQME_CLK_IN0 ,FC5_P2 ,FC3_P6 ,CT3_MAT0 ,SCT0_IN6 ,FLEXIO0_D26 ,EZH_PIO14 ,PLU_IN4 ,ENET0_COL , ,CAN0_TXD , , , , ,ADC1_A18 +PORT1 ,P1_19 ,P1_19 ,FREQME_CLK_IN1 ,FC5_P3 , ,CT3_MAT1 ,SCT0_IN7 ,FLEXIO0_D27 ,EZH_PIO15 ,PLU_IN5 ,ENET0_CRS , ,CAN0_RXD , , , , ,ADC1_A19 +PORT1 ,P1_20 ,P1_20 ,TRIG_IN2 ,FC5_P4 ,FC4_P0 ,CT3_MAT2 ,SCT0_OUT8 ,FLEXIO0_D28 ,EZH_PIO16 ,PLU_OUT6 ,ENET0_MDC , ,CAN1_TXD , , , , ,ADC1_A20 +PORT1 ,P1_21 ,P1_21 ,TRIG_OUT2 ,FC5_P5 ,FC4_P1 ,CT3_MAT3 ,SCT0_OUT9 ,FLEXIO0_D29 ,EZH_PIO17 ,PLU_OUT7 ,ENET0_MDIO ,SAI1_MCLK ,CAN1_RXD , , , , ,ADC1_A21 +PORT1 ,P1_22 ,P1_22 ,TRIG_IN3 ,FC5_P6 ,FC4_P2 ,CT_INP14 ,SCT0_OUT4 ,FLEXIO0_D30 ,EZH_PIO18 , , , , , , , , ,ADC1_A22 +PORT1 ,P1_23 ,P1_23 , , ,FC4_P3 ,CT_INP15 ,SCT0_OUT5 ,FLEXIO0_D31 ,EZH_PIO19 , , , , , , , , ,ADC1_A23 +PORT1 ,P1_30 ,P1_30 ,TRIG_OUT3 , , ,CT_INP16 ,SCT0_OUT8 , , , , ,SAI0_MCLK , , , , , , +PORT1 ,P1_31 ,P1_31 ,TRIG_IN4 , , ,CT_INP17 ,SCT0_OUT9 , , , , , , , , , , , +PORT2 ,P2_0 ,P2_0 ,TRIG_IN5 ,FC9_P6 ,uSDHC0_DATA5 ,SCT0_IN0 ,PWM1_A3 ,FLEXIO0_D8 ,EZH_PIO20 ,FLEXSPI0_B_SS1_b, ,SAI0_RX_BCLK ,ESPI0_RST , , , , , +PORT2 ,P2_1 ,P2_1 ,TRACE_CLK , ,uSDHC0_DATA4 ,SCT0_IN1 ,PWM1_B3 ,FLEXIO0_D9 ,EZH_PIO21 ,FLEXSPI0_B_DQS ,SINC0_MCLK_OUT0 ,SAI0_RX_FS ,ESPI0_NOTIFY , , , , , +PORT2 ,P2_2 ,P2_2 ,CLKOUT ,FC9_P3 ,uSDHC0_DATA1 ,SCT0_OUT0 ,PWM1_A2 ,FLEXIO0_D10 ,EZH_PIO22 ,FLEXSPI0_B_SS0_b,SINC0_MCLK0 ,SAI0_TXD0 ,ESPI0_CSn , , , , , +PORT2 ,P2_3 ,P2_3 , ,FC9_P1 ,uSDHC0_DATA0 ,SCT0_OUT1 ,PWM1_B2 ,FLEXIO0_D11 ,EZH_PIO23 ,FLEXSPI0_B_SCLK ,SINC0_MBIT0 ,SAI0_RXD0 ,ESPI0_CLK , , , , , +PORT2 ,P2_4 ,P2_4 , ,FC9_P0 ,uSDHC0_CLK ,SCT0_OUT2 ,PWM1_A1 ,FLEXIO0_D12 ,EZH_PIO24 ,FLEXSPI0_B_DATA0,SINC0_MCLK1 ,SAI0_RXD1 ,ESPI0_DATA0 , , , , , +PORT2 ,P2_5 ,P2_5 ,TRIG_OUT3 ,FC9_P2 ,uSDHC0_CMD ,SCT0_OUT3 ,PWM1_B1 ,FLEXIO0_D13 ,EZH_PIO25 ,FLEXSPI0_B_DATA1,SINC0_MBIT1 ,SAI0_TXD1 ,ESPI0_DATA1 , , , , , +PORT2 ,P2_6 ,P2_6 ,TRIG_IN4 ,FC9_P4 ,uSDHC0_DATA3 ,SCT0_OUT4 ,PWM1_A0 ,FLEXIO0_D14 ,EZH_PIO26 ,FLEXSPI0_B_DATA2,SINC0_MCLK2 ,SAI0_TX_BCLK ,ESPI0_DATA2 , , , , , +PORT2 ,P2_7 ,P2_7 ,TRIG_IN5 ,FC9_P5 ,uSDHC0_DATA2 ,SCT0_OUT5 ,PWM1_B0 ,FLEXIO0_D15 ,EZH_PIO27 ,FLEXSPI0_B_DATA3,SINC0_MBIT2 ,SAI0_TX_FS ,ESPI0_DATA3 , , , , , +PORT2 ,P2_8 ,P2_8 ,TRACE_DATA0 , ,uSDHC0_DATA7 ,SCT0_IN2 ,PWM1_X0 ,FLEXIO0_D16 ,EZH_PIO28 ,FLEXSPI0_B_DATA4,SINC0_MCLK3 ,SAI1_TXD0 , , , , , , +PORT2 ,P2_9 ,P2_9 ,TRACE_DATA1 , ,uSDHC0_DATA6 ,SCT0_IN3 ,PWM1_X1 ,FLEXIO0_D17 ,EZH_PIO29 ,FLEXSPI0_B_DATA5,SINC0_MBIT3 ,SAI1_RXD0 , , , , , , +PORT2 ,P2_10 ,P2_10 ,TRACE_DATA2 , , ,SCT0_IN4 ,PWM1_X2 ,FLEXIO0_D18 ,EZH_PIO31 ,FLEXSPI0_B_DATA6,SINC0_MCLK4 ,SAI1_RXD1 , , , , , , +PORT2 ,P2_11 ,P2_11 ,TRACE_DATA3 , , ,SCT0_IN5 ,PWM1_X3 ,FLEXIO0_D19 ,EZH_PIO30 ,FLEXSPI0_B_DATA7,SINC0_MBIT4 ,SAI1_TXD1 , , , , , , +PORT4 ,P4_0 ,P4_0 ,TRIG_IN6 ,FC2_P0 , ,CT_INP16 , , ,EZH_PIO24 ,PLU_IN0 ,SINC0_MCLK3 , , , , , , , +PORT4 ,P4_1 ,P4_1 ,TRIG_IN7 ,FC2_P1 , ,CT_INP17 , , ,EZH_PIO25 ,PLU_IN1 , , , , , , , , +PORT4 ,P4_2 ,P4_2 ,TRIG_IN6 ,FC2_P2 , ,CT_INP12 , , ,EZH_PIO26 ,PLU_IN2 ,SINC0_MBIT3 , , , , , , ,ADC1_A4 +PORT4 ,P4_3 ,P4_3 ,TRIG_IN7 ,FC2_P3 , ,CT_INP13 , , ,EZH_PIO27 ,PLU_IN3 , , , , , , , ,ADC1_B4 +PORT4 ,P4_4 ,P4_4 , ,FC2_P4 , ,CT_INP14 , , ,EZH_PIO28 ,PLU_IN4 ,SINC0_MCLK4 , , , , , , , +PORT4 ,P4_5 ,P4_5 , ,FC2_P5 , ,CT_INP15 , , ,EZH_PIO29 ,PLU_IN5 ,SINC0_MBIT4 , , , , , , , +PORT4 ,P4_6 ,P4_6 ,TRIG_OUT4 ,FC2_P6 , ,CT_INP18 , , ,EZH_PIO30 ,PLU_CLK , , , , , , , , +PORT4 ,P4_7 ,P4_7 , , , ,CT_INP19 , , ,EZH_PIO31 , , , , , , , , , +PORT4 ,P4_12 ,P4_12 ,USB0_VBUS_DET ,FC2_P0 , ,CT4_MAT0 , ,FLEXIO0_D20 , ,PLU_OUT0 ,SINC0_MCLK0 , ,CAN0_RXD , , , , ,ADC1_A5 +PORT4 ,P4_13 ,P4_13 ,TRIG_IN8 ,FC2_P1 ,USB1_OTGn_ID ,CT4_MAT1 , ,FLEXIO0_D21 , ,PLU_OUT1 ,SINC0_MBIT0 , ,CAN0_TXD , , , , ,ADC1_B5 +PORT4 ,P4_14 ,P4_14 , , , ,CT4_MAT2 , ,FLEXIO0_D22 , ,PLU_OUT2 , , , , , , , , +PORT4 ,P4_15 ,P4_15 ,TRIG_OUT4 , ,#N/A ,CT4_MAT3 , ,FLEXIO0_D23 , ,PLU_OUT3 ,SINC0_MCLK_OUT0 , ,CAN1_RXD , , , , ,ADC0_A1 +PORT4 ,P4_16 ,P4_16 , ,FC2_P2 ,USB1_OTGn_PWR ,CT3_MAT0 , ,FLEXIO0_D24 , ,PLU_OUT4 ,SINC0_MCLK1 , ,CAN1_TXD , , , , ,ADC0_A6 +PORT4 ,P4_17 ,P4_17 ,TRIG_IN9 ,FC2_P3 ,USB1_OTGn_OC ,CT3_MAT1 , ,FLEXIO0_D25 , ,PLU_OUT5 ,SINC0_MBIT1 , , , , , , ,ADC0_B6 +PORT4 ,P4_18 ,P4_18 , , , ,CT3_MAT2 , ,FLEXIO0_D26 , ,PLU_OUT6 , , , , , , , , +PORT4 ,P4_19 ,P4_19 ,TRIG_OUT5 , , ,CT3_MAT3 , ,FLEXIO0_D27 , ,PLU_OUT7 ,SINC0_MCLK_OUT1 , , , , , , ,ADC0_B1 +PORT4 ,P4_20 ,P4_20 ,TRIG_IN8 ,FC2_P4 , ,CT2_MAT0 , ,FLEXIO0_D28 , , ,SINC0_MCLK2 , , , , , , ,ADC1_A6 +PORT4 ,P4_21 ,P4_21 ,TRIG_IN9 ,FC2_P5 , ,CT2_MAT1 , ,FLEXIO0_D29 , , ,SINC0_MBIT2 , , , , , , ,ADC1_B6 +PORT4 ,P4_22 ,P4_22 , , , ,CT2_MAT2 , ,FLEXIO0_D30 , , , , , , , , , , +PORT4 ,P4_23 ,P4_23 ,TRIG_OUT5 ,FC2_P6 , ,CT2_MAT3 , ,FLEXIO0_D31 , , ,SINC0_MCLK_OUT2 , , , , , , ,ADC1_B3 +PORT5 ,P5_0 ,P5_0 ,TRIG_IN10 ,LPTMR0_ALT2 , , , , , , , , , , , , , ,ADC1_B8 +PORT5 ,P5_1 ,P5_1 ,TRIG_OUT6 ,LPTMR1_ALT2 , , , , , , , , , , , , , ,ADC1_B9 +PORT5 ,P5_2 ,P5_2 ,VBAT_WAKEUP_b ,SPC_LPREQ ,TAMPER0 , , , , , , , , , , , , ,ADC1_B10 +PORT5 ,P5_3 ,P5_3 ,TRIG_IN11 ,RTC_CLKOUT ,TAMPER1 , , , , , , , , , , , , ,ADC1_B11 +PORT5 ,P5_4 ,P5_4 ,TRIG_OUT7 ,SPC_LPREQ ,TAMPER2 , , , , , , , , , , , , ,ADC1_B12 +PORT5 ,P5_5 ,P5_5 ,TRIG_IN10 ,LPTMR0_ALT2 ,TAMPER3 , , , , , , , , , , , , ,ADC1_B13 +PORT5 ,P5_6 ,P5_6 ,TRIG_OUT6 ,LPTMR1_ALT2 ,TAMPER4 , , , , , , , , , , , , ,ADC1_B14 +PORT5 ,P5_7 ,P5_7 ,TRIG_IN11 , ,TAMPER5 , , , , , , , , , , , , ,ADC1_B15 +PORT5 ,P5_8 ,P5_8 ,TRIG_OUT7 , ,TAMPER6 , , , , , , , , , , , , ,ADC1_B16 +PORT5 ,P5_9 ,P5_9 , , ,TAMPER7 , , , , , , , , , , , , ,ADC1_B17 +PORT3 ,P3_23 ,P3_23 , , ,FC6_P3 ,CT_INP11 ,PWM1_X3 ,FLEXIO0_D31 ,EZH_PIO23 , , ,SAI1_TXD1 , , , , , , +PORT3 ,P3_22 ,P3_22 , ,FC8_P6 ,FC6_P2 ,CT_INP10 ,PWM1_X2 ,FLEXIO0_D30 ,EZH_PIO22 , ,SIM0_VCCEN ,SAI1_RXD1 , , , , , , +PORT3 ,P3_21 ,P3_21 ,TRIG_OUT1 ,FC8_P5 ,FC6_P1 ,CT2_MAT3 ,PWM1_B3 ,FLEXIO0_D29 ,EZH_PIO21 , ,SIM0_RST ,SAI1_RXD0 ,PF_SPI_CS1_DIS_n, , , , , +PORT3 ,P3_20 ,P3_20 ,TRIG_OUT0 ,FC8_P4 ,FC6_P0 ,CT2_MAT2 ,PWM1_A3 ,FLEXIO0_D28 ,EZH_PIO20 , ,SIM0_PD ,SAI1_TXD0 ,PF_SPI_CS0_DIS_n, , , , , +PORT3 ,P3_19 ,P3_19 , ,FC7_P6 , ,CT2_MAT1 ,PWM1_X1 ,FLEXIO0_D27 ,EZH_PIO19 , , ,SAI1_RX_FS , , , , , , +PORT3 ,P3_18 ,P3_18 , , ,FC6_P6 ,CT2_MAT0 ,PWM1_X0 ,FLEXIO0_D26 ,EZH_PIO18 , , ,SAI1_RX_BCLK , , , , , , +PORT3 ,P3_17 ,P3_17 , ,FC8_P3 , ,CT_INP9 ,PWM1_B2 ,FLEXIO0_D25 ,EZH_PIO17 , ,SIM0_IO ,SAI1_TX_FS , , , , , , +PORT3 ,P3_16 ,P3_16 , ,FC8_P2 , ,CT_INP8 ,PWM1_A2 ,FLEXIO0_D24 ,EZH_PIO16 , ,SIM0_CLK ,SAI1_TX_BCLK , , , , , , +PORT3 ,P3_15 ,P3_15 , ,FC8_P1 , ,CT_INP7 ,PWM1_B1 ,FLEXIO0_D23 ,EZH_PIO15 ,FLEXSPI0_A_DATA7, ,SAI0_RX_FS ,PF_SPI_SCKIN , , , , , +PORT3 ,P3_14 ,P3_14 , ,FC8_P0 , ,CT_INP6 ,PWM1_A1 ,FLEXIO0_D22 ,EZH_PIO14 ,FLEXSPI0_A_DATA6, ,SAI0_RX_BCLK ,PF_SPI_DATA , , , , , +PORT3 ,P3_13 ,P3_13 , ,FC7_P5 ,FC6_P5 ,CT1_MAT3 ,PWM1_B0 ,FLEXIO0_D21 ,EZH_PIO13 ,FLEXSPI0_A_DATA5, ,SAI0_TXD1 ,PF_SPI_CS0_n , , , , , +PORT3 ,P3_12 ,P3_12 , ,FC7_P4 ,FC6_P4 ,CT1_MAT2 ,PWM1_A0 ,FLEXIO0_D20 ,EZH_PIO12 ,FLEXSPI0_A_DATA4, ,SAI0_RXD1 , , , , , , +PORT3 ,P3_11 ,P3_11 , ,FC6_P3 ,FC7_P5 ,CT1_MAT1 ,PWM0_B3 ,FLEXIO0_D19 ,EZH_PIO11 ,FLEXSPI0_A_DATA3,SIM0_IO ,SAI0_RXD0 ,PF_QSPI_DATA3 , , , , , +PORT3 ,P3_10 ,P3_10 , ,FC6_P2 ,FC7_P4 ,CT1_MAT0 ,PWM0_A3 ,FLEXIO0_D18 ,EZH_PIO10 ,FLEXSPI0_A_DATA2,SIM0_CLK ,SAI0_TXD0 ,PF_QSPI_DATA2 , , , , , +PORT3 ,P3_9 ,P3_9 , ,FC6_P5 ,FC7_P2 ,CT_INP5 ,PWM0_B2 ,FLEXIO0_D17 ,EZH_PIO9 ,FLEXSPI0_A_DATA1,SIM0_RST ,SAI0_TX_FS ,PF_QSPI_DATA1 , , , , , +PORT3 ,P3_8 ,P3_8 , ,FC6_P4 ,FC7_P0 ,CT_INP4 ,PWM0_A2 ,FLEXIO0_D16 ,EZH_PIO8 ,FLEXSPI0_A_DATA0,SIM0_PD ,SAI0_TX_BCLK ,PF_QSPI_DATA0 , , , , , +PORT3 ,P3_7 ,P3_7 , ,FC6_P6 ,FC7_P1 ,CT4_MAT3 ,PWM0_B1 ,FLEXIO0_D15 ,EZH_PIO7 ,FLEXSPI0_A_SCLK ,SIM0_VCCEN ,SAI0_MCLK ,PF_QSPI_SCKIN , , , , , +PORT3 ,P3_6 ,P3_6 ,CLKOUT ,FC6_P1 , ,CT4_MAT2 ,PWM0_A1 ,FLEXIO0_D14 ,EZH_PIO6 ,FLEXSPI0_A_DQS ,SIM1_VCCEN ,SAI1_MCLK ,PF_QSPI_CS_n ,FREQME_CLK_OUT1 , , , , +PORT3 ,P3_5 ,P3_5 , ,FC7_P3 , ,CT_INP19 ,PWM0_X3 ,FLEXIO0_D13 ,EZH_PIO5 , ,SIM1_IO , , , , , , , +PORT3 ,P3_4 ,P3_4 , ,FC7_P2 , ,CT_INP18 ,PWM0_X2 ,FLEXIO0_D12 ,EZH_PIO4 , ,SIM1_CLK , , , , , , , +PORT3 ,P3_3 ,P3_3 , ,FC7_P1 , ,CT4_MAT1 ,PWM0_X1 ,FLEXIO0_D11 ,EZH_PIO3 , ,SIM1_RST , , , , , , , +PORT3 ,P3_2 ,P3_2 , ,FC7_P0 , ,CT4_MAT0 ,PWM0_X0 ,FLEXIO0_D10 ,EZH_PIO2 , ,SIM1_PD , , , , , , , +PORT3 ,P3_1 ,P3_1 ,TRIG_IN1 ,FC6_P0 ,FC7_P6 ,CT_INP17 ,PWM0_B0 ,FLEXIO0_D9 ,EZH_PIO1 ,FLEXSPI0_A_SS1_b, , ,PF_QSPI_CS1_DIS ,FREQME_CLK_OUT0 , , , , +PORT3 ,P3_0 ,P3_0 ,TRIG_IN0 , ,FC7_P3 ,CT_INP16 ,PWM0_A0 ,FLEXIO0_D8 ,EZH_PIO0 ,FLEXSPI0_A_SS0_b, , ,PF_QSPI_CS0_DIS , , , , , +PORT0 ,P0_0 ,P0_0 ,TMS/SWDIO ,FC1_P0 , ,CT_INP0 , , , , , , , , , , , , +PORT0 ,P0_1 ,P0_1 ,TCLK/SWCLK ,FC1_P1 , ,CT_INP1 , , , , , , , , , , , , +PORT0 ,P0_2 ,P0_2 ,TDO/SWO ,FC1_P2 , ,CT0_MAT0 ,UTICK_CAP0 , , , , ,I3C0_PUR , , , , , , +PORT0 ,P0_3 ,P0_3 ,TDI ,FC1_P3 , ,CT0_MAT1 ,UTICK_CAP1 , , ,HSCMP0_OUT , , , , , , , , +PORT0 ,P0_4 ,P0_4 ,EWM0_IN ,FC0_P0 ,FC1_P4 ,CT0_MAT2 ,UTICK_CAP2 , , ,HSCMP1_OUT ,PDM0_CLK , , , , , , , +PORT0 ,P0_5 ,P0_5 ,EWM0_OUT_b ,FC0_P1 ,FC1_P5 ,CT0_MAT3 ,UTICK_CAP3 , , , ,PDM0_DATA0 , , , , , , , +PORT0 ,P0_6 ,P0_6 ,ISPMODE_N ,FC0_P2 ,FC1_P6 ,CT_INP2 , , , ,HSCMP2_OUT ,PDM0_DATA1 , , ,CLKOUT , , , , +PORT0 ,P0_7 ,P0_7 , ,FC0_P3 , ,CT_INP3 , , , , , , , , , , , , +PORT0 ,P0_8 ,P0_8 , ,FC0_P4 , ,CT_INP0 , ,FLEXIO0_D0 , , , , , , , , , ,ADC0_B8 +PORT0 ,P0_9 ,P0_9 , ,FC0_P5 , ,CT_INP1 , ,FLEXIO0_D1 , , , , , , , , , ,ADC0_B9 +PORT0 ,P0_10 ,P0_10 , ,FC0_P6 , ,CT0_MAT0 , ,FLEXIO0_D2 , , , , , , , , , ,ADC0_B10 +PORT0 ,P0_11 ,P0_11 , , , ,CT0_MAT1 , ,FLEXIO0_D3 , ,HSCMP2_OUT , , , , , , , ,ADC0_B11 +PORT0 ,P0_12 ,P0_12 , ,FC1_P4 ,FC0_P0 ,CT0_MAT2 , ,FLEXIO0_D4 , , , , , , , , , ,ADC0_B12 +PORT0 ,P0_13 ,P0_13 , ,FC1_P5 ,FC0_P1 ,CT0_MAT3 , ,FLEXIO0_D5 , , , , , , , , , ,ADC0_B13 +PORT0 ,P0_14 ,P0_14 , ,FC1_P6 ,FC0_P2 ,CT_INP2 ,UTICK_CAP0 ,FLEXIO0_D6 , , , , , , , , , ,ADC0_B14 +PORT0 ,P0_15 ,P0_15 , , ,FC0_P3 ,CT_INP3 ,UTICK_CAP1 ,FLEXIO0_D7 , , , , , , , , , ,ADC0_B15 +PORT0 ,P0_16 ,P0_16 , ,FC0_P0 , ,CT0_MAT0 ,UTICK_CAP2 ,FLEXIO0_D0 , , ,PDM0_CLK ,I3C0_SDA , , , , , ,ADC0_A8 +PORT0 ,P0_17 ,P0_17 , ,FC0_P1 , ,CT0_MAT1 ,UTICK_CAP3 ,FLEXIO0_D1 , , ,PDM0_DATA0 ,I3C0_SCL , , , , , ,ADC0_A9 +PORT0 ,P0_18 ,P0_18 ,EWM0_IN ,FC0_P2 , ,CT0_MAT2 , ,FLEXIO0_D2 , ,HSCMP0_OUT ,PDM0_DATA1 , , , , , , ,ADC0_A10 +PORT0 ,P0_19 ,P0_19 ,EWM0_OUT_b ,FC0_P3 , ,CT0_MAT3 , ,FLEXIO0_D3 , ,HSCMP1_OUT , , , , , , , ,ADC0_A11 +PORT0 ,P0_20 ,P0_20 , ,FC0_P4 ,FC1_P0 ,CT_INP0 , ,FLEXIO0_D4 , , , ,I3C0_SDA , , , , , ,ADC0_A12 +PORT0 ,P0_21 ,P0_21 , ,FC0_P5 ,FC1_P1 ,CT_INP1 , ,FLEXIO0_D5 , , , ,I3C0_SCL , , , , , ,ADC0_A13 +PORT0 ,P0_22 ,P0_22 ,EWM0_IN ,FC0_P6 ,FC1_P2 ,CT_INP2 , ,FLEXIO0_D6 , , , ,I3C0_PUR , , , , , ,ADC0_A14 +PORT0 ,P0_23 ,P0_23 ,EWM0_OUT_b , ,FC1_P3 ,CT_INP3 , ,FLEXIO0_D7 , , , , , , , , , ,ADC0_A15 +PORT0 ,P0_24 ,P0_24 , ,FC1_P0 , ,CT0_MAT0 , , , , , , , , , , , ,ADC0_B16 +PORT0 ,P0_25 ,P0_25 , ,FC1_P1 , ,CT0_MAT1 , , , , , , , , , , , ,ADC0_B17 +PORT0 ,P0_26 ,P0_26 , ,FC1_P2 , ,CT0_MAT2 , , , , , , , , , , , ,ADC0_B18 +PORT0 ,P0_27 ,P0_27 , ,FC1_P3 , ,CT0_MAT3 , , , , , , , , , , , ,ADC0_B19 +PORT0 ,P0_28 ,P0_28 , ,FC1_P4 ,FC0_P4 ,CT_INP0 , , , , , , , , , , , ,ADC0_B20 +PORT0 ,P0_29 ,P0_29 , ,FC1_P5 ,FC0_P5 ,CT_INP1 , , , , , , , , , , , ,ADC0_B21 +PORT0 ,P0_30 ,P0_30 , ,FC1_P6 ,FC0_P6 ,CT_INP2 , , , , , , , , , , , ,ADC0_B22 +PORT0 ,P0_31 ,P0_31 , , , ,CT_INP3 , , , , , , , , , , , ,ADC0_B23 +PORT1 ,P1_0 ,P1_0 ,TRIG_IN0 ,FC3_P0 ,FC4_P4 ,CT_INP4 ,SCT0_OUT6 ,FLEXIO0_D8 , , , ,SAI1_TX_BCLK , , , , , ,ADC0_A16 +PORT1 ,P1_1 ,P1_1 ,TRIG_IN1 ,FC3_P1 ,FC4_P5 ,CT_INP5 ,SCT0_OUT7 ,FLEXIO0_D9 , , , ,SAI1_TX_FS , , , , , ,ADC0_A17 +PORT1 ,P1_2 ,P1_2 ,TRIG_OUT0 ,FC3_P2 ,FC4_P6 ,CT1_MAT0 ,SCT0_IN6 ,FLEXIO0_D10 , , ,ENET0_MDC ,SAI1_TXD0 ,CAN0_TXD , , , , ,ADC0_A18 +PORT1 ,P1_3 ,P1_3 ,TRIG_OUT1 ,FC3_P3 , ,CT1_MAT1 ,SCT0_IN7 ,FLEXIO0_D11 , , ,ENET0_MDIO ,SAI1_RXD0 ,CAN0_RXD , , , , ,ADC0_A19 +PORT1 ,P1_4 ,P1_4 ,FREQME_CLK_IN0 ,FC3_P4 ,FC5_P0 ,CT1_MAT2 ,SCT0_OUT0 ,FLEXIO0_D12 ,EZH_PIO0 , ,ENET0_TX_CLK ,SAI0_TXD1 , , , , , ,ADC0_A20 +PORT1 ,P1_5 ,P1_5 ,FREQME_CLK_IN1 ,FC3_P5 ,FC5_P1 ,CT1_MAT3 ,SCT0_OUT1 ,FLEXIO0_D13 ,EZH_PIO1 , ,ENET0_TXEN ,SAI0_RXD1 , , , , , ,ADC0_A21 +PORT1 ,P1_6 ,P1_6 ,TRIG_IN2 ,FC3_P6 ,FC5_P2 ,CT_INP6 ,SCT0_IN0 ,FLEXIO0_D14 ,EZH_PIO2 , ,ENET0_TXD0 ,SAI1_RX_BCLK ,CAN1_TXD , , , , ,ADC0_A22 +PORT1 ,P1_7 ,P1_7 ,TRIG_OUT2 , ,FC5_P3 ,CT_INP7 ,SCT0_IN1 ,FLEXIO0_D15 ,EZH_PIO3 ,PLU_CLK ,ENET0_TXD1 ,SAI1_RX_FS ,CAN1_RXD , , , , ,ADC0_A23 diff --git a/ports/mcx/devices/MCXN947/MCXN947_cm33_core0_flash.ld b/ports/mcx/devices/MCXN947/MCXN947_cm33_core0_flash.ld new file mode 100644 index 0000000000..18bd9da3de --- /dev/null +++ b/ports/mcx/devices/MCXN947/MCXN947_cm33_core0_flash.ld @@ -0,0 +1,249 @@ +/* +** ################################################################### +** Processors: MCXN947VDF_cm33_core0 +** MCXN947VNL_cm33_core0 +** +** Compiler: GNU C Compiler +** Reference manual: MCXNx4x Reference Manual +** Version: rev. 1.0, 2021-08-03 +** Build: b230607 +** +** Abstract: +** Linker file for the GNU C Compiler +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2023 NXP +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** ################################################################### +*/ + + + +/* Entry Point */ +ENTRY(Reset_Handler) + +HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400; +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0800; +RPMSG_SHMEM_SIZE = DEFINED(__use_shmem__) ? 0x2000 : 0; + +TEXT_START = DEFINED(__qspi_xip__) ? 0x80001000 : 0x00000000; /* flexspi boot image start with 0x80000000 */ +TEXT_SIZE = DEFINED(__qspi_xip__) ? 0x0FFFF000 : 0x000C0000; /* flexspi boot image offset at 0x80001000 */ + +/* Specify the memory areas */ +MEMORY +{ + m_interrupts (RX) : ORIGIN = TEXT_START, LENGTH = 0x00000400 + m_text (RX) : ORIGIN = TEXT_START + 0x00000400, LENGTH = TEXT_SIZE - 0x00000400 + m_core1_image (RX) : ORIGIN = 0x000C0000, LENGTH = 0x00040000 + m_data (RW) : ORIGIN = 0x20000000, LENGTH = 0x0004E000 - RPMSG_SHMEM_SIZE + rpmsg_sh_mem (RW) : ORIGIN = 0x2004E000 - RPMSG_SHMEM_SIZE, LENGTH = RPMSG_SHMEM_SIZE + m_flash1 (RX) : ORIGIN = 0x00100000, LENGTH = 0x00100000 + m_sramx (RW) : ORIGIN = 0x04000000, LENGTH = 0x00018000 + m_flash_config (RX) : ORIGIN = 0x80000400, LENGTH = 0x00000200 + m_usb_sram (RW) : ORIGIN = 0x400BA000, LENGTH = 0x00001000 +} + +/* Define output sections */ +SECTIONS +{ + /* section for storing the secondary core image */ + .core1_code : + { + . = ALIGN(4) ; + KEEP (*(.core1_code)) + *(.core1_code*) + . = ALIGN(4) ; + } > m_core1_image + + /* NOINIT section for rpmsg_sh_mem */ + .noinit_rpmsg_sh_mem (NOLOAD) : ALIGN(4) + { + __RPMSG_SH_MEM_START__ = .; + *(.noinit.$rpmsg_sh_mem*) + . = ALIGN(4) ; + __RPMSG_SH_MEM_END__ = .; + } > rpmsg_sh_mem + + .flash_config : + { + . = ALIGN(4); + __FLASH_BASE = .; + KEEP(* (.flexspi_fcb)) /* FCB section */ + . = ALIGN(4); + } > m_flash_config + + /* The startup code goes first into internal flash */ + .interrupts : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } > m_interrupts + + /* The program code and other data goes into internal flash */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + } > m_text + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > m_text + + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > m_text + + .ctors : + { + __CTOR_LIST__ = .; + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + } > m_text + + .dtors : + { + __DTOR_LIST__ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + } > m_text + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > m_text + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } > m_text + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > m_text + + __etext = .; /* define a global symbol at end of code */ + __DATA_ROM = .; /* Symbol is used by startup for data initialization */ + + .data : AT(__DATA_ROM) + { + . = ALIGN(4); + __DATA_RAM = .; + __data_start__ = .; /* create a global symbol at data start */ + *(.ramfunc*) /* for functions in ram */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(NonCacheable.init) /* NonCacheable init section */ + *(NonCacheable) /* NonCacheable section */ + *(CodeQuickAccess) /* quick access code section */ + *(DataQuickAccess) /* quick access data section */ + KEEP(*(.jcr*)) + . = ALIGN(4); + __data_end__ = .; /* define a global symbol at data end */ + } > m_data + + __DATA_END = __DATA_ROM + (__data_end__ - __data_start__); + text_end = ORIGIN(m_text) + LENGTH(m_text); + ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data") + + /* Uninitialized data section */ + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + . = ALIGN(4); + __START_BSS = .; + __bss_start__ = .; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + __END_BSS = .; + } > m_data + + .heap : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + __HeapBase = .; + . += HEAP_SIZE; + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + } > m_data + + .stack : + { + . = ALIGN(8); + . += STACK_SIZE; + } > m_data + + m_usb_bdt (NOLOAD) : + { + . = ALIGN(512); + *(m_usb_bdt) + } > m_usb_sram + + m_usb_global (NOLOAD) : + { + *(m_usb_global) + } > m_usb_sram + + /* Initializes stack on the end of block */ + __StackTop = ORIGIN(m_data) + LENGTH(m_data); + __StackLimit = __StackTop - STACK_SIZE; + PROVIDE(__stack = __StackTop); + + .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap") +} + diff --git a/ports/mcx/devices/MCXN947/startup_MCXN947_cm33_core0.S b/ports/mcx/devices/MCXN947/startup_MCXN947_cm33_core0.S new file mode 100644 index 0000000000..39d3a56d7a --- /dev/null +++ b/ports/mcx/devices/MCXN947/startup_MCXN947_cm33_core0.S @@ -0,0 +1,1948 @@ +/* ------------------------------------------------------------------------- */ +/* @file: startup_MCXN947_cm33_core0.s */ +/* @purpose: CMSIS Cortex-M33 Core Device Startup File */ +/* MCXN947_cm33_core0 */ +/* @version: 2.0 */ +/* @date: 2023-2-1 */ +/* @build: b231018 */ +/* ------------------------------------------------------------------------- */ +/* */ +/* Copyright 1997-2016 Freescale Semiconductor, Inc. */ +/* Copyright 2016-2023 NXP */ +/* SPDX-License-Identifier: BSD-3-Clause */ +/*****************************************************************************/ +/* Version: GCC for ARM Embedded Processors */ +/*****************************************************************************/ + .syntax unified + .arch armv8-m.main + + .section .isr_vector, "a" + .align 2 + .globl __Vectors +__Vectors: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler*/ + .long HardFault_Handler /* Hard Fault Handler*/ + .long MemManage_Handler /* MPU Fault Handler*/ + .long BusFault_Handler /* Bus Fault Handler*/ + .long UsageFault_Handler /* Usage Fault Handler*/ + .long SecureFault_Handler /* Secure Fault Handler*/ + .long 0 /* Reserved*/ + .long 0 /* Reserved*/ + .long 0 /* Reserved*/ + .long SVC_Handler /* SVCall Handler*/ + .long DebugMon_Handler /* Debug Monitor Handler*/ + .long 0 /* Reserved*/ + .long PendSV_Handler /* PendSV Handler*/ + .long SysTick_Handler /* SysTick Handler*/ + + /* External Interrupts*/ + .long OR_IRQHandler /* OR IRQ*/ + .long EDMA_0_CH0_IRQHandler /* eDMA_0_CH0 error or transfer complete*/ + .long EDMA_0_CH1_IRQHandler /* eDMA_0_CH1 error or transfer complete*/ + .long EDMA_0_CH2_IRQHandler /* eDMA_0_CH2 error or transfer complete*/ + .long EDMA_0_CH3_IRQHandler /* eDMA_0_CH3 error or transfer complete*/ + .long EDMA_0_CH4_IRQHandler /* eDMA_0_CH4 error or transfer complete*/ + .long EDMA_0_CH5_IRQHandler /* eDMA_0_CH5 error or transfer complete*/ + .long EDMA_0_CH6_IRQHandler /* eDMA_0_CH6 error or transfer complete*/ + .long EDMA_0_CH7_IRQHandler /* eDMA_0_CH7 error or transfer complete*/ + .long EDMA_0_CH8_IRQHandler /* eDMA_0_CH8 error or transfer complete*/ + .long EDMA_0_CH9_IRQHandler /* eDMA_0_CH9 error or transfer complete*/ + .long EDMA_0_CH10_IRQHandler /* eDMA_0_CH10 error or transfer complete*/ + .long EDMA_0_CH11_IRQHandler /* eDMA_0_CH11 error or transfer complete*/ + .long EDMA_0_CH12_IRQHandler /* eDMA_0_CH12 error or transfer complete*/ + .long EDMA_0_CH13_IRQHandler /* eDMA_0_CH13 error or transfer complete*/ + .long EDMA_0_CH14_IRQHandler /* eDMA_0_CH14 error or transfer complete*/ + .long EDMA_0_CH15_IRQHandler /* eDMA_0_CH15 error or transfer complete*/ + .long GPIO00_IRQHandler /* GPIO0 interrupt 0*/ + .long GPIO01_IRQHandler /* GPIO0 interrupt 1*/ + .long GPIO10_IRQHandler /* GPIO1 interrupt 0*/ + .long GPIO11_IRQHandler /* GPIO1 interrupt 1*/ + .long GPIO20_IRQHandler /* GPIO2 interrupt 0*/ + .long GPIO21_IRQHandler /* GPIO2 interrupt 1*/ + .long GPIO30_IRQHandler /* GPIO3 interrupt 0*/ + .long GPIO31_IRQHandler /* GPIO3 interrupt 1*/ + .long GPIO40_IRQHandler /* GPIO4 interrupt 0*/ + .long GPIO41_IRQHandler /* GPIO4 interrupt 1*/ + .long GPIO50_IRQHandler /* GPIO5 interrupt 0*/ + .long GPIO51_IRQHandler /* GPIO5 interrupt 1*/ + .long UTICK0_IRQHandler /* Micro-Tick Timer interrupt*/ + .long MRT0_IRQHandler /* Multi-Rate Timer interrupt*/ + .long CTIMER0_IRQHandler /* Standard counter/timer 0 interrupt*/ + .long CTIMER1_IRQHandler /* Standard counter/timer 1 interrupt*/ + .long SCT0_IRQHandler /* SCTimer/PWM interrupt*/ + .long CTIMER2_IRQHandler /* Standard counter/timer 2 interrupt*/ + .long LP_FLEXCOMM0_IRQHandler /* LP_FLEXCOMM0 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long LP_FLEXCOMM1_IRQHandler /* LP_FLEXCOMM1 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long LP_FLEXCOMM2_IRQHandler /* LP_FLEXCOMM2 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long LP_FLEXCOMM3_IRQHandler /* LP_FLEXCOMM3 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long LP_FLEXCOMM4_IRQHandler /* LP_FLEXCOMM4 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long LP_FLEXCOMM5_IRQHandler /* LP_FLEXCOMM5 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long LP_FLEXCOMM6_IRQHandler /* LP_FLEXCOMM6 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long LP_FLEXCOMM7_IRQHandler /* LP_FLEXCOMM7 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long LP_FLEXCOMM8_IRQHandler /* LP_FLEXCOMM8 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long LP_FLEXCOMM9_IRQHandler /* LP_FLEXCOMM9 (LPSPI interrupt or LPI2C interrupt or LPUART Receive/Transmit interrupt)*/ + .long ADC0_IRQHandler /* Analog-to-Digital Converter 0 - General Purpose interrupt*/ + .long ADC1_IRQHandler /* Analog-to-Digital Converter 1 - General Purpose interrupt*/ + .long PINT0_IRQHandler /* Pin Interrupt Pattern Match Interrupt*/ + .long PDM_EVENT_IRQHandler /* Microphone Interface interrupt*/ + .long Reserved65_IRQHandler /* Reserved interrupt*/ + .long USB0_FS_IRQHandler /* Universal Serial Bus - Full Speed interrupt*/ + .long USB0_DCD_IRQHandler /* Universal Serial Bus - Device Charge Detect interrupt*/ + .long RTC_IRQHandler /* RTC Subsystem interrupt (RTC interrupt or Wake timer interrupt)*/ + .long SMARTDMA_IRQHandler /* SmartDMA_IRQ*/ + .long MAILBOX_IRQHandler /* Inter-CPU Mailbox interrupt0 for CPU0 Inter-CPU Mailbox interrupt1 for CPU1*/ + .long CTIMER3_IRQHandler /* Standard counter/timer 3 interrupt*/ + .long CTIMER4_IRQHandler /* Standard counter/timer 4 interrupt*/ + .long OS_EVENT_IRQHandler /* OS event timer interrupt*/ + .long FLEXSPI0_IRQHandler /* Flexible Serial Peripheral Interface interrupt*/ + .long SAI0_IRQHandler /* Serial Audio Interface 0 interrupt*/ + .long SAI1_IRQHandler /* Serial Audio Interface 1 interrupt*/ + .long USDHC0_IRQHandler /* Ultra Secured Digital Host Controller interrupt*/ + .long CAN0_IRQHandler /* Controller Area Network 0 interrupt*/ + .long CAN1_IRQHandler /* Controller Area Network 1 interrupt*/ + .long Reserved80_IRQHandler /* Reserved interrupt*/ + .long Reserved81_IRQHandler /* Reserved interrupt*/ + .long USB1_HS_PHY_IRQHandler /* USBHS DCD or USBHS Phy interrupt*/ + .long USB1_HS_IRQHandler /* USB High Speed OTG Controller interrupt */ + .long SEC_HYPERVISOR_CALL_IRQHandler /* AHB Secure Controller hypervisor call interrupt*/ + .long Reserved85_IRQHandler /* Reserved interrupt*/ + .long PLU_IRQHandler /* Programmable Logic Unit interrupt*/ + .long Freqme_IRQHandler /* Frequency Measurement interrupt*/ + .long SEC_VIO_IRQHandler /* Secure violation interrupt (Memory Block Checker interrupt or secure AHB matrix violation interrupt)*/ + .long ELS_IRQHandler /* ELS interrupt*/ + .long PKC_IRQHandler /* PKC interrupt*/ + .long PUF_IRQHandler /* Physical Unclonable Function interrupt*/ + .long PQ_IRQHandler /* Power Quad interrupt*/ + .long EDMA_1_CH0_IRQHandler /* eDMA_1_CH0 error or transfer complete*/ + .long EDMA_1_CH1_IRQHandler /* eDMA_1_CH1 error or transfer complete*/ + .long EDMA_1_CH2_IRQHandler /* eDMA_1_CH2 error or transfer complete*/ + .long EDMA_1_CH3_IRQHandler /* eDMA_1_CH3 error or transfer complete*/ + .long EDMA_1_CH4_IRQHandler /* eDMA_1_CH4 error or transfer complete*/ + .long EDMA_1_CH5_IRQHandler /* eDMA_1_CH5 error or transfer complete*/ + .long EDMA_1_CH6_IRQHandler /* eDMA_1_CH6 error or transfer complete*/ + .long EDMA_1_CH7_IRQHandler /* eDMA_1_CH7 error or transfer complete*/ + .long EDMA_1_CH8_IRQHandler /* eDMA_1_CH8 error or transfer complete*/ + .long EDMA_1_CH9_IRQHandler /* eDMA_1_CH9 error or transfer complete*/ + .long EDMA_1_CH10_IRQHandler /* eDMA_1_CH10 error or transfer complete*/ + .long EDMA_1_CH11_IRQHandler /* eDMA_1_CH11 error or transfer complete*/ + .long EDMA_1_CH12_IRQHandler /* eDMA_1_CH12 error or transfer complete*/ + .long EDMA_1_CH13_IRQHandler /* eDMA_1_CH13 error or transfer complete*/ + .long EDMA_1_CH14_IRQHandler /* eDMA_1_CH14 error or transfer complete*/ + .long EDMA_1_CH15_IRQHandler /* eDMA_1_CH15 error or transfer complete*/ + .long CDOG0_IRQHandler /* Code Watchdog Timer 0 interrupt*/ + .long CDOG1_IRQHandler /* Code Watchdog Timer 1 interrupt*/ + .long I3C0_IRQHandler /* Improved Inter Integrated Circuit interrupt 0*/ + .long I3C1_IRQHandler /* Improved Inter Integrated Circuit interrupt 1*/ + .long NPU_IRQHandler /* NPU interrupt*/ + .long GDET_IRQHandler /* Digital Glitch Detect 0 interrupt or Digital Glitch Detect 1 interrupt*/ + .long VBAT0_IRQHandler /* VBAT interrupt( VBAT interrupt or digital tamper interrupt)*/ + .long EWM0_IRQHandler /* External Watchdog Monitor interrupt*/ + .long TSI_END_OF_SCAN_IRQHandler /* TSI End of Scan interrupt*/ + .long TSI_OUT_OF_SCAN_IRQHandler /* TSI Out of Scan interrupt*/ + .long EMVSIM0_IRQHandler /* EMVSIM0 interrupt*/ + .long EMVSIM1_IRQHandler /* EMVSIM1 interrupt*/ + .long FLEXIO_IRQHandler /* Flexible Input/Output interrupt*/ + .long DAC0_IRQHandler /* Digital-to-Analog Converter 0 - General Purpose interrupt*/ + .long DAC1_IRQHandler /* Digital-to-Analog Converter 1 - General Purpose interrupt*/ + .long DAC2_IRQHandler /* 14-bit Digital-to-Analog Converter interrupt*/ + .long HSCMP0_IRQHandler /* High-Speed comparator0 interrupt*/ + .long HSCMP1_IRQHandler /* High-Speed comparator1 interrupt*/ + .long HSCMP2_IRQHandler /* High-Speed comparator2 interrupt*/ + .long FLEXPWM0_RELOAD_ERROR_IRQHandler /* FlexPWM0_reload_error interrupt*/ + .long FLEXPWM0_FAULT_IRQHandler /* FlexPWM0_fault interrupt*/ + .long FLEXPWM0_SUBMODULE0_IRQHandler /* FlexPWM0 Submodule 0 capture/compare/reload interrupt*/ + .long FLEXPWM0_SUBMODULE1_IRQHandler /* FlexPWM0 Submodule 1 capture/compare/reload interrupt*/ + .long FLEXPWM0_SUBMODULE2_IRQHandler /* FlexPWM0 Submodule 2 capture/compare/reload interrupt*/ + .long FLEXPWM0_SUBMODULE3_IRQHandler /* FlexPWM0 Submodule 3 capture/compare/reload interrupt*/ + .long FLEXPWM1_RELOAD_ERROR_IRQHandler /* FlexPWM1_reload_error interrupt*/ + .long FLEXPWM1_FAULT_IRQHandler /* FlexPWM1_fault interrupt*/ + .long FLEXPWM1_SUBMODULE0_IRQHandler /* FlexPWM1 Submodule 0 capture/compare/reload interrupt*/ + .long FLEXPWM1_SUBMODULE1_IRQHandler /* FlexPWM1 Submodule 1 capture/compare/reload interrupt*/ + .long FLEXPWM1_SUBMODULE2_IRQHandler /* FlexPWM1 Submodule 2 capture/compare/reload interrupt*/ + .long FLEXPWM1_SUBMODULE3_IRQHandler /* FlexPWM1 Submodule 3 capture/compare/reload interrupt*/ + .long ENC0_COMPARE_IRQHandler /* ENC0_Compare interrupt*/ + .long ENC0_HOME_IRQHandler /* ENC0_Home interrupt*/ + .long ENC0_WDG_SAB_IRQHandler /* ENC0_WDG_IRQ/SAB interrupt*/ + .long ENC0_IDX_IRQHandler /* ENC0_IDX interrupt*/ + .long ENC1_COMPARE_IRQHandler /* ENC1_Compare interrupt*/ + .long ENC1_HOME_IRQHandler /* ENC1_Home interrupt*/ + .long ENC1_WDG_SAB_IRQHandler /* ENC1_WDG_IRQ/SAB interrupt*/ + .long ENC1_IDX_IRQHandler /* ENC1_IDX interrupt*/ + .long ITRC0_IRQHandler /* Intrusion and Tamper Response Controller interrupt*/ + .long BSP32_IRQHandler /* CoolFlux BSP32 interrupt*/ + .long ELS_ERR_IRQHandler /* ELS error interrupt*/ + .long PKC_ERR_IRQHandler /* PKC error interrupt*/ + .long ERM_SINGLE_BIT_ERROR_IRQHandler /* ERM Single Bit error interrupt*/ + .long ERM_MULTI_BIT_ERROR_IRQHandler /* ERM Multi Bit error interrupt*/ + .long FMU0_IRQHandler /* Flash Management Unit interrupt*/ + .long ETHERNET_IRQHandler /* Ethernet QoS interrupt*/ + .long ETHERNET_PMT_IRQHandler /* Ethernet QoS power management interrupt*/ + .long ETHERNET_MACLP_IRQHandler /* Ethernet QoS MAC interrupt*/ + .long SINC_FILTER_IRQHandler /* SINC Filter interrupt */ + .long LPTMR0_IRQHandler /* Low Power Timer 0 interrupt*/ + .long LPTMR1_IRQHandler /* Low Power Timer 1 interrupt*/ + .long SCG_IRQHandler /* System Clock Generator interrupt*/ + .long SPC_IRQHandler /* System Power Controller interrupt*/ + .long WUU_IRQHandler /* Wake Up Unit interrupt*/ + .long PORT_EFT_IRQHandler /* PORT0~5 EFT interrupt*/ + .long ETB0_IRQHandler /* ETB counter expires interrupt*/ + .long SM3_IRQHandler /* Secure Generic Interface (SGI) SAFO interrupt */ + .long TRNG0_IRQHandler /* True Random Number Generator interrupt*/ + .long WWDT0_IRQHandler /* Windowed Watchdog Timer 0 interrupt*/ + .long WWDT1_IRQHandler /* Windowed Watchdog Timer 1 interrupt*/ + .long CMC0_IRQHandler /* Core Mode Controller interrupt*/ + .long CTI0_IRQHandler /* Cross Trigger Interface interrupt*/ + + .size __Vectors, . - __Vectors + + .text + .thumb + +#if defined (__cplusplus) +#ifdef __REDLIB__ +#error Redlib does not support C++ +#endif +#endif +/* Reset Handler */ + + .thumb_func + .align 2 + .globl Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + cpsid i /* Mask interrupts */ + .equ VTOR, 0xE000ED08 + ldr r0, =VTOR + ldr r1, =__Vectors + str r1, [r0] + ldr r2, [r1] + msr msp, r2 + ldr r0, =__StackLimit + msr msplim, r0 +#ifndef __NO_SYSTEM_INIT + ldr r0,=SystemInit + blx r0 +#endif +/* Loop to copy data from read only memory to RAM. The ranges + * of copy from/to are specified by following symbols evaluated in + * linker script. + * __etext: End of code section, i.e., begin of data sections to copy from. + * __data_start__/__data_end__: RAM address range that data should be + * copied to. Both must be aligned to 4 bytes boundary. */ + + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + +#if 1 +/* Here are two copies of loop implementations. First one favors code size + * and the second one favors performance. Default uses the first one. + * Change to "#if 0" to use the second one */ +.LC0: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .LC0 +#else + subs r3, r2 + ble .LC1 +.LC0: + subs r3, #4 + ldr r0, [r1, r3] + str r0, [r2, r3] + bgt .LC0 +.LC1: +#endif + +#ifdef __STARTUP_CLEAR_BSS +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * Loop to zero out BSS section, which uses following symbols + * in linker script: + * __bss_start__: start of BSS section. Must align to 4 + * __bss_end__: end of BSS section. Must align to 4 + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 +.LC2: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .LC2 +#endif /* __STARTUP_CLEAR_BSS */ + +/* Add stack / heap initialization */ + movs r0, 0 + ldr r1, =__HeapBase + ldr r2, =__HeapLimit +.LC3: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .LC3 + + ldr r1, =__StackLimit + ldr r2, =__StackTop +.LC4: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .LC4 + +/*End of stack / heap initialization */ + cpsie i /* Unmask interrupts */ +#ifndef __START +#ifdef __REDLIB__ +#define __START __main +#else +#define __START _start +#endif +#endif +#ifndef __ATOLLIC__ + ldr r0,=__START + blx r0 +#else + ldr r0,=__libc_init_array + blx r0 + ldr r0,=main + bx r0 +#endif + .pool + .size Reset_Handler, . - Reset_Handler + + .align 1 + .thumb_func + .weak DefaultISR + .type DefaultISR, %function +DefaultISR: + b DefaultISR + .size DefaultISR, . - DefaultISR + + .align 1 + .thumb_func + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + ldr r0,=NMI_Handler + bx r0 + .size NMI_Handler, . - NMI_Handler + + .align 1 + .thumb_func + .weak HardFault_Handler + .type HardFault_Handler, %function +HardFault_Handler: + ldr r0,=HardFault_Handler + bx r0 + .size HardFault_Handler, . - HardFault_Handler + + .align 1 + .thumb_func + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + ldr r0,=SVC_Handler + bx r0 + .size SVC_Handler, . - SVC_Handler + + .align 1 + .thumb_func + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + ldr r0,=PendSV_Handler + bx r0 + .size PendSV_Handler, . - PendSV_Handler + + .align 1 + .thumb_func + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + ldr r0,=SysTick_Handler + bx r0 + .size SysTick_Handler, . - SysTick_Handler + + .align 1 + .thumb_func + .weak OR_IRQHandler + .type OR_IRQHandler, %function +OR_IRQHandler: + ldr r0,=OR_DriverIRQHandler + bx r0 + .size OR_IRQHandler, . - OR_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH0_IRQHandler + .type EDMA_0_CH0_IRQHandler, %function +EDMA_0_CH0_IRQHandler: + ldr r0,=EDMA_0_CH0_DriverIRQHandler + bx r0 + .size EDMA_0_CH0_IRQHandler, . - EDMA_0_CH0_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH1_IRQHandler + .type EDMA_0_CH1_IRQHandler, %function +EDMA_0_CH1_IRQHandler: + ldr r0,=EDMA_0_CH1_DriverIRQHandler + bx r0 + .size EDMA_0_CH1_IRQHandler, . - EDMA_0_CH1_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH2_IRQHandler + .type EDMA_0_CH2_IRQHandler, %function +EDMA_0_CH2_IRQHandler: + ldr r0,=EDMA_0_CH2_DriverIRQHandler + bx r0 + .size EDMA_0_CH2_IRQHandler, . - EDMA_0_CH2_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH3_IRQHandler + .type EDMA_0_CH3_IRQHandler, %function +EDMA_0_CH3_IRQHandler: + ldr r0,=EDMA_0_CH3_DriverIRQHandler + bx r0 + .size EDMA_0_CH3_IRQHandler, . - EDMA_0_CH3_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH4_IRQHandler + .type EDMA_0_CH4_IRQHandler, %function +EDMA_0_CH4_IRQHandler: + ldr r0,=EDMA_0_CH4_DriverIRQHandler + bx r0 + .size EDMA_0_CH4_IRQHandler, . - EDMA_0_CH4_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH5_IRQHandler + .type EDMA_0_CH5_IRQHandler, %function +EDMA_0_CH5_IRQHandler: + ldr r0,=EDMA_0_CH5_DriverIRQHandler + bx r0 + .size EDMA_0_CH5_IRQHandler, . - EDMA_0_CH5_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH6_IRQHandler + .type EDMA_0_CH6_IRQHandler, %function +EDMA_0_CH6_IRQHandler: + ldr r0,=EDMA_0_CH6_DriverIRQHandler + bx r0 + .size EDMA_0_CH6_IRQHandler, . - EDMA_0_CH6_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH7_IRQHandler + .type EDMA_0_CH7_IRQHandler, %function +EDMA_0_CH7_IRQHandler: + ldr r0,=EDMA_0_CH7_DriverIRQHandler + bx r0 + .size EDMA_0_CH7_IRQHandler, . - EDMA_0_CH7_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH8_IRQHandler + .type EDMA_0_CH8_IRQHandler, %function +EDMA_0_CH8_IRQHandler: + ldr r0,=EDMA_0_CH8_DriverIRQHandler + bx r0 + .size EDMA_0_CH8_IRQHandler, . - EDMA_0_CH8_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH9_IRQHandler + .type EDMA_0_CH9_IRQHandler, %function +EDMA_0_CH9_IRQHandler: + ldr r0,=EDMA_0_CH9_DriverIRQHandler + bx r0 + .size EDMA_0_CH9_IRQHandler, . - EDMA_0_CH9_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH10_IRQHandler + .type EDMA_0_CH10_IRQHandler, %function +EDMA_0_CH10_IRQHandler: + ldr r0,=EDMA_0_CH10_DriverIRQHandler + bx r0 + .size EDMA_0_CH10_IRQHandler, . - EDMA_0_CH10_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH11_IRQHandler + .type EDMA_0_CH11_IRQHandler, %function +EDMA_0_CH11_IRQHandler: + ldr r0,=EDMA_0_CH11_DriverIRQHandler + bx r0 + .size EDMA_0_CH11_IRQHandler, . - EDMA_0_CH11_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH12_IRQHandler + .type EDMA_0_CH12_IRQHandler, %function +EDMA_0_CH12_IRQHandler: + ldr r0,=EDMA_0_CH12_DriverIRQHandler + bx r0 + .size EDMA_0_CH12_IRQHandler, . - EDMA_0_CH12_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH13_IRQHandler + .type EDMA_0_CH13_IRQHandler, %function +EDMA_0_CH13_IRQHandler: + ldr r0,=EDMA_0_CH13_DriverIRQHandler + bx r0 + .size EDMA_0_CH13_IRQHandler, . - EDMA_0_CH13_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH14_IRQHandler + .type EDMA_0_CH14_IRQHandler, %function +EDMA_0_CH14_IRQHandler: + ldr r0,=EDMA_0_CH14_DriverIRQHandler + bx r0 + .size EDMA_0_CH14_IRQHandler, . - EDMA_0_CH14_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_0_CH15_IRQHandler + .type EDMA_0_CH15_IRQHandler, %function +EDMA_0_CH15_IRQHandler: + ldr r0,=EDMA_0_CH15_DriverIRQHandler + bx r0 + .size EDMA_0_CH15_IRQHandler, . - EDMA_0_CH15_IRQHandler + + .align 1 + .thumb_func + .weak GPIO00_IRQHandler + .type GPIO00_IRQHandler, %function +GPIO00_IRQHandler: + ldr r0,=GPIO00_DriverIRQHandler + bx r0 + .size GPIO00_IRQHandler, . - GPIO00_IRQHandler + + .align 1 + .thumb_func + .weak GPIO01_IRQHandler + .type GPIO01_IRQHandler, %function +GPIO01_IRQHandler: + ldr r0,=GPIO01_DriverIRQHandler + bx r0 + .size GPIO01_IRQHandler, . - GPIO01_IRQHandler + + .align 1 + .thumb_func + .weak GPIO10_IRQHandler + .type GPIO10_IRQHandler, %function +GPIO10_IRQHandler: + ldr r0,=GPIO10_DriverIRQHandler + bx r0 + .size GPIO10_IRQHandler, . - GPIO10_IRQHandler + + .align 1 + .thumb_func + .weak GPIO11_IRQHandler + .type GPIO11_IRQHandler, %function +GPIO11_IRQHandler: + ldr r0,=GPIO11_DriverIRQHandler + bx r0 + .size GPIO11_IRQHandler, . - GPIO11_IRQHandler + + .align 1 + .thumb_func + .weak GPIO20_IRQHandler + .type GPIO20_IRQHandler, %function +GPIO20_IRQHandler: + ldr r0,=GPIO20_DriverIRQHandler + bx r0 + .size GPIO20_IRQHandler, . - GPIO20_IRQHandler + + .align 1 + .thumb_func + .weak GPIO21_IRQHandler + .type GPIO21_IRQHandler, %function +GPIO21_IRQHandler: + ldr r0,=GPIO21_DriverIRQHandler + bx r0 + .size GPIO21_IRQHandler, . - GPIO21_IRQHandler + + .align 1 + .thumb_func + .weak GPIO30_IRQHandler + .type GPIO30_IRQHandler, %function +GPIO30_IRQHandler: + ldr r0,=GPIO30_DriverIRQHandler + bx r0 + .size GPIO30_IRQHandler, . - GPIO30_IRQHandler + + .align 1 + .thumb_func + .weak GPIO31_IRQHandler + .type GPIO31_IRQHandler, %function +GPIO31_IRQHandler: + ldr r0,=GPIO31_DriverIRQHandler + bx r0 + .size GPIO31_IRQHandler, . - GPIO31_IRQHandler + + .align 1 + .thumb_func + .weak GPIO40_IRQHandler + .type GPIO40_IRQHandler, %function +GPIO40_IRQHandler: + ldr r0,=GPIO40_DriverIRQHandler + bx r0 + .size GPIO40_IRQHandler, . - GPIO40_IRQHandler + + .align 1 + .thumb_func + .weak GPIO41_IRQHandler + .type GPIO41_IRQHandler, %function +GPIO41_IRQHandler: + ldr r0,=GPIO41_DriverIRQHandler + bx r0 + .size GPIO41_IRQHandler, . - GPIO41_IRQHandler + + .align 1 + .thumb_func + .weak GPIO50_IRQHandler + .type GPIO50_IRQHandler, %function +GPIO50_IRQHandler: + ldr r0,=GPIO50_DriverIRQHandler + bx r0 + .size GPIO50_IRQHandler, . - GPIO50_IRQHandler + + .align 1 + .thumb_func + .weak GPIO51_IRQHandler + .type GPIO51_IRQHandler, %function +GPIO51_IRQHandler: + ldr r0,=GPIO51_DriverIRQHandler + bx r0 + .size GPIO51_IRQHandler, . - GPIO51_IRQHandler + + .align 1 + .thumb_func + .weak UTICK0_IRQHandler + .type UTICK0_IRQHandler, %function +UTICK0_IRQHandler: + ldr r0,=UTICK0_DriverIRQHandler + bx r0 + .size UTICK0_IRQHandler, . - UTICK0_IRQHandler + + .align 1 + .thumb_func + .weak MRT0_IRQHandler + .type MRT0_IRQHandler, %function +MRT0_IRQHandler: + ldr r0,=MRT0_DriverIRQHandler + bx r0 + .size MRT0_IRQHandler, . - MRT0_IRQHandler + + .align 1 + .thumb_func + .weak CTIMER0_IRQHandler + .type CTIMER0_IRQHandler, %function +CTIMER0_IRQHandler: + ldr r0,=CTIMER0_DriverIRQHandler + bx r0 + .size CTIMER0_IRQHandler, . - CTIMER0_IRQHandler + + .align 1 + .thumb_func + .weak CTIMER1_IRQHandler + .type CTIMER1_IRQHandler, %function +CTIMER1_IRQHandler: + ldr r0,=CTIMER1_DriverIRQHandler + bx r0 + .size CTIMER1_IRQHandler, . - CTIMER1_IRQHandler + + .align 1 + .thumb_func + .weak SCT0_IRQHandler + .type SCT0_IRQHandler, %function +SCT0_IRQHandler: + ldr r0,=SCT0_DriverIRQHandler + bx r0 + .size SCT0_IRQHandler, . - SCT0_IRQHandler + + .align 1 + .thumb_func + .weak CTIMER2_IRQHandler + .type CTIMER2_IRQHandler, %function +CTIMER2_IRQHandler: + ldr r0,=CTIMER2_DriverIRQHandler + bx r0 + .size CTIMER2_IRQHandler, . - CTIMER2_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM0_IRQHandler + .type LP_FLEXCOMM0_IRQHandler, %function +LP_FLEXCOMM0_IRQHandler: + ldr r0,=LP_FLEXCOMM0_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM0_IRQHandler, . - LP_FLEXCOMM0_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM1_IRQHandler + .type LP_FLEXCOMM1_IRQHandler, %function +LP_FLEXCOMM1_IRQHandler: + ldr r0,=LP_FLEXCOMM1_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM1_IRQHandler, . - LP_FLEXCOMM1_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM2_IRQHandler + .type LP_FLEXCOMM2_IRQHandler, %function +LP_FLEXCOMM2_IRQHandler: + ldr r0,=LP_FLEXCOMM2_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM2_IRQHandler, . - LP_FLEXCOMM2_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM3_IRQHandler + .type LP_FLEXCOMM3_IRQHandler, %function +LP_FLEXCOMM3_IRQHandler: + ldr r0,=LP_FLEXCOMM3_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM3_IRQHandler, . - LP_FLEXCOMM3_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM4_IRQHandler + .type LP_FLEXCOMM4_IRQHandler, %function +LP_FLEXCOMM4_IRQHandler: + ldr r0,=LP_FLEXCOMM4_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM4_IRQHandler, . - LP_FLEXCOMM4_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM5_IRQHandler + .type LP_FLEXCOMM5_IRQHandler, %function +LP_FLEXCOMM5_IRQHandler: + ldr r0,=LP_FLEXCOMM5_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM5_IRQHandler, . - LP_FLEXCOMM5_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM6_IRQHandler + .type LP_FLEXCOMM6_IRQHandler, %function +LP_FLEXCOMM6_IRQHandler: + ldr r0,=LP_FLEXCOMM6_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM6_IRQHandler, . - LP_FLEXCOMM6_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM7_IRQHandler + .type LP_FLEXCOMM7_IRQHandler, %function +LP_FLEXCOMM7_IRQHandler: + ldr r0,=LP_FLEXCOMM7_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM7_IRQHandler, . - LP_FLEXCOMM7_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM8_IRQHandler + .type LP_FLEXCOMM8_IRQHandler, %function +LP_FLEXCOMM8_IRQHandler: + ldr r0,=LP_FLEXCOMM8_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM8_IRQHandler, . - LP_FLEXCOMM8_IRQHandler + + .align 1 + .thumb_func + .weak LP_FLEXCOMM9_IRQHandler + .type LP_FLEXCOMM9_IRQHandler, %function +LP_FLEXCOMM9_IRQHandler: + ldr r0,=LP_FLEXCOMM9_DriverIRQHandler + bx r0 + .size LP_FLEXCOMM9_IRQHandler, . - LP_FLEXCOMM9_IRQHandler + + .align 1 + .thumb_func + .weak ADC0_IRQHandler + .type ADC0_IRQHandler, %function +ADC0_IRQHandler: + ldr r0,=ADC0_DriverIRQHandler + bx r0 + .size ADC0_IRQHandler, . - ADC0_IRQHandler + + .align 1 + .thumb_func + .weak ADC1_IRQHandler + .type ADC1_IRQHandler, %function +ADC1_IRQHandler: + ldr r0,=ADC1_DriverIRQHandler + bx r0 + .size ADC1_IRQHandler, . - ADC1_IRQHandler + + .align 1 + .thumb_func + .weak PINT0_IRQHandler + .type PINT0_IRQHandler, %function +PINT0_IRQHandler: + ldr r0,=PINT0_DriverIRQHandler + bx r0 + .size PINT0_IRQHandler, . - PINT0_IRQHandler + + .align 1 + .thumb_func + .weak PDM_EVENT_IRQHandler + .type PDM_EVENT_IRQHandler, %function +PDM_EVENT_IRQHandler: + ldr r0,=PDM_EVENT_DriverIRQHandler + bx r0 + .size PDM_EVENT_IRQHandler, . - PDM_EVENT_IRQHandler + + .align 1 + .thumb_func + .weak Reserved65_IRQHandler + .type Reserved65_IRQHandler, %function +Reserved65_IRQHandler: + ldr r0,=Reserved65_DriverIRQHandler + bx r0 + .size Reserved65_IRQHandler, . - Reserved65_IRQHandler + + .align 1 + .thumb_func + .weak USB0_FS_IRQHandler + .type USB0_FS_IRQHandler, %function +USB0_FS_IRQHandler: + ldr r0,=USB0_FS_DriverIRQHandler + bx r0 + .size USB0_FS_IRQHandler, . - USB0_FS_IRQHandler + + .align 1 + .thumb_func + .weak USB0_DCD_IRQHandler + .type USB0_DCD_IRQHandler, %function +USB0_DCD_IRQHandler: + ldr r0,=USB0_DCD_DriverIRQHandler + bx r0 + .size USB0_DCD_IRQHandler, . - USB0_DCD_IRQHandler + + .align 1 + .thumb_func + .weak RTC_IRQHandler + .type RTC_IRQHandler, %function +RTC_IRQHandler: + ldr r0,=RTC_DriverIRQHandler + bx r0 + .size RTC_IRQHandler, . - RTC_IRQHandler + + .align 1 + .thumb_func + .weak SMARTDMA_IRQHandler + .type SMARTDMA_IRQHandler, %function +SMARTDMA_IRQHandler: + ldr r0,=SMARTDMA_DriverIRQHandler + bx r0 + .size SMARTDMA_IRQHandler, . - SMARTDMA_IRQHandler + + .align 1 + .thumb_func + .weak MAILBOX_IRQHandler + .type MAILBOX_IRQHandler, %function +MAILBOX_IRQHandler: + ldr r0,=MAILBOX_DriverIRQHandler + bx r0 + .size MAILBOX_IRQHandler, . - MAILBOX_IRQHandler + + .align 1 + .thumb_func + .weak CTIMER3_IRQHandler + .type CTIMER3_IRQHandler, %function +CTIMER3_IRQHandler: + ldr r0,=CTIMER3_DriverIRQHandler + bx r0 + .size CTIMER3_IRQHandler, . - CTIMER3_IRQHandler + + .align 1 + .thumb_func + .weak CTIMER4_IRQHandler + .type CTIMER4_IRQHandler, %function +CTIMER4_IRQHandler: + ldr r0,=CTIMER4_DriverIRQHandler + bx r0 + .size CTIMER4_IRQHandler, . - CTIMER4_IRQHandler + + .align 1 + .thumb_func + .weak OS_EVENT_IRQHandler + .type OS_EVENT_IRQHandler, %function +OS_EVENT_IRQHandler: + ldr r0,=OS_EVENT_DriverIRQHandler + bx r0 + .size OS_EVENT_IRQHandler, . - OS_EVENT_IRQHandler + + .align 1 + .thumb_func + .weak FLEXSPI0_IRQHandler + .type FLEXSPI0_IRQHandler, %function +FLEXSPI0_IRQHandler: + ldr r0,=FLEXSPI0_DriverIRQHandler + bx r0 + .size FLEXSPI0_IRQHandler, . - FLEXSPI0_IRQHandler + + .align 1 + .thumb_func + .weak SAI0_IRQHandler + .type SAI0_IRQHandler, %function +SAI0_IRQHandler: + ldr r0,=SAI0_DriverIRQHandler + bx r0 + .size SAI0_IRQHandler, . - SAI0_IRQHandler + + .align 1 + .thumb_func + .weak SAI1_IRQHandler + .type SAI1_IRQHandler, %function +SAI1_IRQHandler: + ldr r0,=SAI1_DriverIRQHandler + bx r0 + .size SAI1_IRQHandler, . - SAI1_IRQHandler + + .align 1 + .thumb_func + .weak USDHC0_IRQHandler + .type USDHC0_IRQHandler, %function +USDHC0_IRQHandler: + ldr r0,=USDHC0_DriverIRQHandler + bx r0 + .size USDHC0_IRQHandler, . - USDHC0_IRQHandler + + .align 1 + .thumb_func + .weak CAN0_IRQHandler + .type CAN0_IRQHandler, %function +CAN0_IRQHandler: + ldr r0,=CAN0_DriverIRQHandler + bx r0 + .size CAN0_IRQHandler, . - CAN0_IRQHandler + + .align 1 + .thumb_func + .weak CAN1_IRQHandler + .type CAN1_IRQHandler, %function +CAN1_IRQHandler: + ldr r0,=CAN1_DriverIRQHandler + bx r0 + .size CAN1_IRQHandler, . - CAN1_IRQHandler + + .align 1 + .thumb_func + .weak Reserved80_IRQHandler + .type Reserved80_IRQHandler, %function +Reserved80_IRQHandler: + ldr r0,=Reserved80_DriverIRQHandler + bx r0 + .size Reserved80_IRQHandler, . - Reserved80_IRQHandler + + .align 1 + .thumb_func + .weak Reserved81_IRQHandler + .type Reserved81_IRQHandler, %function +Reserved81_IRQHandler: + ldr r0,=Reserved81_DriverIRQHandler + bx r0 + .size Reserved81_IRQHandler, . - Reserved81_IRQHandler + + .align 1 + .thumb_func + .weak USB1_HS_PHY_IRQHandler + .type USB1_HS_PHY_IRQHandler, %function +USB1_HS_PHY_IRQHandler: + ldr r0,=USB1_HS_PHY_DriverIRQHandler + bx r0 + .size USB1_HS_PHY_IRQHandler, . - USB1_HS_PHY_IRQHandler + + .align 1 + .thumb_func + .weak USB1_HS_IRQHandler + .type USB1_HS_IRQHandler, %function +USB1_HS_IRQHandler: + ldr r0,=USB1_HS_DriverIRQHandler + bx r0 + .size USB1_HS_IRQHandler, . - USB1_HS_IRQHandler + + .align 1 + .thumb_func + .weak SEC_HYPERVISOR_CALL_IRQHandler + .type SEC_HYPERVISOR_CALL_IRQHandler, %function +SEC_HYPERVISOR_CALL_IRQHandler: + ldr r0,=SEC_HYPERVISOR_CALL_DriverIRQHandler + bx r0 + .size SEC_HYPERVISOR_CALL_IRQHandler, . - SEC_HYPERVISOR_CALL_IRQHandler + + .align 1 + .thumb_func + .weak Reserved85_IRQHandler + .type Reserved85_IRQHandler, %function +Reserved85_IRQHandler: + ldr r0,=Reserved85_DriverIRQHandler + bx r0 + .size Reserved85_IRQHandler, . - Reserved85_IRQHandler + + .align 1 + .thumb_func + .weak PLU_IRQHandler + .type PLU_IRQHandler, %function +PLU_IRQHandler: + ldr r0,=PLU_DriverIRQHandler + bx r0 + .size PLU_IRQHandler, . - PLU_IRQHandler + + .align 1 + .thumb_func + .weak Freqme_IRQHandler + .type Freqme_IRQHandler, %function +Freqme_IRQHandler: + ldr r0,=Freqme_DriverIRQHandler + bx r0 + .size Freqme_IRQHandler, . - Freqme_IRQHandler + + .align 1 + .thumb_func + .weak SEC_VIO_IRQHandler + .type SEC_VIO_IRQHandler, %function +SEC_VIO_IRQHandler: + ldr r0,=SEC_VIO_DriverIRQHandler + bx r0 + .size SEC_VIO_IRQHandler, . - SEC_VIO_IRQHandler + + .align 1 + .thumb_func + .weak ELS_IRQHandler + .type ELS_IRQHandler, %function +ELS_IRQHandler: + ldr r0,=ELS_DriverIRQHandler + bx r0 + .size ELS_IRQHandler, . - ELS_IRQHandler + + .align 1 + .thumb_func + .weak PKC_IRQHandler + .type PKC_IRQHandler, %function +PKC_IRQHandler: + ldr r0,=PKC_DriverIRQHandler + bx r0 + .size PKC_IRQHandler, . - PKC_IRQHandler + + .align 1 + .thumb_func + .weak PUF_IRQHandler + .type PUF_IRQHandler, %function +PUF_IRQHandler: + ldr r0,=PUF_DriverIRQHandler + bx r0 + .size PUF_IRQHandler, . - PUF_IRQHandler + + .align 1 + .thumb_func + .weak PQ_IRQHandler + .type PQ_IRQHandler, %function +PQ_IRQHandler: + ldr r0,=PQ_DriverIRQHandler + bx r0 + .size PQ_IRQHandler, . - PQ_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH0_IRQHandler + .type EDMA_1_CH0_IRQHandler, %function +EDMA_1_CH0_IRQHandler: + ldr r0,=EDMA_1_CH0_DriverIRQHandler + bx r0 + .size EDMA_1_CH0_IRQHandler, . - EDMA_1_CH0_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH1_IRQHandler + .type EDMA_1_CH1_IRQHandler, %function +EDMA_1_CH1_IRQHandler: + ldr r0,=EDMA_1_CH1_DriverIRQHandler + bx r0 + .size EDMA_1_CH1_IRQHandler, . - EDMA_1_CH1_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH2_IRQHandler + .type EDMA_1_CH2_IRQHandler, %function +EDMA_1_CH2_IRQHandler: + ldr r0,=EDMA_1_CH2_DriverIRQHandler + bx r0 + .size EDMA_1_CH2_IRQHandler, . - EDMA_1_CH2_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH3_IRQHandler + .type EDMA_1_CH3_IRQHandler, %function +EDMA_1_CH3_IRQHandler: + ldr r0,=EDMA_1_CH3_DriverIRQHandler + bx r0 + .size EDMA_1_CH3_IRQHandler, . - EDMA_1_CH3_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH4_IRQHandler + .type EDMA_1_CH4_IRQHandler, %function +EDMA_1_CH4_IRQHandler: + ldr r0,=EDMA_1_CH4_DriverIRQHandler + bx r0 + .size EDMA_1_CH4_IRQHandler, . - EDMA_1_CH4_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH5_IRQHandler + .type EDMA_1_CH5_IRQHandler, %function +EDMA_1_CH5_IRQHandler: + ldr r0,=EDMA_1_CH5_DriverIRQHandler + bx r0 + .size EDMA_1_CH5_IRQHandler, . - EDMA_1_CH5_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH6_IRQHandler + .type EDMA_1_CH6_IRQHandler, %function +EDMA_1_CH6_IRQHandler: + ldr r0,=EDMA_1_CH6_DriverIRQHandler + bx r0 + .size EDMA_1_CH6_IRQHandler, . - EDMA_1_CH6_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH7_IRQHandler + .type EDMA_1_CH7_IRQHandler, %function +EDMA_1_CH7_IRQHandler: + ldr r0,=EDMA_1_CH7_DriverIRQHandler + bx r0 + .size EDMA_1_CH7_IRQHandler, . - EDMA_1_CH7_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH8_IRQHandler + .type EDMA_1_CH8_IRQHandler, %function +EDMA_1_CH8_IRQHandler: + ldr r0,=EDMA_1_CH8_DriverIRQHandler + bx r0 + .size EDMA_1_CH8_IRQHandler, . - EDMA_1_CH8_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH9_IRQHandler + .type EDMA_1_CH9_IRQHandler, %function +EDMA_1_CH9_IRQHandler: + ldr r0,=EDMA_1_CH9_DriverIRQHandler + bx r0 + .size EDMA_1_CH9_IRQHandler, . - EDMA_1_CH9_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH10_IRQHandler + .type EDMA_1_CH10_IRQHandler, %function +EDMA_1_CH10_IRQHandler: + ldr r0,=EDMA_1_CH10_DriverIRQHandler + bx r0 + .size EDMA_1_CH10_IRQHandler, . - EDMA_1_CH10_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH11_IRQHandler + .type EDMA_1_CH11_IRQHandler, %function +EDMA_1_CH11_IRQHandler: + ldr r0,=EDMA_1_CH11_DriverIRQHandler + bx r0 + .size EDMA_1_CH11_IRQHandler, . - EDMA_1_CH11_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH12_IRQHandler + .type EDMA_1_CH12_IRQHandler, %function +EDMA_1_CH12_IRQHandler: + ldr r0,=EDMA_1_CH12_DriverIRQHandler + bx r0 + .size EDMA_1_CH12_IRQHandler, . - EDMA_1_CH12_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH13_IRQHandler + .type EDMA_1_CH13_IRQHandler, %function +EDMA_1_CH13_IRQHandler: + ldr r0,=EDMA_1_CH13_DriverIRQHandler + bx r0 + .size EDMA_1_CH13_IRQHandler, . - EDMA_1_CH13_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH14_IRQHandler + .type EDMA_1_CH14_IRQHandler, %function +EDMA_1_CH14_IRQHandler: + ldr r0,=EDMA_1_CH14_DriverIRQHandler + bx r0 + .size EDMA_1_CH14_IRQHandler, . - EDMA_1_CH14_IRQHandler + + .align 1 + .thumb_func + .weak EDMA_1_CH15_IRQHandler + .type EDMA_1_CH15_IRQHandler, %function +EDMA_1_CH15_IRQHandler: + ldr r0,=EDMA_1_CH15_DriverIRQHandler + bx r0 + .size EDMA_1_CH15_IRQHandler, . - EDMA_1_CH15_IRQHandler + + .align 1 + .thumb_func + .weak CDOG0_IRQHandler + .type CDOG0_IRQHandler, %function +CDOG0_IRQHandler: + ldr r0,=CDOG0_DriverIRQHandler + bx r0 + .size CDOG0_IRQHandler, . - CDOG0_IRQHandler + + .align 1 + .thumb_func + .weak CDOG1_IRQHandler + .type CDOG1_IRQHandler, %function +CDOG1_IRQHandler: + ldr r0,=CDOG1_DriverIRQHandler + bx r0 + .size CDOG1_IRQHandler, . - CDOG1_IRQHandler + + .align 1 + .thumb_func + .weak I3C0_IRQHandler + .type I3C0_IRQHandler, %function +I3C0_IRQHandler: + ldr r0,=I3C0_DriverIRQHandler + bx r0 + .size I3C0_IRQHandler, . - I3C0_IRQHandler + + .align 1 + .thumb_func + .weak I3C1_IRQHandler + .type I3C1_IRQHandler, %function +I3C1_IRQHandler: + ldr r0,=I3C1_DriverIRQHandler + bx r0 + .size I3C1_IRQHandler, . - I3C1_IRQHandler + + .align 1 + .thumb_func + .weak NPU_IRQHandler + .type NPU_IRQHandler, %function +NPU_IRQHandler: + ldr r0,=NPU_DriverIRQHandler + bx r0 + .size NPU_IRQHandler, . - NPU_IRQHandler + + .align 1 + .thumb_func + .weak GDET_IRQHandler + .type GDET_IRQHandler, %function +GDET_IRQHandler: + ldr r0,=GDET_DriverIRQHandler + bx r0 + .size GDET_IRQHandler, . - GDET_IRQHandler + + .align 1 + .thumb_func + .weak VBAT0_IRQHandler + .type VBAT0_IRQHandler, %function +VBAT0_IRQHandler: + ldr r0,=VBAT0_DriverIRQHandler + bx r0 + .size VBAT0_IRQHandler, . - VBAT0_IRQHandler + + .align 1 + .thumb_func + .weak EWM0_IRQHandler + .type EWM0_IRQHandler, %function +EWM0_IRQHandler: + ldr r0,=EWM0_DriverIRQHandler + bx r0 + .size EWM0_IRQHandler, . - EWM0_IRQHandler + + .align 1 + .thumb_func + .weak TSI_END_OF_SCAN_IRQHandler + .type TSI_END_OF_SCAN_IRQHandler, %function +TSI_END_OF_SCAN_IRQHandler: + ldr r0,=TSI_END_OF_SCAN_DriverIRQHandler + bx r0 + .size TSI_END_OF_SCAN_IRQHandler, . - TSI_END_OF_SCAN_IRQHandler + + .align 1 + .thumb_func + .weak TSI_OUT_OF_SCAN_IRQHandler + .type TSI_OUT_OF_SCAN_IRQHandler, %function +TSI_OUT_OF_SCAN_IRQHandler: + ldr r0,=TSI_OUT_OF_SCAN_DriverIRQHandler + bx r0 + .size TSI_OUT_OF_SCAN_IRQHandler, . - TSI_OUT_OF_SCAN_IRQHandler + + .align 1 + .thumb_func + .weak EMVSIM0_IRQHandler + .type EMVSIM0_IRQHandler, %function +EMVSIM0_IRQHandler: + ldr r0,=EMVSIM0_DriverIRQHandler + bx r0 + .size EMVSIM0_IRQHandler, . - EMVSIM0_IRQHandler + + .align 1 + .thumb_func + .weak EMVSIM1_IRQHandler + .type EMVSIM1_IRQHandler, %function +EMVSIM1_IRQHandler: + ldr r0,=EMVSIM1_DriverIRQHandler + bx r0 + .size EMVSIM1_IRQHandler, . - EMVSIM1_IRQHandler + + .align 1 + .thumb_func + .weak FLEXIO_IRQHandler + .type FLEXIO_IRQHandler, %function +FLEXIO_IRQHandler: + ldr r0,=FLEXIO_DriverIRQHandler + bx r0 + .size FLEXIO_IRQHandler, . - FLEXIO_IRQHandler + + .align 1 + .thumb_func + .weak DAC0_IRQHandler + .type DAC0_IRQHandler, %function +DAC0_IRQHandler: + ldr r0,=DAC0_DriverIRQHandler + bx r0 + .size DAC0_IRQHandler, . - DAC0_IRQHandler + + .align 1 + .thumb_func + .weak DAC1_IRQHandler + .type DAC1_IRQHandler, %function +DAC1_IRQHandler: + ldr r0,=DAC1_DriverIRQHandler + bx r0 + .size DAC1_IRQHandler, . - DAC1_IRQHandler + + .align 1 + .thumb_func + .weak DAC2_IRQHandler + .type DAC2_IRQHandler, %function +DAC2_IRQHandler: + ldr r0,=DAC2_DriverIRQHandler + bx r0 + .size DAC2_IRQHandler, . - DAC2_IRQHandler + + .align 1 + .thumb_func + .weak HSCMP0_IRQHandler + .type HSCMP0_IRQHandler, %function +HSCMP0_IRQHandler: + ldr r0,=HSCMP0_DriverIRQHandler + bx r0 + .size HSCMP0_IRQHandler, . - HSCMP0_IRQHandler + + .align 1 + .thumb_func + .weak HSCMP1_IRQHandler + .type HSCMP1_IRQHandler, %function +HSCMP1_IRQHandler: + ldr r0,=HSCMP1_DriverIRQHandler + bx r0 + .size HSCMP1_IRQHandler, . - HSCMP1_IRQHandler + + .align 1 + .thumb_func + .weak HSCMP2_IRQHandler + .type HSCMP2_IRQHandler, %function +HSCMP2_IRQHandler: + ldr r0,=HSCMP2_DriverIRQHandler + bx r0 + .size HSCMP2_IRQHandler, . - HSCMP2_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM0_RELOAD_ERROR_IRQHandler + .type FLEXPWM0_RELOAD_ERROR_IRQHandler, %function +FLEXPWM0_RELOAD_ERROR_IRQHandler: + ldr r0,=FLEXPWM0_RELOAD_ERROR_DriverIRQHandler + bx r0 + .size FLEXPWM0_RELOAD_ERROR_IRQHandler, . - FLEXPWM0_RELOAD_ERROR_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM0_FAULT_IRQHandler + .type FLEXPWM0_FAULT_IRQHandler, %function +FLEXPWM0_FAULT_IRQHandler: + ldr r0,=FLEXPWM0_FAULT_DriverIRQHandler + bx r0 + .size FLEXPWM0_FAULT_IRQHandler, . - FLEXPWM0_FAULT_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM0_SUBMODULE0_IRQHandler + .type FLEXPWM0_SUBMODULE0_IRQHandler, %function +FLEXPWM0_SUBMODULE0_IRQHandler: + ldr r0,=FLEXPWM0_SUBMODULE0_DriverIRQHandler + bx r0 + .size FLEXPWM0_SUBMODULE0_IRQHandler, . - FLEXPWM0_SUBMODULE0_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM0_SUBMODULE1_IRQHandler + .type FLEXPWM0_SUBMODULE1_IRQHandler, %function +FLEXPWM0_SUBMODULE1_IRQHandler: + ldr r0,=FLEXPWM0_SUBMODULE1_DriverIRQHandler + bx r0 + .size FLEXPWM0_SUBMODULE1_IRQHandler, . - FLEXPWM0_SUBMODULE1_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM0_SUBMODULE2_IRQHandler + .type FLEXPWM0_SUBMODULE2_IRQHandler, %function +FLEXPWM0_SUBMODULE2_IRQHandler: + ldr r0,=FLEXPWM0_SUBMODULE2_DriverIRQHandler + bx r0 + .size FLEXPWM0_SUBMODULE2_IRQHandler, . - FLEXPWM0_SUBMODULE2_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM0_SUBMODULE3_IRQHandler + .type FLEXPWM0_SUBMODULE3_IRQHandler, %function +FLEXPWM0_SUBMODULE3_IRQHandler: + ldr r0,=FLEXPWM0_SUBMODULE3_DriverIRQHandler + bx r0 + .size FLEXPWM0_SUBMODULE3_IRQHandler, . - FLEXPWM0_SUBMODULE3_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM1_RELOAD_ERROR_IRQHandler + .type FLEXPWM1_RELOAD_ERROR_IRQHandler, %function +FLEXPWM1_RELOAD_ERROR_IRQHandler: + ldr r0,=FLEXPWM1_RELOAD_ERROR_DriverIRQHandler + bx r0 + .size FLEXPWM1_RELOAD_ERROR_IRQHandler, . - FLEXPWM1_RELOAD_ERROR_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM1_FAULT_IRQHandler + .type FLEXPWM1_FAULT_IRQHandler, %function +FLEXPWM1_FAULT_IRQHandler: + ldr r0,=FLEXPWM1_FAULT_DriverIRQHandler + bx r0 + .size FLEXPWM1_FAULT_IRQHandler, . - FLEXPWM1_FAULT_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM1_SUBMODULE0_IRQHandler + .type FLEXPWM1_SUBMODULE0_IRQHandler, %function +FLEXPWM1_SUBMODULE0_IRQHandler: + ldr r0,=FLEXPWM1_SUBMODULE0_DriverIRQHandler + bx r0 + .size FLEXPWM1_SUBMODULE0_IRQHandler, . - FLEXPWM1_SUBMODULE0_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM1_SUBMODULE1_IRQHandler + .type FLEXPWM1_SUBMODULE1_IRQHandler, %function +FLEXPWM1_SUBMODULE1_IRQHandler: + ldr r0,=FLEXPWM1_SUBMODULE1_DriverIRQHandler + bx r0 + .size FLEXPWM1_SUBMODULE1_IRQHandler, . - FLEXPWM1_SUBMODULE1_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM1_SUBMODULE2_IRQHandler + .type FLEXPWM1_SUBMODULE2_IRQHandler, %function +FLEXPWM1_SUBMODULE2_IRQHandler: + ldr r0,=FLEXPWM1_SUBMODULE2_DriverIRQHandler + bx r0 + .size FLEXPWM1_SUBMODULE2_IRQHandler, . - FLEXPWM1_SUBMODULE2_IRQHandler + + .align 1 + .thumb_func + .weak FLEXPWM1_SUBMODULE3_IRQHandler + .type FLEXPWM1_SUBMODULE3_IRQHandler, %function +FLEXPWM1_SUBMODULE3_IRQHandler: + ldr r0,=FLEXPWM1_SUBMODULE3_DriverIRQHandler + bx r0 + .size FLEXPWM1_SUBMODULE3_IRQHandler, . - FLEXPWM1_SUBMODULE3_IRQHandler + + .align 1 + .thumb_func + .weak ENC0_COMPARE_IRQHandler + .type ENC0_COMPARE_IRQHandler, %function +ENC0_COMPARE_IRQHandler: + ldr r0,=ENC0_COMPARE_DriverIRQHandler + bx r0 + .size ENC0_COMPARE_IRQHandler, . - ENC0_COMPARE_IRQHandler + + .align 1 + .thumb_func + .weak ENC0_HOME_IRQHandler + .type ENC0_HOME_IRQHandler, %function +ENC0_HOME_IRQHandler: + ldr r0,=ENC0_HOME_DriverIRQHandler + bx r0 + .size ENC0_HOME_IRQHandler, . - ENC0_HOME_IRQHandler + + .align 1 + .thumb_func + .weak ENC0_WDG_SAB_IRQHandler + .type ENC0_WDG_SAB_IRQHandler, %function +ENC0_WDG_SAB_IRQHandler: + ldr r0,=ENC0_WDG_SAB_DriverIRQHandler + bx r0 + .size ENC0_WDG_SAB_IRQHandler, . - ENC0_WDG_SAB_IRQHandler + + .align 1 + .thumb_func + .weak ENC0_IDX_IRQHandler + .type ENC0_IDX_IRQHandler, %function +ENC0_IDX_IRQHandler: + ldr r0,=ENC0_IDX_DriverIRQHandler + bx r0 + .size ENC0_IDX_IRQHandler, . - ENC0_IDX_IRQHandler + + .align 1 + .thumb_func + .weak ENC1_COMPARE_IRQHandler + .type ENC1_COMPARE_IRQHandler, %function +ENC1_COMPARE_IRQHandler: + ldr r0,=ENC1_COMPARE_DriverIRQHandler + bx r0 + .size ENC1_COMPARE_IRQHandler, . - ENC1_COMPARE_IRQHandler + + .align 1 + .thumb_func + .weak ENC1_HOME_IRQHandler + .type ENC1_HOME_IRQHandler, %function +ENC1_HOME_IRQHandler: + ldr r0,=ENC1_HOME_DriverIRQHandler + bx r0 + .size ENC1_HOME_IRQHandler, . - ENC1_HOME_IRQHandler + + .align 1 + .thumb_func + .weak ENC1_WDG_SAB_IRQHandler + .type ENC1_WDG_SAB_IRQHandler, %function +ENC1_WDG_SAB_IRQHandler: + ldr r0,=ENC1_WDG_SAB_DriverIRQHandler + bx r0 + .size ENC1_WDG_SAB_IRQHandler, . - ENC1_WDG_SAB_IRQHandler + + .align 1 + .thumb_func + .weak ENC1_IDX_IRQHandler + .type ENC1_IDX_IRQHandler, %function +ENC1_IDX_IRQHandler: + ldr r0,=ENC1_IDX_DriverIRQHandler + bx r0 + .size ENC1_IDX_IRQHandler, . - ENC1_IDX_IRQHandler + + .align 1 + .thumb_func + .weak ITRC0_IRQHandler + .type ITRC0_IRQHandler, %function +ITRC0_IRQHandler: + ldr r0,=ITRC0_DriverIRQHandler + bx r0 + .size ITRC0_IRQHandler, . - ITRC0_IRQHandler + + .align 1 + .thumb_func + .weak BSP32_IRQHandler + .type BSP32_IRQHandler, %function +BSP32_IRQHandler: + ldr r0,=BSP32_DriverIRQHandler + bx r0 + .size BSP32_IRQHandler, . - BSP32_IRQHandler + + .align 1 + .thumb_func + .weak ELS_ERR_IRQHandler + .type ELS_ERR_IRQHandler, %function +ELS_ERR_IRQHandler: + ldr r0,=ELS_ERR_DriverIRQHandler + bx r0 + .size ELS_ERR_IRQHandler, . - ELS_ERR_IRQHandler + + .align 1 + .thumb_func + .weak PKC_ERR_IRQHandler + .type PKC_ERR_IRQHandler, %function +PKC_ERR_IRQHandler: + ldr r0,=PKC_ERR_DriverIRQHandler + bx r0 + .size PKC_ERR_IRQHandler, . - PKC_ERR_IRQHandler + + .align 1 + .thumb_func + .weak ERM_SINGLE_BIT_ERROR_IRQHandler + .type ERM_SINGLE_BIT_ERROR_IRQHandler, %function +ERM_SINGLE_BIT_ERROR_IRQHandler: + ldr r0,=ERM_SINGLE_BIT_ERROR_DriverIRQHandler + bx r0 + .size ERM_SINGLE_BIT_ERROR_IRQHandler, . - ERM_SINGLE_BIT_ERROR_IRQHandler + + .align 1 + .thumb_func + .weak ERM_MULTI_BIT_ERROR_IRQHandler + .type ERM_MULTI_BIT_ERROR_IRQHandler, %function +ERM_MULTI_BIT_ERROR_IRQHandler: + ldr r0,=ERM_MULTI_BIT_ERROR_DriverIRQHandler + bx r0 + .size ERM_MULTI_BIT_ERROR_IRQHandler, . - ERM_MULTI_BIT_ERROR_IRQHandler + + .align 1 + .thumb_func + .weak FMU0_IRQHandler + .type FMU0_IRQHandler, %function +FMU0_IRQHandler: + ldr r0,=FMU0_DriverIRQHandler + bx r0 + .size FMU0_IRQHandler, . - FMU0_IRQHandler + + .align 1 + .thumb_func + .weak ETHERNET_IRQHandler + .type ETHERNET_IRQHandler, %function +ETHERNET_IRQHandler: + ldr r0,=ETHERNET_DriverIRQHandler + bx r0 + .size ETHERNET_IRQHandler, . - ETHERNET_IRQHandler + + .align 1 + .thumb_func + .weak ETHERNET_PMT_IRQHandler + .type ETHERNET_PMT_IRQHandler, %function +ETHERNET_PMT_IRQHandler: + ldr r0,=ETHERNET_PMT_DriverIRQHandler + bx r0 + .size ETHERNET_PMT_IRQHandler, . - ETHERNET_PMT_IRQHandler + + .align 1 + .thumb_func + .weak ETHERNET_MACLP_IRQHandler + .type ETHERNET_MACLP_IRQHandler, %function +ETHERNET_MACLP_IRQHandler: + ldr r0,=ETHERNET_MACLP_DriverIRQHandler + bx r0 + .size ETHERNET_MACLP_IRQHandler, . - ETHERNET_MACLP_IRQHandler + + .align 1 + .thumb_func + .weak SINC_FILTER_IRQHandler + .type SINC_FILTER_IRQHandler, %function +SINC_FILTER_IRQHandler: + ldr r0,=SINC_FILTER_DriverIRQHandler + bx r0 + .size SINC_FILTER_IRQHandler, . - SINC_FILTER_IRQHandler + + .align 1 + .thumb_func + .weak LPTMR0_IRQHandler + .type LPTMR0_IRQHandler, %function +LPTMR0_IRQHandler: + ldr r0,=LPTMR0_DriverIRQHandler + bx r0 + .size LPTMR0_IRQHandler, . - LPTMR0_IRQHandler + + .align 1 + .thumb_func + .weak LPTMR1_IRQHandler + .type LPTMR1_IRQHandler, %function +LPTMR1_IRQHandler: + ldr r0,=LPTMR1_DriverIRQHandler + bx r0 + .size LPTMR1_IRQHandler, . - LPTMR1_IRQHandler + + .align 1 + .thumb_func + .weak SCG_IRQHandler + .type SCG_IRQHandler, %function +SCG_IRQHandler: + ldr r0,=SCG_DriverIRQHandler + bx r0 + .size SCG_IRQHandler, . - SCG_IRQHandler + + .align 1 + .thumb_func + .weak SPC_IRQHandler + .type SPC_IRQHandler, %function +SPC_IRQHandler: + ldr r0,=SPC_DriverIRQHandler + bx r0 + .size SPC_IRQHandler, . - SPC_IRQHandler + + .align 1 + .thumb_func + .weak WUU_IRQHandler + .type WUU_IRQHandler, %function +WUU_IRQHandler: + ldr r0,=WUU_DriverIRQHandler + bx r0 + .size WUU_IRQHandler, . - WUU_IRQHandler + + .align 1 + .thumb_func + .weak PORT_EFT_IRQHandler + .type PORT_EFT_IRQHandler, %function +PORT_EFT_IRQHandler: + ldr r0,=PORT_EFT_DriverIRQHandler + bx r0 + .size PORT_EFT_IRQHandler, . - PORT_EFT_IRQHandler + + .align 1 + .thumb_func + .weak ETB0_IRQHandler + .type ETB0_IRQHandler, %function +ETB0_IRQHandler: + ldr r0,=ETB0_DriverIRQHandler + bx r0 + .size ETB0_IRQHandler, . - ETB0_IRQHandler + + .align 1 + .thumb_func + .weak SM3_IRQHandler + .type SM3_IRQHandler, %function +SM3_IRQHandler: + ldr r0,=SM3_DriverIRQHandler + bx r0 + .size SM3_IRQHandler, . - SM3_IRQHandler + + .align 1 + .thumb_func + .weak TRNG0_IRQHandler + .type TRNG0_IRQHandler, %function +TRNG0_IRQHandler: + ldr r0,=TRNG0_DriverIRQHandler + bx r0 + .size TRNG0_IRQHandler, . - TRNG0_IRQHandler + + .align 1 + .thumb_func + .weak WWDT0_IRQHandler + .type WWDT0_IRQHandler, %function +WWDT0_IRQHandler: + ldr r0,=WWDT0_DriverIRQHandler + bx r0 + .size WWDT0_IRQHandler, . - WWDT0_IRQHandler + + .align 1 + .thumb_func + .weak WWDT1_IRQHandler + .type WWDT1_IRQHandler, %function +WWDT1_IRQHandler: + ldr r0,=WWDT1_DriverIRQHandler + bx r0 + .size WWDT1_IRQHandler, . - WWDT1_IRQHandler + + .align 1 + .thumb_func + .weak CMC0_IRQHandler + .type CMC0_IRQHandler, %function +CMC0_IRQHandler: + ldr r0,=CMC0_DriverIRQHandler + bx r0 + .size CMC0_IRQHandler, . - CMC0_IRQHandler + + .align 1 + .thumb_func + .weak CTI0_IRQHandler + .type CTI0_IRQHandler, %function +CTI0_IRQHandler: + ldr r0,=CTI0_DriverIRQHandler + bx r0 + .size CTI0_IRQHandler, . - CTI0_IRQHandler + + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, DefaultISR + .endm +/* Exception Handlers */ + def_irq_handler MemManage_Handler + def_irq_handler BusFault_Handler + def_irq_handler UsageFault_Handler + def_irq_handler SecureFault_Handler + def_irq_handler DebugMon_Handler + def_irq_handler OR_DriverIRQHandler + def_irq_handler EDMA_0_CH0_DriverIRQHandler + def_irq_handler EDMA_0_CH1_DriverIRQHandler + def_irq_handler EDMA_0_CH2_DriverIRQHandler + def_irq_handler EDMA_0_CH3_DriverIRQHandler + def_irq_handler EDMA_0_CH4_DriverIRQHandler + def_irq_handler EDMA_0_CH5_DriverIRQHandler + def_irq_handler EDMA_0_CH6_DriverIRQHandler + def_irq_handler EDMA_0_CH7_DriverIRQHandler + def_irq_handler EDMA_0_CH8_DriverIRQHandler + def_irq_handler EDMA_0_CH9_DriverIRQHandler + def_irq_handler EDMA_0_CH10_DriverIRQHandler + def_irq_handler EDMA_0_CH11_DriverIRQHandler + def_irq_handler EDMA_0_CH12_DriverIRQHandler + def_irq_handler EDMA_0_CH13_DriverIRQHandler + def_irq_handler EDMA_0_CH14_DriverIRQHandler + def_irq_handler EDMA_0_CH15_DriverIRQHandler + def_irq_handler GPIO00_DriverIRQHandler + def_irq_handler GPIO01_DriverIRQHandler + def_irq_handler GPIO10_DriverIRQHandler + def_irq_handler GPIO11_DriverIRQHandler + def_irq_handler GPIO20_DriverIRQHandler + def_irq_handler GPIO21_DriverIRQHandler + def_irq_handler GPIO30_DriverIRQHandler + def_irq_handler GPIO31_DriverIRQHandler + def_irq_handler GPIO40_DriverIRQHandler + def_irq_handler GPIO41_DriverIRQHandler + def_irq_handler GPIO50_DriverIRQHandler + def_irq_handler GPIO51_DriverIRQHandler + def_irq_handler UTICK0_DriverIRQHandler + def_irq_handler MRT0_DriverIRQHandler + def_irq_handler CTIMER0_DriverIRQHandler + def_irq_handler CTIMER1_DriverIRQHandler + def_irq_handler SCT0_DriverIRQHandler + def_irq_handler CTIMER2_DriverIRQHandler + def_irq_handler LP_FLEXCOMM0_DriverIRQHandler + def_irq_handler LP_FLEXCOMM1_DriverIRQHandler + def_irq_handler LP_FLEXCOMM2_DriverIRQHandler + def_irq_handler LP_FLEXCOMM3_DriverIRQHandler + def_irq_handler LP_FLEXCOMM4_DriverIRQHandler + def_irq_handler LP_FLEXCOMM5_DriverIRQHandler + def_irq_handler LP_FLEXCOMM6_DriverIRQHandler + def_irq_handler LP_FLEXCOMM7_DriverIRQHandler + def_irq_handler LP_FLEXCOMM8_DriverIRQHandler + def_irq_handler LP_FLEXCOMM9_DriverIRQHandler + def_irq_handler ADC0_DriverIRQHandler + def_irq_handler ADC1_DriverIRQHandler + def_irq_handler PINT0_DriverIRQHandler + def_irq_handler PDM_EVENT_DriverIRQHandler + def_irq_handler Reserved65_DriverIRQHandler + def_irq_handler USB0_FS_DriverIRQHandler + def_irq_handler USB0_DCD_DriverIRQHandler + def_irq_handler RTC_DriverIRQHandler + def_irq_handler SMARTDMA_DriverIRQHandler + def_irq_handler MAILBOX_DriverIRQHandler + def_irq_handler CTIMER3_DriverIRQHandler + def_irq_handler CTIMER4_DriverIRQHandler + def_irq_handler OS_EVENT_DriverIRQHandler + def_irq_handler FLEXSPI0_DriverIRQHandler + def_irq_handler SAI0_DriverIRQHandler + def_irq_handler SAI1_DriverIRQHandler + def_irq_handler USDHC0_DriverIRQHandler + def_irq_handler CAN0_DriverIRQHandler + def_irq_handler CAN1_DriverIRQHandler + def_irq_handler Reserved80_DriverIRQHandler + def_irq_handler Reserved81_DriverIRQHandler + def_irq_handler USB1_HS_PHY_DriverIRQHandler + def_irq_handler USB1_HS_DriverIRQHandler + def_irq_handler SEC_HYPERVISOR_CALL_DriverIRQHandler + def_irq_handler Reserved85_DriverIRQHandler + def_irq_handler PLU_DriverIRQHandler + def_irq_handler Freqme_DriverIRQHandler + def_irq_handler SEC_VIO_DriverIRQHandler + def_irq_handler ELS_DriverIRQHandler + def_irq_handler PKC_DriverIRQHandler + def_irq_handler PUF_DriverIRQHandler + def_irq_handler PQ_DriverIRQHandler + def_irq_handler EDMA_1_CH0_DriverIRQHandler + def_irq_handler EDMA_1_CH1_DriverIRQHandler + def_irq_handler EDMA_1_CH2_DriverIRQHandler + def_irq_handler EDMA_1_CH3_DriverIRQHandler + def_irq_handler EDMA_1_CH4_DriverIRQHandler + def_irq_handler EDMA_1_CH5_DriverIRQHandler + def_irq_handler EDMA_1_CH6_DriverIRQHandler + def_irq_handler EDMA_1_CH7_DriverIRQHandler + def_irq_handler EDMA_1_CH8_DriverIRQHandler + def_irq_handler EDMA_1_CH9_DriverIRQHandler + def_irq_handler EDMA_1_CH10_DriverIRQHandler + def_irq_handler EDMA_1_CH11_DriverIRQHandler + def_irq_handler EDMA_1_CH12_DriverIRQHandler + def_irq_handler EDMA_1_CH13_DriverIRQHandler + def_irq_handler EDMA_1_CH14_DriverIRQHandler + def_irq_handler EDMA_1_CH15_DriverIRQHandler + def_irq_handler CDOG0_DriverIRQHandler + def_irq_handler CDOG1_DriverIRQHandler + def_irq_handler I3C0_DriverIRQHandler + def_irq_handler I3C1_DriverIRQHandler + def_irq_handler NPU_DriverIRQHandler + def_irq_handler GDET_DriverIRQHandler + def_irq_handler VBAT0_DriverIRQHandler + def_irq_handler EWM0_DriverIRQHandler + def_irq_handler TSI_END_OF_SCAN_DriverIRQHandler + def_irq_handler TSI_OUT_OF_SCAN_DriverIRQHandler + def_irq_handler EMVSIM0_DriverIRQHandler + def_irq_handler EMVSIM1_DriverIRQHandler + def_irq_handler FLEXIO_DriverIRQHandler + def_irq_handler DAC0_DriverIRQHandler + def_irq_handler DAC1_DriverIRQHandler + def_irq_handler DAC2_DriverIRQHandler + def_irq_handler HSCMP0_DriverIRQHandler + def_irq_handler HSCMP1_DriverIRQHandler + def_irq_handler HSCMP2_DriverIRQHandler + def_irq_handler FLEXPWM0_RELOAD_ERROR_DriverIRQHandler + def_irq_handler FLEXPWM0_FAULT_DriverIRQHandler + def_irq_handler FLEXPWM0_SUBMODULE0_DriverIRQHandler + def_irq_handler FLEXPWM0_SUBMODULE1_DriverIRQHandler + def_irq_handler FLEXPWM0_SUBMODULE2_DriverIRQHandler + def_irq_handler FLEXPWM0_SUBMODULE3_DriverIRQHandler + def_irq_handler FLEXPWM1_RELOAD_ERROR_DriverIRQHandler + def_irq_handler FLEXPWM1_FAULT_DriverIRQHandler + def_irq_handler FLEXPWM1_SUBMODULE0_DriverIRQHandler + def_irq_handler FLEXPWM1_SUBMODULE1_DriverIRQHandler + def_irq_handler FLEXPWM1_SUBMODULE2_DriverIRQHandler + def_irq_handler FLEXPWM1_SUBMODULE3_DriverIRQHandler + def_irq_handler ENC0_COMPARE_DriverIRQHandler + def_irq_handler ENC0_HOME_DriverIRQHandler + def_irq_handler ENC0_WDG_SAB_DriverIRQHandler + def_irq_handler ENC0_IDX_DriverIRQHandler + def_irq_handler ENC1_COMPARE_DriverIRQHandler + def_irq_handler ENC1_HOME_DriverIRQHandler + def_irq_handler ENC1_WDG_SAB_DriverIRQHandler + def_irq_handler ENC1_IDX_DriverIRQHandler + def_irq_handler ITRC0_DriverIRQHandler + def_irq_handler BSP32_DriverIRQHandler + def_irq_handler ELS_ERR_DriverIRQHandler + def_irq_handler PKC_ERR_DriverIRQHandler + def_irq_handler ERM_SINGLE_BIT_ERROR_DriverIRQHandler + def_irq_handler ERM_MULTI_BIT_ERROR_DriverIRQHandler + def_irq_handler FMU0_DriverIRQHandler + def_irq_handler ETHERNET_DriverIRQHandler + def_irq_handler ETHERNET_PMT_DriverIRQHandler + def_irq_handler ETHERNET_MACLP_DriverIRQHandler + def_irq_handler SINC_FILTER_DriverIRQHandler + def_irq_handler LPTMR0_DriverIRQHandler + def_irq_handler LPTMR1_DriverIRQHandler + def_irq_handler SCG_DriverIRQHandler + def_irq_handler SPC_DriverIRQHandler + def_irq_handler WUU_DriverIRQHandler + def_irq_handler PORT_EFT_DriverIRQHandler + def_irq_handler ETB0_DriverIRQHandler + def_irq_handler SM3_DriverIRQHandler + def_irq_handler TRNG0_DriverIRQHandler + def_irq_handler WWDT0_DriverIRQHandler + def_irq_handler WWDT1_DriverIRQHandler + def_irq_handler CMC0_DriverIRQHandler + def_irq_handler CTI0_DriverIRQHandler + + .end diff --git a/ports/mcx/devices/MCXN947/system_MCXN947_cm33_core0.c b/ports/mcx/devices/MCXN947/system_MCXN947_cm33_core0.c new file mode 100644 index 0000000000..d63cab9ff8 --- /dev/null +++ b/ports/mcx/devices/MCXN947/system_MCXN947_cm33_core0.c @@ -0,0 +1,129 @@ +/* +** ################################################################### +** Processors: MCXN947VDF_cm33_core0 +** MCXN947VNL_cm33_core0 +** +** Compilers: GNU C Compiler +** IAR ANSI C/C++ Compiler for ARM +** Keil ARM C/C++ Compiler +** MCUXpresso Compiler +** +** Reference manual: MCXNx4x Reference Manual +** Version: rev. 2.0, 2023-02-01 +** Build: b231120 +** +** Abstract: +** Provides a system configuration function and a global variable that +** contains the system frequency. It configures the device and initializes +** the oscillator (PLL) that is part of the microcontroller device. +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2023 NXP +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** Revisions: +** - rev. 1.0 (2022-10-01) +** Initial version +** - rev. 2.0 (2023-02-01) +** Initial version based on Rev. 2 Draft B +** +** ################################################################### +*/ + +/*! + * @file MCXN947_cm33_core0 + * @version 2.0 + * @date 2023-02-01 + * @brief Device specific configuration file for MCXN947_cm33_core0 + * (implementation file) + * + * Provides a system configuration function and a global variable that contains + * the system frequency. It configures the device and initializes the oscillator + * (PLL) that is part of the microcontroller device. + */ + +#include +#include "fsl_device_registers.h" + + + + + + +/* ---------------------------------------------------------------------------- + -- Core clock + ---------------------------------------------------------------------------- */ + +uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK; + +/* ---------------------------------------------------------------------------- + -- SystemInit() + ---------------------------------------------------------------------------- */ + +__attribute__ ((weak)) void SystemInit(void) { + #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) + SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access in Secure mode */ + #if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + SCB_NS->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access in Non-secure mode */ + #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + #endif /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */ + + + SCB->CPACR |= ((3UL << 0 * 2) | (3UL << 1 * 2)); /* set CP0, CP1 Full Access in Secure mode (enable PowerQuad) */ + #if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + SCB_NS->CPACR |= ((3UL << 0 * 2) | (3UL << 1 * 2)); /* set CP0, CP1 Full Access in Normal mode (enable PowerQuad) */ + #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + SCB->NSACR |= ((3UL << 0) | (3UL << 10)); /* enable CP0, CP1, CP10, CP11 Non-secure Access */ + + SYSCON->ECC_ENABLE_CTRL = 0; /* disable RAM ECC to get max RAM size */ + + // SYSCON->NVM_CTRL &= ~SYSCON_NVM_CTRL_DIS_MBECC_ERR_DATA_MASK; /* enables bus error on multi-bit ECC error for data */ + + #if defined(__MCUXPRESSO) + extern void(*const g_pfnVectors[]) (void); + SCB->VTOR = (uint32_t)&g_pfnVectors; + #else + extern void *__Vectors; + SCB->VTOR = (uint32_t)&__Vectors; + #endif + /* enable the flash cache LPCAC */ + SYSCON->LPCAC_CTRL &= ~SYSCON_LPCAC_CTRL_DIS_LPCAC_MASK; + + /* Disable aGDET trigger the CHIP_RESET */ + ITRC0->OUT_SEL[4][0] = (ITRC0->OUT_SEL[4][0] & ~ITRC_OUTX_SEL_OUTX_SELY_OUT_SEL_IN9_SELn_MASK) | (ITRC_OUTX_SEL_OUTX_SELY_OUT_SEL_IN9_SELn(0x2)); + ITRC0->OUT_SEL[4][1] = (ITRC0->OUT_SEL[4][1] & ~ITRC_OUTX_SEL_OUTX_SELY_OUT_SEL_IN9_SELn_MASK) | (ITRC_OUTX_SEL_OUTX_SELY_OUT_SEL_IN9_SELn(0x2)); + /* Disable aGDET interrupt and reset */ + SPC0->ACTIVE_CFG |= SPC_ACTIVE_CFG_GLITCH_DETECT_DISABLE_MASK; + SPC0->VDD_CORE_GLITCH_DETECT_SC &= ~SPC_VDD_CORE_GLITCH_DETECT_SC_LOCK_MASK; + SPC0->VDD_CORE_GLITCH_DETECT_SC = 0x3C; + + /* Disable dGDET trigger the CHIP_RESET */ + ITRC0->OUT_SEL[4][0] = (ITRC0->OUT_SEL[4][0] & ~ITRC_OUTX_SEL_OUTX_SELY_OUT_SEL_IN0_SELn_MASK) | (ITRC_OUTX_SEL_OUTX_SELY_OUT_SEL_IN0_SELn(0x2)); + ITRC0->OUT_SEL[4][1] = (ITRC0->OUT_SEL[4][1] & ~ITRC_OUTX_SEL_OUTX_SELY_OUT_SEL_IN0_SELn_MASK) | (ITRC_OUTX_SEL_OUTX_SELY_OUT_SEL_IN0_SELn(0x2)); + GDET0->GDET_ENABLE1 = 0; + GDET1->GDET_ENABLE1 = 0; + + SystemInitHook(); +} + +/* ---------------------------------------------------------------------------- + -- SystemCoreClockUpdate() + ---------------------------------------------------------------------------- */ + +void SystemCoreClockUpdate(void) { + + + +} + +/* ---------------------------------------------------------------------------- + -- SystemInitHook() + ---------------------------------------------------------------------------- */ + +__attribute__ ((weak)) void SystemInitHook(void) { + /* Void implementation of the weak function. */ +} diff --git a/ports/mcx/devices/MCXN947/system_MCXN947_cm33_core0.h b/ports/mcx/devices/MCXN947/system_MCXN947_cm33_core0.h new file mode 100644 index 0000000000..fefd2fb9a4 --- /dev/null +++ b/ports/mcx/devices/MCXN947/system_MCXN947_cm33_core0.h @@ -0,0 +1,108 @@ +/* +** ################################################################### +** Processors: MCXN947VDF_cm33_core0 +** MCXN947VNL_cm33_core0 +** +** Compilers: GNU C Compiler +** IAR ANSI C/C++ Compiler for ARM +** Keil ARM C/C++ Compiler +** MCUXpresso Compiler +** +** Reference manual: MCXNx4x Reference Manual +** Version: rev. 2.0, 2023-02-01 +** Build: b231026 +** +** Abstract: +** Provides a system configuration function and a global variable that +** contains the system frequency. It configures the device and initializes +** the oscillator (PLL) that is part of the microcontroller device. +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2023 NXP +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** Revisions: +** - rev. 1.0 (2022-10-01) +** Initial version +** - rev. 2.0 (2023-02-01) +** Initial version based on Rev. 2 Draft B +** +** ################################################################### +*/ + +/*! + * @file MCXN947_cm33_core0 + * @version 2.0 + * @date 2023-02-01 + * @brief Device specific configuration file for MCXN947_cm33_core0 (header file) + * + * Provides a system configuration function and a global variable that contains + * the system frequency. It configures the device and initializes the oscillator + * (PLL) that is part of the microcontroller device. + */ + +#ifndef _SYSTEM_MCXN947_cm33_core0_H_ +#define _SYSTEM_MCXN947_cm33_core0_H_ /**< Symbol preventing repeated inclusion */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + + +#define DEFAULT_SYSTEM_CLOCK 48000000u /* Default System clock value */ +#define CLK_FRO_12MHZ 12000000u /* FRO 12 MHz (fro_12m) */ +#define CLK_FRO_144MHZ 144000000u /* FRO 144 MHz (fro_144m) */ + + + +/** + * @brief System clock frequency (core clock) + * + * The system clock frequency supplied to the SysTick timer and the processor + * core clock. This variable can be used by the user application to setup the + * SysTick timer or configure other parameters. It may also be used by debugger to + * query the frequency of the debug timer or configure the trace clock speed + * SystemCoreClock is initialized with a correct predefined value. + */ +extern uint32_t SystemCoreClock; + +/** + * @brief Setup the microcontroller system. + * + * Typically this function configures the oscillator (PLL) that is part of the + * microcontroller device. For systems with variable clock speed it also updates + * the variable SystemCoreClock. SystemInit is called from startup_device file. + */ +void SystemInit(void); + +/** + * @brief Updates the SystemCoreClock variable. + * + * It must be called whenever the core clock is changed during program + * execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates + * the current core clock. + */ +void SystemCoreClockUpdate(void); + +/** + * @brief SystemInit function hook. + * + * This weak function allows to call specific initialization code during the + * SystemInit() execution.This can be used when an application specific code needs + * to be called as close to the reset entry as possible (for example the Multicore + * Manager MCMGR_EarlyInit() function call). + * NOTE: No global r/w variables can be used in this hook function because the + * initialization of these variables happens after this function. + */ +void SystemInitHook(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYSTEM_MCXN947_cm33_core0_H_ */ diff --git a/ports/mcx/drv_adc.c b/ports/mcx/drv_adc.c new file mode 100644 index 0000000000..d43cdc9a48 --- /dev/null +++ b/ports/mcx/drv_adc.c @@ -0,0 +1,108 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "board.h" + +#include "fsl_lpadc.h" +#include "fsl_spc.h" +#include "fsl_vref.h" + +#include "drv_adc.h" + +int drv_adc_init(drv_adc_t *adc, uint8_t id) { + adc->instance = MCX_BoardGetADCInstance(id); + if (adc->instance == NULL) { + return -EINVAL; + } + + adc->id = id; + + int adc_inputfreq = MCX_BoardConfigureADCClock(id); + if (adc_inputfreq <= 0) { + return -EINVAL; + } + + ADC_Type *lpadc = adc->instance; + + SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlVref); + + vref_config_t vref_cfg; + VREF_GetDefaultConfig(&vref_cfg); + + vref_cfg.bufferMode = kVREF_ModeBandgapOnly; + + VREF_Init(VREF0, &vref_cfg); + + lpadc_config_t adc_cfg; + LPADC_GetDefaultConfig(&adc_cfg); + + adc_cfg.enableAnalogPreliminary = true; + adc_cfg.referenceVoltageSource = kLPADC_ReferenceVoltageAlt3; + + LPADC_Init(lpadc, &adc_cfg); + LPADC_DoOffsetCalibration(lpadc); + LPADC_DoAutoCalibration(lpadc); + + return 0; +} + +int drv_adc_measure(drv_adc_t *adc, drv_adc_side_t side, uint8_t ch, uint16_t *result) { + ADC_Type *lpadc = adc->instance; + + lpadc_conv_command_config_t cmd_cfg; + LPADC_GetDefaultConvCommandConfig(&cmd_cfg); + + cmd_cfg.channelNumber = ch; + cmd_cfg.conversionResolutionMode = kLPADC_ConversionResolutionHigh; + + if (side == DRV_ADCSideA) { + cmd_cfg.sampleChannelMode = kLPADC_SampleChannelSingleEndSideA; + } else { + cmd_cfg.sampleChannelMode = kLPADC_SampleChannelSingleEndSideB; + } + + LPADC_SetConvCommandConfig(lpadc, 15, &cmd_cfg); + + lpadc_conv_trigger_config_t trig_cfg; + LPADC_GetDefaultConvTriggerConfig(&trig_cfg); + + trig_cfg.targetCommandId = 15; + trig_cfg.enableHardwareTrigger = false; + + LPADC_SetConvTriggerConfig(lpadc, 0U, &trig_cfg); + + LPADC_DoSoftwareTrigger(lpadc, 1U << 0U); + + lpadc_conv_result_t rs; + + while (!LPADC_GetConvResult(lpadc, &rs, 0U)) { + ; + } + + *result = rs.convValue; + + return 0; +} diff --git a/ports/mcx/drv_adc.h b/ports/mcx/drv_adc.h new file mode 100644 index 0000000000..2b1650a274 --- /dev/null +++ b/ports/mcx/drv_adc.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_DRV_ADC_H +#define MP_PORT_MCX_DRV_ADC_H + +#include + +typedef enum { + DRV_ADCSideA, + DRV_ADCSideB, +} drv_adc_side_t; + +typedef struct { + uint8_t id; + void *instance; +} drv_adc_t; + +int drv_adc_init(drv_adc_t *adc, uint8_t id); +int drv_adc_measure(drv_adc_t *adc, drv_adc_side_t side, uint8_t ch, uint16_t *result); + +#endif diff --git a/ports/mcx/drv_i2c.c b/ports/mcx/drv_i2c.c new file mode 100644 index 0000000000..24cffdf131 --- /dev/null +++ b/ports/mcx/drv_i2c.c @@ -0,0 +1,96 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "board.h" + +/* SDK drivers */ +#include "fsl_lpi2c.h" + +#include "drv_i2c.h" + +int drv_i2c_init(drv_i2c_t *i2c, uint8_t id, drv_i2c_config_t *cfg) { + i2c->instance = MCX_BoardGetI2CInstance(id); + if (i2c->instance == NULL) { + return -EINVAL; + } + + i2c->id = id; + + int i2c_inputfreq = MCX_BoardConfigureI2CClock(id); + if (i2c_inputfreq <= 0) { + return -EINVAL; + } + + lpi2c_master_config_t i2c_cfg; + LPI2C_MasterGetDefaultConfig(&i2c_cfg); + + i2c_cfg.baudRate_Hz = cfg->frequency; + + LPI2C_Type *lpi2c = i2c->instance; + LPI2C_MasterInit(lpi2c, &i2c_cfg, i2c_inputfreq); + + return 0; +} + +int drv_i2c_write(drv_i2c_t *i2c, uint16_t addr, uint8_t *data, uint32_t len, uint32_t timeout, bool stop) { + LPI2C_Type *lpi2c = i2c->instance; + + lpi2c_master_transfer_t xfer = { + .direction = kLPI2C_Write, + .slaveAddress = addr, + .subaddress = 0, + .subaddressSize = 0U, + .data = data, + .dataSize = len, + .flags = stop ? kLPI2C_TransferDefaultFlag : kLPI2C_TransferNoStopFlag, + }; + + if (LPI2C_MasterTransferBlocking(lpi2c, &xfer) != kStatus_Success) { + return -EIO; + } + + return 0; +} + +int drv_i2c_read(drv_i2c_t *i2c, uint16_t addr, uint8_t *data, uint32_t len, uint32_t timeout, bool stop) { + LPI2C_Type *lpi2c = i2c->instance; + + lpi2c_master_transfer_t xfer = { + .direction = kLPI2C_Read, + .slaveAddress = addr, + .subaddress = 0, + .subaddressSize = 0U, + .data = data, + .dataSize = len, + .flags = stop ? kLPI2C_TransferDefaultFlag : kLPI2C_TransferNoStopFlag, + }; + + if (LPI2C_MasterTransferBlocking(lpi2c, &xfer) != kStatus_Success) { + return -EIO; + } + + return 0; +} diff --git a/ports/mcx/drv_i2c.h b/ports/mcx/drv_i2c.h new file mode 100644 index 0000000000..6da1c8e84f --- /dev/null +++ b/ports/mcx/drv_i2c.h @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_DRV_I2C_H +#define MP_PORT_MCX_DRV_I2C_H + +#include "py/obj.h" + +typedef enum { + DRV_I2CDirectionRead, + DRV_I2CDirectionWrite, +} drv_i2c_xfer_direction_t; + +typedef struct { + uint32_t frequency; +} drv_i2c_config_t; + +typedef struct { + uint8_t id; + void *instance; +} drv_i2c_t; + +int drv_i2c_init(drv_i2c_t *i2c, uint8_t id, drv_i2c_config_t *cfg); +int drv_i2c_write(drv_i2c_t *i2c, uint16_t addr, uint8_t *data, uint32_t len, uint32_t timeout, bool stop); +int drv_i2c_read(drv_i2c_t *i2c, uint16_t addr, uint8_t *data, uint32_t len, uint32_t timeout, bool stop); + +#endif diff --git a/ports/mcx/drv_iflash.c b/ports/mcx/drv_iflash.c new file mode 100644 index 0000000000..98e434a5f1 --- /dev/null +++ b/ports/mcx/drv_iflash.c @@ -0,0 +1,95 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "board.h" + +#include "fsl_cache_lpcac.h" + +#include "drv_iflash.h" + +int drv_iflash_init(drv_iflash_t *iflash) { + status_t ret = FLASH_Init(&iflash->flash_cfg); + if (ret != kStatus_Success) { + return -1; + } + + return 0; +} + +int drv_iflash_attr_get(drv_iflash_t *iflash, drv_iflash_attr_t *attr) { + status_t ret; + + ret = FLASH_GetProperty(&iflash->flash_cfg, kFLASH_PropertyPflashSectorSize, &attr->sector_size); + if (ret != kStatus_Success) { + return -1; + } + + ret = FLASH_GetProperty(&iflash->flash_cfg, kFLASH_PropertyPflashPageSize, &attr->page_size); + if (ret != kStatus_Success) { + return -1; + } + + return 0; +} + +int drv_iflash_read(drv_iflash_t *iflash, uint32_t addr, uint8_t *data, uint32_t len) { + memcpy(data, (uint8_t *)addr, len); + return 0; +} + +int drv_iflash_erase_sector(drv_iflash_t *iflash, uint32_t sector_addr) { + uint32_t sector_size = 0U; + status_t ret = FLASH_GetProperty(&iflash->flash_cfg, kFLASH_PropertyPflashSectorSize, §or_size); + if (ret != kStatus_Success) { + return -1; + } + + ret = FLASH_Erase(&iflash->flash_cfg, sector_addr, sector_size, kFLASH_ApiEraseKey); + if (ret != kStatus_Success) { + return -1; + } + + L1CACHE_InvalidateCodeCache(); + + return 0; +} + +int drv_iflash_program_page(drv_iflash_t *iflash, uint32_t page_addr, uint8_t *data) { + uint32_t page_size = 0U; + status_t ret = FLASH_GetProperty(&iflash->flash_cfg, kFLASH_PropertyPflashPageSize, &page_size); + if (ret != kStatus_Success) { + return -1; + } + + ret = FLASH_Program(&iflash->flash_cfg, page_addr, data, page_size); + if (ret != kStatus_Success) { + return -1; + } + + L1CACHE_InvalidateCodeCache(); + + return 0; +} diff --git a/ports/mcx/drv_iflash.h b/ports/mcx/drv_iflash.h new file mode 100644 index 0000000000..cf7e5cebcd --- /dev/null +++ b/ports/mcx/drv_iflash.h @@ -0,0 +1,49 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_DRV_IFLASH_H +#define MP_PORT_MCX_DRV_IFLASH_H + +#include + +#include "fsl_flash.h" + +typedef struct drv_iflash_attr_type { + uint32_t sector_size; + uint32_t page_size; +} drv_iflash_attr_t; + +typedef struct { + flash_config_t flash_cfg; +} drv_iflash_t; + +int drv_iflash_init(drv_iflash_t *iflash); +int drv_iflash_attr_get(drv_iflash_t *iflash, drv_iflash_attr_t *attr); +int drv_iflash_read(drv_iflash_t *iflash, uint32_t addr, uint8_t *data, uint32_t len); +int drv_iflash_erase_sector(drv_iflash_t *iflash, uint32_t sector_addr); +int drv_iflash_program_page(drv_iflash_t *iflash, uint32_t page_addr, uint8_t *data); + +#endif diff --git a/ports/mcx/drv_pin.c b/ports/mcx/drv_pin.c new file mode 100644 index 0000000000..7456f4da64 --- /dev/null +++ b/ports/mcx/drv_pin.c @@ -0,0 +1,351 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "board.h" + +/* SDK drivers */ +#include "fsl_gpio.h" +#include "fsl_port.h" + +#include "drv_pin.h" + +int drv_pin_init(drv_pin_t *pin) { + if (MCX_BoardConfigurePORTClock(pin->port) != 0) { + return -ENOENT; + } + + if (MCX_BoardConfigureGPIOClock(pin->port) != 0) { + return -ENOENT; + } + + return 0; +} + +/** + * Initialize pin to specific AF or analog function +*/ +int drv_pin_config_set(drv_pin_t *pin, drv_pin_config_t *cfg) { + int ret = 0; + + ret = drv_pin_mode_set(pin, cfg->mode, cfg->af); + if (ret < 0) { + return ret; + } + + ret = drv_pin_pull_set(pin, cfg->pull); + if (ret < 0) { + return ret; + } + + ret = drv_pin_drive_set(pin, cfg->drive); + if (ret < 0) { + return ret; + } + + return ret; +} + +int drv_pin_config_get(drv_pin_t *pin, drv_pin_config_t *cfg) { + int ret = 0; + + ret = drv_pin_mode_get(pin, &cfg->mode, &cfg->af); + if (ret < 0) { + return ret; + } + + ret = drv_pin_pull_get(pin, &cfg->pull); + if (ret < 0) { + return ret; + } + + ret = drv_pin_drive_get(pin, &cfg->drive); + if (ret < 0) { + return ret; + } + + return ret; +} + +int drv_pin_drive_set(drv_pin_t *pin, drv_pin_drive_t drive) { + PORT_Type *port = MCX_BoardGetPORTInstance(pin->port); + uint8_t pin_num = pin->pin; + + /* Sanity checks */ + if (port == NULL) { + return -ENOENT; + } + if (pin_num >= 32) { + return -EINVAL; + } + + uint32_t pcr = port->PCR[pin_num]; + + pcr &= ~(PORT_PCR_DSE_MASK); + + switch (drive) { + case DRV_PIN_DRIVE_HIGH: + pcr |= PORT_PCR_DSE(1U); + break; + + case DRV_PIN_DRIVE_LOW: + default: + break; + } + + port->PCR[pin_num] = pcr; + + return 0; +} + +int drv_pin_drive_get(drv_pin_t *pin, drv_pin_drive_t *drive) { + PORT_Type *port = MCX_BoardGetPORTInstance(pin->port); + uint8_t pin_num = pin->pin; + + /* Sanity checks */ + if (port == NULL) { + return -ENOENT; + } + if (pin_num >= 32) { + return -EINVAL; + } + + uint32_t pcr = port->PCR[pin_num]; + + /* Drive */ + if (pcr & PORT_PCR_DSE_MASK) { + *drive = DRV_PIN_DRIVE_HIGH; + } else { + *drive = DRV_PIN_DRIVE_LOW; + } + + return 0; +} + +int drv_pin_pull_set(drv_pin_t *pin, drv_pin_pull_type_t pull) { + PORT_Type *port = MCX_BoardGetPORTInstance(pin->port); + uint8_t pin_num = pin->pin; + + /* Sanity checks */ + if (port == NULL) { + return -ENOENT; + } + if (pin_num >= 32) { + return -EINVAL; + } + + uint32_t pcr = port->PCR[pin_num]; + + pcr &= ~(PORT_PCR_PE_MASK | PORT_PCR_PS_MASK); + + switch (pull) { + case DRV_PIN_PULL_UP: + pcr |= (PORT_PCR_PE_MASK | PORT_PCR_PS_MASK); + break; + + case DRV_PIN_PULL_DOWN: + pcr |= PORT_PCR_PE_MASK; + break; + + default: + case DRV_PIN_PULL_NONE: + break; + } + + port->PCR[pin_num] = pcr; + + return 0; +} + +int drv_pin_pull_get(drv_pin_t *pin, drv_pin_pull_type_t *pull) { + PORT_Type *port = MCX_BoardGetPORTInstance(pin->port); + uint8_t pin_num = pin->pin; + + /* Sanity checks */ + if (port == NULL) { + return -ENOENT; + } + if (pin_num >= 32) { + return -EINVAL; + } + + uint32_t pcr = port->PCR[pin_num]; + + /* Pull enabled */ + if (pcr & PORT_PCR_PE_MASK) { + if (pcr & PORT_PCR_PS_MASK) { + *pull = DRV_PIN_PULL_UP; + } else { + *pull = DRV_PIN_PULL_DOWN; + } + } else { + *pull = DRV_PIN_PULL_NONE; + } + + return 0; +} + +int drv_pin_mode_set(drv_pin_t *pin, drv_pin_mode_t mode, uint8_t af) { + PORT_Type *port = MCX_BoardGetPORTInstance(pin->port); + GPIO_Type *gpio = MCX_BoardGetGPIOInstance(pin->port); + uint8_t pin_num = pin->pin; + + /* Sanity checks */ + if (port == NULL) { + return -ENOENT; + } + if (gpio == NULL) { + return -ENOENT; + } + if (pin_num >= 32) { + return -EINVAL; + } + + uint32_t pcr = port->PCR[pin_num]; + + pcr &= ~(PORT_PCR_MUX_MASK | PORT_PCR_ODE_MASK); + pcr |= PORT_PCR_IBE(1U); + + gpio_pin_config_t gpio_cfg = { + .pinDirection = kGPIO_DigitalInput, + .outputLogic = 0U, + }; + + uint8_t alt_id = af; + + switch (mode) { + case DRV_PIN_MODE_INPUT: + alt_id = kPORT_MuxAlt0; + break; + + case DRV_PIN_MODE_AF_PP: + break; + + case DRV_PIN_MODE_OUTPUT_PP: + gpio_cfg.pinDirection = kGPIO_DigitalOutput; + GPIO_PinInit(gpio, pin_num, &gpio_cfg); + + alt_id = kPORT_MuxAlt0; + break; + + case DRV_PIN_MODE_OUTPUT_OD: + gpio_cfg.pinDirection = kGPIO_DigitalOutput; + GPIO_PinInit(gpio, pin_num, &gpio_cfg); + + pcr |= PORT_PCR_ODE(1U); + alt_id = kPORT_MuxAlt0; + break; + + case DRV_PIN_MODE_AF_OD: + pcr |= PORT_PCR_ODE(1U); + break; + + case DRV_PIN_MODE_ANALOG: + default: + /* Clear IBE for analog functions */ + pcr &= ~(PORT_PCR_IBE_MASK); + break; + } + + /* Apply corresponding AF */ + pcr |= PORT_PCR_MUX(alt_id); + + port->PCR[pin_num] = pcr; + + return 0; +} + +int drv_pin_mode_get(drv_pin_t *pin, drv_pin_mode_t *mode, uint8_t *af) { + PORT_Type *port = MCX_BoardGetPORTInstance(pin->port); + GPIO_Type *gpio = MCX_BoardGetGPIOInstance(pin->port); + uint8_t pin_num = pin->pin; + + /* Sanity checks */ + if (port == NULL) { + return -ENOENT; + } + if (gpio == NULL) { + return -ENOENT; + } + if (pin_num >= 32) { + return -EINVAL; + } + + uint32_t pcr = port->PCR[pin_num]; + + uint8_t mux = (pcr & PORT_PCR_MUX_MASK) >> PORT_PCR_MUX_SHIFT; + bool od = (pcr & PORT_PCR_ODE_MASK) >> PORT_PCR_ODE_SHIFT; + + if (mux == 0) { /* GPIO or Analog mode */ + if ((pcr & PORT_PCR_IBE_MASK) == 0U) { + *mode = DRV_PIN_MODE_ANALOG; + } else { + bool gpio_mode = (gpio->PDDR & (1U << pin_num)) ? true : false; + if (gpio_mode) { + if (od) { + *mode = DRV_PIN_MODE_OUTPUT_OD; + } else { + *mode = DRV_PIN_MODE_OUTPUT_PP; + } + } else { + *mode = DRV_PIN_MODE_INPUT; + } + } + } else { + if (od) { + *mode = DRV_PIN_MODE_AF_OD; + } else { + *mode = DRV_PIN_MODE_AF_PP; + } + + *af = mux; + } + + return 0; +} + +int drv_pin_read(drv_pin_t *pin) { + GPIO_Type *gpio = MCX_BoardGetGPIOInstance(pin->port); + if (gpio == NULL) { + return -ENOENT; + } + + uint32_t gpio_value = GPIO_PinRead(gpio, pin->pin); + + return gpio_value ? 1 : 0; +} + +int drv_pin_write(drv_pin_t *pin, bool value) { + GPIO_Type *gpio = MCX_BoardGetGPIOInstance(pin->port); + if (gpio == NULL) { + return -ENOENT; + } + + uint8_t val = value ? 1 : 0; + + GPIO_PinWrite(gpio, pin->pin, val); + + return 0; +} diff --git a/ports/mcx/drv_pin.h b/ports/mcx/drv_pin.h new file mode 100644 index 0000000000..2956ce9656 --- /dev/null +++ b/ports/mcx/drv_pin.h @@ -0,0 +1,83 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_DRV_PIN_H +#define MP_PORT_MCX_DRV_PIN_H + +#include "py/obj.h" + +typedef enum { + DRV_PIN_PULL_NONE, + DRV_PIN_PULL_UP, + DRV_PIN_PULL_DOWN, + + DRV_PIN_PULL_END, +} drv_pin_pull_type_t; + +typedef enum { + DRV_PIN_DRIVE_LOW, + DRV_PIN_DRIVE_HIGH, + + DRV_PIN_DRIVE_END, +} drv_pin_drive_t; + +typedef enum { + DRV_PIN_MODE_ANALOG = 0U, + DRV_PIN_MODE_INPUT, + DRV_PIN_MODE_OUTPUT_PP, + DRV_PIN_MODE_OUTPUT_OD, + DRV_PIN_MODE_AF_PP, + DRV_PIN_MODE_AF_OD, + + DRV_PIN_MODE_END, +} drv_pin_mode_t; + +typedef struct drv_pin_config_type { + drv_pin_mode_t mode; + drv_pin_pull_type_t pull; + drv_pin_drive_t drive; + + uint8_t af; +} drv_pin_config_t; + +typedef struct drv_pin_type { + uint8_t port; + uint8_t pin; +} drv_pin_t; + +int drv_pin_init(drv_pin_t *pin); +int drv_pin_config_set(drv_pin_t *pin, drv_pin_config_t *cfg); +int drv_pin_config_get(drv_pin_t *pin, drv_pin_config_t *cfg); +int drv_pin_drive_set(drv_pin_t *pin, drv_pin_drive_t drive); +int drv_pin_drive_get(drv_pin_t *pin, drv_pin_drive_t *drive); +int drv_pin_pull_set(drv_pin_t *pin, drv_pin_pull_type_t pull); +int drv_pin_pull_get(drv_pin_t *pin, drv_pin_pull_type_t *pull); +int drv_pin_mode_set(drv_pin_t *pin, drv_pin_mode_t mode, uint8_t af); +int drv_pin_mode_get(drv_pin_t *pin, drv_pin_mode_t *mode, uint8_t *af); +int drv_pin_read(drv_pin_t *pin); +int drv_pin_write(drv_pin_t *pin, bool value); + +#endif diff --git a/ports/mcx/drv_pwm.c b/ports/mcx/drv_pwm.c new file mode 100644 index 0000000000..fcba32840f --- /dev/null +++ b/ports/mcx/drv_pwm.c @@ -0,0 +1,307 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "board.h" + +/* SDK drivers */ +#include "fsl_ctimer.h" + +#include "drv_pwm.h" + +static int drv_pwm_current_period_channel(drv_pwm_t *pwm) { + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + uint32_t mcr = ct->MCR; + + for (uint8_t i = 0; i < 4; i++) { + if (mcr & (1U << (3 * i + CTIMER_MCR_MR0R_SHIFT))) { + return i; + } + } + + return -1; +} + +static int drv_pwm_first_free_channel(drv_pwm_t *pwm) { + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + int pc = drv_pwm_current_period_channel(pwm); + + uint32_t pwmc = ct->PWMC; + + for (uint8_t i = 0; i < 4; i++) { + if (pwmc & (1U << i)) { + /* Skip this channel if there's an active PWM output */ + continue; + } + + if (i == pc) { + /* Skip this channel if this channel is the current period channel */ + continue; + } + + return i; + } + + /* There are no free channels left. */ + return -1; +} + +int drv_pwm_init(drv_pwm_t *pwm, uint8_t id, uint8_t channel, uint32_t freq, bool inverted) { + pwm->id = id; + pwm->channel = channel; + pwm->instance = MCX_BoardGetCT32Instance(id); + + if (pwm->instance == NULL) { + return -EINVAL; + } + + pwm->input_freq = MCX_BoardConfigureCT32Clock(id); + + pwm->inverted = inverted; + + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + if ((ct->TCR & CTIMER_TCR_CEN_MASK) == 0U) { + /* There's two conditions for a all-zero TCR: either a reset condition or timer is stopped. */ + /* In either case, we need to initialize the timer instance (AHB RST CTRL). */ + + /* TODO: Do not use SDK functions */ + + ctimer_config_t ct_cfg = { + .mode = kCTIMER_TimerMode, + .prescale = 1U, + }; + + /* Frequency: 150MHz max., we got 32bit counters, we can take that. */ + /* Approx. maximum period: 28.6 seconds. */ + + CTIMER_Init(ct, &ct_cfg); + + /* Current timer is not running, we are the first channel being configured. */ + + ct->TC = 0U; /* Reset counter */ + ct->PC = 0U; /* Reset prescaler counter */ + ct->PR = 0U; /* Prescaler, divide by 1 to get best resolution */ + ct->MCR = 0U; /* Reset interrupt and reset condition */ + ct->EMR = 0U; /* Do nothing on match event and output 0 as default state */ + ct->PWMC = 0U; /* Disable all PWM channels, outputs will be controlled by EMn */ + + /* Here, we have a favoritism of using channel 3 as period channel, unless channel 3 is used for output */ + if (channel != 3) { + ct->MR[3] = pwm->input_freq / freq; + ct->MCR |= CTIMER_MCR_MR3R_MASK; + } else { + /* Use channel 2 as period channel. */ + ct->MR[2] = pwm->input_freq / freq; + ct->MCR |= CTIMER_MCR_MR2R_MASK; + } + + /* Start counter */ + ct->TCR |= CTIMER_TCR_CEN_MASK; + } else { + /* + * Due to the nature of the CTimer, one of the 4 match channels is needed for period control (frequency) + * To find out which one is the current period channel, check the MRxR bit for each match output. + * If we are configuring the same match being used as periodic channel, configure the next free match as period + * then current channel can be re-used. If all 4 channels are in use then the function will fail with an errno. + */ + + /* The timer is running, check whether we need to re-locate the period channel */ + int p_channel = drv_pwm_current_period_channel(pwm); + if (p_channel < 0) { + return -EINVAL; + } + + if (p_channel == channel) { + /* We need to re-locate the period channel */ + + int f_channel = drv_pwm_first_free_channel(pwm); + if (f_channel < 0) { + /* There's no free channel, bail out. */ + return -EBUSY; + } + + /* Transfer the period channel to first free channel */ + + /* Step 1: Copy current period to first free channel */ + ct->MR[f_channel] = ct->MR[p_channel]; + + /* Step 2: Enable reset for new period channel */ + /* Note: it's safe doing it here since both old and new channel MRs contains same value */ + ct->MCR |= (CTIMER_MCR_MR0R_MASK << (3 * f_channel)); + + /* Step 3: Disable reset for old period channel */ + ct->MCR &= ~(CTIMER_MCR_MR0R_MASK << (3 * p_channel)); + + /* The old period channel is now available for PWM output */ + p_channel = f_channel; + } + + if (drv_pwm_freq_set(pwm, freq) < 0) { + return -EINVAL; + } + + } + + return 0; +} + +int drv_pwm_deinit(drv_pwm_t *pwm) { + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + /* Disable PWM output for channel, now the output is controlled by EMR */ + ct->PWMC &= ~(CTIMER_PWMC_PWMEN0_MASK << pwm->channel); + + /* Check whether there's still enabled channels */ + if ((ct->PWMC & 0x0FU) == 0) { + /* Stop counter if this is the last. */ + ct->TCR &= ~CTIMER_TCR_CEN_MASK; + } + + return 0; +} + +int drv_pwm_start(drv_pwm_t *pwm) { + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + ct->PWMC |= (1U << pwm->channel); + + return 0; +} + +int drv_pwm_stop(drv_pwm_t *pwm) { + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + ct->PWMC &= ~(1U << pwm->channel); + + return 0; +} + +int drv_pwm_freq_set(drv_pwm_t *pwm, uint32_t freq) { + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + int p_channel = drv_pwm_current_period_channel(pwm); + if (p_channel < 0) { + return -EINVAL; + } + + /* Store new values in shadow registers */ + ct->MSR[p_channel] = pwm->input_freq / freq; + + /* Enable period channel interrupt to check a reload event occurs. + * Since interrupts are not configured from NVIC, so no ISR will occur. + * Check IR[MRnINT] for reload point. + */ + uint32_t mcr_mask = (CTIMER_MCR_MR0RL_MASK << p_channel) | (CTIMER_MCR_MR0I_MASK << (3 * p_channel)); + + for (uint8_t i = 0; i < 4; i++) { + if (ct->PWMC & (1U << i)) { + /* Channel PWM output is enabled, calculate new values and store into shadow registers */ + uint32_t new_mr = ct->MR[i] * ct->MSR[p_channel] / ct->MR[p_channel]; + ct->MSR[i] = new_mr; + + /* Update MRnRL map */ + mcr_mask |= CTIMER_MCR_MR0RL_MASK << i; + } + } + + /* Reload MRs on next counter reset, enable reload MR interrupt */ + ct->MCR |= mcr_mask; + + while ((ct->IR & (CTIMER_IR_MR0INT_MASK << p_channel)) == 0U) { + /* -- */ + } + + /* Disable reload channel interrupt and MSR synchronization */ + ct->MCR &= ~mcr_mask; + + /* Clear interrupt flags. */ + ct->IR |= (CTIMER_IR_MR0INT_MASK << p_channel); + + return 0; +} + +int drv_pwm_freq_get(drv_pwm_t *pwm, uint32_t *freq) { + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + int p_channel = drv_pwm_current_period_channel(pwm); + if (p_channel < 0) { + return -1; + } + + *freq = pwm->input_freq / ct->MR[p_channel]; + + return 0; +} + +int drv_pwm_duty_set(drv_pwm_t *pwm, uint16_t duty_u16) { + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + int p_channel = drv_pwm_current_period_channel(pwm); + if (p_channel < 0) { + return -1; + } + + /* To avoid overflow, use 64bit values here. */ + uint64_t period = ct->MR[p_channel]; + + if (pwm->inverted) { + ct->MSR[pwm->channel] = period * duty_u16 / 65535; + } else { + ct->MSR[pwm->channel] = period - (period * duty_u16 / 65535); + } + + /* Reload MRn on the next cycle */ + ct->MCR |= (CTIMER_MCR_MR0RL_MASK << pwm->channel); + + /* Wait for new duty cycle loaded into the MRn */ + while (ct->MR[pwm->channel] != ct->MSR[pwm->channel]) { + /* -- */ + } + + /* Disable shadow register updates */ + ct->MCR &= ~(CTIMER_MCR_MR0RL_MASK << pwm->channel); + + return 0; +} + +int drv_pwm_duty_get(drv_pwm_t *pwm, uint16_t *duty_u16) { + CTIMER_Type *ct = (CTIMER_Type *)pwm->instance; + + int p_channel = drv_pwm_current_period_channel(pwm); + if (p_channel < 0) { + return -1; + } + + uint32_t period = ct->MR[p_channel]; + + /* To avoid overflow, use 64bit values here. */ + uint64_t duty = ct->MR[pwm->channel]; + *duty_u16 = duty * 65535 / period; + + return 0; +} diff --git a/ports/mcx/drv_pwm.h b/ports/mcx/drv_pwm.h new file mode 100644 index 0000000000..c4759b24dd --- /dev/null +++ b/ports/mcx/drv_pwm.h @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_DRV_PWM_H +#define MP_PORT_MCX_DRV_PWM_H + +#include +#include + +typedef struct drv_pwm_type { + uint8_t id; + void *instance; + + uint8_t channel; + bool inverted; + uint32_t input_freq; +} drv_pwm_t; + +int drv_pwm_init(drv_pwm_t *pwm, uint8_t id, uint8_t channel, uint32_t freq, bool inverted); +int drv_pwm_deinit(drv_pwm_t *pwm); +int drv_pwm_start(drv_pwm_t *pwm); +int drv_pwm_stop(drv_pwm_t *pwm); +int drv_pwm_freq_set(drv_pwm_t *pwm, uint32_t freq); +int drv_pwm_freq_get(drv_pwm_t *pwm, uint32_t *freq); +int drv_pwm_duty_set(drv_pwm_t *pwm, uint16_t duty_u16); +int drv_pwm_duty_get(drv_pwm_t *pwm, uint16_t *duty_u16); + +#endif diff --git a/ports/mcx/drv_spi.c b/ports/mcx/drv_spi.c new file mode 100644 index 0000000000..d76caf9837 --- /dev/null +++ b/ports/mcx/drv_spi.c @@ -0,0 +1,79 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "board.h" + +/* SDK drivers */ +#include "fsl_lpspi.h" + +#include "drv_spi.h" + +int drv_spi_init(drv_spi_t *spi, uint8_t id, drv_spi_config_t *cfg) { + spi->instance = MCX_BoardGetSPIInstance(id); + if (spi->instance == NULL) { + return -ENOENT; + } + + spi->id = id; + + int spi_inputfreq = MCX_BoardConfigureSPIClock(id); + if (spi_inputfreq <= 0) { + return -EINVAL; + } + + lpspi_master_config_t spi_cfg; + LPSPI_MasterGetDefaultConfig(&spi_cfg); + + spi_cfg.baudRate = cfg->frequency; + spi_cfg.bitsPerFrame = cfg->frame_size; + spi_cfg.cpol = cfg->cpol ? kLPSPI_ClockPolarityActiveLow : kLPSPI_ClockPolarityActiveHigh; + spi_cfg.cpha = cfg->cpha ? kLPSPI_ClockPhaseSecondEdge : kLPSPI_ClockPhaseFirstEdge; + spi_cfg.direction = cfg->lsbfirst ? kLPSPI_LsbFirst : kLPSPI_MsbFirst; + + LPSPI_Type *lpspi = spi->instance; + LPSPI_MasterInit(lpspi, &spi_cfg, spi_inputfreq); + + return 0; +} + +int drv_spi_transfer(drv_spi_t *spi, drv_spi_transfer_t *transfer) { + LPSPI_Type *lpspi = spi->instance; + + /* TODO: Ditch SDK drivers, prepare DMA transfer. */ + + lpspi_transfer_t xfer = { + .txData = (uint8_t *)transfer->tx_data, /* To SDK: Please do not touch that. */ + .rxData = transfer->rx_data, + .dataSize = transfer->len, + }; + + status_t status = LPSPI_MasterTransferBlocking(lpspi, &xfer); + if (status != kStatus_Success) { + return -EIO; + } + + return 0; +} diff --git a/ports/mcx/drv_spi.h b/ports/mcx/drv_spi.h new file mode 100644 index 0000000000..b101ad15eb --- /dev/null +++ b/ports/mcx/drv_spi.h @@ -0,0 +1,54 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_DRV_SPI_H +#define MP_PORT_MCX_DRV_SPI_H + +#include "py/obj.h" + +typedef struct drv_spi_config_type { + uint32_t frequency; + uint8_t cpol; + uint8_t cpha; + uint8_t frame_size; + bool lsbfirst; +} drv_spi_config_t; + +typedef struct drv_spi_transfer_type { + const uint8_t *tx_data; + uint8_t *rx_data; + uint32_t len; +} drv_spi_transfer_t; + +typedef struct drv_spi_type { + uint8_t id; + void *instance; +} drv_spi_t; + +int drv_spi_init(drv_spi_t *spi, uint8_t id, drv_spi_config_t *cfg); +int drv_spi_transfer(drv_spi_t *spi, drv_spi_transfer_t *transfer); + +#endif diff --git a/ports/mcx/drv_uart.c b/ports/mcx/drv_uart.c new file mode 100644 index 0000000000..c9e3117d19 --- /dev/null +++ b/ports/mcx/drv_uart.c @@ -0,0 +1,299 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "board.h" + +/* SDK drivers */ +#include "fsl_lpuart.h" + +#if defined(MICROPY_HW_HAS_LPFLEXCOMM) +#include "fsl_lpflexcomm.h" +#endif + +#include "drv_uart.h" + +static void drv_uart_irq_handler(void *handle); + +int drv_uart_init(drv_uart_t *uart, uint8_t id, drv_uart_config_t *cfg) { + uart->instance = MCX_BoardGetUARTInstance(id); + if (uart->instance == NULL) { + return -EINVAL; + } + + uart->id = id; + + int uart_inputfreq = MCX_BoardConfigureUARTClock(id); + if (uart_inputfreq <= 0) { + return -EINVAL; + } + + lpuart_config_t uart_cfg; + LPUART_GetDefaultConfig(&uart_cfg); + + uart_cfg.baudRate_Bps = cfg->baud_rate; + uart_cfg.enableRx = true; + uart_cfg.enableTx = true; + + #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT + if (cfg->data_bits == DRV_Uart7DataBits) { + uart_cfg.dataBitsCount = kLPUART_SevenDataBits; + } + #endif + if (cfg->data_bits == DRV_Uart8DataBits) { + uart_cfg.dataBitsCount = kLPUART_EightDataBits; + } + + switch (cfg->parity) { + case DRV_UartNoParity: + uart_cfg.parityMode = kLPUART_ParityDisabled; + break; + case DRV_UartEvenParity: + uart_cfg.parityMode = kLPUART_ParityEven; + break; + case DRV_UartOddParity: + uart_cfg.parityMode = kLPUART_ParityOdd; + break; + default: + break; + } + + /* TODO: Flow control settings. */ + + LPUART_Type *lpuart = uart->instance; + + if (LPUART_Init(lpuart, &uart_cfg, uart_inputfreq) != kStatus_Success) { + return -EIO; + } + + #if defined(MICROPY_HW_HAS_LPFLEXCOMM) + /* For now, SDK drivers does not handle LPUART using P2/P3 correctly, initialize the pin functions manually. */ + if (cfg->i2c_shared) { + LP_FLEXCOMM_Init(id, LP_FLEXCOMM_PERIPH_LPI2CAndLPUART); + } + #endif + + uart->status = DRV_UartStatusIdle; + + return 0; +} + +int drv_uart_deinit(drv_uart_t *uart) { + int ret = 0; + LPUART_Type *lpuart = uart->instance; + + LPUART_EnableTx(lpuart, false); + LPUART_EnableRx(lpuart, false); + + LPUART_DisableInterrupts(lpuart, kLPUART_RxDataRegFullInterruptEnable); + + lpuart->FIFO |= LPUART_FIFO_TXFLUSH_MASK | LPUART_FIFO_RXFLUSH_MASK; + + return ret; +} + +int drv_uart_write(drv_uart_t *uart, const uint8_t *data, int len, mp_uint_t timeout) { + int ret = 0; + LPUART_Type *lpuart = uart->instance; + + /* TX can be used when async RX is enabled */ + + if (uart->status == DRV_UartStatusBusy) { + return -EBUSY; + } + + /* Flush TX FIFO */ + lpuart->FIFO |= LPUART_FIFO_TXFLUSH_MASK; + + LPUART_EnableTx(lpuart, true); + + mp_uint_t time_start = mp_hal_ticks_ms(); + + int tx_count; + for (tx_count = 0; tx_count < len; tx_count++) { + /* Wait for room in TX FIFO */ + while (LPUART_GetTxFifoCount(lpuart) >= FSL_FEATURE_LPUART_FIFO_SIZEn(uart->id) - 1) { + if (timeout && (mp_hal_ticks_ms() - time_start > timeout)) { + ret = -ETIMEDOUT; + goto timeout_exit; + } + + MICROPY_EVENT_POLL_HOOK + } + + LPUART_WriteByte(lpuart, data[tx_count]); + } + + /* Wait for all items in FIFO has been sent... */ + while (LPUART_GetTxFifoCount(lpuart) > 0) { + if (timeout && (mp_hal_ticks_ms() - time_start > timeout)) { + ret = -ETIMEDOUT; + goto timeout_exit; + } + } + + ret = tx_count; + +timeout_exit: + + LPUART_EnableTx(lpuart, false); + + return ret; +} + +int drv_uart_send_break(drv_uart_t *uart) { + /* TODO: Implement this */ + + return 0; +} + +int drv_uart_read(drv_uart_t *uart, uint8_t *data, int len, mp_uint_t timeout) { + int ret = 0; + LPUART_Type *lpuart = uart->instance; + + if (uart->status != DRV_UartStatusIdle) { + return -EBUSY; + } + + uart->status = DRV_UartStatusBusy; + + lpuart->FIFO |= LPUART_FIFO_RXFLUSH_MASK; + + LPUART_EnableRx(lpuart, true); + + mp_uint_t time_start = mp_hal_ticks_ms(); + + int rx_count; + for (rx_count = 0; rx_count < len; rx_count++) { + while (LPUART_GetRxFifoCount(lpuart) == 0) { + if (timeout && (mp_hal_ticks_ms() - time_start > timeout)) { + ret = rx_count; + goto timeout_exit; + } + + MICROPY_EVENT_POLL_HOOK + } + + data[rx_count] = LPUART_ReadByte(lpuart); + } + + ret = rx_count; + +timeout_exit: + LPUART_EnableRx(lpuart, false); + + uart->status = DRV_UartStatusIdle; + + return ret; +} + +int drv_uart_async_callback(drv_uart_t *uart, drv_uart_async_fn_t fn) { + if (uart->status != DRV_UartStatusIdle) { + return -EBUSY; + } + + uart->async_fn = fn; + + return 0; +} + +int drv_uart_async_start(drv_uart_t *uart, drv_uart_async_fn_t fn, void *param) { + if (uart->status != DRV_UartStatusIdle) { + return -EBUSY; + } + + LPUART_Type *lpuart = uart->instance; + + uart->async_fn = fn; + uart->async_fn_param = param; + + uart->status = DRV_UartStatusAsyncRx; + + /* Flush FIFO */ + lpuart->FIFO |= LPUART_FIFO_RXFLUSH_MASK; + + /* Set watermark to 0 to generate a interrupt whenever there's data in FIFO. */ + LPUART_SetRxFifoWatermark(lpuart, 0U); + + /* RXFE interrupt */ + LPUART_EnableInterrupts(lpuart, kLPUART_RxDataRegFullInterruptEnable); + + MCX_BoardConfigureUARTISR(uart->id, drv_uart_irq_handler, uart); + + LPUART_EnableRx(lpuart, true); + + return 0; +} + +int drv_uart_async_read(drv_uart_t *uart, uint8_t *data, uint8_t len) { + LPUART_Type *lpuart = uart->instance; + + for (uint8_t i = 0; i < len; i++) { + data[i] = lpuart->DATA; + } + + return len; +} + +int drv_uart_async_cancel(drv_uart_t *uart) { + drv_uart_status_t status = uart->status; + LPUART_Type *lpuart = uart->instance; + + if (status == DRV_UartStatusBusy) { + return -EBUSY; + } + + if (status == DRV_UartStatusIdle) { + return -EINVAL; + } + + if (status == DRV_UartStatusAsyncRx) { + LPUART_EnableRx(lpuart, false); + lpuart->FIFO |= LPUART_FIFO_RXFLUSH_MASK; + + LPUART_DisableInterrupts(lpuart, kLPUART_RxDataRegFullInterruptEnable); + MCX_BoardConfigureUARTISR(uart->id, NULL, NULL); + } + + return 0; +} + +static void drv_uart_irq_handler(void *handle) { + drv_uart_t *uart = (drv_uart_t *)handle; + LPUART_Type *lpuart = uart->instance; + + uint32_t ip_status = LPUART_GetStatusFlags(lpuart); + + if (ip_status & kLPUART_RxDataRegFullFlag) { + if (uart->status == DRV_UartStatusAsyncRx) { + /* Interrupt is only active for Async RX mode. */ + uint8_t lvl = LPUART_GetRxFifoCount(lpuart); + + uart->async_fn(uart, uart->async_fn_param, lvl); + } + } + + LPUART_ClearStatusFlags(lpuart, ip_status); +} diff --git a/ports/mcx/drv_uart.h b/ports/mcx/drv_uart.h new file mode 100644 index 0000000000..7923807493 --- /dev/null +++ b/ports/mcx/drv_uart.h @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_DRV_UART_H +#define MP_PORT_MCX_DRV_UART_H + +#include +#include + +typedef enum { + DRV_Uart7DataBits, + DRV_Uart8DataBits, +} drv_uart_data_bits_t; + +typedef enum { + DRV_Uart1StopBits, + DRV_Uart2StopBits, +} drv_uart_stop_bits_t; + +typedef enum { + DRV_UartNoParity, + DRV_UartEvenParity, + DRV_UartOddParity, +} drv_uart_parity_t; + +typedef enum { + DRV_UartNoFlowControl, + DRV_UartCtsFlowControl, + DRV_UartRtsFlowControl, + DRV_UartCtsRtsFlowControl, +} drv_uart_flow_control_t; + +typedef enum { + DRV_UartStatusIdle, + DRV_UartStatusBusy, + DRV_UartStatusAsyncRx, +} drv_uart_status_t; + +typedef void (*drv_uart_async_fn_t)(void *uart, void *param, uint8_t len); + +typedef struct drv_uart_type { + uint8_t id; + void *instance; + drv_uart_status_t status; + drv_uart_async_fn_t async_fn; + void *async_fn_param; +} drv_uart_t; + +typedef struct drv_uart_config_type { + uint32_t baud_rate; + bool i2c_shared; + drv_uart_data_bits_t data_bits; + drv_uart_stop_bits_t stop_bits; + drv_uart_parity_t parity; + drv_uart_flow_control_t flow_control; +} drv_uart_config_t; + +int drv_uart_init(drv_uart_t *uart, uint8_t id, drv_uart_config_t *cfg); +int drv_uart_deinit(drv_uart_t *uart); +int drv_uart_write(drv_uart_t *uart, const uint8_t *data, int len, mp_uint_t timeout); +int drv_uart_send_break(drv_uart_t *uart); +int drv_uart_read(drv_uart_t *uart, uint8_t *data, int len, mp_uint_t timeout); +int drv_uart_async_start(drv_uart_t *uart, drv_uart_async_fn_t fn, void *param); +int drv_uart_async_read(drv_uart_t *uart, uint8_t *data, uint8_t len); +int drv_uart_async_cancel(drv_uart_t *uart); + +#endif diff --git a/ports/mcx/hal_pin.c b/ports/mcx/hal_pin.c new file mode 100644 index 0000000000..7170b27a6f --- /dev/null +++ b/ports/mcx/hal_pin.c @@ -0,0 +1,227 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "py/mphal.h" + +#include "fsl_common.h" +#include "fsl_common_arm.h" + +/* Note: the HAL pin interface is used by several extmods, + * which requires a machine.Pin object as its parameter. + * As the corresponding PORT and GPIO clocks are initialized in drv_pin_init(), + * which is called by Machine.Pin() constructor, only basic functions are required here. + * Same for alternative functions and pin modes. + */ + +const mp_hal_pin_obj_t mp_hal_pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { + const mp_map_t *named_map = &named_pins->map; + + mp_map_elem_t *named_elem = mp_map_lookup((mp_map_t *)named_map, name, MP_MAP_LOOKUP); + + if (named_elem == NULL || named_elem->value == MP_OBJ_NULL) { + return NULL; + } + + return MP_OBJ_TO_PTR(named_elem->value); +} + +const machine_pin_af_t *mp_hal_pin_find_af(const mp_hal_pin_obj_t pin, machine_pin_af_type_t type, + uint8_t idx, machine_pin_af_attr_t attr) { + for (uint8_t i = 0; i < pin->af_count; i++) { + if (pin->af[i].af_type != type) { + continue; + } + + if (pin->af[i].af_instance_id != idx) { + continue; + } + + if (pin->af[i].af_attribute != attr) { + continue; + } + + return &pin->af[i]; + } + + return NULL; +} + +const machine_pin_adc_t *mp_hal_pin_find_adc(const mp_hal_pin_obj_t pin) { + return pin->adc; +} + +const machine_pin_af_t *mp_hal_pin_find_pwm(const mp_hal_pin_obj_t pin) { + for (uint8_t i = 0; i < pin->af_count; i++) { + if (pin->af[i].af_type != MACHINE_PIN_AF_TYPE_CT32) { + continue; + } + + /* Attribute with bit 7 set is a input capture channel */ + if (pin->af[i].af_attribute & 0x80) { + continue; + } + + return &pin->af[i]; + } + + return NULL; +} + +bool mp_hal_pin_read(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + return drv_pin_read(&p); +} + +void mp_hal_pin_write(mp_hal_pin_obj_t pin, bool value) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_write(&p, value); +} + +void mp_hal_pin_high(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_write(&p, true); +} + +void mp_hal_pin_od_high(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_write(&p, true); +} + +void mp_hal_pin_low(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_write(&p, false); +} + +void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_write(&p, false); +} + +void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_mode_set(&p, DRV_PIN_MODE_OUTPUT_OD, 0U); +} + +void mp_hal_pin_output(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_mode_set(&p, DRV_PIN_MODE_OUTPUT_PP, 0U); +} + +void mp_hal_pin_input(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_mode_set(&p, DRV_PIN_MODE_INPUT, 0U); +} + +void mp_hal_pin_analog(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_mode_set(&p, DRV_PIN_MODE_ANALOG, 0U); +} + +void mp_hal_pin_af(mp_hal_pin_obj_t pin, uint8_t af_num) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_mode_set(&p, DRV_PIN_MODE_AF_PP, af_num); +} + +void mp_hal_pin_af_od(mp_hal_pin_obj_t pin, uint8_t af_num) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_mode_set(&p, DRV_PIN_MODE_AF_OD, af_num); +} + +void mp_hal_pin_pull_up(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_pull_set(&p, DRV_PIN_PULL_UP); +} + +void mp_hal_pin_pull_down(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_pull_set(&p, DRV_PIN_PULL_DOWN); +} + +void mp_hal_pin_pull_none(mp_hal_pin_obj_t pin) { + drv_pin_t p = { + .port = pin->port, + .pin = pin->pin, + }; + + drv_pin_pull_set(&p, DRV_PIN_PULL_NONE); +} diff --git a/ports/mcx/hal_pin.h b/ports/mcx/hal_pin.h new file mode 100644 index 0000000000..4719aa1dbc --- /dev/null +++ b/ports/mcx/hal_pin.h @@ -0,0 +1,84 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_HAL_PIN_H +#define MP_PORT_MCX_HAL_PIN_H + +#include "drv_pin.h" + +#include "machine_pin.h" + +#define mp_hal_pin_obj_t machine_pin_obj_t * +#define mp_hal_get_pin_obj(p) (p) + +#define MP_HAL_PIN_MODE_ANALOG (DRV_PIN_MODE_ANALOG) +#define MP_HAL_PIN_MODE_INPUT (DRV_PIN_MODE_INPUT) +#define MP_HAL_PIN_MODE_OUTPUT (DRV_PIN_MODE_OUTPUT_PP) +#define MP_HAL_PIN_MODE_OPEN_DRAIN (DRV_PIN_MODE_OUTPUT_OD) +#define MP_HAL_PIN_MODE_ALT (DRV_PIN_MODE_AF_PP) +#define MP_HAL_PIN_MODE_ALT_OPEN_DRAIN (DRV_PIN_MODE_AF_OD) + +#define MP_HAL_PIN_PULL_NONE (DRV_PIN_PULL_NONE) +#define MP_HAL_PIN_PULL_UP (DRV_PIN_PULL_UP) +#define MP_HAL_PIN_PULL_DOWN (DRV_PIN_PULL_DOWN) + +#define MP_HAL_PIN_TRIGGER_FALLING (GPIO_IRQ_FALLING) +#define MP_HAL_PIN_TRIGGER_RISING (GPIO_IRQ_RISING) +#define MP_HAL_PIN_TRIGGER_LOWLEVEL (GPIO_IRQ_LOWLEVEL) +#define MP_HAL_PIN_TRIGGER_HIGHLEVEL (GPIO_IRQ_HIGHLEVEL) + +#define MP_HAL_PIN_DRIVE_0 (DRV_PIN_DRIVE_LOW) +#define MP_HAL_PIN_DRIVE_1 (DRV_PIN_DRIVE_HIGH) + +const mp_hal_pin_obj_t mp_hal_pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name); +const machine_pin_af_t *mp_hal_pin_find_af(const mp_hal_pin_obj_t pin, machine_pin_af_type_t type, + uint8_t idx, machine_pin_af_attr_t attr); +const machine_pin_adc_t *mp_hal_pin_find_adc(const mp_hal_pin_obj_t pin); +const machine_pin_af_t *mp_hal_pin_find_pwm(const mp_hal_pin_obj_t pin); + +void mp_hal_pin_high(mp_hal_pin_obj_t pin); +void mp_hal_pin_od_high(mp_hal_pin_obj_t pin); + +void mp_hal_pin_low(mp_hal_pin_obj_t pin); +void mp_hal_pin_od_low(mp_hal_pin_obj_t pin); + +bool mp_hal_pin_read(mp_hal_pin_obj_t pin); +void mp_hal_pin_write(mp_hal_pin_obj_t pin, bool value); + +void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin); +void mp_hal_pin_output(mp_hal_pin_obj_t pin); +void mp_hal_pin_input(mp_hal_pin_obj_t pin); +void mp_hal_pin_analog(mp_hal_pin_obj_t pin); + +void mp_hal_pin_af(mp_hal_pin_obj_t pin, uint8_t af_num); +void mp_hal_pin_af_od(mp_hal_pin_obj_t pin, uint8_t af_num); + +void mp_hal_pin_pull_up(mp_hal_pin_obj_t pin); +void mp_hal_pin_pull_down(mp_hal_pin_obj_t pin); +void mp_hal_pin_pull_none(mp_hal_pin_obj_t pin); + + +#endif diff --git a/ports/mcx/hal_stdio.c b/ports/mcx/hal_stdio.c new file mode 100644 index 0000000000..96a875fb3a --- /dev/null +++ b/ports/mcx/hal_stdio.c @@ -0,0 +1,154 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "py/stream.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "py/ringbuf.h" +#include "extmod/misc.h" +#include "tusb.h" + +#include "drv_uart.h" +#include "pendsv.h" + +static uint8_t s_stdin_rb_array[512]; +static ringbuf_t s_stdin_rb = { + .buf = s_stdin_rb_array, + .size = sizeof(s_stdin_rb_array), +}; + +static void mp_hal_stdin_intr_callback(void *handle, void *param, uint8_t len); + +int mp_hal_stdio_init(void) { + drv_uart_t *uart = MP_STATE_PORT(stdio_uart); + + return drv_uart_async_start(uart, mp_hal_stdin_intr_callback, &s_stdin_rb); +} + +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + return mp_os_dupterm_poll(poll_flags); +} + +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + mp_uint_t ret = len; + bool write_done = false; + + #if MICROPY_HW_ENABLE_UART_REPL + drv_uart_t *uart = MP_STATE_PORT(stdio_uart); + drv_uart_write(uart, (const uint8_t *)str, len, 1000); + + write_done = true; + #endif + + #if MICROPY_HW_USB_CDC + if (tud_cdc_connected()) { + size_t i = 0; + while (i < len) { + uint32_t n = len - i; + if (n > CFG_TUD_CDC_EP_BUFSIZE) { + n = CFG_TUD_CDC_EP_BUFSIZE; + } + int timeout = 0; + // Wait with a max of USC_CDC_TIMEOUT ms + while (n > tud_cdc_write_available() && timeout++ < 1000) { + MICROPY_EVENT_POLL_HOOK + } + if (timeout >= 1000) { + break; + } + uint32_t n2 = tud_cdc_write(str + i, n); + tud_cdc_write_flush(); + i += n2; + } + + write_done = true; + } + #endif + + #if MICROPY_PY_OS_DUPTERM + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + ret = MIN((mp_uint_t)dupterm_res, ret); + } + #endif + + if (!write_done) { + ret = 0U; + } + + return ret; +} + +int mp_hal_stdin_rx_chr(void) { + char ch = 0x00; + for (;;) { + + if (ringbuf_avail(&s_stdin_rb)) { + ch = ringbuf_get(&s_stdin_rb); + break; + } + MICROPY_EVENT_POLL_HOOK + } + + return ch; +} + +void tud_cdc_rx_cb(uint8_t itf) { + /* TODO: This implementation is not safe when UART ISR is interrupted by USB ISR. */ + /* Both terminals will write to the same ring-buffer, which is not guarded. */ + + uint32_t bytes_avail = tud_cdc_n_available(itf); + + while (bytes_avail > 0) { + int ch = tud_cdc_read_char(); + if (ch == mp_interrupt_char) { + mp_sched_keyboard_interrupt(); + } else { + ringbuf_put(&s_stdin_rb, ch); + } + + bytes_avail--; + } +} + +static void mp_hal_stdin_intr_callback(void *handle, void *param, uint8_t len) { + ringbuf_t *rb = (ringbuf_t *)param; + drv_uart_t *uart = (drv_uart_t *)handle; + + uint8_t ch; + + for (uint8_t i = 0; i < len; i++) { + drv_uart_async_read(uart, &ch, 1); + if (ch == mp_interrupt_char) { + pendsv_kbd_intr(); + } else { + ringbuf_put(rb, ch); + } + } +} + +MP_REGISTER_ROOT_POINTER(struct drv_uart_type *stdio_uart); diff --git a/ports/mcx/hal_systick.c b/ports/mcx/hal_systick.c new file mode 100644 index 0000000000..908d4433a1 --- /dev/null +++ b/ports/mcx/hal_systick.c @@ -0,0 +1,76 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "py/mphal.h" + +#include "fsl_common.h" +#include "fsl_common_arm.h" + +volatile mp_uint_t s_current_tick; + +void mp_hal_delay_ms(mp_uint_t ms) { + mp_uint_t t_start = s_current_tick; + + while (s_current_tick < (t_start + ms)) { + MICROPY_EVENT_POLL_HOOK + } +} + +void mp_hal_delay_us(mp_uint_t us) { + mp_uint_t t_end = mp_hal_ticks_us() + us; + + while (mp_hal_ticks_us() < t_end) { + /* Do not poll events here */ + } + + /* TODO: handle condition when interrupts are disabled. */ +} + +mp_uint_t mp_hal_ticks_ms(void) { + return s_current_tick * 1000 / MICROPY_HAL_SYSTICK_RATE; +} + +mp_uint_t mp_hal_ticks_us(void) { + mp_uint_t reload = SysTick->LOAD; + mp_uint_t usec = (reload - SysTick->VAL) * (1000000 / MICROPY_HAL_SYSTICK_RATE) / reload; + + return s_current_tick * (1000000 / MICROPY_HAL_SYSTICK_RATE) + usec; +} + +uint64_t mp_hal_time_ns(void) { + return mp_hal_ticks_us() * 1000; +} + +mp_uint_t mp_hal_ticks_cpu(void) { + for (;;) { + /* -- */ + } +} + +void SysTick_Handler(void) { + s_current_tick++; +} diff --git a/ports/mcx/machine_adc.c b/ports/mcx/machine_adc.c new file mode 100644 index 0000000000..2a7988d315 --- /dev/null +++ b/ports/mcx/machine_adc.c @@ -0,0 +1,107 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 is never compiled standalone, it's included directly from +// extmod/machine_adc.c via MICROPY_PY_MACHINE_ADC_INCLUDEFILE. + + +#include "py/mphal.h" + +#include "drv_adc.h" + +#define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS + +typedef struct _machine_adc_obj_t { + mp_obj_base_t base; + uint8_t id; + drv_adc_t drv; + drv_adc_side_t side; + uint8_t channel; +} machine_adc_obj_t; + +static void mp_machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "ADC(%u,", self->id); + + char side = 'A'; + if (self->side == DRV_ADCSideB) { + side = 'B'; + } + + mp_printf(print, " side=%c, channel=%u)", side, self->channel); +} + +static mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + mp_obj_t pin_obj = args[0]; + if (!mp_obj_is_type(pin_obj, &machine_pin_type)) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Object is not a Pin object.")); + } + + mp_hal_pin_obj_t pin = MP_OBJ_TO_PTR(pin_obj); + const machine_pin_adc_t *adc = mp_hal_pin_find_adc(pin); + if (adc == NULL) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Pin does not have ADC capabilities.")); + } + + machine_adc_obj_t *self = mp_obj_malloc(machine_adc_obj_t, &machine_adc_type); + + mp_hal_pin_analog(pin); + + self->id = adc->adc_id; + self->channel = adc->adc_channel; + + switch (adc->adc_side) { + case 'A': + default: + self->side = DRV_ADCSideA; + break; + + case 'B': + self->side = DRV_ADCSideB; + break; + } + + if (drv_adc_init(&self->drv, self->id) < 0) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("failed to initialize ADC")); + } + + return MP_OBJ_FROM_PTR(self); + +} + +static mp_int_t mp_machine_adc_read_u16(machine_adc_obj_t *self) { + uint16_t ad_val; + int ret = drv_adc_measure(&self->drv, self->side, self->channel, &ad_val); + if (ret < 0) { + return ret; + } + + return ad_val; +} diff --git a/ports/mcx/machine_i2c.c b/ports/mcx/machine_i2c.c new file mode 100644 index 0000000000..09693a3fc8 --- /dev/null +++ b/ports/mcx/machine_i2c.c @@ -0,0 +1,153 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 "extmod/modmachine.h" + +#include "drv_i2c.h" + +typedef struct _machine_i2c_obj_t { + mp_obj_base_t base; + uint8_t id; + uint32_t frequency; + drv_i2c_t drv; + uint32_t timeout; +} machine_i2c_obj_t; + +static void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "I2C(%u, freq=%u)", self->id, self->frequency); +} + +static void mp_machine_i2c_init_helper(machine_i2c_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_freq, ARG_scl, ARG_sda, ARG_timeout }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_freq, MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 500}}, + }; + + 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); + + + drv_i2c_config_t i2c_cfg; + self->frequency = args[ARG_freq].u_int; + i2c_cfg.frequency = self->frequency; + + if (args[ARG_scl].u_obj == mp_const_none) { + /* TODO: Prepare a default pin for SCL*/ + } else { + mp_hal_pin_obj_t pin = args[ARG_scl].u_obj; + + /* TODO: Non LP-Flexcomm pinmap for future A series */ + const machine_pin_af_t *af = mp_hal_pin_find_af(pin, MACHINE_PIN_AF_TYPE_LPFC, self->id, MACHINE_PIN_AF_ATTR_LPFC_P1); + if (af == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("unsupported SCL AF")); + } + + mp_hal_pin_af_od(pin, af->af_id); + mp_hal_pin_pull_up(pin); + } + + if (args[ARG_sda].u_obj == mp_const_none) { + /* TODO: Prepare a default pin for SCL*/ + } else { + mp_hal_pin_obj_t pin = args[ARG_sda].u_obj; + + /* TODO: Non LP-Flexcomm pinmap for future A series */ + const machine_pin_af_t *af = mp_hal_pin_find_af(pin, MACHINE_PIN_AF_TYPE_LPFC, self->id, MACHINE_PIN_AF_ATTR_LPFC_P0); + if (af == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("unsupported SDA AF")); + } + + mp_hal_pin_af_od(pin, af->af_id); + mp_hal_pin_pull_up(pin); + } + + self->timeout = args[ARG_timeout].u_int; + + /* TODO: Check return values */ + drv_i2c_init(&self->drv, self->id, &i2c_cfg); +} + +mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + + if (!mp_obj_is_int(args[0])) { + mp_raise_ValueError(MP_ERROR_TEXT("unsupported I2C id.")); + return mp_const_none; + } + + machine_i2c_obj_t *self = mp_obj_malloc(machine_i2c_obj_t, &machine_i2c_type); + + self->id = mp_obj_get_int(args[0]); + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + mp_machine_i2c_init_helper(self, n_args - 1, args + 1, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +static int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) { + machine_i2c_obj_t *self = MP_OBJ_FROM_PTR(self_in); + + int ret; + + bool stop = (flags & MP_MACHINE_I2C_FLAG_STOP) ? true : false; + if (flags & MP_MACHINE_I2C_FLAG_READ) { + ret = drv_i2c_read(&self->drv, addr, buf, len, self->timeout, stop); + if (ret < 0) { + return ret; + } + } else { + ret = drv_i2c_write(&self->drv, addr, buf, len, self->timeout, stop); + if (ret < 0) { + return ret; + } + } + + return len; +} + +static const mp_machine_i2c_p_t machine_i2c_p = { + .transfer = mp_machine_i2c_transfer_adaptor, + .transfer_single = machine_i2c_transfer_single, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + machine_i2c_type, + MP_QSTR_I2C, + MP_TYPE_FLAG_NONE, + make_new, machine_i2c_make_new, + print, machine_i2c_print, + protocol, &machine_i2c_p, + locals_dict, &mp_machine_i2c_locals_dict + ); diff --git a/ports/mcx/machine_pin.c b/ports/mcx/machine_pin.c new file mode 100644 index 0000000000..a5a9d24add --- /dev/null +++ b/ports/mcx/machine_pin.c @@ -0,0 +1,349 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 "extmod/modmachine.h" +#include "extmod/virtpin.h" + +#include "machine_pin.h" +#include "machine_pin_defs.h" + +static mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_pull, ARG_value, ARG_drive, ARG_alt }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE }}, + { MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + { MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + }; + + 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); + + drv_pin_t pin = { + .port = self->port, + .pin = self->pin, + }; + + drv_pin_config_t pin_cfg; + + /* Retrieve current (default) configuration */ + drv_pin_config_get(&pin, &pin_cfg); + /* TODO: check return value */ + + /* Validate and set mode */ + if (args[ARG_mode].u_obj != mp_const_none) { + pin_cfg.mode = (drv_pin_mode_t)mp_obj_get_int(args[ARG_mode].u_obj); + if (pin_cfg.mode >= DRV_PIN_MODE_END) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin mode: %d"), pin_cfg.mode); + } + } + + /* Validate and set pull mode */ + if (args[ARG_pull].u_obj != mp_const_none) { + pin_cfg.pull = (drv_pin_pull_type_t)mp_obj_get_int(args[ARG_pull].u_obj); + if (pin_cfg.pull >= DRV_PIN_PULL_END) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pull mode: %d"), pin_cfg.pull); + } + } + + /* Validate and set drive strength */ + if (args[ARG_drive].u_obj != mp_const_none) { + pin_cfg.drive = (drv_pin_drive_t)mp_obj_get_int(args[ARG_drive].u_obj); + if (pin_cfg.drive >= DRV_PIN_DRIVE_END) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid drive strength settings: %d"), pin_cfg.drive); + } + } + + /* Validate and set alternative function */ + pin_cfg.af = args[ARG_alt].u_int; + + int ret = drv_pin_config_set(&pin, &pin_cfg); + if (ret != 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("failed to set pin mode: %d"), ret); + } + + /* Validate and set initial value IF MODE IS GPIO OUTPUT OR OD */ + if ((pin_cfg.mode == DRV_PIN_MODE_OUTPUT_OD) || (pin_cfg.mode == DRV_PIN_MODE_OUTPUT_PP)) { + if (args[ARG_value].u_obj != mp_const_none) { + bool write_value = mp_obj_get_int(args[ARG_value].u_obj) ? true : false; + drv_pin_write(&pin, write_value); + } + } + + return mp_const_none; +} + +static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + + drv_pin_t pin = { + .port = self->port, + .pin = self->pin, + }; + + /* Note: a common hardfault reason is a direct print call from Pin.cpu._ or Pin.board._, + * which is not initialized using a proper constructor. Currently it seems there's no way + * finding out whether this pin is initialized or not (every obj is a const ROM obj). + * WORKAROUND: Init the called pin (enable the PORT and GPIO clocks). + */ + drv_pin_init(&pin); + + drv_pin_config_t pin_cfg; + drv_pin_config_get(&pin, &pin_cfg); + + mp_printf(print, "Pin(Pin.cpu.%q, mode=Pin.", self->name); + + qstr mode_qst; + + switch (pin_cfg.mode) { + case DRV_PIN_MODE_INPUT: + mode_qst = MP_QSTR_IN; + break; + + case DRV_PIN_MODE_OUTPUT_PP: + mode_qst = MP_QSTR_OUTPUT; + break; + + case DRV_PIN_MODE_OUTPUT_OD: + mode_qst = MP_QSTR_OPEN_DRAIN; + break; + + case DRV_PIN_MODE_AF_PP: + mode_qst = MP_QSTR_ALT; + break; + + case DRV_PIN_MODE_AF_OD: + mode_qst = MP_QSTR_ALT_OPEN_DRAIN; + break; + + case DRV_PIN_MODE_ANALOG: + default: + mode_qst = MP_QSTR_ANALOG; + break; + + } + + mp_printf(print, "%s", qstr_str(mode_qst)); + + qstr pull_qst; + + switch (pin_cfg.pull) { + case DRV_PIN_PULL_UP: + pull_qst = MP_QSTR_PULL_UP; + break; + + case DRV_PIN_PULL_DOWN: + pull_qst = MP_QSTR_PULL_DOWN; + break; + + case DRV_PIN_PULL_NONE: + default: + pull_qst = MP_QSTR_PULL_NONE; + break; + } + + mp_printf(print, " pull=Pin.%s", qstr_str(pull_qst)); + + qstr drive_qst; + switch (pin_cfg.drive) { + case DRV_PIN_DRIVE_HIGH: + drive_qst = MP_QSTR_DRIVE_HIGH; + break; + + case DRV_PIN_DRIVE_LOW: + default: + drive_qst = MP_QSTR_DRIVE_LOW; + break; + } + + mp_printf(print, " drive=Pin.%s", qstr_str(drive_qst)); + + /* AF */ + mp_printf(print, " alt=%d", pin_cfg.af); + + /* TODO: Add other attributes */ + + mp_printf(print, ")"); +} + +static mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (n_args == 0) { + int read_val = mp_hal_pin_read(self); + /* TODO: Check negative read errors (does this even occur?). */ + return MP_OBJ_NEW_SMALL_INT(read_val); + } else { + mp_hal_pin_write(self, mp_obj_is_true(args[0])); + return mp_const_none; + } +} + +static mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); + +static mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { + return machine_pin_call(args[0], n_args - 1, 0, args + 1); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); + +static mp_obj_t machine_pin_high(mp_obj_t self_in) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_hal_pin_high(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high); + +static mp_obj_t machine_pin_low(mp_obj_t self_in) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_hal_pin_low(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low); + +static mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + + bool output_val = (int)arg ? true : false; + + switch (request) { + case MP_PIN_READ: + return mp_hal_pin_read(self); + break; + case MP_PIN_WRITE: + mp_hal_pin_write(self, output_val); + break; + default: + return -1; + break; + } + + return 0; +} + +mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + mp_obj_t pin_obj = args[0]; + + const machine_pin_obj_t *pin; + + if (mp_obj_is_type(pin_obj, &machine_pin_type)) { + pin = MP_OBJ_TO_PTR(pin_obj); + } else { + pin = mp_hal_pin_find_named_pin(&machine_pin_board_pins_locals_dict, pin_obj); + if (pin == NULL) { + pin = mp_hal_pin_find_named_pin(&machine_pin_cpu_pins_locals_dict, pin_obj); + } + + if (pin == NULL) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Pin(%s) doesn't exist"), mp_obj_str_get_str(pin_obj)); + } + } + + drv_pin_t drv_pin = { + .port = pin->port, + .pin = pin->pin, + }; + + /* TODO: check return value */ + drv_pin_init(&drv_pin); + + if (n_args > 1 || n_kw > 0) { + // pin mode given, so configure this GPIO + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); + } + + return MP_OBJ_FROM_PTR(pin); +} + +static const mp_pin_p_t machine_pin_pin_p = { + .ioctl = machine_pin_ioctl, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_cpu_pins_obj_type, + MP_QSTR_cpu, + MP_TYPE_FLAG_NONE, + locals_dict, &machine_pin_cpu_pins_locals_dict + ); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_board_pins_obj_type, + MP_QSTR_board, + MP_TYPE_FLAG_NONE, + locals_dict, &machine_pin_board_pins_locals_dict + ); + +static const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { + /* Instance methods */ + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&machine_pin_high_obj) }, + { MP_ROM_QSTR(MP_QSTR_low), MP_ROM_PTR(&machine_pin_low_obj) }, + { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_high_obj) }, + { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_low_obj) }, + + // class attributes + { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&machine_pin_board_pins_obj_type) }, + { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&machine_pin_cpu_pins_obj_type) }, + + /* Class constants */ + { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(MP_HAL_PIN_MODE_INPUT) }, + { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(MP_HAL_PIN_MODE_OUTPUT) }, + { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(MP_HAL_PIN_MODE_OPEN_DRAIN) }, + { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(MP_HAL_PIN_MODE_ALT) }, + { MP_ROM_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_ROM_INT(MP_HAL_PIN_MODE_ALT_OPEN_DRAIN) }, + { MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(MP_HAL_PIN_MODE_ANALOG) }, + { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(MP_HAL_PIN_PULL_NONE) }, + { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(MP_HAL_PIN_PULL_UP) }, + { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(MP_HAL_PIN_PULL_DOWN) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_HIGH), MP_ROM_INT(MP_HAL_PIN_DRIVE_0) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_LOW), MP_ROM_INT(MP_HAL_PIN_DRIVE_1) }, +}; + +static MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + make_new, mp_pin_make_new, + locals_dict, &machine_pin_locals_dict, + print, machine_pin_print, + call, machine_pin_call, + protocol, &machine_pin_pin_p + ); diff --git a/ports/mcx/machine_pin.h b/ports/mcx/machine_pin.h new file mode 100644 index 0000000000..78a7e73c55 --- /dev/null +++ b/ports/mcx/machine_pin.h @@ -0,0 +1,71 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_MACHINE_PIN_H +#define MP_PORT_MCX_MACHINE_PIN_H + +#include "shared/runtime/mpirq.h" +#include "py/obj.h" + +#include "machine_pin_defs.h" + +typedef struct { + uint8_t af_id; /* AF0 - AF15 */ + + machine_pin_af_type_t af_type; + uint8_t af_instance_id; + machine_pin_af_attr_t af_attribute; /* Identify what signal this is. */ +} machine_pin_af_t; + +typedef struct { + uint8_t adc_id; + char adc_side; + uint8_t adc_channel; +} machine_pin_adc_t; + +typedef struct { + mp_obj_base_t base; + qstr name; + + uint8_t port; + uint8_t pin; + + uint8_t af_count; + const machine_pin_af_t *af; + + const machine_pin_adc_t *adc; +} machine_pin_obj_t; + +#include "genhdr/pins.h" + +extern const mp_obj_type_t machine_pin_board_pins_obj_type; +extern const mp_obj_type_t machine_pin_cpu_pins_obj_type; + +extern const mp_obj_dict_t machine_pin_cpu_pins_locals_dict; +extern const mp_obj_dict_t machine_pin_board_pins_locals_dict; + +#endif diff --git a/ports/mcx/machine_pin_defs.h b/ports/mcx/machine_pin_defs.h new file mode 100644 index 0000000000..5fcabed3a3 --- /dev/null +++ b/ports/mcx/machine_pin_defs.h @@ -0,0 +1,106 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_MACHINE_PIN_DEFS_H +#define MP_PORT_MCX_MACHINE_PIN_DEFS_H + +typedef enum { + MACHINE_PIN_AF_TYPE_GPIO = 0U, /* GPIO */ + MACHINE_PIN_AF_TYPE_LPFC, /* LP_FLEXCOMM */ + MACHINE_PIN_AF_TYPE_UART, /* LPUART */ + MACHINE_PIN_AF_TYPE_CT32, /* CTIMER */ +} machine_pin_af_type_t; + +typedef enum { + MACHINE_PIN_AF_ATTR_GPIO_P0 = 0U, + MACHINE_PIN_AF_ATTR_GPIO_P1, + MACHINE_PIN_AF_ATTR_GPIO_P2, + MACHINE_PIN_AF_ATTR_GPIO_P3, + MACHINE_PIN_AF_ATTR_GPIO_P4, + MACHINE_PIN_AF_ATTR_GPIO_P5, + MACHINE_PIN_AF_ATTR_GPIO_P6, + MACHINE_PIN_AF_ATTR_GPIO_P7, + MACHINE_PIN_AF_ATTR_GPIO_P8, + MACHINE_PIN_AF_ATTR_GPIO_P9, + MACHINE_PIN_AF_ATTR_GPIO_P10, + MACHINE_PIN_AF_ATTR_GPIO_P11, + MACHINE_PIN_AF_ATTR_GPIO_P12, + MACHINE_PIN_AF_ATTR_GPIO_P13, + MACHINE_PIN_AF_ATTR_GPIO_P14, + MACHINE_PIN_AF_ATTR_GPIO_P15, + MACHINE_PIN_AF_ATTR_GPIO_P16, + MACHINE_PIN_AF_ATTR_GPIO_P17, + MACHINE_PIN_AF_ATTR_GPIO_P18, + MACHINE_PIN_AF_ATTR_GPIO_P19, + MACHINE_PIN_AF_ATTR_GPIO_P20, + MACHINE_PIN_AF_ATTR_GPIO_P21, + MACHINE_PIN_AF_ATTR_GPIO_P22, + MACHINE_PIN_AF_ATTR_GPIO_P23, + MACHINE_PIN_AF_ATTR_GPIO_P24, + MACHINE_PIN_AF_ATTR_GPIO_P25, + MACHINE_PIN_AF_ATTR_GPIO_P26, + MACHINE_PIN_AF_ATTR_GPIO_P27, + MACHINE_PIN_AF_ATTR_GPIO_P28, + MACHINE_PIN_AF_ATTR_GPIO_P29, + MACHINE_PIN_AF_ATTR_GPIO_P30, + MACHINE_PIN_AF_ATTR_GPIO_P31, + + MACHINE_PIN_AF_ATTR_LPFC_P0 = 0U, + MACHINE_PIN_AF_ATTR_LPFC_P1, + MACHINE_PIN_AF_ATTR_LPFC_P2, + MACHINE_PIN_AF_ATTR_LPFC_P3, + MACHINE_PIN_AF_ATTR_LPFC_P4, + MACHINE_PIN_AF_ATTR_LPFC_P5, + MACHINE_PIN_AF_ATTR_LPFC_P6, + + MACHINE_PIN_AF_ATTR_CT32_MAT0 = 0U, + MACHINE_PIN_AF_ATTR_CT32_MAT1, + MACHINE_PIN_AF_ATTR_CT32_MAT2, + MACHINE_PIN_AF_ATTR_CT32_MAT3, + + MACHINE_PIN_AF_ATTR_CT32_INP0 = (0x80U | 0U), /* Special mark */ + MACHINE_PIN_AF_ATTR_CT32_INP1 = (0x80U | 1U), + MACHINE_PIN_AF_ATTR_CT32_INP2 = (0x80U | 2U), + MACHINE_PIN_AF_ATTR_CT32_INP3 = (0x80U | 3U), + MACHINE_PIN_AF_ATTR_CT32_INP4 = (0x80U | 4U), + MACHINE_PIN_AF_ATTR_CT32_INP5 = (0x80U | 5U), + MACHINE_PIN_AF_ATTR_CT32_INP6 = (0x80U | 6U), + MACHINE_PIN_AF_ATTR_CT32_INP7 = (0x80U | 7U), + MACHINE_PIN_AF_ATTR_CT32_INP8 = (0x80U | 8U), + MACHINE_PIN_AF_ATTR_CT32_INP9 = (0x80U | 9U), + MACHINE_PIN_AF_ATTR_CT32_INP10 = (0x80U | 10U), + MACHINE_PIN_AF_ATTR_CT32_INP11 = (0x80U | 11U), + MACHINE_PIN_AF_ATTR_CT32_INP12 = (0x80U | 12U), + MACHINE_PIN_AF_ATTR_CT32_INP13 = (0x80U | 13U), + MACHINE_PIN_AF_ATTR_CT32_INP14 = (0x80U | 14U), + MACHINE_PIN_AF_ATTR_CT32_INP15 = (0x80U | 15U), + MACHINE_PIN_AF_ATTR_CT32_INP16 = (0x80U | 16U), + MACHINE_PIN_AF_ATTR_CT32_INP17 = (0x80U | 17U), + MACHINE_PIN_AF_ATTR_CT32_INP18 = (0x80U | 18U), + MACHINE_PIN_AF_ATTR_CT32_INP19 = (0x80U | 19U), +} machine_pin_af_attr_t; + +#endif diff --git a/ports/mcx/machine_pwm.c b/ports/mcx/machine_pwm.c new file mode 100644 index 0000000000..e7e9efd15e --- /dev/null +++ b/ports/mcx/machine_pwm.c @@ -0,0 +1,180 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 is never compiled standalone, it's included directly from +// extmod/machine_pwm.c via MICROPY_PY_MACHINE_PWM_INCLUDEFILE. + +#include "py/mphal.h" +#include "py/mperrno.h" + +#include "drv_pwm.h" + +typedef struct _machine_pwm_obj_t { + mp_obj_base_t base; + + uint8_t instance; + uint8_t channel; + + drv_pwm_t drv; +} machine_pwm_obj_t; + +static void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + uint32_t freq; + uint16_t duty; + + drv_pwm_freq_get(&self->drv, &freq); + drv_pwm_duty_get(&self->drv, &duty); + + uint32_t duty_ns = (uint64_t)duty * 1000000000 / 65536 / freq; + + mp_printf(print, "PWM(%d, ch=%d, ", self->instance, self->channel); + mp_printf(print, "freq=%d, duty_u16=%d, duty_ns=%d", freq, duty, duty_ns); + mp_printf(print, ")"); +} + +static mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + machine_pwm_obj_t *self = mp_obj_malloc(machine_pwm_obj_t, &machine_pwm_type); + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + mp_machine_pwm_init_helper(self, n_args, args, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +static void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + /* Differences from RA port: freq is a kw_arg (compatible with machine.PWM class). */ + + enum { ARG_pin, ARG_freq, ARG_duty_u16, ARG_duty_ns, ARG_invert }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_duty_u16, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_duty_ns, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + + 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); + + if (args[ARG_pin].u_obj == mp_const_none) { + mp_raise_ValueError(MP_ERROR_TEXT("pin does not exists.")); + } else { + mp_hal_pin_obj_t pin = args[ARG_pin].u_obj; + + const machine_pin_af_t *af = mp_hal_pin_find_pwm(pin); + if (af == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("pin is not PWM capable.")); + } + + self->instance = af->af_instance_id; + self->channel = af->af_attribute; + + mp_hal_pin_af(pin, af->af_id); + } + + if (args[ARG_freq].u_int == -1) { + mp_raise_ValueError(MP_ERROR_TEXT("freq is not provided.")); + } + + bool inverted = args[ARG_invert].u_int ? true : false; + + int ret = drv_pwm_init(&self->drv, self->instance, self->channel, args[ARG_freq].u_int, inverted); + if (ret < 0) { + if (ret == -EBUSY) { + /* No free channel for the PWM instance */ + mp_raise_ValueError(MP_ERROR_TEXT("channel is not available")); + } else { + mp_raise_ValueError(MP_ERROR_TEXT("channel initialization failed")); + } + } + + if ((args[ARG_duty_u16].u_int == -1) && (args[ARG_duty_ns].u_int == -1)) { + mp_raise_ValueError(MP_ERROR_TEXT("one of the duty options must be provided")); + } + + if ((args[ARG_duty_u16].u_int != -1) && (args[ARG_duty_ns].u_int != -1)) { + mp_raise_ValueError(MP_ERROR_TEXT("only one of the duty options can be provided")); + } + + if (args[ARG_duty_u16].u_int != -1) { + drv_pwm_duty_set(&self->drv, args[ARG_duty_u16].u_int); + } + + if (args[ARG_duty_ns].u_int != -1) { + uint16_t duty_u16 = (args[ARG_duty_ns].u_int * 65536 * args[ARG_freq].u_int) / 1000000000; + drv_pwm_duty_set(&self->drv, duty_u16); + } + + drv_pwm_start(&self->drv); +} + +static void mp_machine_pwm_deinit(machine_pwm_obj_t *self) { + drv_pwm_deinit(&self->drv); + + /* TODO: Do we need to configure the IO to its previous state? */ +} + +static mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) { + uint32_t freq; + + drv_pwm_freq_get(&self->drv, &freq); + + return MP_OBJ_NEW_SMALL_INT(freq); +} + +static void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) { + drv_pwm_freq_set(&self->drv, freq); +} + +static mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) { + uint16_t duty_u16; + drv_pwm_duty_get(&self->drv, &duty_u16); + return MP_OBJ_NEW_SMALL_INT(duty_u16); +} + +static void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16) { + drv_pwm_duty_set(&self->drv, duty_u16); +} + +static mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) { + return MP_OBJ_NEW_SMALL_INT(0); +} + +static void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns) { + uint32_t freq; + + drv_pwm_freq_get(&self->drv, &freq); + + uint64_t duty = ((uint64_t)duty_ns * freq * 65536) / 1000000000; + + drv_pwm_duty_set(&self->drv, duty); +} diff --git a/ports/mcx/machine_spi.c b/ports/mcx/machine_spi.c new file mode 100644 index 0000000000..dfabc6becc --- /dev/null +++ b/ports/mcx/machine_spi.c @@ -0,0 +1,185 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2021 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 "py/mphal.h" +#include "py/mperrno.h" +#include "extmod/modmachine.h" + +#include "drv_spi.h" + +typedef struct _machine_spi_obj_t { + mp_obj_base_t base; + + uint8_t id; + uint32_t baudrate; + + drv_spi_t drv; +} machine_spi_obj_t; + +static void machine_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "SPI(%d, ", self->id); + mp_printf(print, "baudrate=%d", self->baudrate); + mp_printf(print, ")"); +} + +static void machine_spi_init_helper(machine_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, + { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} }, + { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + }; + + 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); + + if (args[ARG_sck].u_obj == mp_const_none) { + /* TODO: Prepare a default pin for SCK */ + } else { + mp_hal_pin_obj_t pin = args[ARG_sck].u_obj; + + /* TODO: Non LP-Flexcomm pinmap for future A series */ + const machine_pin_af_t *af = mp_hal_pin_find_af(pin, MACHINE_PIN_AF_TYPE_LPFC, self->id, MACHINE_PIN_AF_ATTR_LPFC_P1); + if (af == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("unsupported SCK af")); + } + + mp_hal_pin_af(pin, af->af_id); + } + + if (args[ARG_mosi].u_obj == mp_const_none) { + /* TODO: Prepare a default pin for MOSI */ + } else { + mp_hal_pin_obj_t pin = args[ARG_mosi].u_obj; + + /* TODO: Non LP-Flexcomm pinmap for future A series */ + const machine_pin_af_t *af = mp_hal_pin_find_af(pin, MACHINE_PIN_AF_TYPE_LPFC, self->id, MACHINE_PIN_AF_ATTR_LPFC_P0); + if (af == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("unsupported MOSI af")); + } + + mp_hal_pin_af(pin, af->af_id); + } + + if (args[ARG_miso].u_obj == mp_const_none) { + /* TODO: Prepare a default pin for MISO */ + } else { + mp_hal_pin_obj_t pin = args[ARG_miso].u_obj; + + /* TODO: Non LP-Flexcomm pinmap for future A series */ + const machine_pin_af_t *af = mp_hal_pin_find_af(pin, MACHINE_PIN_AF_TYPE_LPFC, self->id, MACHINE_PIN_AF_ATTR_LPFC_P2); + if (af == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("unsupported MISO af")); + } + + mp_hal_pin_af(pin, af->af_id); + } + + /* TODO: Initialize SPI peripheral */ + drv_spi_config_t spi_cfg; + + self->baudrate = args[ARG_baudrate].u_int; + + spi_cfg.frequency = self->baudrate; + spi_cfg.cpol = args[ARG_polarity].u_int; + spi_cfg.cpha = args[ARG_phase].u_int; + spi_cfg.frame_size = args[ARG_bits].u_int; + + if (args[ARG_firstbit].u_int == MICROPY_PY_MACHINE_SPI_MSB) { + spi_cfg.lsbfirst = false; + } else { + spi_cfg.lsbfirst = true; + } + + int ret = drv_spi_init(&self->drv, self->id, &spi_cfg); + if (ret < 0) { + if (ret == -ENOENT) { + mp_raise_ValueError(MP_ERROR_TEXT("SPI not found.")); + } else { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("failed to init SPI instance")); + } + } +} + +mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + machine_spi_obj_t *self = mp_obj_malloc(machine_spi_obj_t, &machine_spi_type); + + self->id = mp_obj_get_int(args[0]); + + /* Initialize SPI instance only if kw arguments are given. */ + if (n_kw > 0) { + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_spi_init_helper(self, n_args - 1, args + 1, &kw_args); + } + + return self; +} + +static void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + machine_spi_obj_t *self = (machine_spi_obj_t *)self_in; + + /* Takes same parameters as constructor. */ + machine_spi_init_helper(self, n_args, pos_args, kw_args); +} + +static void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { + machine_spi_obj_t *self = (machine_spi_obj_t *)self_in; + + drv_spi_transfer_t xfer = { + .tx_data = src, + .rx_data = dest, + .len = len, + }; + + drv_spi_transfer(&self->drv, &xfer); +} + +static const mp_machine_spi_p_t machine_spi_p = { + .init = machine_spi_init, + .transfer = machine_spi_transfer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + machine_spi_type, + MP_QSTR_SPI, + MP_TYPE_FLAG_NONE, + make_new, machine_spi_make_new, + print, machine_spi_print, + protocol, &machine_spi_p, + locals_dict, &mp_machine_spi_locals_dict + ); diff --git a/ports/mcx/machine_uart.c b/ports/mcx/machine_uart.c new file mode 100644 index 0000000000..12e3f60f2c --- /dev/null +++ b/ports/mcx/machine_uart.c @@ -0,0 +1,320 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 is never compiled standalone, it's included directly from +// extmod/machine_uart.c via MICROPY_PY_MACHINE_UART_INCLUDEFILE. + +#include "py/ringbuf.h" + +#include "drv_uart.h" + +#define MACHINE_UART_FC_FLAG_RTS 1U +#define MACHINE_UART_FC_FLAG_CTS 2U + +#define MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS \ + { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(MACHINE_UART_FC_FLAG_RTS) }, \ + { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(MACHINE_UART_FC_FLAG_CTS) }, \ + +struct _machine_uart_obj_t { + mp_obj_base_t base; + uint8_t id; + mp_uint_t timeout; + drv_uart_t drv; + ringbuf_t rx_buf; +}; + +static void mp_machine_uart_sendbreak(machine_uart_obj_t *self) { + drv_uart_send_break(&self->drv); +} + +static mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) { + return ringbuf_avail(&self->rx_buf); +} + +static bool mp_machine_uart_txdone(machine_uart_obj_t *self) { + return true; +} + +static mp_int_t mp_machine_uart_readchar(machine_uart_obj_t *self) { + uint8_t ch = 0U; + drv_uart_read(&self->drv, &ch, 1U, self->timeout); + return ch; +} + +static mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + uint8_t *rx_buf = buf_in; + + mp_uint_t buf_avail = ringbuf_avail(&self->rx_buf); + if (buf_avail > size) { + buf_avail = size; + } + + ringbuf_get_bytes(&self->rx_buf, rx_buf, buf_avail); + + if (buf_avail < size) { + mp_uint_t bytes_left = size - buf_avail; + + mp_uint_t time_start = mp_hal_ticks_ms(); + + while (bytes_left) { + if (ringbuf_avail(&self->rx_buf)) { + rx_buf[buf_avail++] = ringbuf_get(&self->rx_buf); + bytes_left--; + } + + if (self->timeout && ((mp_hal_ticks_ms() - time_start) > self->timeout)) { + *errcode = MP_EAGAIN; + break; + } + + MICROPY_EVENT_POLL_HOOK + } + } + + return buf_avail; +} + +static void mp_machine_uart_writechar(machine_uart_obj_t *self, uint16_t data) { + uint8_t data_buf[1] = { data }; + + /* TODO: Use async write? */ + /* TODO: Check return values */ + drv_uart_write(&self->drv, data_buf, 1U, self->timeout); +} + +static mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + /* TODO: Use async write? */ + /* TODO: Check return values */ + drv_uart_write(&self->drv, buf_in, size, self->timeout); + + return 0; +} + +static mp_uint_t mp_machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + mp_uint_t ret = 0; + + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + switch (request) { + case MP_STREAM_POLL: + if ((arg & MP_STREAM_POLL_RD) && ringbuf_avail(&self->rx_buf)) { + ret |= MP_STREAM_POLL_RD; + } + break; + + case MP_STREAM_FLUSH: + /* TX is blocking, so no flush is needed. */ + break; + + default: + ret = MP_STREAM_ERROR; + break; + } + + return ret; +} + +static void mp_machine_uart_async_rx_callback(void *uart, void *param, uint8_t len) { + machine_uart_obj_t *self = param; + + uint8_t ch; + + for (uint8_t i = 0; i < len; i++) { + if (drv_uart_async_read(uart, &ch, 1) == 1) { + ringbuf_put(&self->rx_buf, ch); + } + } +} + +static void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "UART(%d)", self->id); +} + +static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, + ARG_tx, ARG_rx, ARG_cts, ARG_rts, ARG_flow, + ARG_timeout, ARG_timeout_char, ARG_txbuf, ARG_rxbuf }; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 9600U} }, + { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, + { MP_QSTR_parity, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, + { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, + }; + + 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); + + drv_uart_config_t uart_cfg; + + uart_cfg.baud_rate = args[ARG_baudrate].u_int; + + switch (args[ARG_bits].u_int) { + case 7: + uart_cfg.data_bits = DRV_Uart7DataBits; + break; + + case 8: + uart_cfg.data_bits = DRV_Uart8DataBits; + break; + + default: + mp_raise_ValueError(MP_ERROR_TEXT("unsupported combination of bits and parity")); + break; + } + + + if (args[ARG_parity].u_obj == mp_const_none) { + uart_cfg.parity = DRV_UartNoParity; + } else { + if (args[ARG_parity].u_int) { + uart_cfg.parity = DRV_UartOddParity; + } else { + uart_cfg.parity = DRV_UartEvenParity; + } + } + + switch (args[ARG_stop].u_int) { + case 1: + uart_cfg.stop_bits = DRV_Uart1StopBits; + break; + case 2: + uart_cfg.stop_bits = DRV_Uart2StopBits; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("unsupportd stop bit")); + break; + } + + switch (args[ARG_flow].u_int) { + case (MACHINE_UART_FC_FLAG_RTS): + uart_cfg.flow_control = DRV_UartRtsFlowControl; + break; + + case (MACHINE_UART_FC_FLAG_CTS): + uart_cfg.flow_control = DRV_UartCtsFlowControl; + break; + + case (MACHINE_UART_FC_FLAG_RTS | MACHINE_UART_FC_FLAG_CTS): + uart_cfg.flow_control = DRV_UartCtsRtsFlowControl; + break; + + default: + uart_cfg.flow_control = DRV_UartNoFlowControl; + break; + } + + if (args[ARG_tx].u_obj == mp_const_none) { + /* TODO: Prepare a default pin for TX */ + } else { + /* TODO: Non LP-Flexcomm pinmap for future A series */ + mp_hal_pin_obj_t pin = args[ARG_tx].u_obj; + const machine_pin_af_t *af = mp_hal_pin_find_af(pin, MACHINE_PIN_AF_TYPE_LPFC, self->id, MACHINE_PIN_AF_ATTR_LPFC_P1); + if (af == NULL) { + af = mp_hal_pin_find_af(pin, MACHINE_PIN_AF_TYPE_LPFC, self->id, MACHINE_PIN_AF_ATTR_LPFC_P2); + if (af == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("unsupported TX AF")); + } + + /* TODO: Validate if both TX and RX are I2C-remapped mode. */ + uart_cfg.i2c_shared = true; + } + + mp_hal_pin_af(pin, af->af_id); + } + + uart_cfg.i2c_shared = false; + + if (args[ARG_rx].u_obj == mp_const_none) { + /* TODO: Prepare a default pin for RX */ + } else { + /* TODO: Non LP-Flexcomm pinmap for future A series */ + mp_hal_pin_obj_t pin = args[ARG_rx].u_obj; + const machine_pin_af_t *af = mp_hal_pin_find_af(pin, MACHINE_PIN_AF_TYPE_LPFC, self->id, MACHINE_PIN_AF_ATTR_LPFC_P0); + if (af == NULL) { + af = mp_hal_pin_find_af(pin, MACHINE_PIN_AF_TYPE_LPFC, self->id, MACHINE_PIN_AF_ATTR_LPFC_P3); + if (af == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("unsupported RX AF")); + } + + /* TODO: Validate if both TX and RX are I2C-remapped mode. */ + uart_cfg.i2c_shared = true; + } + + mp_hal_pin_af(pin, af->af_id); + } + + self->timeout = args[ARG_timeout].u_int; + + ringbuf_alloc(&self->rx_buf, args[ARG_rxbuf].u_int + 1); + + drv_uart_init(&self->drv, self->id, &uart_cfg); + + drv_uart_async_start(&self->drv, mp_machine_uart_async_rx_callback, self); +} + +static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + + if (!mp_obj_is_int(args[0])) { + mp_raise_ValueError(MP_ERROR_TEXT("unsupported UART id.")); + return mp_const_none; + } + + machine_uart_obj_t *self = mp_obj_malloc(machine_uart_obj_t, &machine_uart_type); + + self->id = mp_obj_get_int(args[0]); + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + mp_machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +static void mp_machine_uart_deinit(machine_uart_obj_t *self) { + drv_uart_async_cancel(&self->drv); + + drv_uart_deinit(&self->drv); +} diff --git a/ports/mcx/main.c b/ports/mcx/main.c new file mode 100644 index 0000000000..ce43c19703 --- /dev/null +++ b/ports/mcx/main.c @@ -0,0 +1,184 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 +#include +#include + +#include "py/builtin.h" +#include "py/compile.h" +#include "py/gc.h" +#include "py/runtime.h" +#include "py/repl.h" +#include "py/stackctrl.h" +#include "py/mperrno.h" +#include "shared/readline/readline.h" +#include "shared/runtime/gchelper.h" +#include "shared/runtime/pyexec.h" + +#include "extmod/vfs.h" + +#include "tusb.h" + +#include "drv_uart.h" +#include "pendsv.h" + +#include "board.h" + +static drv_uart_t s_stdio_uart_obj; + +#if MICROPY_HW_ENABLE_USBDEV +static inline void board_usb_irq_handler(void *param) { + uint8_t rhport = (uint8_t)((int)param & 0xFFU); + tud_int_handler(rhport); + + /* TODO: Use sched. */ + tud_task(); + __SEV(); +} +#endif + +#if MICROPY_ENABLE_COMPILER +void do_str(const char *src, mp_parse_input_kind_t input_kind) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); + qstr source_name = lex->source_name; + mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); + mp_call_function_0(module_fun); + nlr_pop(); + } else { + // uncaught exception + mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); + } +} +#endif + +extern uint32_t __StackTop, __StackLimit, __HeapBase, __HeapLimit; + +int main(int argc, char **argv) { + MCX_BoardEarlyInit(); + + #ifdef MICROPY_HW_ENABLE_USBDEV + MCX_BoardConfigureUSBClock(MICROPY_HW_USBDEV); + MCX_BoardConfigureUSBPHY(MICROPY_HW_USBDEV); + MCX_BoardConfigureUSBISR(MICROPY_HW_USBDEV, board_usb_irq_handler, (void *)MICROPY_HW_USBDEV); + + tusb_init(); + #endif + +soft_reset: + mp_stack_set_top(&__StackTop); + mp_stack_set_limit((char *)&__StackTop - (char *)&__StackLimit - 1024); + + gc_init((void *)&__HeapBase, (void *)&__HeapLimit); + + mp_hal_init(); + pendsv_init(); + + #if defined(MICROPY_HW_UART_REPL) + MP_STATE_PORT(stdio_uart) = &s_stdio_uart_obj; + drv_uart_config_t uart_cfg = { + .baud_rate = 115200, + .data_bits = DRV_Uart8DataBits, + .stop_bits = DRV_Uart1StopBits, + .parity = DRV_UartNoParity, + }; + + drv_uart_init(&s_stdio_uart_obj, MICROPY_HW_UART_REPL, &uart_cfg); + + mp_hal_stdio_init(); + #endif + + mp_init(); + readline_init0(); + + /* Exec boot script to set up internal flash */ + pyexec_frozen_module("_boot.py", false); + + /* Execute start-up script. */ + if (pyexec_file_if_exists("boot.py") == PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + + if (pyexec_file_if_exists("main.py") == PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + + #if MICROPY_ENABLE_COMPILER + // Main script is finished, so now go into REPL mode. + // The REPL mode can change, or it can request a soft reset. + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if (pyexec_raw_repl() != 0) { + break; + } + } else { + if (pyexec_friendly_repl() != 0) { + break; + } + } + } + #endif +soft_reset_exit: + + mp_printf(&mp_plat_print, "MPY: soft reboot\n"); + + drv_uart_deinit(&s_stdio_uart_obj); + + gc_sweep_all(); + mp_deinit(); + + goto soft_reset; +} + +void gc_collect(void) { + gc_collect_start(); + gc_helper_collect_regs_and_stack(); + gc_collect_end(); + gc_dump_info(&mp_plat_print); +} + +void NORETURN __fatal_error(const char *msg) { + while (1) { + ; + } +} + +void nlr_jump_fail(void *val) { + printf("FATAL: uncaught exception %p\n", val); + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val)); + __fatal_error(""); +} + +#ifndef NDEBUG +void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { + printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); + __fatal_error("Assertion failed"); +} +#endif diff --git a/ports/mcx/mcx.mk b/ports/mcx/mcx.mk new file mode 100644 index 0000000000..1596a7437d --- /dev/null +++ b/ports/mcx/mcx.mk @@ -0,0 +1,31 @@ +ifeq ($(TARGET_MCU_SERIES), $(filter $(TARGET_MCU_SERIES), MCXN947 MCXN547 MCXN946 MCXN546)) +TARGET_MCU_HAS_LPFLEXCOMM = 1 +TARGET_MCU_HAS_FLEXSPI = 1 +TARGET_MCU_HAS_OSTIMER = 1 +TARGET_MCU_HAS_USB_HS = 1 +endif + +# Generic CPU features + +ifeq ($(TARGET_MCU_CORE_HAS_DSP), 1) +TARGET_CFLAGS_CPU += -mcpu=cortex-m33 +else +TARGET_CFLAGS_CPU += -mcpu=cortex-m33+nodsp +endif + +ifeq ($(TARGET_MCU_CORE_HAS_FPU), 1) +TARGET_CFLAGS_CPU += -mfloat-abi=hard -mfpu=fpv5-sp-d16 +else +TARGET_CFLAGS_CPU += -mfloat-abi=soft +endif + +TARGET_CFLAGS_CPU += -mthumb + +# Common macros +ifeq ($(TARGET_MCU_CORE),) # Single core MCU +TARGET_MCU_VARIANT = $(TARGET_MCU_SERIES) +TARGET_MCU_DEF = CPU_$(TARGET_MCU_PART) +else # Multi core MCU +TARGET_MCU_VARIANT = $(TARGET_MCU_SERIES)_$(TARGET_MCU_CORE) +TARGET_MCU_DEF = CPU_$(TARGET_MCU_PART)_$(TARGET_MCU_CORE) +endif diff --git a/ports/mcx/mcx_flash.c b/ports/mcx/mcx_flash.c new file mode 100644 index 0000000000..7b9c675648 --- /dev/null +++ b/ports/mcx/mcx_flash.c @@ -0,0 +1,230 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "extmod/vfs.h" + +#include "drv_iflash.h" + +#include "modmcx.h" + +typedef enum { + MCX_FLASH_TYPE_INTERNAL, + #if MICROPY_HW_ENABLE_EFS + MCX_FLASH_TYPE_EXTERNAL, + #endif + MCX_FLASH_TYPE_END, +} mcx_flash_type_t; + +typedef struct mcx_flash_obj_type { + mp_obj_base_t base; + mcx_flash_type_t type; + drv_iflash_t iflash; +} mcx_flash_obj_t; + +static mp_obj_t mcx_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, true); + + mcx_flash_obj_t *self = mp_obj_malloc(mcx_flash_obj_t, &mcx_flash_type); + + if (n_args > 1) { + self->type = mp_obj_get_int(args[1]); + } + + if (self->type >= MCX_FLASH_TYPE_END) { + self->type = MCX_FLASH_TYPE_INTERNAL; + } + + if (self->type == MCX_FLASH_TYPE_INTERNAL) { + if (drv_iflash_init(&self->iflash) < 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to initialize Flash API")); + } + } + + return MP_OBJ_FROM_PTR(self); +} + +static void mcx_flash_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mcx_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + + qstr type_qst; + + switch (self->type) { + #if MICROPY_HW_ENABLE_EFS + case MCX_FLASH_TYPE_EXTERNAL: + type_qst = MP_QSTR_EXTERNAL; + break; + #endif + + default: + case MCX_FLASH_TYPE_INTERNAL: + type_qst = MP_QSTR_INTERNAL; + break; + } + + mp_printf(print, "Flash(Flash.%s)", qstr_str(type_qst)); +} + +static mp_obj_t mcx_flash_readblocks(size_t n_args, const mp_obj_t *args) { + mcx_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + uint32_t block_id = mp_obj_get_int(args[1]); + uint32_t block_off = 0; + + if (n_args == 4) { + block_off = mp_obj_get_int(args[3]); + } + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); + + if (self->type == MCX_FLASH_TYPE_INTERNAL) { + drv_iflash_attr_t attr; + drv_iflash_attr_get(&self->iflash, &attr); + + uint32_t flash_addr = MICROPY_HW_IFS_START + attr.sector_size * block_id + block_off; + + drv_iflash_read(&self->iflash, flash_addr, bufinfo.buf, bufinfo.len); + } + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mcx_flash_readblocks_obj, 3, 4, mcx_flash_readblocks); + + +static mp_obj_t mcx_flash_writeblocks(size_t n_args, const mp_obj_t *args) { + mcx_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + uint32_t block_id = mp_obj_get_int(args[1]); + uint32_t block_off = 0; + + if (n_args == 4) { + block_off = mp_obj_get_int(args[3]); + } + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + + if (self->type == MCX_FLASH_TYPE_INTERNAL) { + drv_iflash_attr_t attr; + drv_iflash_attr_get(&self->iflash, &attr); + + uint32_t page_addr = MICROPY_HW_IFS_START + block_id * attr.sector_size + block_off; + uint32_t page_count = bufinfo.len / attr.page_size; + + for (uint32_t i = 0; i < page_count; i++) { + uint8_t *buf_ptr = &((uint8_t *)bufinfo.buf)[i * attr.page_size]; + int ret = drv_iflash_program_page(&self->iflash, page_addr + i * attr.page_size, buf_ptr); + if (ret < 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("program phrase failed: %d"), ret); + } + } + } + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mcx_flash_writeblocks_obj, 3, 4, mcx_flash_writeblocks); + +static mp_obj_t mcx_flash_progsize(mp_obj_t self_in) { + mcx_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->type == MCX_FLASH_TYPE_INTERNAL) { + drv_iflash_attr_t attr; + drv_iflash_attr_get(&self->iflash, &attr); + + return MP_OBJ_NEW_SMALL_INT(attr.page_size); + } + + return MP_OBJ_NEW_SMALL_INT(0); +} +static MP_DEFINE_CONST_FUN_OBJ_1(mcx_flash_progsize_obj, mcx_flash_progsize); + +static mp_obj_t mcx_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { + mcx_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + + uint32_t erase_size = 0U; + uint32_t block_count = 0U; + uint32_t block_id = mp_obj_get_int(arg_in); + + if (self->type == MCX_FLASH_TYPE_INTERNAL) { + drv_iflash_attr_t attr; + drv_iflash_attr_get(&self->iflash, &attr); + + erase_size = attr.sector_size; + block_count = MICROPY_HW_IFS_LENGTH / erase_size; + } + + mp_int_t cmd = mp_obj_get_int(cmd_in); + switch (cmd) { + case MP_BLOCKDEV_IOCTL_INIT: + case MP_BLOCKDEV_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_SYNC: + return MP_OBJ_NEW_SMALL_INT(0); + + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + return MP_OBJ_NEW_SMALL_INT(block_count); + + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + return MP_OBJ_NEW_SMALL_INT(erase_size); + + case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: { + if (self->type == MCX_FLASH_TYPE_INTERNAL) { + if (drv_iflash_erase_sector(&self->iflash, MICROPY_HW_IFS_START + block_id * erase_size) < 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Erase sector failed.")); + } + } + + return MP_OBJ_NEW_SMALL_INT(0); + } + + default: + return mp_const_none; + } +} +static MP_DEFINE_CONST_FUN_OBJ_3(mcx_flash_ioctl_obj, mcx_flash_ioctl); + +static const mp_rom_map_elem_t mcx_flash_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&mcx_flash_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&mcx_flash_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_progsize), MP_ROM_PTR(&mcx_flash_progsize_obj)}, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mcx_flash_ioctl_obj) }, + + /* Constants */ + { MP_ROM_QSTR(MP_QSTR_INTERNAL), MP_ROM_INT(MCX_FLASH_TYPE_INTERNAL) }, + #if MICROPY_HW_ENABLE_EFS + { MP_ROM_QSTR(MP_QSTR_EXTERNAL), MP_ROM_INT(MCX_FLASH_TYPE_EXTERNAL) }, + #endif +}; +static MP_DEFINE_CONST_DICT(mcx_flash_locals_dict, mcx_flash_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + mcx_flash_type, + MP_QSTR_Flash, + MP_TYPE_FLAG_NONE, + make_new, mcx_flash_make_new, + print, mcx_flash_print, + locals_dict, &mcx_flash_locals_dict + ); diff --git a/ports/mcx/modmachine.c b/ports/mcx/modmachine.c new file mode 100644 index 0000000000..60022eaf29 --- /dev/null +++ b/ports/mcx/modmachine.c @@ -0,0 +1,43 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020-2023 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 is never compiled standalone, it's included directly from +// extmod/modmachine.c via MICROPY_PY_MACHINE_INCLUDEFILE. + + +#define MICROPY_PY_MACHINE_EXTRA_GLOBALS \ + { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, \ + +void machine_init(void) { +} + +void machine_deinit(void) { +} + +static void mp_machine_idle(void) { + __WFI(); +} diff --git a/ports/mcx/modmachine.h b/ports/mcx/modmachine.h new file mode 100644 index 0000000000..878cdcb029 --- /dev/null +++ b/ports/mcx/modmachine.h @@ -0,0 +1,6 @@ +#ifndef MP_PORT_MCX_MODMACHINE_H +#define MP_PORT_MCX_MODMACHINE_H + +#include "py/obj.h" + +#endif diff --git a/ports/mcx/modmcx.c b/ports/mcx/modmcx.c new file mode 100644 index 0000000000..61569e1be2 --- /dev/null +++ b/ports/mcx/modmcx.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * Copyright (c) 2024 NXP + * + * 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" + +extern const mp_obj_type_t mcx_flash_type; + +static const mp_rom_map_elem_t mcx_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mcx) }, + { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&mcx_flash_type) }, +}; + +static MP_DEFINE_CONST_DICT(mcx_module_globals, mcx_module_globals_table); + +const mp_obj_module_t mp_module_mcx = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mcx_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_mcx, mp_module_mcx); diff --git a/ports/mcx/modmcx.h b/ports/mcx/modmcx.h new file mode 100644 index 0000000000..a1b4b3a7d2 --- /dev/null +++ b/ports/mcx/modmcx.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_MODMCX_H +#define MP_PORT_MCX_MODMCX_H + +#include "py/obj.h" + +extern const mp_obj_type_t mcx_flash_type; + +#endif diff --git a/ports/mcx/modos.c b/ports/mcx/modos.c new file mode 100644 index 0000000000..1a012cbb26 --- /dev/null +++ b/ports/mcx/modos.c @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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" + +bool mp_os_dupterm_is_builtin_stream(mp_const_obj_t stream) { + return true; +} + +void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached) { +} diff --git a/ports/mcx/modules/_boot.py b/ports/mcx/modules/_boot.py new file mode 100644 index 0000000000..681aad2f5c --- /dev/null +++ b/ports/mcx/modules/_boot.py @@ -0,0 +1,15 @@ +import os, mcx + +ifs = mcx.Flash() + +prog_size = ifs.progsize() + +try: + vfs = os.VfsLfs2(ifs, progsize=prog_size) +except: + os.VfsLfs2.mkfs(ifs, progsize=prog_size) + vfs = os.VfsLfs2(ifs, progsize=prog_size) + +os.mount(vfs, "/") + +del os, ifs, vfs, prog_size diff --git a/ports/mcx/mpconfigboard_common.h b/ports/mcx/mpconfigboard_common.h new file mode 100644 index 0000000000..27182e1a7a --- /dev/null +++ b/ports/mcx/mpconfigboard_common.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_MPCONFIGBOARD_COMMON_H +#define MP_PORT_MCX_MPCONFIGBOARD_COMMON_H + +#include +#include + +#include "fsl_common.h" +#include "fsl_common_arm.h" + +#define MICROPY_HAL_SYSTICK_RATE (1000) + +#endif diff --git a/ports/mcx/mpconfigport.h b/ports/mcx/mpconfigport.h new file mode 100644 index 0000000000..350f429fc0 --- /dev/null +++ b/ports/mcx/mpconfigport.h @@ -0,0 +1,207 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 + +// Options to control how MicroPython is built for this port, +// overriding defaults in py/mpconfig.h. + +// board specific definitions +#include "mpconfigboard_common.h" +#include "mpconfigboard.h" + +// Default configuration +#ifndef MICROPY_CONFIG_ROM_LEVEL +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) +#endif + +// You can disable the built-in MicroPython compiler by setting the following +// config option to 0. If you do this then you won't get a REPL prompt, but you +// will still be able to execute pre-compiled scripts, compiled with mpy-cross. +#define MICROPY_ENABLE_COMPILER (1) + +// Python internal features +#define MICROPY_READER_VFS (1) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) +#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) +#define MICROPY_REPL_INFO (1) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#ifndef MICROPY_FLOAT_IMPL // can be configured by each board via mpconfigboard.mk +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#endif +#define MICROPY_USE_INTERNAL_ERRNO (1) +#define MICROPY_SCHEDULER_STATIC_NODES (1) +#define MICROPY_SCHEDULER_DEPTH (8) + +#define MICROPY_VFS (1) + +#ifndef MICROPY_VFS_LFS2 +#define MICROPY_VFS_LFS2 (1) +#endif + +// Hardware features +#ifndef MICROPY_HW_ENABLE_USBDEV +#define MICROPY_HW_ENABLE_USBDEV (0) +#endif + +#ifndef MICROPY_HW_ENABLE_UART_REPL +#define MICROPY_HW_ENABLE_UART_REPL (1) // useful if there is no USB +#endif + +#if MICROPY_HW_ENABLE_USBDEV + +#ifndef MICROPY_HW_USBDEV +#define MICROPY_HW_USBDEV (0) +#endif + +// Enable USB-CDC serial port +#ifndef MICROPY_HW_USB_CDC +#define MICROPY_HW_USB_CDC (1) +#endif + +// Enable USB Mass Storage with FatFS filesystem. +#ifndef MICROPY_HW_USB_MSC +#define MICROPY_HW_USB_MSC (0) +#endif + +#endif + +#if MICROPY_HW_ENABLE_UART_REPL +#ifndef MICROPY_HW_UART_REPL +#define MICROPY_HW_UART_REPL (0) +#endif +#endif + +#ifndef MICROPY_HW_ENABLE_IFS +#define MICROPY_HW_ENABLE_IFS (0) +#endif + +#if MICROPY_HW_ENABLE_IFS +// IFS start +#ifndef MICROPY_HW_IFS_START +#define MICROPY_HW_IFS_START (0x100000) +#endif +// IFS length +#ifndef MICROPY_HW_IFS_LENGTH +#define MICROPY_HW_IFS_LENGTH (0x100000) +#endif +#endif + +#ifndef MICROPY_HW_ENABLE_EFS +#define MICROPY_HW_ENABLE_EFS (0) +#endif + + +// Extended modules +#define MICROPY_PY_OS_INCLUDEFILE "ports/mcx/modos.c" +#define MICROPY_PY_OS_DUPTERM (3) +#define MICROPY_PY_OS_DUPTERM_BUILTIN_STREAM (1) +#define MICROPY_PY_OS_DUPTERM_STREAM_DETACHED_ATTACHED (1) + +#define MICROPY_PY_ONEWIRE (1) + +// Machine configs +#define MICROPY_PY_MACHINE (1) +#define MICROPY_PY_MACHINE_INCLUDEFILE "ports/mcx/modmachine.c" + +#define MICROPY_PY_MACHINE_DHT_READINTO (1) +#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new +#define MICROPY_PY_MACHINE_PULSE (1) + +#define MICROPY_PY_MACHINE_ADC (1) +#define MICROPY_PY_MACHINE_ADC_INCLUDEFILE "ports/mcx/machine_adc.c" + +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_UART_INCLUDEFILE "ports/mcx/machine_uart.c" +#define MICROPY_PY_MACHINE_UART_IRQ (0) +#define MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR (1) +#define MICROPY_PY_MACHINE_UART_SENDBREAK (1) + +#define MICROPY_PY_MACHINE_I2C (1) + +#define MICROPY_PY_MACHINE_SPI (1) +#define MICROPY_PY_MACHINE_SPI_MSB (0) +#define MICROPY_PY_MACHINE_SPI_LSB (1) + +#define MICROPY_PY_MACHINE_PWM (1) +#define MICROPY_PY_MACHINE_PWM_DUTY (0) +#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/mcx/machine_pwm.c" + +// type definitions for the specific machine + +typedef intptr_t mp_int_t; // must be pointer size +typedef uintptr_t mp_uint_t; // must be pointer size +typedef long mp_off_t; + +// We need to provide a declaration/definition of alloca() +#include + +#ifndef MICROPY_HW_BOARD_NAME +#define MICROPY_HW_BOARD_NAME "Unknown MCX series board" +#endif + +#ifndef MICROPY_HW_MCU_NAME +#define MICROPY_HW_MCU_NAME "Unknown MCX series MCU" +#endif + +#ifndef MICROPY_PY_SYS_PLATFORM +#define MICROPY_PY_SYS_PLATFORM "mcx" +#endif + +// We need an implementation of the log2 function which is not a macro +#define MP_NEED_LOG2 (1) + +#define MP_SSIZE_MAX (0x7fffffff) + +#define MP_STATE_PORT MP_STATE_VM + +#if MICROPY_PY_THREAD +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + extern void mp_handle_pending(bool); \ + mp_handle_pending(true); \ + if (pyb_thread_enabled) { \ + MP_THREAD_GIL_EXIT(); \ + pyb_thread_yield(); \ + MP_THREAD_GIL_ENTER(); \ + } else { \ + __WFI(); \ + } \ + } while (0); + +#define MICROPY_THREAD_YIELD() pyb_thread_yield() +#else +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + extern void mp_handle_pending(bool); \ + mp_handle_pending(true); \ + __WFI(); \ + } while (0); + +#define MICROPY_THREAD_YIELD() +#endif diff --git a/ports/mcx/mphalport.c b/ports/mcx/mphalport.c new file mode 100644 index 0000000000..bd39910537 --- /dev/null +++ b/ports/mcx/mphalport.c @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 "board.h" + +extern volatile mp_uint_t s_current_tick; + +void mp_hal_init(void) { + SysTick_Config(CLOCK_GetCoreSysClkFreq() / MICROPY_HAL_SYSTICK_RATE); + + s_current_tick = 0ULL; + + NVIC_SetPriority(SysTick_IRQn, 0U); + EnableIRQ(SysTick_IRQn); +} + +void mp_hal_deinit(void) { + DisableIRQ(SysTick_IRQn); + SysTick->CTRL = 0U; +} + +void mp_hal_get_unique_id(uint8_t *uid) { + uint64_t uuid; + + MCX_BoardGetUniqueID(&uuid); + + for (uint8_t i = 0; i < 8; i++) { + uid[i] = (uuid >> (i * 8)) & 0xFFU; + } +} diff --git a/ports/mcx/mphalport.h b/ports/mcx/mphalport.h new file mode 100644 index 0000000000..d776f2de5b --- /dev/null +++ b/ports/mcx/mphalport.h @@ -0,0 +1,79 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_MPHALPORT_H +#define MP_PORT_MCX_MPHALPORT_H + +void mp_hal_init(void); + +/* UUID*/ +void mp_hal_get_unique_id(uint8_t *uid); + +/* STDIO */ +int mp_hal_stdio_init(void); + +/* Pin */ +#include "hal_pin.h" + +static inline void enable_irq(mp_uint_t state) { + __set_PRIMASK(state); +} + +static inline mp_uint_t disable_irq(void) { + mp_uint_t state = __get_PRIMASK(); + __disable_irq(); + return state; +} + +static inline uint32_t raise_irq_pri(uint32_t pri) { + uint32_t basepri = __get_BASEPRI(); + // If non-zero, the processor does not process any exception with a + // priority value greater than or equal to BASEPRI. + // When writing to BASEPRI_MAX the write goes to BASEPRI only if either: + // - Rn is non-zero and the current BASEPRI value is 0 + // - Rn is non-zero and less than the current BASEPRI value + pri <<= (8 - __NVIC_PRIO_BITS); + __ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory"); + return basepri; +} + +// "basepri" should be the value returned from raise_irq_pri +static inline void restore_irq_pri(uint32_t basepri) { + __set_BASEPRI(basepri); +} + +#define mp_hal_quiet_timing_enter() raise_irq_pri(1) +#define mp_hal_quiet_timing_exit(irq_state) restore_irq_pri(irq_state) + +/* Additional delay */ +#define mp_hal_delay_us_fast mp_hal_delay_us + +extern int mp_interrupt_char; +static inline void mp_hal_set_interrupt_char(char c) { + mp_interrupt_char = c; +} + +#endif diff --git a/ports/mcx/pendsv.c b/ports/mcx/pendsv.c new file mode 100644 index 0000000000..5750914132 --- /dev/null +++ b/ports/mcx/pendsv.c @@ -0,0 +1,146 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 + +#include "MCXN947_cm33_core0.h" + +#include "py/runtime.h" + +#include "pendsv.h" + +volatile void *pendsv_object; + +#if defined(PENDSV_DISPATCH_NUM_SLOTS) +uint32_t pendsv_dispatch_active; +pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS]; +#endif + +void pendsv_init(void) { + #if defined(PENDSV_DISPATCH_NUM_SLOTS) + pendsv_dispatch_active = false; + #endif + + NVIC_SetPriority(PendSV_IRQn, 7); +} + +void pendsv_kbd_intr(void) { + if (MP_STATE_MAIN_THREAD(mp_pending_exception) == MP_OBJ_NULL) { + mp_sched_keyboard_interrupt(); + } else { + MP_STATE_MAIN_THREAD(mp_pending_exception) = MP_OBJ_NULL; + pendsv_object = &MP_STATE_VM(mp_kbd_exception); + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + } +} + +#if defined(PENDSV_DISPATCH_NUM_SLOTS) +void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) { + pendsv_dispatch_table[slot] = f; + pendsv_dispatch_active = true; + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; +} + +void pendsv_dispatch_handler(void) { + for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) { + if (pendsv_dispatch_table[i] != NULL) { + pendsv_dispatch_t f = pendsv_dispatch_table[i]; + pendsv_dispatch_table[i] = NULL; + f(); + } + } +} +#endif + + +__attribute__((naked)) void PendSV_Handler(void) { + // Handle a PendSV interrupt + // + // For the case of an asynchronous exception, re-jig the + // stack so that when we return from this interrupt handler + // it returns instead to nlr_jump with argument pendsv_object + // note that stack has a different layout if DEBUG is enabled + // + // For the case of a thread switch, swap stacks. + // + // on entry to this (naked) function, stack has the following layout: + // + // stack layout with DEBUG disabled: + // sp[6]: pc=r15 + // sp[5]: lr=r14 + // sp[4]: r12 + // sp[3]: r3 + // sp[2]: r2 + // sp[1]: r1 + // sp[0]: r0 + // + // stack layout with DEBUG enabled: + // sp[8]: pc=r15 + // sp[7]: lr=r14 + // sp[6]: r12 + // sp[5]: r3 + // sp[4]: r2 + // sp[3]: r1 + // sp[2]: r0 + // sp[1]: 0xfffffff9 + // sp[0]: ? + + __asm volatile ( + #if defined(PENDSV_DISPATCH_NUM_SLOTS) + // Check if there are any pending calls to dispatch to + "ldr r1, pendsv_dispatch_active_ptr\n" + "ldr r0, [r1]\n" + "cmp r0, #0\n" + "beq .no_dispatch\n" + "mov r2, #0\n" + "str r2, [r1]\n" // clear pendsv_dispatch_active + "b pendsv_dispatch_handler\n" // jump to the handler + ".no_dispatch:\n" + #endif + + // Check if there is an active object to throw via nlr_jump + "ldr r1, pendsv_object_ptr\n" + "ldr r0, [r1]\n" + "cmp r0, #0\n" + "beq .no_obj\n" + "str r0, [sp, #0]\n" // store to r0 on stack + "mov r0, #0\n" + "str r0, [r1]\n" // clear pendsv_object + "ldr r0, nlr_jump_ptr\n" + "str r0, [sp, #24]\n" // store to pc on stack + "bx lr\n" // return from interrupt; will return to nlr_jump + ".no_obj:\n" // pendsv_object==NULL + + // Data + ".align 2\n" + #if defined(PENDSV_DISPATCH_NUM_SLOTS) + "pendsv_dispatch_active_ptr: .word pendsv_dispatch_active\n" + #endif + "pendsv_object_ptr: .word pendsv_object\n" + "nlr_jump_ptr: .word nlr_jump\n" + ); +} diff --git a/ports/mcx/pendsv.h b/ports/mcx/pendsv.h new file mode 100644 index 0000000000..2c275211d9 --- /dev/null +++ b/ports/mcx/pendsv.h @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Damien P. George + * Copyright (c) 2024 NXP + * + * 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 MP_PORT_MCX_PENDSV_H +#define MP_PORT_MCX_PENDSV_H + +enum { + PENDSV_DISPATCH_SOFT_TIMER, + PENDSV_DISPATCH_MAX +}; + +#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX + +typedef void (*pendsv_dispatch_t)(void); + +void pendsv_init(void); +void pendsv_kbd_intr(void); +void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f); + +#endif diff --git a/ports/mcx/qstrdefsport.h b/ports/mcx/qstrdefsport.h new file mode 100644 index 0000000000..00d3e2ae3c --- /dev/null +++ b/ports/mcx/qstrdefsport.h @@ -0,0 +1,2 @@ +// qstrs specific to this port +// *FORMAT-OFF* diff --git a/ports/mcx/tusb_config.h b/ports/mcx/tusb_config.h new file mode 100644 index 0000000000..0d4de8b3f4 --- /dev/null +++ b/ports/mcx/tusb_config.h @@ -0,0 +1,36 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jim Mussared + * + * 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_MCX_TUSB_CONFIG_H +#define MICROPY_INCLUDED_MCX_TUSB_CONFIG_H + +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) + +#define CFG_TUSB_OS (OPT_OS_NONE) + +#define CFG_TUD_CDC (1) +#define CFG_TUD_CDC_RX_BUFSIZE (512) +#define CFG_TUD_CDC_TX_BUFSIZE (512) + +#endif // MICROPY_INCLUDED_MIMXRT_TUSB_CONFIG_H diff --git a/ports/mcx/tusb_port.c b/ports/mcx/tusb_port.c new file mode 100644 index 0000000000..f359d44e4d --- /dev/null +++ b/ports/mcx/tusb_port.c @@ -0,0 +1,138 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 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 "tusb.h" +#include "mphalport.h" + +#ifndef MICROPY_HW_USB_VID +#define MICROPY_HW_USB_VID (0xf055) +#endif + +#ifndef MICROPY_HW_USB_PID +#define MICROPY_HW_USB_PID (0x9802) +#endif + +#ifndef MICROPY_HW_USB_MANUFACTURER_STRING +#define MICROPY_HW_USB_MANUFACTURER_STRING ("MicroPython") +#endif + +#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) +#define USBD_MAX_POWER_MA (250) + +#define USBD_ITF_CDC (0) // needs 2 interfaces +#define USBD_ITF_MAX (2) + +#define USBD_CDC_EP_CMD (0x81) +#define USBD_CDC_EP_OUT (0x02) +#define USBD_CDC_EP_IN (0x82) +#define USBD_CDC_CMD_MAX_SIZE (8) +#define USBD_CDC_IN_OUT_MAX_SIZE (512) + +#define USBD_STR_0 (0x00) +#define USBD_STR_MANUF (0x01) +#define USBD_STR_PRODUCT (0x02) +#define USBD_STR_SERIAL (0x03) +#define USBD_STR_CDC (0x04) + +// Note: descriptors returned from callbacks must exist long enough for transfer to complete + +static const tusb_desc_device_t usbd_desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = MICROPY_HW_USB_VID, + .idProduct = MICROPY_HW_USB_PID, + .bcdDevice = 0x0100, + .iManufacturer = USBD_STR_MANUF, + .iProduct = USBD_STR_PRODUCT, + .iSerialNumber = USBD_STR_SERIAL, + .bNumConfigurations = 1, +}; + +static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { + TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA), + + TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, + USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE), +}; + +static const char *const usbd_desc_str[] = { + [USBD_STR_MANUF] = MICROPY_HW_USB_MANUFACTURER_STRING, + [USBD_STR_PRODUCT] = MICROPY_HW_BOARD_NAME, + [USBD_STR_SERIAL] = "00000000000000000000", + [USBD_STR_CDC] = "Board CDC", +}; + +const uint8_t *tud_descriptor_device_cb(void) { + return (const uint8_t *)&usbd_desc_device; +} + +const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { + (void)index; + return usbd_desc_cfg; +} + +const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + #define DESC_STR_MAX (20) + static uint16_t desc_str[DESC_STR_MAX]; + static const char hexchr[16] = "0123456789ABCDEF"; + + memset(desc_str, 0, sizeof(desc_str)); + + uint8_t len; + if (index == 0) { + desc_str[1] = 0x0409; // supported language is English + len = 1; + } else { + if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { + return NULL; + } + if (index == USBD_STR_SERIAL) { + uint8_t uid[8]; + mp_hal_get_unique_id(uid); + // store it as a hex string + for (len = 0; len < 16; len += 2) { + desc_str[1 + len] = hexchr[uid[len / 2] >> 4]; + desc_str[1 + len + 1] = hexchr[uid[len / 2] & 0x0f]; + } + } else { + const char *str = usbd_desc_str[index]; + for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { + desc_str[1 + len] = str[len]; + } + } + } + + // first byte is length (including header), second byte is string type + desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * len + 2); + + return desc_str; +} From 3171c925b740b2a26e8fd38abb3bc5be8ff2b9f0 Mon Sep 17 00:00:00 2001 From: Yilin Sun Date: Tue, 19 Mar 2024 19:17:49 +0800 Subject: [PATCH 2/2] ports: mimxrt: Fix SNVS_LP build on non-RT1176 devices. The SDK updates includes a breaking change on devices without valid external tamper support. This is done by adding a macro checking whether the `FSL_FEATURE_SNVS_HAS_MULTIPLE_TAMPER` macro is defined and contains non-zero values in SDK driver. Currently this is only enabled on RT1176, so here we are adding the same check to prevent calling the non-exist function on other devices. Signed-off-by: Yilin Sun --- ports/mimxrt/machine_rtc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/mimxrt/machine_rtc.c b/ports/mimxrt/machine_rtc.c index 294942cf5a..6d86c07b75 100644 --- a/ports/mimxrt/machine_rtc.c +++ b/ports/mimxrt/machine_rtc.c @@ -156,8 +156,11 @@ void machine_rtc_start(void) { SNVS->HPCOMR |= SNVS_HPCOMR_NPSWA_EN_MASK; // Do a basic init. SNVS_LP_Init(SNVS); + + #if defined(FSL_FEATURE_SNVS_HAS_MULTIPLE_TAMPER) && (FSL_FEATURE_SNVS_HAS_MULTIPLE_TAMPER > 0) // Disable all external Tamper SNVS_LP_DisableAllExternalTamper(SNVS); + #endif SNVS_LP_SRTC_StartTimer(SNVS); // If the date is not set, set it to a more recent start date,