mirror of
https://github.com/micropython/micropython.git
synced 2025-12-15 17:30:14 +01:00
alif: Add initial port to Alif Ensemble MCUs.
This commit adds the beginning of a new alif port with support for Alif Ensemble MCUs. See https://alifsemi.com/ Supported features of this port added by this commit: - UART REPL. - TinyUSB support, for REPL and MSC. - Octal SPI flash support, for filesystem. - machine.Pin support. General notes about the port: - It uses make, similar to other bare-metal ports here. - The toolchain is the standard arm-none-eabi- toolchain. - Flashing a board can be done using either the built-in serial bootloader, or JLink (both supported here). - There are two required submodules (one for drivers/SDK, one for security tools), both of which are open source and on GitHub. - No special hardware or software is needed for development, just a board connected over USB. OpenMV have generously sponsored the development of this port. Signed-off-by: Damien George <damien@micropython.org> Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
This commit is contained in:
261
ports/alif/Makefile
Normal file
261
ports/alif/Makefile
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
################################################################################
|
||||||
|
# Initial setup of Makefile environment
|
||||||
|
|
||||||
|
BOARD ?= ALIF_ENSEMBLE
|
||||||
|
BOARD_DIR ?= boards/$(BOARD)
|
||||||
|
BUILD ?= build-$(BOARD)
|
||||||
|
|
||||||
|
ifeq ($(wildcard $(BOARD_DIR)/.),)
|
||||||
|
$(error Invalid BOARD specified: $(BOARD_DIR))
|
||||||
|
endif
|
||||||
|
|
||||||
|
include ../../py/mkenv.mk
|
||||||
|
include mpconfigport.mk
|
||||||
|
include $(BOARD_DIR)/mpconfigboard.mk
|
||||||
|
|
||||||
|
# qstr definitions (must come before including py.mk)
|
||||||
|
QSTR_DEFS += qstrdefsport.h
|
||||||
|
|
||||||
|
# include py core make definitions
|
||||||
|
include $(TOP)/py/py.mk
|
||||||
|
include $(TOP)/extmod/extmod.mk
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Project specific settings and compiler/linker flags
|
||||||
|
|
||||||
|
CROSS_COMPILE ?= arm-none-eabi-
|
||||||
|
GIT_SUBMODULES += lib/tinyusb lib/alif_ensemble-cmsis-dfp lib/alif-security-toolkit
|
||||||
|
PORT ?= /dev/ttyACM0
|
||||||
|
|
||||||
|
ALIF_TOOLS ?= ../../lib/alif-security-toolkit/toolkit
|
||||||
|
ALIF_DFP_REL_TOP ?= lib/alif_ensemble-cmsis-dfp
|
||||||
|
ALIF_DFP_REL_HERE ?= $(TOP)/lib/alif_ensemble-cmsis-dfp
|
||||||
|
CMSIS_DIR ?= $(TOP)/lib/cmsis/inc
|
||||||
|
|
||||||
|
MCU_CORE ?= M55_HP
|
||||||
|
ALIF_CONFIG ?= mcu/$(MCU_CORE)_cfg.json
|
||||||
|
LD_FILE ?= mcu/ensemble.ld.S
|
||||||
|
|
||||||
|
INC += -I.
|
||||||
|
INC += -I$(TOP)
|
||||||
|
INC += -I$(BUILD)
|
||||||
|
INC += -I$(BOARD_DIR)
|
||||||
|
INC += -I$(CMSIS_DIR)
|
||||||
|
INC += -I$(ALIF_DFP_REL_HERE)/drivers/include/
|
||||||
|
INC += -I$(ALIF_DFP_REL_HERE)/ospi_xip/source/ospi
|
||||||
|
INC += -I$(ALIF_DFP_REL_HERE)/Device/common/config/
|
||||||
|
INC += -I$(ALIF_DFP_REL_HERE)/Device/common/include/
|
||||||
|
INC += -I$(ALIF_DFP_REL_HERE)/Device/core/$(MCU_CORE)/config/
|
||||||
|
INC += -I$(ALIF_DFP_REL_HERE)/Device/core/$(MCU_CORE)/include/
|
||||||
|
INC += -I$(ALIF_DFP_REL_HERE)/Device/$(MCU_SERIES)/$(MCU_VARIANT)/
|
||||||
|
INC += -I$(TOP)/lib/tinyusb/src
|
||||||
|
INC += -Itinyusb_port
|
||||||
|
|
||||||
|
GEN_PIN_MKPINS = mcu/make-pins.py
|
||||||
|
GEN_PIN_PREFIX = mcu/pins_prefix.c
|
||||||
|
GEN_PINS_BOARD_CSV = $(BOARD_DIR)/pins.csv
|
||||||
|
GEN_PINS_SRC = $(BUILD)/pins_board.c
|
||||||
|
GEN_PINS_HDR = $(HEADER_BUILD)/pins_board.h
|
||||||
|
|
||||||
|
CFLAGS_FPU += -mfloat-abi=hard -mfpu=fpv5-d16
|
||||||
|
CFLAGS_CORTEX_M55 += -mthumb -mcpu=cortex-m55 -mtune=cortex-m55 $(CFLAGS_FPU)
|
||||||
|
|
||||||
|
CFLAGS += $(INC) -Wall -Werror -std=c99 $(CFLAGS_CORTEX_M55) -nostdlib
|
||||||
|
CFLAGS += -Wdouble-promotion -Wfloat-conversion
|
||||||
|
CFLAGS += -fdata-sections -ffunction-sections
|
||||||
|
CFLAGS += -D$(MCU_CORE) -DCORE_$(MCU_CORE) -DALIF_CMSIS_H="\"$(MCU_CORE).h\""
|
||||||
|
|
||||||
|
ifeq ($(MICROPY_FLOAT_IMPL),float)
|
||||||
|
CFLAGS += -fsingle-precision-constant
|
||||||
|
CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT
|
||||||
|
else
|
||||||
|
CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE
|
||||||
|
endif
|
||||||
|
|
||||||
|
AFLAGS = -mthumb -march=armv8.1-m.main $(CFLAGS_FPU)
|
||||||
|
|
||||||
|
LDFLAGS += -nostdlib
|
||||||
|
LDFLAGS += -T$(BUILD)/ensemble.ld -Map=$@.map --cref --gc-sections
|
||||||
|
LDFLAGS += --wrap=dcd_event_handler
|
||||||
|
|
||||||
|
# Tune for Debugging or Optimization
|
||||||
|
ifeq ($(DEBUG), 1)
|
||||||
|
CFLAGS += -Og -ggdb3
|
||||||
|
# Disable text compression in debug builds
|
||||||
|
MICROPY_ROM_TEXT_COMPRESSION = 0
|
||||||
|
else
|
||||||
|
CFLAGS += -O2 -DNDEBUG
|
||||||
|
endif
|
||||||
|
|
||||||
|
LIBS += "$(shell $(CC) $(CFLAGS) -print-libgcc-file-name)"
|
||||||
|
|
||||||
|
JLINK_CMD = '\
|
||||||
|
ExitOnError 1\n\
|
||||||
|
Device $(JLINK_DEV)\n\
|
||||||
|
SelectInterface SWD\n\
|
||||||
|
Speed auto\n\
|
||||||
|
Connect\n\
|
||||||
|
Reset\n\
|
||||||
|
ShowHWStatus\n\
|
||||||
|
LoadFile "$(BUILD)/firmware_toc.bin",0x8057f1c0\n\
|
||||||
|
LoadFile "$(BUILD)/firmware.bin",0x80000000\n\
|
||||||
|
Reset\n\
|
||||||
|
Exit'
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Source files and libraries
|
||||||
|
|
||||||
|
SRC_O += \
|
||||||
|
shared/runtime/gchelper_thumb2.o
|
||||||
|
|
||||||
|
SRC_C = \
|
||||||
|
alif_flash.c \
|
||||||
|
fatfs_port.c \
|
||||||
|
machine_pin.c \
|
||||||
|
main.c \
|
||||||
|
modalif.c \
|
||||||
|
mphalport.c \
|
||||||
|
mpuart.c \
|
||||||
|
msc_disk.c \
|
||||||
|
ospi_flash.c \
|
||||||
|
pendsv.c \
|
||||||
|
usbd.c \
|
||||||
|
$(wildcard $(BOARD_DIR)/*.c)
|
||||||
|
|
||||||
|
ifeq ($(MICROPY_FLOAT_IMPL),float)
|
||||||
|
LIBM_SRC_C += $(SRC_LIB_LIBM_C)
|
||||||
|
LIBM_SRC_C += $(SRC_LIB_LIBM_SQRT_HW_C)
|
||||||
|
$(BUILD)/lib/libm/%.o: CFLAGS += -Wno-maybe-uninitialized
|
||||||
|
else
|
||||||
|
LIBM_SRC_C += $(SRC_LIB_LIBM_DBL_C)
|
||||||
|
LIBM_SRC_C += $(SRC_LIB_LIBM_DBL_SQRT_HW_C)
|
||||||
|
$(BUILD)/lib/libm_dbl/%.o: CFLAGS += -Wno-maybe-uninitialized
|
||||||
|
endif
|
||||||
|
|
||||||
|
SHARED_SRC_C += $(addprefix shared/,\
|
||||||
|
libc/string0.c \
|
||||||
|
netutils/dhcpserver.c \
|
||||||
|
netutils/netutils.c \
|
||||||
|
netutils/trace.c \
|
||||||
|
readline/readline.c \
|
||||||
|
runtime/gchelper_native.c \
|
||||||
|
runtime/interrupt_char.c \
|
||||||
|
runtime/mpirq.c \
|
||||||
|
runtime/pyexec.c \
|
||||||
|
runtime/softtimer.c \
|
||||||
|
runtime/stdout_helpers.c \
|
||||||
|
runtime/sys_stdio_mphal.c \
|
||||||
|
timeutils/timeutils.c \
|
||||||
|
tinyusb/mp_usbd.c \
|
||||||
|
tinyusb/mp_usbd_cdc.c \
|
||||||
|
tinyusb/mp_usbd_descriptor.c \
|
||||||
|
)
|
||||||
|
|
||||||
|
DRIVERS_SRC_C += $(addprefix drivers/,\
|
||||||
|
bus/softspi.c \
|
||||||
|
bus/softqspi.c \
|
||||||
|
memory/spiflash.c \
|
||||||
|
dht/dht.c \
|
||||||
|
)
|
||||||
|
|
||||||
|
TINYUSB_SRC_C += \
|
||||||
|
lib/tinyusb/src/tusb.c \
|
||||||
|
lib/tinyusb/src/class/cdc/cdc_device.c \
|
||||||
|
lib/tinyusb/src/class/msc/msc_device.c \
|
||||||
|
lib/tinyusb/src/common/tusb_fifo.c \
|
||||||
|
lib/tinyusb/src/device/usbd.c \
|
||||||
|
lib/tinyusb/src/device/usbd_control.c \
|
||||||
|
tinyusb_port/tusb_alif_dcd.c \
|
||||||
|
|
||||||
|
ALIF_SRC_C += $(addprefix $(ALIF_DFP_REL_TOP)/,\
|
||||||
|
Device/common/source/clk.c \
|
||||||
|
Device/common/source/mpu_M55.c \
|
||||||
|
Device/common/source/system_M55.c \
|
||||||
|
Device/common/source/system_utils.c \
|
||||||
|
Device/core/$(MCU_CORE)/source/startup_$(MCU_CORE).c \
|
||||||
|
drivers/source/pinconf.c \
|
||||||
|
drivers/source/uart.c \
|
||||||
|
ospi_xip/source/ospi/ospi_drv.c \
|
||||||
|
)
|
||||||
|
|
||||||
|
$(BUILD)/tinyusb_port/tusb_alif_dcd.o: CFLAGS += -Wno-unused-variable -DTUSB_ALIF_NO_IRQ_CFG=1
|
||||||
|
|
||||||
|
# List of sources for qstr extraction
|
||||||
|
SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(GEN_PINS_SRC)
|
||||||
|
|
||||||
|
OBJ += $(PY_O)
|
||||||
|
OBJ += $(addprefix $(BUILD)/, $(SRC_O))
|
||||||
|
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||||
|
OBJ += $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o))
|
||||||
|
OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
|
||||||
|
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
|
||||||
|
OBJ += $(addprefix $(BUILD)/, $(TINYUSB_SRC_C:.c=.o))
|
||||||
|
OBJ += $(addprefix $(BUILD)/, $(ALIF_SRC_C:.c=.o))
|
||||||
|
OBJ += $(GEN_PINS_SRC:.c=.o)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Main targets
|
||||||
|
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: $(BUILD)/firmware_toc.bin
|
||||||
|
|
||||||
|
$(BUILD)/ensemble.ld: $(LD_FILE)
|
||||||
|
$(ECHO) "Preprocess linker script $@"
|
||||||
|
$(Q)$(CPP) -P -E $(CFLAGS) $^ > $@
|
||||||
|
|
||||||
|
$(BUILD)/firmware.elf: $(OBJ) $(BUILD)/ensemble.ld
|
||||||
|
$(ECHO) "Link $@"
|
||||||
|
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
|
||||||
|
$(Q)$(SIZE) $@
|
||||||
|
|
||||||
|
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
|
||||||
|
$(Q)$(OBJCOPY) -Obinary $^ $(BUILD)/firmware.bin
|
||||||
|
|
||||||
|
$(BUILD)/firmware_toc.bin: $(BUILD)/firmware.bin
|
||||||
|
$(Q)python $(ALIF_TOOLS)/app-gen-toc.py \
|
||||||
|
--filename $(abspath $(BUILD)/$(ALIF_TOC_CONFIG)) \
|
||||||
|
--output-dir $(BUILD) \
|
||||||
|
--firmware-dir $(BUILD) \
|
||||||
|
--output $@
|
||||||
|
|
||||||
|
.PHONY: deploy
|
||||||
|
deploy: $(BUILD)/firmware_toc.bin
|
||||||
|
$(ECHO) "Writing $< to the board"
|
||||||
|
$(Q)python $(ALIF_TOOLS)/app-write-mram.py \
|
||||||
|
--cfg-part $(ALIF_TOOLKIT_CFG_PART) \
|
||||||
|
--port $(PORT) \
|
||||||
|
--pad \
|
||||||
|
--images file:$(BUILD)/application_package.ds
|
||||||
|
|
||||||
|
.PHONY: deploy-jlink
|
||||||
|
deploy-jlink: $(BUILD)/firmware_toc.bin
|
||||||
|
$(Q)echo -e $(JLINK_CMD) | $(JLINK_EXE)
|
||||||
|
|
||||||
|
.PHONY: maintenance
|
||||||
|
maintenance:
|
||||||
|
$(Q)python $(ALIF_TOOLS)/maintenance.py \
|
||||||
|
--cfg-part $(ALIF_TOOLKIT_CFG_PART) \
|
||||||
|
--port $(PORT)
|
||||||
|
|
||||||
|
.PHONY: update-system-package
|
||||||
|
update-system-package:
|
||||||
|
$(Q)python $(ALIF_TOOLS)/updateSystemPackage.py \
|
||||||
|
--cfg-part $(ALIF_TOOLKIT_CFG_PART) \
|
||||||
|
--port $(PORT)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Remaining make rules
|
||||||
|
|
||||||
|
# Use a pattern rule here so that make will only call make-pins.py once to make
|
||||||
|
# both pins_board.c and pins_board.h
|
||||||
|
$(BUILD)/%_board.c $(HEADER_BUILD)/%_board.h: $(BOARD_DIR)/%.csv $(GEN_PIN_MKPINS) $(GEN_PIN_PREFIX) | $(HEADER_BUILD)
|
||||||
|
$(ECHO) "GEN $@"
|
||||||
|
$(Q)$(PYTHON) $(GEN_PIN_MKPINS) \
|
||||||
|
--board-csv $(GEN_PINS_BOARD_CSV) \
|
||||||
|
--prefix $(GEN_PIN_PREFIX) \
|
||||||
|
--output-source $(GEN_PINS_SRC) \
|
||||||
|
--output-header $(GEN_PINS_HDR)
|
||||||
|
|
||||||
|
include $(TOP)/py/mkrules.mk
|
||||||
21
ports/alif/README.md
Normal file
21
ports/alif/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MicroPython port to Alif Ensemble MCUs
|
||||||
|
======================================
|
||||||
|
|
||||||
|
This is a port of MicroPython to the Alif Ensemble series of microcontrollers.
|
||||||
|
|
||||||
|
Initial development of this Alif port was sponsored by OpenMV LLC.
|
||||||
|
|
||||||
|
Features currently supported:
|
||||||
|
- UART REPL.
|
||||||
|
- TinyUSB with CDC and MSC device support.
|
||||||
|
- Octal SPI flash with XIP mode.
|
||||||
|
- machine.Pin support with named pins.
|
||||||
|
- machine.UART, machine.SPI, machine.I2C, machine.RTC peripherals.
|
||||||
|
- WiFi and Bluetooth using cyw43.
|
||||||
|
- Dual core support of the HE and HP cores using Open-AMP.
|
||||||
|
- Low power modes.
|
||||||
|
|
||||||
|
The following more advanced features will follow later:
|
||||||
|
- Ethernet support.
|
||||||
|
- SDRAM support.
|
||||||
|
- Other machine modules.
|
||||||
160
ports/alif/alif_flash.c
Normal file
160
ports/alif/alif_flash.c
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "extmod/vfs.h"
|
||||||
|
#include "modalif.h"
|
||||||
|
#include "ospi_flash.h"
|
||||||
|
|
||||||
|
typedef struct _alif_flash_obj_t {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
uint32_t flash_base_addr;
|
||||||
|
uint32_t flash_size;
|
||||||
|
} alif_flash_obj_t;
|
||||||
|
|
||||||
|
static alif_flash_obj_t alif_flash_obj = {
|
||||||
|
.base = { &alif_flash_type },
|
||||||
|
.flash_base_addr = MICROPY_HW_FLASH_STORAGE_BASE_ADDR,
|
||||||
|
.flash_size = MICROPY_HW_FLASH_STORAGE_BYTES,
|
||||||
|
};
|
||||||
|
|
||||||
|
static mp_obj_t alif_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||||
|
// Parse arguments
|
||||||
|
enum { ARG_start, ARG_len };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||||
|
{ MP_QSTR_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||||
|
};
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
|
if (args[ARG_start].u_int == -1 && args[ARG_len].u_int == -1) {
|
||||||
|
// Default singleton object that accesses entire flash
|
||||||
|
return MP_OBJ_FROM_PTR(&alif_flash_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
alif_flash_obj_t *self = mp_obj_malloc(alif_flash_obj_t, &alif_flash_type);
|
||||||
|
|
||||||
|
mp_int_t start = args[ARG_start].u_int;
|
||||||
|
if (start == -1) {
|
||||||
|
start = 0;
|
||||||
|
} else if (!(0 <= start && start < MICROPY_HW_FLASH_STORAGE_BYTES && start % MICROPY_HW_FLASH_BLOCK_SIZE_BYTES == 0)) {
|
||||||
|
mp_raise_ValueError(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_int_t len = args[ARG_len].u_int;
|
||||||
|
if (len == -1) {
|
||||||
|
len = MICROPY_HW_FLASH_STORAGE_BYTES - start;
|
||||||
|
} else if (!(0 < len && start + len <= MICROPY_HW_FLASH_STORAGE_BYTES && len % MICROPY_HW_FLASH_BLOCK_SIZE_BYTES == 0)) {
|
||||||
|
mp_raise_ValueError(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->flash_base_addr = MICROPY_HW_FLASH_STORAGE_BASE_ADDR + start;
|
||||||
|
self->flash_size = len;
|
||||||
|
|
||||||
|
return MP_OBJ_FROM_PTR(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t alif_flash_readblocks(size_t n_args, const mp_obj_t *args) {
|
||||||
|
alif_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||||
|
uint32_t offset = mp_obj_get_int(args[1]) * MICROPY_HW_FLASH_BLOCK_SIZE_BYTES;
|
||||||
|
mp_buffer_info_t bufinfo;
|
||||||
|
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);
|
||||||
|
if (n_args == 4) {
|
||||||
|
offset += mp_obj_get_int(args[3]);
|
||||||
|
}
|
||||||
|
int ret = ospi_flash_read(self->flash_base_addr + offset, bufinfo.len, bufinfo.buf);
|
||||||
|
mp_event_handle_nowait();
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(ret);
|
||||||
|
}
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alif_flash_readblocks_obj, 3, 4, alif_flash_readblocks);
|
||||||
|
|
||||||
|
static mp_obj_t alif_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
|
||||||
|
alif_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||||
|
uint32_t offset = mp_obj_get_int(args[1]) * MICROPY_HW_FLASH_BLOCK_SIZE_BYTES;
|
||||||
|
mp_buffer_info_t bufinfo;
|
||||||
|
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
|
||||||
|
if (n_args == 3) {
|
||||||
|
uint32_t addr = self->flash_base_addr + offset;
|
||||||
|
int32_t len = bufinfo.len;
|
||||||
|
while (len > 0) {
|
||||||
|
int ret = ospi_flash_erase_sector(addr);
|
||||||
|
mp_event_handle_nowait();
|
||||||
|
if (ret < 0) {
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(ret);
|
||||||
|
}
|
||||||
|
addr += MICROPY_HW_FLASH_BLOCK_SIZE_BYTES;
|
||||||
|
len -= MICROPY_HW_FLASH_BLOCK_SIZE_BYTES;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
offset += mp_obj_get_int(args[3]);
|
||||||
|
}
|
||||||
|
int ret = ospi_flash_write(self->flash_base_addr + offset, bufinfo.len, bufinfo.buf);
|
||||||
|
mp_event_handle_nowait();
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(ret);
|
||||||
|
}
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alif_flash_writeblocks_obj, 3, 4, alif_flash_writeblocks);
|
||||||
|
|
||||||
|
static mp_obj_t alif_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) {
|
||||||
|
alif_flash_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||||
|
mp_int_t cmd = mp_obj_get_int(cmd_in);
|
||||||
|
switch (cmd) {
|
||||||
|
case MP_BLOCKDEV_IOCTL_INIT:
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(0);
|
||||||
|
case MP_BLOCKDEV_IOCTL_DEINIT:
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(0);
|
||||||
|
case MP_BLOCKDEV_IOCTL_SYNC:
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(0);
|
||||||
|
case MP_BLOCKDEV_IOCTL_BLOCK_COUNT:
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(self->flash_size / MICROPY_HW_FLASH_BLOCK_SIZE_BYTES);
|
||||||
|
case MP_BLOCKDEV_IOCTL_BLOCK_SIZE:
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(MICROPY_HW_FLASH_BLOCK_SIZE_BYTES);
|
||||||
|
case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: {
|
||||||
|
uint32_t offset = mp_obj_get_int(arg_in) * MICROPY_HW_FLASH_BLOCK_SIZE_BYTES;
|
||||||
|
int ret = ospi_flash_erase_sector(self->flash_base_addr + offset);
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(ret);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_3(alif_flash_ioctl_obj, alif_flash_ioctl);
|
||||||
|
|
||||||
|
static const mp_rom_map_elem_t alif_flash_locals_dict_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&alif_flash_readblocks_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&alif_flash_writeblocks_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&alif_flash_ioctl_obj) },
|
||||||
|
};
|
||||||
|
static MP_DEFINE_CONST_DICT(alif_flash_locals_dict, alif_flash_locals_dict_table);
|
||||||
|
|
||||||
|
MP_DEFINE_CONST_OBJ_TYPE(
|
||||||
|
alif_flash_type,
|
||||||
|
MP_QSTR_Flash,
|
||||||
|
MP_TYPE_FLAG_NONE,
|
||||||
|
make_new, alif_flash_make_new,
|
||||||
|
locals_dict, &alif_flash_locals_dict
|
||||||
|
);
|
||||||
5
ports/alif/boards/manifest.py
Normal file
5
ports/alif/boards/manifest.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
freeze("$(PORT_DIR)/modules")
|
||||||
|
include("$(MPY_DIR)/extmod/asyncio")
|
||||||
|
require("dht")
|
||||||
|
require("neopixel")
|
||||||
|
require("onewire")
|
||||||
38
ports/alif/fatfs_port.c
Normal file
38
ports/alif/fatfs_port.c
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib/oofatfs/ff.h"
|
||||||
|
|
||||||
|
DWORD get_fattime(void) {
|
||||||
|
// TODO
|
||||||
|
int year = 2024;
|
||||||
|
int month = 1;
|
||||||
|
int day = 1;
|
||||||
|
int hour = 0;
|
||||||
|
int min = 0;
|
||||||
|
int sec = 0;
|
||||||
|
return ((year - 1980) << 25) | (month << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec / 2);
|
||||||
|
}
|
||||||
84
ports/alif/irq.h
Normal file
84
ports/alif/irq.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2023 Damien P. George
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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_ALIF_IRQ_H
|
||||||
|
#define MICROPY_INCLUDED_ALIF_IRQ_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include ALIF_CMSIS_H
|
||||||
|
|
||||||
|
// IRQ priority definitions.
|
||||||
|
//
|
||||||
|
// The M55-HP CPU has __NVIC_PRIO_BITS==8 bits for setting the IRQ priority.
|
||||||
|
// It uses NVIC_SetPriorityGrouping(0) which is 7 bits for preempt priority
|
||||||
|
// and 1 bit for the sub-priority.
|
||||||
|
//
|
||||||
|
// Lower number implies higher interrupt priority.
|
||||||
|
|
||||||
|
#define NVIC_PRIORITYGROUP_7 ((uint32_t)0x00000000U)
|
||||||
|
#define IRQ_PRI_SYSTEM_TICK NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 0, 0)
|
||||||
|
#define IRQ_PRI_QUIET_TIMING NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 1, 0)
|
||||||
|
#define IRQ_PRI_UART_REPL NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 1, 0)
|
||||||
|
#define IRQ_PRI_USB NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 5, 0)
|
||||||
|
#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 127, 0)
|
||||||
|
|
||||||
|
// these states correspond to values from query_irq, enable_irq and disable_irq
|
||||||
|
#define IRQ_STATE_DISABLED (0x00000001)
|
||||||
|
#define IRQ_STATE_ENABLED (0x00000000)
|
||||||
|
|
||||||
|
static inline uint32_t query_irq(void) {
|
||||||
|
return __get_PRIMASK();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void enable_irq(uint32_t state) {
|
||||||
|
__set_PRIMASK(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t disable_irq(void) {
|
||||||
|
uint32_t state = __get_PRIMASK();
|
||||||
|
__disable_irq();
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// irqs with a priority value greater or equal to "pri" will be disabled
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_ALIF_IRQ_H
|
||||||
298
ports/alif/machine_pin.c
Normal file
298
ports/alif/machine_pin.c
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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 "extmod/modmachine.h"
|
||||||
|
#include "extmod/virtpin.h"
|
||||||
|
#include "shared/runtime/mpirq.h"
|
||||||
|
|
||||||
|
extern const mp_obj_dict_t machine_pin_cpu_pins_locals_dict;
|
||||||
|
extern const mp_obj_dict_t machine_pin_board_pins_locals_dict;
|
||||||
|
|
||||||
|
static const machine_pin_obj_t *machine_pin_find_named(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 != NULL) {
|
||||||
|
return MP_OBJ_TO_PTR(named_elem->value);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const machine_pin_obj_t *machine_pin_find(mp_obj_t pin) {
|
||||||
|
// Is already a object of the proper type
|
||||||
|
if (mp_obj_is_type(pin, &machine_pin_type)) {
|
||||||
|
return MP_OBJ_TO_PTR(pin);
|
||||||
|
}
|
||||||
|
if (mp_obj_is_str(pin)) {
|
||||||
|
// Try to find the pin in the board pins first.
|
||||||
|
const machine_pin_obj_t *self = machine_pin_find_named(&machine_pin_board_pins_locals_dict, pin);
|
||||||
|
if (self != NULL) {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not found, try to find the pin in the cpu pins.
|
||||||
|
self = machine_pin_find_named(&machine_pin_cpu_pins_locals_dict, pin);
|
||||||
|
if (self != NULL) {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pin name not found.
|
||||||
|
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unknown named pin \"%s\""), mp_obj_str_get_str(pin));
|
||||||
|
}
|
||||||
|
mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = self_in;
|
||||||
|
|
||||||
|
uint8_t alt_func, pad_ctrl;
|
||||||
|
pinconf_get(self->port, self->pin, &alt_func, &pad_ctrl);
|
||||||
|
|
||||||
|
qstr mode_qst;
|
||||||
|
if (gpio_get_direction(self->gpio, self->pin) == GPIO_PIN_DIR_INPUT) {
|
||||||
|
mode_qst = MP_QSTR_IN;
|
||||||
|
} else {
|
||||||
|
if (pad_ctrl & PADCTRL_DRIVER_OPEN_DRAIN) {
|
||||||
|
mode_qst = MP_QSTR_OPEN_DRAIN;
|
||||||
|
} else {
|
||||||
|
mode_qst = MP_QSTR_OUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mp_printf(print, "Pin(%q, mode=%q", self->name, mode_qst);
|
||||||
|
uint8_t pad_ctrl_pull = pad_ctrl & (PADCTRL_DRIVER_DISABLED_PULL_DOWN | PADCTRL_DRIVER_DISABLED_PULL_UP);
|
||||||
|
if (pad_ctrl_pull == PADCTRL_DRIVER_DISABLED_PULL_UP) {
|
||||||
|
mp_printf(print, ", pull=%q", MP_QSTR_PULL_UP);
|
||||||
|
} else if (pad_ctrl_pull == PADCTRL_DRIVER_DISABLED_PULL_DOWN) {
|
||||||
|
mp_printf(print, ", pull=%q", MP_QSTR_PULL_DOWN);
|
||||||
|
}
|
||||||
|
if (alt_func != PINMUX_ALTERNATE_FUNCTION_0) {
|
||||||
|
mp_printf(print, ", alt=%u", alt_func);
|
||||||
|
}
|
||||||
|
mp_printf(print, ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ARG_mode, ARG_pull, ARG_value, 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_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}},
|
||||||
|
};
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
// parse args
|
||||||
|
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);
|
||||||
|
|
||||||
|
// get initial value of pin (only valid for OUT and OPEN_DRAIN modes)
|
||||||
|
int value = -1;
|
||||||
|
if (args[ARG_value].u_obj != mp_const_none) {
|
||||||
|
value = mp_obj_is_true(args[ARG_value].u_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure mode
|
||||||
|
if (args[ARG_mode].u_obj != mp_const_none) {
|
||||||
|
mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj);
|
||||||
|
if (mode == MP_HAL_PIN_MODE_INPUT) {
|
||||||
|
mp_hal_pin_input(self);
|
||||||
|
} else if (mode == MP_HAL_PIN_MODE_OUTPUT) {
|
||||||
|
if (value != -1) {
|
||||||
|
// set initial output value before configuring mode
|
||||||
|
mp_hal_pin_write(self, value);
|
||||||
|
}
|
||||||
|
mp_hal_pin_output(self);
|
||||||
|
} else if (mode == MP_HAL_PIN_MODE_OPEN_DRAIN) {
|
||||||
|
if (value != -1) {
|
||||||
|
// set initial output value before configuring mode
|
||||||
|
mp_hal_pin_write(self, value);
|
||||||
|
}
|
||||||
|
mp_hal_pin_open_drain(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure pull (unconditionally because None means no-pull).
|
||||||
|
uint32_t pull = 0;
|
||||||
|
if (args[ARG_pull].u_obj != mp_const_none) {
|
||||||
|
pull = mp_obj_get_int(args[ARG_pull].u_obj);
|
||||||
|
}
|
||||||
|
uint8_t alt_func;
|
||||||
|
uint8_t pad_ctrl;
|
||||||
|
pinconf_get(self->port, self->pin, &alt_func, &pad_ctrl);
|
||||||
|
alt_func = PINMUX_ALTERNATE_FUNCTION_0;
|
||||||
|
pad_ctrl |= PADCTRL_READ_ENABLE;
|
||||||
|
pad_ctrl &= ~(PADCTRL_DRIVER_DISABLED_PULL_DOWN | PADCTRL_DRIVER_DISABLED_PULL_UP);
|
||||||
|
if (pull & MP_HAL_PIN_PULL_UP) {
|
||||||
|
pad_ctrl |= PADCTRL_DRIVER_DISABLED_PULL_UP;
|
||||||
|
}
|
||||||
|
if (pull & MP_HAL_PIN_PULL_DOWN) {
|
||||||
|
pad_ctrl |= PADCTRL_DRIVER_DISABLED_PULL_DOWN;
|
||||||
|
}
|
||||||
|
pinconf_set(self->port, self->pin, alt_func, pad_ctrl);
|
||||||
|
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor(id, ...)
|
||||||
|
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);
|
||||||
|
|
||||||
|
const machine_pin_obj_t *self = machine_pin_find(args[0]);
|
||||||
|
|
||||||
|
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(self, n_args - 1, args + 1, &kw_args);
|
||||||
|
}
|
||||||
|
return MP_OBJ_FROM_PTR(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fast method for getting/setting pin value
|
||||||
|
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 = self_in;
|
||||||
|
if (n_args == 0) {
|
||||||
|
// get pin
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self));
|
||||||
|
} else {
|
||||||
|
// set pin
|
||||||
|
bool value = mp_obj_is_true(args[0]);
|
||||||
|
mp_hal_pin_write(self, value);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pin.init(mode, pull)
|
||||||
|
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);
|
||||||
|
|
||||||
|
// pin.value([value])
|
||||||
|
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);
|
||||||
|
|
||||||
|
// pin.low()
|
||||||
|
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);
|
||||||
|
|
||||||
|
// pin.high()
|
||||||
|
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);
|
||||||
|
|
||||||
|
// pin.toggle()
|
||||||
|
static mp_obj_t machine_pin_toggle(mp_obj_t self_in) {
|
||||||
|
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||||
|
gpio_toggle_value(self->gpio, self->pin);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle);
|
||||||
|
|
||||||
|
static MP_DEFINE_CONST_OBJ_TYPE(
|
||||||
|
pin_cpu_pins_obj_type,
|
||||||
|
MP_QSTR_cpu,
|
||||||
|
MP_TYPE_FLAG_NONE,
|
||||||
|
locals_dict, &machine_pin_cpu_pins_locals_dict
|
||||||
|
);
|
||||||
|
|
||||||
|
static MP_DEFINE_CONST_OBJ_TYPE(
|
||||||
|
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_low), MP_ROM_PTR(&machine_pin_low_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&machine_pin_high_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_off), 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_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) },
|
||||||
|
|
||||||
|
// class attributes
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&pin_board_pins_obj_type) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&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_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) },
|
||||||
|
};
|
||||||
|
static MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
|
||||||
|
|
||||||
|
static mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||||
|
(void)errcode;
|
||||||
|
machine_pin_obj_t *self = self_in;
|
||||||
|
|
||||||
|
switch (request) {
|
||||||
|
case MP_PIN_READ: {
|
||||||
|
return mp_hal_pin_read(self);
|
||||||
|
}
|
||||||
|
case MP_PIN_WRITE: {
|
||||||
|
mp_hal_pin_write(self, arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const mp_pin_p_t pin_pin_p = {
|
||||||
|
.ioctl = pin_ioctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
MP_DEFINE_CONST_OBJ_TYPE(
|
||||||
|
machine_pin_type,
|
||||||
|
MP_QSTR_Pin,
|
||||||
|
MP_TYPE_FLAG_NONE,
|
||||||
|
make_new, mp_pin_make_new,
|
||||||
|
print, machine_pin_print,
|
||||||
|
call, machine_pin_call,
|
||||||
|
protocol, &pin_pin_p,
|
||||||
|
locals_dict, &machine_pin_locals_dict
|
||||||
|
);
|
||||||
|
|
||||||
|
mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) {
|
||||||
|
return machine_pin_find(obj);
|
||||||
|
}
|
||||||
145
ports/alif/main.c
Normal file
145
ports/alif/main.c
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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/compile.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/gc.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "py/stackctrl.h"
|
||||||
|
#include "shared/readline/readline.h"
|
||||||
|
#include "shared/runtime/gchelper.h"
|
||||||
|
#include "shared/runtime/pyexec.h"
|
||||||
|
#include "shared/tinyusb/mp_usbd.h"
|
||||||
|
#include "tusb.h"
|
||||||
|
#include "mpuart.h"
|
||||||
|
#include "ospi_flash.h"
|
||||||
|
#include "pendsv.h"
|
||||||
|
|
||||||
|
extern uint8_t __StackTop, __StackLimit;
|
||||||
|
extern uint8_t __GcHeapStart, __GcHeapEnd;
|
||||||
|
|
||||||
|
NORETURN void panic(const char *msg) {
|
||||||
|
mp_hal_stdout_tx_strn("\nFATAL ERROR:\n", 14);
|
||||||
|
mp_hal_stdout_tx_strn(msg, strlen(msg));
|
||||||
|
for (;;) {
|
||||||
|
*(volatile uint32_t *)0x4900C000 ^= 9;
|
||||||
|
for (volatile uint delay = 0; delay < 10000000; delay++) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _start(void) {
|
||||||
|
SysTick_Config(SystemCoreClock / 1000);
|
||||||
|
|
||||||
|
MICROPY_BOARD_STARTUP();
|
||||||
|
|
||||||
|
pendsv_init();
|
||||||
|
|
||||||
|
MICROPY_BOARD_EARLY_INIT();
|
||||||
|
|
||||||
|
#if MICROPY_HW_ENABLE_UART_REPL
|
||||||
|
mp_uart_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ospi_flash_init() != 0) {
|
||||||
|
MICROPY_BOARD_FATAL_ERROR("ospi_init failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MICROPY_HW_ENABLE_USBDEV
|
||||||
|
NVIC_ClearPendingIRQ(USB_IRQ_IRQn);
|
||||||
|
NVIC_SetPriority(USB_IRQ_IRQn, IRQ_PRI_USB);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialise stack extents and GC heap.
|
||||||
|
mp_stack_set_top(&__StackTop);
|
||||||
|
mp_stack_set_limit(&__StackTop - &__StackLimit - 1024);
|
||||||
|
gc_init(&__GcHeapStart, &__GcHeapEnd);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// Initialise MicroPython runtime.
|
||||||
|
mp_init();
|
||||||
|
|
||||||
|
// Initialise sub-systems.
|
||||||
|
readline_init0();
|
||||||
|
|
||||||
|
// Execute _boot.py to set up the filesystem.
|
||||||
|
pyexec_frozen_module("_boot.py", false);
|
||||||
|
|
||||||
|
// Execute user scripts.
|
||||||
|
int ret = pyexec_file_if_exists("boot.py");
|
||||||
|
#if MICROPY_HW_ENABLE_USBDEV
|
||||||
|
mp_usbd_init();
|
||||||
|
#endif
|
||||||
|
if (ret & PYEXEC_FORCED_EXIT) {
|
||||||
|
goto soft_reset_exit;
|
||||||
|
}
|
||||||
|
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL && ret != 0) {
|
||||||
|
ret = pyexec_file_if_exists("main.py");
|
||||||
|
if (ret & PYEXEC_FORCED_EXIT) {
|
||||||
|
goto soft_reset_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
|
||||||
|
if (pyexec_raw_repl() != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pyexec_friendly_repl() != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
soft_reset_exit:
|
||||||
|
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
|
||||||
|
gc_sweep_all();
|
||||||
|
mp_deinit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gc_collect(void) {
|
||||||
|
gc_collect_start();
|
||||||
|
gc_helper_collect_regs_and_stack();
|
||||||
|
gc_collect_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nlr_jump_fail(void *val) {
|
||||||
|
mp_printf(&mp_plat_print, "FATAL: uncaught exception %p\n", val);
|
||||||
|
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val));
|
||||||
|
for (;;) {
|
||||||
|
__WFE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
|
||||||
|
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
|
||||||
|
panic("Assertion failed");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
14
ports/alif/mcu/M55_HP_cfg.json
Normal file
14
ports/alif/mcu/M55_HP_cfg.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"USER_APP": {
|
||||||
|
"binary": "firmware.bin",
|
||||||
|
"mramAddress": "0x80000000",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"cpu_id": "M55_HP",
|
||||||
|
"flags": ["boot"],
|
||||||
|
"signed": false
|
||||||
|
},
|
||||||
|
"DEVICE": {
|
||||||
|
"binary": "app-device-config.json",
|
||||||
|
"version" : "0.5.00"
|
||||||
|
}
|
||||||
|
}
|
||||||
165
ports/alif/mcu/ensemble.ld.S
Normal file
165
ports/alif/mcu/ensemble.ld.S
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Entry Point
|
||||||
|
ENTRY(Reset_Handler)
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
ROM (rx) : ORIGIN = 0x80000000, LENGTH = 0x0057F000
|
||||||
|
ITCM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
|
||||||
|
#ifdef CORE_M55_HP
|
||||||
|
DTCM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00100000
|
||||||
|
#else
|
||||||
|
DTCM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
|
||||||
|
#endif
|
||||||
|
SRAM0 (rwx) : ORIGIN = 0x02000000, LENGTH = 0x00400000
|
||||||
|
SRAM1 (rwx) : ORIGIN = 0x08000000, LENGTH = 0x00280000
|
||||||
|
}
|
||||||
|
|
||||||
|
__STACK_SIZE = 0x00004000;
|
||||||
|
__HEAP_SIZE = 0x00004000;
|
||||||
|
__MP_HEAP_SIZE = 0x00040000;
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.text : ALIGN(16)
|
||||||
|
{
|
||||||
|
KEEP(*(.vectors))
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.text*)
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.rodata*)
|
||||||
|
. = ALIGN(16);
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
.copy.table : ALIGN(4)
|
||||||
|
{
|
||||||
|
__copy_table_start__ = .;
|
||||||
|
LONG ( LOADADDR(.data) )
|
||||||
|
LONG ( ADDR(.data) )
|
||||||
|
LONG ( SIZEOF(.data)/4 )
|
||||||
|
__copy_table_end__ = .;
|
||||||
|
. = ALIGN(16);
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
.zero.table : ALIGN(4)
|
||||||
|
{
|
||||||
|
__zero_table_start__ = .;
|
||||||
|
LONG (ADDR(.bss))
|
||||||
|
LONG (SIZEOF(.bss)/4)
|
||||||
|
LONG (ADDR(.bss.sram0))
|
||||||
|
LONG (SIZEOF(.bss.sram0)/4)
|
||||||
|
__zero_table_end__ = .;
|
||||||
|
. = ALIGN(16);
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
.data : ALIGN(8)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
. = ALIGN(8);
|
||||||
|
*(.data.*)
|
||||||
|
. = ALIGN(16);
|
||||||
|
} > DTCM AT > ROM
|
||||||
|
|
||||||
|
/* Peripherals in expansion master 0 (USB, Ethernet, SD/MMC)
|
||||||
|
are by default configured as non-secure, so they don't
|
||||||
|
have access to DTCMs. This can be fixed in the ToC by allowing
|
||||||
|
access to DTCMs to all bus masters, for now these peripherals
|
||||||
|
should place buffers in regular SRAM */
|
||||||
|
.bss.sram0 (NOLOAD) : ALIGN(4)
|
||||||
|
{
|
||||||
|
* (.bss.sram0*)
|
||||||
|
} > SRAM0
|
||||||
|
|
||||||
|
.bss : ALIGN(4)
|
||||||
|
{
|
||||||
|
__bss_start__ = .;
|
||||||
|
*(.bss)
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.bss.*)
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(4);
|
||||||
|
__bss_end__ = .;
|
||||||
|
} > DTCM
|
||||||
|
|
||||||
|
.heap (NOLOAD) : ALIGN(4)
|
||||||
|
{
|
||||||
|
__end__ = .;
|
||||||
|
PROVIDE(end = .);
|
||||||
|
. = . + __HEAP_SIZE;
|
||||||
|
. = ALIGN(4);
|
||||||
|
__HeapLimit = .;
|
||||||
|
|
||||||
|
/* MicroPython GC heap */
|
||||||
|
. = ALIGN(16);
|
||||||
|
__GcHeapStart = .;
|
||||||
|
. = . + __MP_HEAP_SIZE;
|
||||||
|
__GcHeapEnd = .;
|
||||||
|
} > DTCM
|
||||||
|
|
||||||
|
.stack (NOLOAD) : ALIGN(4)
|
||||||
|
{
|
||||||
|
__StackLimit = .;
|
||||||
|
. = . + __STACK_SIZE;
|
||||||
|
. = ALIGN(4);
|
||||||
|
__StackTop = .;
|
||||||
|
} > DTCM
|
||||||
|
PROVIDE(__stack = __StackTop);
|
||||||
|
|
||||||
|
.init_fini_arrays : ALIGN(16)
|
||||||
|
{
|
||||||
|
KEEP(*(.init))
|
||||||
|
KEEP(*(.fini))
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
/* preinit data */
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP(*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
/* init data */
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP(*(SORT(.init_array.*)))
|
||||||
|
KEEP(*(.init_array))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
/* finit data */
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP(*(SORT(.fini_array.*)))
|
||||||
|
KEEP(*(.fini_array))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
|
||||||
|
KEEP(*(.eh_frame*))
|
||||||
|
. = ALIGN(16);
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
/* Check if data + heap + stack exceeds RAM limit */
|
||||||
|
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||||
|
}
|
||||||
64
ports/alif/mcu/make-pins.py
Executable file
64
ports/alif/mcu/make-pins.py
Executable file
@@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../../tools"))
|
||||||
|
import boardgen
|
||||||
|
|
||||||
|
NUM_PORTS = 16
|
||||||
|
NUM_PINS_PER_PORT = 8
|
||||||
|
|
||||||
|
|
||||||
|
class AlifPin(boardgen.Pin):
|
||||||
|
# Emit the struct which contains the pin instance.
|
||||||
|
def definition(self):
|
||||||
|
port, pin = self.name()[1:].split("_")
|
||||||
|
base = "LPGPIO_BASE" if port == "15" else "GPIO{}_BASE".format(port)
|
||||||
|
return (
|
||||||
|
"{{ "
|
||||||
|
".base = {{ .type = &machine_pin_type }}, "
|
||||||
|
".gpio = (GPIO_Type *){base}, "
|
||||||
|
".port = PORT_{port}, "
|
||||||
|
".pin = PIN_{pin}, "
|
||||||
|
".name = MP_QSTR_P{port}_{pin} "
|
||||||
|
"}}".format(port=port, pin=pin, base=base)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Alif cpu names must be "Pn_m".
|
||||||
|
@staticmethod
|
||||||
|
def validate_cpu_pin_name(cpu_pin_name):
|
||||||
|
boardgen.Pin.validate_cpu_pin_name(cpu_pin_name)
|
||||||
|
|
||||||
|
if not (m := re.match("P([0-9]){1,2}_([0-9])", cpu_pin_name)):
|
||||||
|
raise boardgen.PinGeneratorError(
|
||||||
|
"Invalid cpu pin name '{}', must be 'Pn_m'".format(cpu_pin_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
port = int(m.group(1))
|
||||||
|
pin = int(m.group(2))
|
||||||
|
if not (0 <= port < NUM_PORTS and 0 <= pin < NUM_PINS_PER_PORT):
|
||||||
|
raise boardgen.PinGeneratorError("Unknown cpu pin '{}'".format(cpu_pin_name))
|
||||||
|
|
||||||
|
|
||||||
|
class AlifPinGenerator(boardgen.PinGenerator):
|
||||||
|
def __init__(self):
|
||||||
|
# Use custom pin type above.
|
||||||
|
super().__init__(pin_type=AlifPin)
|
||||||
|
|
||||||
|
# Pre-define the pins (i.e. don't require them to be listed in pins.csv).
|
||||||
|
for i in range(NUM_PORTS):
|
||||||
|
for j in range(NUM_PINS_PER_PORT):
|
||||||
|
self.add_cpu_pin("P{}_{}".format(i, j))
|
||||||
|
|
||||||
|
# Only use pre-defined cpu pins (do not let board.csv create them).
|
||||||
|
def find_pin_by_cpu_pin_name(self, cpu_pin_name, create=True):
|
||||||
|
return super().find_pin_by_cpu_pin_name(cpu_pin_name, create=False)
|
||||||
|
|
||||||
|
def cpu_table_size(self):
|
||||||
|
return "{} * {}".format(NUM_PORTS, NUM_PINS_PER_PORT)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
AlifPinGenerator().main()
|
||||||
2
ports/alif/mcu/pins_prefix.c
Normal file
2
ports/alif/mcu/pins_prefix.c
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#include "py/mphal.h"
|
||||||
|
#include "extmod/modmachine.h"
|
||||||
46
ports/alif/modalif.c
Normal file
46
ports/alif/modalif.c
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "modalif.h"
|
||||||
|
|
||||||
|
static const mp_rom_map_elem_t alif_module_globals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alif) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&alif_flash_type) },
|
||||||
|
#if MICROPY_HW_USB_MSC
|
||||||
|
// Attribute to indicate USB MSC is enabled.
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_usb_msc), MP_ROM_TRUE },
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
static MP_DEFINE_CONST_DICT(alif_module_globals, alif_module_globals_table);
|
||||||
|
|
||||||
|
const mp_obj_module_t mp_module_alif = {
|
||||||
|
.base = { &mp_type_module },
|
||||||
|
.globals = (mp_obj_dict_t *)&alif_module_globals,
|
||||||
|
};
|
||||||
|
|
||||||
|
MP_REGISTER_MODULE(MP_QSTR_alif, mp_module_alif);
|
||||||
33
ports/alif/modalif.h
Normal file
33
ports/alif/modalif.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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_ALIF_MODALIF_H
|
||||||
|
#define MICROPY_INCLUDED_ALIF_MODALIF_H
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
extern const mp_obj_type_t alif_flash_type;
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_ALIF_MODALIF_H
|
||||||
79
ports/alif/modmachine.c
Normal file
79
ports/alif/modmachine.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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) }, \
|
||||||
|
|
||||||
|
static void mp_machine_idle(void) {
|
||||||
|
mp_event_wait_indefinite();
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t mp_machine_unique_id(void) {
|
||||||
|
return mp_obj_new_bytes((const uint8_t *)"ABCD", 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN static void mp_machine_reset(void) {
|
||||||
|
NVIC_SystemReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args) {
|
||||||
|
__disable_irq();
|
||||||
|
|
||||||
|
MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_int_t mp_machine_reset_cause(void) {
|
||||||
|
// TODO
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t mp_machine_get_freq(void) {
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(SystemCoreClock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) {
|
||||||
|
mp_raise_NotImplementedError(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
|
||||||
|
mp_int_t delay = -1;
|
||||||
|
if (n_args == 1) {
|
||||||
|
delay = mp_obj_get_int(args[0]);
|
||||||
|
}
|
||||||
|
mp_hal_delay_ms(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args) {
|
||||||
|
mp_machine_lightsleep(n_args, args);
|
||||||
|
mp_machine_reset();
|
||||||
|
}
|
||||||
23
ports/alif/modules/_boot.py
Normal file
23
ports/alif/modules/_boot.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import sys, os, alif
|
||||||
|
|
||||||
|
|
||||||
|
bdev = alif.Flash()
|
||||||
|
if hasattr(alif, "usb_msc"):
|
||||||
|
try:
|
||||||
|
# This may fail on VfsFat construction, or mount.
|
||||||
|
os.mount(os.VfsFat(bdev), "/flash")
|
||||||
|
except:
|
||||||
|
os.VfsFat.mkfs(bdev)
|
||||||
|
os.mount(os.VfsFat(bdev), "/flash")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
os.mount(os.VfsLfs2(bdev, progsize=256), "/flash")
|
||||||
|
except:
|
||||||
|
os.VfsLfs2.mkfs(bdev, progsize=256)
|
||||||
|
os.mount(os.VfsLfs2(bdev, progsize=256), "/flash")
|
||||||
|
|
||||||
|
sys.path.append("/flash")
|
||||||
|
sys.path.append("/flash/lib")
|
||||||
|
os.chdir("/flash")
|
||||||
|
|
||||||
|
del sys, os, alif, bdev
|
||||||
155
ports/alif/mpconfigport.h
Normal file
155
ports/alif/mpconfigport.h
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Options controlling how MicroPython is built, overriding defaults in py/mpconfig.h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <alloca.h> // for alloca()
|
||||||
|
|
||||||
|
// board specific definitions
|
||||||
|
#include "mpconfigboard.h"
|
||||||
|
|
||||||
|
#ifndef MICROPY_CONFIG_ROM_LEVEL
|
||||||
|
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_FULL_FEATURES)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MICROPY_HW_ENABLE_UART_REPL (1) // useful if there is no USB
|
||||||
|
#define MICROPY_HW_ENABLE_USBDEV (1)
|
||||||
|
|
||||||
|
#ifndef MICROPY_HW_USB_PRODUCT_FS_STRING
|
||||||
|
#define MICROPY_HW_USB_PRODUCT_FS_STRING "Board in HS mode"
|
||||||
|
#endif
|
||||||
|
#define MICROPY_HW_USB_CDC (1)
|
||||||
|
#define MICROPY_HW_USB_CDC_TX_TIMEOUT (500)
|
||||||
|
#ifndef MICROPY_HW_USB_MSC
|
||||||
|
#define MICROPY_HW_USB_MSC (0)
|
||||||
|
#endif
|
||||||
|
#ifndef MICROPY_HW_USB_VID
|
||||||
|
#define MICROPY_HW_USB_VID (0xf055)
|
||||||
|
#endif
|
||||||
|
#ifndef MICROPY_HW_USB_PID
|
||||||
|
#define MICROPY_HW_USB_PID (0x9802) // interface has CDC only
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MICROPY_HW_FLASH_BLOCK_SIZE_BYTES (4096)
|
||||||
|
|
||||||
|
// Memory allocation policies
|
||||||
|
#ifndef MICROPY_ALLOC_GC_STACK_SIZE
|
||||||
|
#define MICROPY_ALLOC_GC_STACK_SIZE (128)
|
||||||
|
#endif
|
||||||
|
#define MICROPY_ALLOC_PATH_MAX (128)
|
||||||
|
#define MICROPY_QSTR_BYTES_IN_HASH (1)
|
||||||
|
|
||||||
|
// MicroPython emitters
|
||||||
|
#define MICROPY_PERSISTENT_CODE_LOAD (1)
|
||||||
|
#define MICROPY_EMIT_THUMB (1)
|
||||||
|
#define MICROPY_EMIT_THUMB_ARMV7M (1)
|
||||||
|
#define MICROPY_EMIT_INLINE_THUMB (1)
|
||||||
|
#define MICROPY_EMIT_INLINE_THUMB_FLOAT (1)
|
||||||
|
|
||||||
|
// Optimisations
|
||||||
|
#define MICROPY_OPT_COMPUTED_GOTO (1)
|
||||||
|
|
||||||
|
// Python internal features
|
||||||
|
#define MICROPY_READER_VFS (1)
|
||||||
|
#define MICROPY_ENABLE_GC (1)
|
||||||
|
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
|
||||||
|
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
|
||||||
|
#define MICROPY_SCHEDULER_DEPTH (8)
|
||||||
|
#define MICROPY_SCHEDULER_STATIC_NODES (1)
|
||||||
|
#define MICROPY_USE_INTERNAL_ERRNO (1)
|
||||||
|
|
||||||
|
// Fine control over Python builtins, classes, modules, etc
|
||||||
|
#define MICROPY_PY_SYS_PLATFORM "alif"
|
||||||
|
|
||||||
|
// Extended modules
|
||||||
|
#define MICROPY_EPOCH_IS_1970 (1)
|
||||||
|
#define MICROPY_PY_OS_DUPTERM (1)
|
||||||
|
#define MICROPY_PY_OS_SEP (1)
|
||||||
|
#define MICROPY_PY_OS_SYNC (1)
|
||||||
|
#define MICROPY_PY_OS_UNAME (1)
|
||||||
|
#define MICROPY_PY_TIME (1)
|
||||||
|
#define MICROPY_PY_MACHINE (1)
|
||||||
|
#define MICROPY_PY_MACHINE_INCLUDEFILE "ports/alif/modmachine.c"
|
||||||
|
#define MICROPY_PY_MACHINE_RESET (1)
|
||||||
|
#define MICROPY_PY_MACHINE_BOOTLOADER (1)
|
||||||
|
#define MICROPY_PY_MACHINE_BARE_METAL_FUNCS (1)
|
||||||
|
#define MICROPY_PY_MACHINE_DISABLE_IRQ_ENABLE_IRQ (1)
|
||||||
|
#define MICROPY_PY_MACHINE_DHT_READINTO (1)
|
||||||
|
#define MICROPY_PY_MACHINE_PULSE (1)
|
||||||
|
#define MICROPY_PY_MACHINE_SOFTI2C (1)
|
||||||
|
#define MICROPY_PY_MACHINE_SOFTSPI (1)
|
||||||
|
#define MICROPY_PY_MACHINE_TIMER (1)
|
||||||
|
#define MICROPY_VFS (1)
|
||||||
|
|
||||||
|
// fatfs configuration
|
||||||
|
#define MICROPY_FATFS_ENABLE_LFN (1)
|
||||||
|
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
|
||||||
|
#define MICROPY_FATFS_RPATH (2)
|
||||||
|
#if MICROPY_HW_USB_MSC
|
||||||
|
#define MICROPY_FATFS_USE_LABEL (1)
|
||||||
|
#define MICROPY_FATFS_MULTI_PARTITION (1)
|
||||||
|
// Set FatFS block size to flash sector size to avoid caching
|
||||||
|
// the flash sector in memory to support smaller block sizes.
|
||||||
|
#define MICROPY_FATFS_MAX_SS (MICROPY_HW_FLASH_BLOCK_SIZE_BYTES)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MP_STATE_PORT MP_STATE_VM
|
||||||
|
|
||||||
|
// Miscellaneous settings
|
||||||
|
|
||||||
|
// We need an implementation of the log2 function which is not a macro
|
||||||
|
#define MP_NEED_LOG2 (1)
|
||||||
|
|
||||||
|
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))
|
||||||
|
|
||||||
|
#define MP_SSIZE_MAX (0x7fffffff)
|
||||||
|
|
||||||
|
// Assume that if we already defined the obj repr then we also defined these items
|
||||||
|
#ifndef MICROPY_OBJ_REPR
|
||||||
|
typedef intptr_t mp_int_t; // must be pointer size
|
||||||
|
typedef uintptr_t mp_uint_t; // must be pointer size
|
||||||
|
typedef intptr_t mp_off_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Board configuration settings.
|
||||||
|
|
||||||
|
#ifndef MICROPY_BOARD_STARTUP
|
||||||
|
#define MICROPY_BOARD_STARTUP()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MICROPY_BOARD_EARLY_INIT
|
||||||
|
#define MICROPY_BOARD_EARLY_INIT()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MICROPY_BOARD_FATAL_ERROR
|
||||||
|
extern void panic(const char *);
|
||||||
|
#define MICROPY_BOARD_FATAL_ERROR panic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MICROPY_BOARD_ENTER_BOOTLOADER
|
||||||
|
#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args)
|
||||||
|
#endif
|
||||||
12
ports/alif/mpconfigport.mk
Normal file
12
ports/alif/mpconfigport.mk
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Enable/disable extra modules and features
|
||||||
|
|
||||||
|
# MicroPython feature configurations
|
||||||
|
MICROPY_ROM_TEXT_COMPRESSION ?= 1
|
||||||
|
MICROPY_FLOAT_IMPL ?= double
|
||||||
|
|
||||||
|
# VFS support.
|
||||||
|
MICROPY_VFS_FAT ?= 1
|
||||||
|
MICROPY_VFS_LFS2 ?= 1
|
||||||
|
|
||||||
|
# File containing description of content to be frozen into firmware.
|
||||||
|
FROZEN_MANIFEST ?= boards/manifest.py
|
||||||
152
ports/alif/mphalport.c
Normal file
152
ports/alif/mphalport.c
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Damien P. George
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "py/ringbuf.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/stream.h"
|
||||||
|
#include "extmod/misc.h"
|
||||||
|
#include "shared/runtime/interrupt_char.h"
|
||||||
|
#include "shared/timeutils/timeutils.h"
|
||||||
|
#include "shared/tinyusb/mp_usbd.h"
|
||||||
|
#include "shared/tinyusb/mp_usbd_cdc.h"
|
||||||
|
#include "tusb.h"
|
||||||
|
#include "mpuart.h"
|
||||||
|
|
||||||
|
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
|
||||||
|
#define MICROPY_HW_STDIN_BUFFER_LEN 512
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uint8_t stdin_ringbuf_array[MICROPY_HW_STDIN_BUFFER_LEN];
|
||||||
|
ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array) };
|
||||||
|
|
||||||
|
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
|
||||||
|
uintptr_t ret = 0;
|
||||||
|
#if MICROPY_HW_USB_CDC
|
||||||
|
ret |= mp_usbd_cdc_poll_interfaces(poll_flags);
|
||||||
|
#endif
|
||||||
|
#if MICROPY_HW_ENABLE_UART_REPL
|
||||||
|
if (poll_flags & MP_STREAM_POLL_WR) {
|
||||||
|
ret |= MP_STREAM_POLL_WR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if MICROPY_PY_OS_DUPTERM
|
||||||
|
ret |= mp_os_dupterm_poll(poll_flags);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive single character
|
||||||
|
int mp_hal_stdin_rx_chr(void) {
|
||||||
|
for (;;) {
|
||||||
|
#if MICROPY_HW_USB_CDC
|
||||||
|
mp_usbd_cdc_poll_interfaces(0);
|
||||||
|
#endif
|
||||||
|
int c = ringbuf_get(&stdin_ringbuf);
|
||||||
|
if (c != -1) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
#if MICROPY_PY_OS_DUPTERM
|
||||||
|
int dupterm_c = mp_os_dupterm_rx_chr();
|
||||||
|
if (dupterm_c >= 0) {
|
||||||
|
return dupterm_c;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
mp_event_wait_indefinite();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send string of given length
|
||||||
|
mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) {
|
||||||
|
mp_uint_t ret = len;
|
||||||
|
bool did_write = false;
|
||||||
|
|
||||||
|
#if MICROPY_HW_ENABLE_UART_REPL
|
||||||
|
mp_uart_write_strn(str, len);
|
||||||
|
did_write = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MICROPY_HW_USB_CDC
|
||||||
|
mp_uint_t cdc_res = mp_usbd_cdc_tx_strn(str, len);
|
||||||
|
if (cdc_res > 0) {
|
||||||
|
did_write = true;
|
||||||
|
ret = MIN(cdc_res, ret);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MICROPY_PY_OS_DUPTERM
|
||||||
|
int dupterm_res = mp_os_dupterm_tx_strn(str, len);
|
||||||
|
if (dupterm_res >= 0) {
|
||||||
|
did_write = true;
|
||||||
|
ret = MIN((mp_uint_t)dupterm_res, ret);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return did_write ? ret : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t volatile ticks_ms;
|
||||||
|
|
||||||
|
void SysTick_Handler(void) {
|
||||||
|
++ticks_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_hal_ticks_cpu(void) {
|
||||||
|
if (!(DWT->CTRL & DWT_CTRL_CYCCNTENA_Msk)) {
|
||||||
|
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||||
|
#if defined(__CORTEX_M) && __CORTEX_M == 7
|
||||||
|
// on Cortex-M7 we must unlock the DWT before writing to its registers
|
||||||
|
DWT->LAR = 0xc5acce55;
|
||||||
|
#endif
|
||||||
|
DWT->CYCCNT = 0;
|
||||||
|
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||||
|
}
|
||||||
|
return DWT->CYCCNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_hal_ticks_us(void) {
|
||||||
|
return ticks_ms / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_hal_ticks_ms(void) {
|
||||||
|
return ticks_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mp_hal_delay_us(mp_uint_t us) {
|
||||||
|
mp_hal_delay_ms(us / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mp_hal_delay_ms(mp_uint_t ms) {
|
||||||
|
uint32_t t0 = mp_hal_ticks_ms();
|
||||||
|
while ((mp_hal_ticks_ms() - t0) < ms) {
|
||||||
|
__WFI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t mp_hal_time_ns(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
152
ports/alif/mphalport.h
Normal file
152
ports/alif/mphalport.h
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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/ringbuf.h"
|
||||||
|
#include "shared/runtime/interrupt_char.h"
|
||||||
|
#include "irq.h"
|
||||||
|
#include ALIF_CMSIS_H
|
||||||
|
|
||||||
|
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
|
||||||
|
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
|
||||||
|
|
||||||
|
// For regular code that wants to prevent "background tasks" from running.
|
||||||
|
// These background tasks (LWIP, Bluetooth) run in PENDSV context.
|
||||||
|
#define MICROPY_PY_PENDSV_ENTER uint32_t atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
|
||||||
|
#define MICROPY_PY_PENDSV_REENTER atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
|
||||||
|
#define MICROPY_PY_PENDSV_EXIT restore_irq_pri(atomic_state);
|
||||||
|
|
||||||
|
// Port level Wait-for-Event macro
|
||||||
|
//
|
||||||
|
// Do not use this macro directly, include py/runtime.h and
|
||||||
|
// call mp_event_wait_indefinite() or mp_event_wait_ms(timeout)
|
||||||
|
#define MICROPY_INTERNAL_WFE(TIMEOUT_MS) \
|
||||||
|
do { \
|
||||||
|
if ((TIMEOUT_MS) < 0) { \
|
||||||
|
__WFE(); \
|
||||||
|
} else { \
|
||||||
|
/* TODO */ \
|
||||||
|
__WFE(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
// TODO requires mods to py/emitglue.c for this to be picked up
|
||||||
|
#define MP_HAL_CLEAN_DCACHE(addr, size) \
|
||||||
|
(SCB_CleanDCache_by_Addr((uint32_t *)((uint32_t)addr & ~0x1f), \
|
||||||
|
((uint32_t)((uint8_t *)addr + size + 0x1f) & ~0x1f) - ((uint32_t)addr & ~0x1f)))
|
||||||
|
|
||||||
|
extern ringbuf_t stdin_ringbuf;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
#define mp_hal_quiet_timing_enter() 0
|
||||||
|
#define mp_hal_quiet_timing_exit(x) (void)x
|
||||||
|
#define mp_hal_delay_us_fast mp_hal_delay_us
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
// C-level pin HAL
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "pinconf.h"
|
||||||
|
|
||||||
|
#define MP_HAL_PIN_FMT "%q"
|
||||||
|
#define MP_HAL_PIN_MODE_INPUT (0)
|
||||||
|
#define MP_HAL_PIN_MODE_OUTPUT (1)
|
||||||
|
#define MP_HAL_PIN_MODE_OPEN_DRAIN (2)
|
||||||
|
#define MP_HAL_PIN_PULL_NONE (0)
|
||||||
|
#define MP_HAL_PIN_PULL_UP (1)
|
||||||
|
#define MP_HAL_PIN_PULL_DOWN (2)
|
||||||
|
|
||||||
|
#define mp_hal_pin_obj_t const machine_pin_obj_t *
|
||||||
|
|
||||||
|
typedef struct _machine_pin_obj_t {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
GPIO_Type *gpio;
|
||||||
|
uint8_t port;
|
||||||
|
uint8_t pin;
|
||||||
|
qstr name;
|
||||||
|
} machine_pin_obj_t;
|
||||||
|
|
||||||
|
mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t pin_in);
|
||||||
|
|
||||||
|
static inline qstr mp_hal_pin_name(mp_hal_pin_obj_t pin) {
|
||||||
|
return pin->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_hal_pin_input(mp_hal_pin_obj_t pin) {
|
||||||
|
uint8_t alt_func = PINMUX_ALTERNATE_FUNCTION_0;
|
||||||
|
uint8_t pad_ctrl = PADCTRL_READ_ENABLE;
|
||||||
|
pinconf_set(pin->port, pin->pin, alt_func, pad_ctrl);
|
||||||
|
gpio_set_direction_input(pin->gpio, pin->pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) {
|
||||||
|
uint8_t alt_func = PINMUX_ALTERNATE_FUNCTION_0;
|
||||||
|
uint8_t pad_ctrl = PADCTRL_READ_ENABLE;
|
||||||
|
pinconf_set(pin->port, pin->pin, alt_func, pad_ctrl);
|
||||||
|
gpio_set_direction_output(pin->gpio, pin->pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) {
|
||||||
|
uint8_t alt_func = PINMUX_ALTERNATE_FUNCTION_0;
|
||||||
|
uint8_t pad_ctrl = PADCTRL_DRIVER_OPEN_DRAIN | PADCTRL_READ_ENABLE;
|
||||||
|
pinconf_set(pin->port, pin->pin, alt_func, pad_ctrl);
|
||||||
|
gpio_set_direction_output(pin->gpio, pin->pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_hal_pin_low(mp_hal_pin_obj_t pin) {
|
||||||
|
gpio_set_value_low(pin->gpio, pin->pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_hal_pin_high(mp_hal_pin_obj_t pin) {
|
||||||
|
gpio_set_value_high(pin->gpio, pin->pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) {
|
||||||
|
return gpio_get_value(pin->gpio, pin->pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_hal_pin_write(mp_hal_pin_obj_t pin, int v) {
|
||||||
|
if (v) {
|
||||||
|
mp_hal_pin_high(pin);
|
||||||
|
} else {
|
||||||
|
mp_hal_pin_low(pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) {
|
||||||
|
mp_hal_pin_low(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_hal_pin_od_high(mp_hal_pin_obj_t pin) {
|
||||||
|
mp_hal_pin_high(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_hal_wake_main_task_from_isr(void) {
|
||||||
|
// Defined for tinyusb support, nothing needs to be done here.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include all the pin definitions.
|
||||||
|
#include "genhdr/pins_board.h"
|
||||||
113
ports/alif/mpuart.c
Normal file
113
ports/alif/mpuart.c
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "mpuart.h"
|
||||||
|
|
||||||
|
#if MICROPY_HW_ENABLE_UART_REPL
|
||||||
|
|
||||||
|
#include "pinconf.h"
|
||||||
|
#include "sys_ctrl_uart.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
#define TX_PORT PORT_12
|
||||||
|
#define TX_PIN PIN_2
|
||||||
|
#define RX_PORT PORT_12
|
||||||
|
#define RX_PIN PIN_1
|
||||||
|
#define UART_ID 4
|
||||||
|
#define UART_IRQN UART4_IRQ_IRQn
|
||||||
|
#define UART_PTR ((UART_Type *)UART4_BASE)
|
||||||
|
#define BAUDRATE 115200
|
||||||
|
#define SYST_PCLK 100000000
|
||||||
|
|
||||||
|
static UART_TRANSFER transfer;
|
||||||
|
|
||||||
|
void mp_uart_init(void) {
|
||||||
|
pinconf_set(TX_PORT, TX_PIN, PINMUX_ALTERNATE_FUNCTION_2, 0);
|
||||||
|
pinconf_set(RX_PORT, RX_PIN, PINMUX_ALTERNATE_FUNCTION_2, PADCTRL_READ_ENABLE);
|
||||||
|
select_uart_clock_syst_pclk(UART_ID);
|
||||||
|
enable_uart_clock(UART_ID);
|
||||||
|
uart_software_reset(UART_PTR);
|
||||||
|
uart_enable_fifo(UART_PTR);
|
||||||
|
uart_disable_tx_irq(UART_PTR);
|
||||||
|
uart_disable_rx_irq(UART_PTR);
|
||||||
|
uart_set_baudrate(UART_PTR, SYST_PCLK, BAUDRATE);
|
||||||
|
uart_set_data_parity_stop_bits(UART_PTR, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1);
|
||||||
|
uart_set_flow_control(UART_PTR, UART_FLOW_CONTROL_NONE);
|
||||||
|
NVIC_ClearPendingIRQ(UART_IRQN);
|
||||||
|
NVIC_SetPriority(UART_IRQN, IRQ_PRI_UART_REPL);
|
||||||
|
NVIC_EnableIRQ(UART_IRQN);
|
||||||
|
uart_set_tx_trigger(UART_PTR, UART_TX_FIFO_EMPTY);
|
||||||
|
uart_set_rx_trigger(UART_PTR, UART_RX_ONE_CHAR_IN_FIFO);
|
||||||
|
uart_enable_rx_irq(UART_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mp_uart_write_strn(const char *str, size_t len) {
|
||||||
|
memset(&transfer, 0, sizeof(transfer));
|
||||||
|
transfer.tx_buf = (uint8_t *)str;
|
||||||
|
transfer.tx_total_num = len;
|
||||||
|
transfer.tx_curr_cnt = 0U;
|
||||||
|
transfer.status = UART_TRANSFER_STATUS_NONE;
|
||||||
|
|
||||||
|
uart_enable_tx_irq(UART_PTR);
|
||||||
|
|
||||||
|
uint32_t start = mp_hal_ticks_ms();
|
||||||
|
while (transfer.status == UART_TRANSFER_STATUS_NONE) {
|
||||||
|
if (mp_hal_ticks_ms() - start > 10 * len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
__WFE();
|
||||||
|
}
|
||||||
|
uart_disable_tx_irq(UART_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UART4_IRQHandler(void) {
|
||||||
|
if (UART_PTR->UART_RFL) {
|
||||||
|
for (;;) {
|
||||||
|
uint32_t rx_fifo_available_cnt = UART_PTR->UART_RFL;
|
||||||
|
if (rx_fifo_available_cnt == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < rx_fifo_available_cnt; ++i) {
|
||||||
|
int c = UART_PTR->UART_RBR;
|
||||||
|
#if MICROPY_KBD_EXCEPTION
|
||||||
|
if (c == mp_interrupt_char) {
|
||||||
|
mp_sched_keyboard_interrupt();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ringbuf_put(&stdin_ringbuf, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uart_irq_handler(UART_PTR, &transfer);
|
||||||
|
}
|
||||||
|
__SEV();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
32
ports/alif/mpuart.h
Normal file
32
ports/alif/mpuart.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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_ALIF2_UART_H
|
||||||
|
#define MICROPY_INCLUDED_ALIF2_UART_H
|
||||||
|
|
||||||
|
void mp_uart_init(void);
|
||||||
|
void mp_uart_write_strn(const char *str, size_t len);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_ALIF2_UART_H
|
||||||
151
ports/alif/msc_disk.c
Normal file
151
ports/alif/msc_disk.c
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* 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 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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/mpconfig.h"
|
||||||
|
#include "py/misc.h"
|
||||||
|
#include "ospi_flash.h"
|
||||||
|
#include "tusb.h"
|
||||||
|
|
||||||
|
#if CFG_TUD_MSC
|
||||||
|
|
||||||
|
#if MICROPY_FATFS_MAX_SS != MICROPY_HW_FLASH_BLOCK_SIZE_BYTES
|
||||||
|
#error MICROPY_FATFS_MAX_SS must be the same size as MICROPY_HW_FLASH_BLOCK_SIZE_BYTES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BLOCK_SIZE (MICROPY_HW_FLASH_BLOCK_SIZE_BYTES)
|
||||||
|
#define BLOCK_COUNT (MICROPY_HW_FLASH_STORAGE_BYTES / BLOCK_SIZE)
|
||||||
|
#define FLASH_BASE_ADDR (MICROPY_HW_FLASH_STORAGE_BASE_ADDR)
|
||||||
|
|
||||||
|
static bool ejected = false;
|
||||||
|
|
||||||
|
// Invoked on SCSI_CMD_INQUIRY.
|
||||||
|
// Fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively.
|
||||||
|
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) {
|
||||||
|
memcpy(vendor_id, MICROPY_HW_USB_MSC_INQUIRY_VENDOR_STRING, MIN(strlen(MICROPY_HW_USB_MSC_INQUIRY_VENDOR_STRING), 8));
|
||||||
|
memcpy(product_id, MICROPY_HW_USB_MSC_INQUIRY_PRODUCT_STRING, MIN(strlen(MICROPY_HW_USB_MSC_INQUIRY_PRODUCT_STRING), 16));
|
||||||
|
memcpy(product_rev, MICROPY_HW_USB_MSC_INQUIRY_REVISION_STRING, MIN(strlen(MICROPY_HW_USB_MSC_INQUIRY_REVISION_STRING), 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked on Test-Unit-Ready command.
|
||||||
|
// Return true allowing host to read/write this LUN (e.g SD card inserted).
|
||||||
|
bool tud_msc_test_unit_ready_cb(uint8_t lun) {
|
||||||
|
if (ejected) {
|
||||||
|
tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked on SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size.
|
||||||
|
void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) {
|
||||||
|
*block_size = BLOCK_SIZE;
|
||||||
|
*block_count = BLOCK_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked on Start-Stop-Unit command:
|
||||||
|
// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
|
||||||
|
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
|
||||||
|
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) {
|
||||||
|
if (load_eject) {
|
||||||
|
if (start) {
|
||||||
|
// load disk storage
|
||||||
|
ejected = false;
|
||||||
|
} else {
|
||||||
|
// unload disk storage
|
||||||
|
ejected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback invoked on READ10 command.
|
||||||
|
// Copy disk's data to buffer (up to bufsize) and return number of read bytes.
|
||||||
|
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) {
|
||||||
|
uint32_t addr = FLASH_BASE_ADDR + lba * BLOCK_SIZE;
|
||||||
|
uint32_t block_count = bufsize / BLOCK_SIZE;
|
||||||
|
int ret = ospi_flash_read(addr, block_count * BLOCK_SIZE, buffer);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return block_count * BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback invoked on WRITE10 command.
|
||||||
|
// Process data in buffer to disk's storage and return number of written bytes.
|
||||||
|
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) {
|
||||||
|
if (bufsize < BLOCK_SIZE) {
|
||||||
|
// Workaround for issue with TinyUSB passing in a small buffer.
|
||||||
|
uint32_t addr = FLASH_BASE_ADDR + lba * BLOCK_SIZE + offset;
|
||||||
|
if (offset == 0) {
|
||||||
|
int ret = ospi_flash_erase_sector(addr);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int ret = ospi_flash_write(addr, bufsize, buffer);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return bufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t addr = FLASH_BASE_ADDR + lba * BLOCK_SIZE;
|
||||||
|
uint32_t block_count = bufsize / BLOCK_SIZE;
|
||||||
|
for (uint32_t block = 0; block < block_count; ++block) {
|
||||||
|
int ret = ospi_flash_erase_sector(addr);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = ospi_flash_write(addr, BLOCK_SIZE, buffer);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
addr += BLOCK_SIZE;
|
||||||
|
buffer += BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
return block_count * BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback invoked on a SCSI command that's not handled by TinyUSB.
|
||||||
|
int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) {
|
||||||
|
int32_t resplen = 0;
|
||||||
|
switch (scsi_cmd[0]) {
|
||||||
|
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
||||||
|
// Sync the logical unit if needed.
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Set Sense = Invalid Command Operation
|
||||||
|
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
|
||||||
|
// negative means error -> tinyusb could stall and/or response with failed status
|
||||||
|
resplen = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return resplen;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
265
ports/alif/ospi_flash.c
Normal file
265
ports/alif/ospi_flash.c
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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/mperrno.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "ospi_flash.h"
|
||||||
|
|
||||||
|
#include "ospi_drv.h"
|
||||||
|
#include "pinconf.h"
|
||||||
|
|
||||||
|
#define CMD_RDSR (0x05)
|
||||||
|
#define CMD_WREN (0x06)
|
||||||
|
#define CMD_SEC_ERASE_32ADDR (0x21) // 4kiB sector erase with 32-bit address
|
||||||
|
#define CMD_WRVOL (0x81)
|
||||||
|
#define CMD_RD_DEVID (0x9f)
|
||||||
|
|
||||||
|
#define WAIT_SR_TIMEOUT (1000000)
|
||||||
|
|
||||||
|
// maximum bytes we can write in one SPI transfer
|
||||||
|
// limited by 256 byte FIFO buffer (can't go up to 256)
|
||||||
|
// need to use DMA to make this 256
|
||||||
|
#define PAGE_SIZE (128)
|
||||||
|
|
||||||
|
#define ISSI_MODE_OCTAL_DDR_DQS (0xe7)
|
||||||
|
|
||||||
|
// All OSPI1 pins use the same alternate function.
|
||||||
|
#define OSPI1_PIN_FUNCTION PINMUX_ALTERNATE_FUNCTION_1
|
||||||
|
|
||||||
|
typedef struct _mp_spiflash_t {
|
||||||
|
ospi_flash_cfg_t cfg;
|
||||||
|
} mp_spiflash_t;
|
||||||
|
|
||||||
|
static mp_spiflash_t global_flash;
|
||||||
|
|
||||||
|
// Alif version of this function can overwrite the destination buffer.
|
||||||
|
static void ospi_recv_blocking2(ospi_flash_cfg_t *ospi_cfg, uint32_t command, uint8_t *buffer) {
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
ospi_writel(ospi_cfg, data_reg, command);
|
||||||
|
ospi_writel(ospi_cfg, ser, ospi_cfg->ser);
|
||||||
|
|
||||||
|
ospi_cfg->rx_cnt = 0;
|
||||||
|
|
||||||
|
while (ospi_cfg->rx_cnt < ospi_cfg->rx_req) {
|
||||||
|
unsigned int timeout = 100000;
|
||||||
|
while (ospi_readl(ospi_cfg, rxflr) == 0) {
|
||||||
|
if (--timeout == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = ospi_readl(ospi_cfg, data_reg);
|
||||||
|
*buffer++ = (uint8_t)val;
|
||||||
|
ospi_cfg->rx_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len, uint8_t *dest) {
|
||||||
|
ospi_setup_read(&self->cfg, 0, len, 8);
|
||||||
|
ospi_recv_blocking2(&self->cfg, cmd, dest);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) {
|
||||||
|
ospi_setup_write(&self->cfg, 0);
|
||||||
|
ospi_send_blocking(&self->cfg, cmd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) {
|
||||||
|
do {
|
||||||
|
uint8_t sr;
|
||||||
|
int ret = mp_spiflash_read_cmd(self, CMD_RDSR, 1, &sr);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if ((sr & mask) == val) {
|
||||||
|
return 0; // success
|
||||||
|
}
|
||||||
|
} while (timeout--);
|
||||||
|
|
||||||
|
return -MP_ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mp_spiflash_wait_wel1(mp_spiflash_t *self) {
|
||||||
|
return mp_spiflash_wait_sr(self, 2, 2, WAIT_SR_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mp_spiflash_wait_wip0(mp_spiflash_t *self) {
|
||||||
|
return mp_spiflash_wait_sr(self, 1, 0, WAIT_SR_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ospi_flash_read_id(mp_spiflash_t *self) {
|
||||||
|
uint8_t buf[8];
|
||||||
|
ospi_setup_read(&self->cfg, 0, 3, ospi_flash_settings.read_id_dummy_cycles);
|
||||||
|
ospi_recv_blocking2(&self->cfg, CMD_RD_DEVID, buf);
|
||||||
|
return buf[0] | buf[1] << 8 | buf[2] << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ospi_flash_write_reg_sdr(mp_spiflash_t *self, uint8_t cmd, uint8_t addr, uint8_t value) {
|
||||||
|
mp_spiflash_write_cmd(self, CMD_WREN);
|
||||||
|
ospi_setup_write_sdr(&self->cfg, 6);
|
||||||
|
ospi_push(&self->cfg, cmd);
|
||||||
|
ospi_push(&self->cfg, 0x00);
|
||||||
|
ospi_push(&self->cfg, 0x00);
|
||||||
|
ospi_push(&self->cfg, addr);
|
||||||
|
ospi_send_blocking(&self->cfg, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ospi_flash_init(void) {
|
||||||
|
mp_spiflash_t *self = &global_flash;
|
||||||
|
|
||||||
|
uint32_t pad_ctrl = PADCTRL_OUTPUT_DRIVE_STRENGTH_12MA | PADCTRL_SLEW_RATE_FAST | PADCTRL_READ_ENABLE;
|
||||||
|
|
||||||
|
pinconf_set(pin_OSPI1_CS->port, pin_OSPI1_CS->pin, OSPI1_PIN_FUNCTION, PADCTRL_OUTPUT_DRIVE_STRENGTH_12MA);
|
||||||
|
pinconf_set(pin_OSPI1_SCLK->port, pin_OSPI1_SCLK->pin, OSPI1_PIN_FUNCTION, PADCTRL_OUTPUT_DRIVE_STRENGTH_12MA | PADCTRL_SLEW_RATE_FAST);
|
||||||
|
pinconf_set(pin_OSPI1_D0->port, pin_OSPI1_D0->pin, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
pinconf_set(pin_OSPI1_D1->port, pin_OSPI1_D1->pin, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
pinconf_set(pin_OSPI1_D2->port, pin_OSPI1_D2->pin, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
pinconf_set(pin_OSPI1_D3->port, pin_OSPI1_D3->pin, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
#if defined(pin_OSPI1_D4)
|
||||||
|
pinconf_set(pin_OSPI1_D4->port, pin_OSPI1_D4->pin, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
pinconf_set(pin_OSPI1_D5->port, pin_OSPI1_D5->pin, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
pinconf_set(pin_OSPI1_D6->port, pin_OSPI1_D6->pin, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
pinconf_set(pin_OSPI1_D7->port, pin_OSPI1_D7->pin, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
#endif
|
||||||
|
#if defined(pin_OSPI1_RXDS)
|
||||||
|
pinconf_set(pin_OSPI1_RXDS->port, pin_OSPI1_RXDS->pin, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(pin_OSPI1_RXDS)
|
||||||
|
if (pin_OSPI1_RXDS->port == PORT_10 && pin_OSPI1_RXDS->pin == PIN_7) {
|
||||||
|
// Alif: P5_6 is needed to support proper alt function selection of P10_7.
|
||||||
|
pinconf_set(PORT_5, PIN_6, OSPI1_PIN_FUNCTION, pad_ctrl);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Reset the SPI flash.
|
||||||
|
mp_hal_pin_output(pin_OSPI1_RESET);
|
||||||
|
mp_hal_pin_low(pin_OSPI1_RESET);
|
||||||
|
mp_hal_delay_us(30);
|
||||||
|
mp_hal_pin_high(pin_OSPI1_RESET);
|
||||||
|
|
||||||
|
// Configure the OSPI peripheral.
|
||||||
|
self->cfg.regs = (ssi_regs_t *)OSPI1_BASE;
|
||||||
|
self->cfg.aes_regs = (aes_regs_t *)AES1_BASE;
|
||||||
|
self->cfg.xip_base = (volatile void *)OSPI1_XIP_BASE;
|
||||||
|
self->cfg.ser = 1;
|
||||||
|
self->cfg.addrlen = 8; // 32-bit address length
|
||||||
|
self->cfg.ospi_clock = ospi_flash_settings.freq_mhz;
|
||||||
|
self->cfg.ddr_en = 0;
|
||||||
|
self->cfg.wait_cycles = 0; // used only for ospi_xip_exit
|
||||||
|
ospi_init(&self->cfg);
|
||||||
|
|
||||||
|
if (ospi_flash_settings.is_oct && ospi_flash_settings.is_ddr) {
|
||||||
|
// Switch SPI flash to Octal DDR mode.
|
||||||
|
ospi_flash_write_reg_sdr(self, CMD_WRVOL, 0x00, ISSI_MODE_OCTAL_DDR_DQS);
|
||||||
|
self->cfg.ddr_en = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the device ID.
|
||||||
|
if (ospi_flash_read_id(self) != ospi_flash_settings.jedec_id) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ospi_flash_erase_sector(uint32_t addr) {
|
||||||
|
mp_spiflash_t *self = &global_flash;
|
||||||
|
|
||||||
|
mp_spiflash_write_cmd(self, CMD_WREN);
|
||||||
|
int ret = mp_spiflash_wait_wel1(self);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ospi_setup_write(&self->cfg, 8 /* 32-bit addr len*/);
|
||||||
|
ospi_push(&self->cfg, CMD_SEC_ERASE_32ADDR);
|
||||||
|
ospi_send_blocking(&self->cfg, addr);
|
||||||
|
|
||||||
|
return mp_spiflash_wait_wip0(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ospi_flash_read(uint32_t addr, uint32_t len, uint8_t *dest) {
|
||||||
|
// OSPI FIFO is limited to 256 bytes. Need DMA to get a longer read.
|
||||||
|
mp_spiflash_t *self = &global_flash;
|
||||||
|
|
||||||
|
while (len) {
|
||||||
|
uint32_t l = len;
|
||||||
|
if (l > 256) {
|
||||||
|
l = 256;
|
||||||
|
}
|
||||||
|
ospi_setup_read(&self->cfg, 8 /* 32-bit addr len*/, l, ospi_flash_settings.read_dummy_cycles);
|
||||||
|
ospi_push(&self->cfg, ospi_flash_settings.read_command);
|
||||||
|
ospi_recv_blocking2(&self->cfg, addr, dest);
|
||||||
|
addr += l;
|
||||||
|
len -= l;
|
||||||
|
dest += l;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ospi_flash_write_page(uint32_t addr, uint32_t len, const uint8_t *src) {
|
||||||
|
mp_spiflash_t *self = &global_flash;
|
||||||
|
|
||||||
|
mp_spiflash_write_cmd(self, CMD_WREN);
|
||||||
|
int ret = mp_spiflash_wait_wel1(self);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ospi_setup_write(&self->cfg, 8 /* 32-bit addr len*/);
|
||||||
|
ospi_push(&self->cfg, ospi_flash_settings.write_command);
|
||||||
|
ospi_push(&self->cfg, addr);
|
||||||
|
while (--len) {
|
||||||
|
ospi_push(&self->cfg, *src++);
|
||||||
|
}
|
||||||
|
ospi_send_blocking(&self->cfg, *src);
|
||||||
|
|
||||||
|
return mp_spiflash_wait_wip0(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ospi_flash_write(uint32_t addr, uint32_t len, const uint8_t *src) {
|
||||||
|
int ret = 0;
|
||||||
|
uint32_t offset = addr & (PAGE_SIZE - 1);
|
||||||
|
while (len) {
|
||||||
|
size_t rest = PAGE_SIZE - offset;
|
||||||
|
if (rest > len) {
|
||||||
|
rest = len;
|
||||||
|
}
|
||||||
|
ret = ospi_flash_write_page(addr, rest, src);
|
||||||
|
if (ret != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len -= rest;
|
||||||
|
addr += rest;
|
||||||
|
src += rest;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
52
ports/alif/ospi_flash.h
Normal file
52
ports/alif/ospi_flash.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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_ALIF_OSPI_FLASH_H
|
||||||
|
#define MICROPY_INCLUDED_ALIF_OSPI_FLASH_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct _ospi_flash_settings_t {
|
||||||
|
uint32_t jedec_id;
|
||||||
|
uint32_t freq_mhz;
|
||||||
|
bool is_quad : 1;
|
||||||
|
bool is_oct : 1;
|
||||||
|
bool is_ddr : 1;
|
||||||
|
uint8_t read_id_dummy_cycles;
|
||||||
|
uint8_t read_dummy_cycles;
|
||||||
|
uint8_t read_command;
|
||||||
|
uint8_t write_command;
|
||||||
|
} ospi_flash_settings_t;
|
||||||
|
|
||||||
|
// Provided by the board when it enables OSPI1.
|
||||||
|
extern const ospi_flash_settings_t ospi_flash_settings;
|
||||||
|
|
||||||
|
int ospi_flash_init(void);
|
||||||
|
int ospi_flash_erase_sector(uint32_t addr);
|
||||||
|
int ospi_flash_read(uint32_t addr, uint32_t len, uint8_t *dest);
|
||||||
|
int ospi_flash_write(uint32_t addr, uint32_t len, const uint8_t *src);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_ALIF_OSPI_FLASH_H
|
||||||
5
ports/alif/ospi_xip_user.h
Normal file
5
ports/alif/ospi_xip_user.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// This file is needed by ospi_xip/source/ospi/ospi_drv.c.
|
||||||
|
#define OSPI_XIP_ENABLE_AES_DECRYPTION (0)
|
||||||
|
#define OSPI_XIP_RX_SAMPLE_DELAY (4)
|
||||||
|
#define OSPI_XIP_DDR_DRIVE_EDGE (1)
|
||||||
|
#define OSPI_XIP_RXDS_DELAY (12)
|
||||||
49
ports/alif/pendsv.c
Normal file
49
ports/alif/pendsv.c
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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 "pendsv.h"
|
||||||
|
#include "irq.h"
|
||||||
|
|
||||||
|
static pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS];
|
||||||
|
|
||||||
|
void pendsv_init(void) {
|
||||||
|
NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) {
|
||||||
|
pendsv_dispatch_table[slot] = f;
|
||||||
|
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PendSV_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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
48
ports/alif/pendsv.h
Normal file
48
ports/alif/pendsv.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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_ALIF_PENDSV_H
|
||||||
|
#define MICROPY_INCLUDED_ALIF_PENDSV_H
|
||||||
|
|
||||||
|
#include "py/mpconfig.h"
|
||||||
|
|
||||||
|
#ifndef MICROPY_BOARD_PENDSV_ENTRIES
|
||||||
|
#define MICROPY_BOARD_PENDSV_ENTRIES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PENDSV_DISPATCH_SOFT_TIMER,
|
||||||
|
MICROPY_BOARD_PENDSV_ENTRIES
|
||||||
|
PENDSV_DISPATCH_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX
|
||||||
|
|
||||||
|
typedef void (*pendsv_dispatch_t)(void);
|
||||||
|
|
||||||
|
void pendsv_init(void);
|
||||||
|
void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_ALIF_PENDSV_H
|
||||||
2
ports/alif/qstrdefsport.h
Normal file
2
ports/alif/qstrdefsport.h
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// qstrs specific to this port
|
||||||
|
// *FORMAT-OFF*
|
||||||
73
ports/alif/tinyusb_port/tusb_config.h
Normal file
73
ports/alif/tinyusb_port/tusb_config.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||||
|
*
|
||||||
|
* 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 _ALIF_TUSB_CONFIG_H_
|
||||||
|
#define _ALIF_TUSB_CONFIG_H_
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------+
|
||||||
|
// Board Specific Configuration
|
||||||
|
// --------------------------------------------------------------------+
|
||||||
|
|
||||||
|
#define CFG_TUSB_MCU OPT_MCU_NONE
|
||||||
|
// #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
|
||||||
|
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
|
||||||
|
#define TUP_DCD_ENDPOINT_MAX 8
|
||||||
|
#define TUD_OPT_RHPORT 0
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
// COMMON CONFIGURATION
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define CFG_TUSB_OS OPT_OS_NONE
|
||||||
|
#define CFG_TUSB_DEBUG 0
|
||||||
|
|
||||||
|
// Enable Device stack
|
||||||
|
#define CFG_TUD_ENABLED 1
|
||||||
|
|
||||||
|
// Default is max speed that hardware controller could support with on-chip PHY
|
||||||
|
#define CFG_TUD_MAX_SPEED OPT_MODE_HIGH_SPEED
|
||||||
|
|
||||||
|
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||||
|
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||||
|
* into those specific section.
|
||||||
|
*/
|
||||||
|
#define CFG_TUSB_MEM_SECTION __attribute__((section(".bss.sram0")))
|
||||||
|
|
||||||
|
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(32)))
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
// DEVICE CONFIGURATION
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||||
|
|
||||||
|
// CDC Endpoint transfer buffer size, more is faster
|
||||||
|
#define CFG_TUD_CDC_EP_BUFSIZE (4096)
|
||||||
|
#define CFG_TUD_CDC_RX_BUFSIZE (4096)
|
||||||
|
#define CFG_TUD_CDC_TX_BUFSIZE (4096)
|
||||||
|
|
||||||
|
#include "shared/tinyusb/tusb_config.h"
|
||||||
|
|
||||||
|
#endif /* _ALIF_TUSB_CONFIG_H_ */
|
||||||
41
ports/alif/usbd.c
Normal file
41
ports/alif/usbd.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024 OpenMV LLC.
|
||||||
|
*
|
||||||
|
* 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/mpconfig.h"
|
||||||
|
|
||||||
|
#if MICROPY_HW_ENABLE_USBDEV
|
||||||
|
|
||||||
|
#include "shared/tinyusb/mp_usbd.h"
|
||||||
|
#include "tusb.h"
|
||||||
|
|
||||||
|
void mp_usbd_port_get_serial_number(char *serial_buf) {
|
||||||
|
// TODO
|
||||||
|
uint8_t id[8] = "ABCDEFGH";
|
||||||
|
MP_STATIC_ASSERT(sizeof(id) * 2 <= MICROPY_HW_USB_DESC_STR_MAX);
|
||||||
|
mp_usbd_hex_str(serial_buf, id, sizeof(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user