This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit f3a3fe8d3cd48689afe55c4a602bd6767ec3abb2 Author: Alan Carvalho de Assis <[email protected]> AuthorDate: Thu Oct 15 16:28:54 2026 -0300 boards/arm/imxrt: add support for the Digital Dream EC300 board The Digital Dream EC300 is a 6 axis Ethernet CNC motion controller based on the NXP i.MX RT1052 (MIMXRT1052CVL5B), with 4 MiB of QSPI NOR flash and a LAN8720A RMII Ethernet PHY. The pin assignments come from the Remora-RT1052 firmware project. This initial port supports: - Boot from the QSPI NOR flash (Winbond W25Q32), no SDRAM. - Serial console on LPUART4. - Ethernet on the LAN8720A at MDIO address 0, using ETH0_PHY_MULTI with a board PHY list. The PHY interrupt line is not connected, so the board emulates it by polling, allowing the NETINIT link monitor to handle cable plug/unplug. - The CONN LED as user LED or NuttX status LED. - An OpenOCD configuration (tools/ddcnc-ec300.cfg) that implements QSPI NOR erase, program, verify and dump through the FlexSPI controller, since OpenOCD has no i.MX RT FlexSPI flash driver. Two configurations are provided: nsh and netnsh. Signed-off-by: Alan Carvalho de Assis <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]> --- boards/Kconfig | 15 + boards/arm/imxrt/ddcnc-ec300/CMakeLists.txt | 23 + boards/arm/imxrt/ddcnc-ec300/Kconfig | 19 + .../arm/imxrt/ddcnc-ec300/configs/netnsh/defconfig | 58 ++ boards/arm/imxrt/ddcnc-ec300/configs/nsh/defconfig | 38 ++ boards/arm/imxrt/ddcnc-ec300/include/board.h | 230 ++++++++ boards/arm/imxrt/ddcnc-ec300/scripts/Make.defs | 38 ++ .../arm/imxrt/ddcnc-ec300/scripts/flash-ocram.ld | 142 +++++ boards/arm/imxrt/ddcnc-ec300/src/CMakeLists.txt | 39 ++ boards/arm/imxrt/ddcnc-ec300/src/Makefile | 38 ++ boards/arm/imxrt/ddcnc-ec300/src/ddcnc-ec300.h | 95 ++++ boards/arm/imxrt/ddcnc-ec300/src/imxrt_autoleds.c | 163 ++++++ boards/arm/imxrt/ddcnc-ec300/src/imxrt_boot.c | 79 +++ boards/arm/imxrt/ddcnc-ec300/src/imxrt_bringup.c | 71 +++ boards/arm/imxrt/ddcnc-ec300/src/imxrt_ethernet.c | 173 ++++++ .../imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.c | 57 ++ .../imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.h | 138 +++++ .../ddcnc-ec300/src/imxrt_flexspi_nor_flash.c | 168 ++++++ .../ddcnc-ec300/src/imxrt_flexspi_nor_flash.h | 352 ++++++++++++ boards/arm/imxrt/ddcnc-ec300/src/imxrt_userleds.c | 82 +++ boards/arm/imxrt/ddcnc-ec300/tools/ddcnc-ec300.cfg | 621 +++++++++++++++++++++ 21 files changed, 2639 insertions(+) diff --git a/boards/Kconfig b/boards/Kconfig index 252cc502fcd..19c4991ed69 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -979,6 +979,17 @@ config ARCH_BOARD_IMXRT1050_EVK This is the board configuration for the port of NuttX to the NXP i.MXRT evaluation kit, MIMXRT1050-EVKB. This board features the MIMXRT1052DVL6A MCU. +config ARCH_BOARD_DDCNC_EC300 + bool "Digital Dream EC300 CNC motion controller" + depends on ARCH_CHIP_MIMXRT1052CVL5A + select ARCH_HAVE_LEDS + select ARCH_PHY_INTERRUPT + ---help--- + This is the board configuration for the port of NuttX to the + Digital Dream EC300 Ethernet CNC motion controller. This board + features the MIMXRT1052CVL5B MCU, 4MiB of QSPI NOR flash and a + LAN8720A Ethernet PHY. + config ARCH_BOARD_ARCX_SOCKET_GRID bool "ARCX Socket Grid board" depends on ARCH_CHIP_MIMXRT1052DVL6A @@ -4156,6 +4167,7 @@ config ARCH_BOARD default "hymini-stm32v" if ARCH_BOARD_HYMINI_STM32V default "imxrt1020-evk" if ARCH_BOARD_IMXRT1020_EVK default "imxrt1050-evk" if ARCH_BOARD_IMXRT1050_EVK + default "ddcnc-ec300" if ARCH_BOARD_DDCNC_EC300 default "arcx-socket-grid" if ARCH_BOARD_ARCX_SOCKET_GRID default "imxrt1060-evk" if ARCH_BOARD_IMXRT1060_EVK default "imxrt1064-evk" if ARCH_BOARD_IMXRT1064_EVK @@ -4657,6 +4669,9 @@ endif if ARCH_BOARD_IMXRT1050_EVK source "boards/arm/imxrt/imxrt1050-evk/Kconfig" endif +if ARCH_BOARD_DDCNC_EC300 +source "boards/arm/imxrt/ddcnc-ec300/Kconfig" +endif if ARCH_BOARD_ARCX_SOCKET_GRID source "boards/arm/imxrt/arcx-socket-grid/Kconfig" endif diff --git a/boards/arm/imxrt/ddcnc-ec300/CMakeLists.txt b/boards/arm/imxrt/ddcnc-ec300/CMakeLists.txt new file mode 100644 index 00000000000..82a689487b3 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/CMakeLists.txt @@ -0,0 +1,23 @@ +# ############################################################################## +# boards/arm/imxrt/ddcnc-ec300/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +add_subdirectory(src) diff --git a/boards/arm/imxrt/ddcnc-ec300/Kconfig b/boards/arm/imxrt/ddcnc-ec300/Kconfig new file mode 100644 index 00000000000..74b030bf755 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/Kconfig @@ -0,0 +1,19 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_DDCNC_EC300 + +config DDCNC_EC300_PHY_POLL_MSEC + int "PHY link poll interval (ms)" + default 1000 + depends on IMXRT_ENET && ARCH_PHY_INTERRUPT + ---help--- + The LAN8720A interrupt output is not connected to the MCU. The PHY + interrupt used by PHY notifications (SIOCMIINOTIFY, for example by + the NETINIT link monitor) is emulated by calling the handler at + this interval, so link up/down events are detected by polling the + PHY. + +endif # ARCH_BOARD_DDCNC_EC300 diff --git a/boards/arm/imxrt/ddcnc-ec300/configs/netnsh/defconfig b/boards/arm/imxrt/ddcnc-ec300/configs/netnsh/defconfig new file mode 100644 index 00000000000..0655737bc4d --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/configs/netnsh/defconfig @@ -0,0 +1,58 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="ddcnc-ec300" +CONFIG_ARCH_BOARD_DDCNC_EC300=y +CONFIG_ARCH_CHIP="imxrt" +CONFIG_ARCH_CHIP_IMXRT=y +CONFIG_ARCH_CHIP_MIMXRT1052CVL5A=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_BOARD_LOOPSPERMSEC=92335 +CONFIG_BUILTIN=y +CONFIG_ETH0_PHY_MULTI=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_IMXRT_ENET=y +CONFIG_IMXRT_LPUART4=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_HOSTNAME="EC300" +CONFIG_LINE_MAX=64 +CONFIG_LPUART4_SERIAL_CONSOLE=y +CONFIG_NET=y +CONFIG_NETDEV_PHY_IOCTL=y +CONFIG_NETDEV_STATISTICS=y +CONFIG_NETINIT_DRIPADDR=0x0a0a0a01 +CONFIG_NETINIT_IPADDR=0x0a0a0a0a +CONFIG_NETINIT_MONITOR=y +CONFIG_NETINIT_THREAD=y +CONFIG_NETUTILS_TELNETD=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_TCP=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_WRITE_BUFFERS=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=524288 +CONFIG_RAM_START=0x20200000 +CONFIG_RAW_BINARY=y +CONFIG_SCHED_LPWORK=y +CONFIG_START_DAY=15 +CONFIG_START_MONTH=10 +CONFIG_START_YEAR=2026 +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y diff --git a/boards/arm/imxrt/ddcnc-ec300/configs/nsh/defconfig b/boards/arm/imxrt/ddcnc-ec300/configs/nsh/defconfig new file mode 100644 index 00000000000..2403af559ed --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/configs/nsh/defconfig @@ -0,0 +1,38 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="ddcnc-ec300" +CONFIG_ARCH_BOARD_DDCNC_EC300=y +CONFIG_ARCH_CHIP="imxrt" +CONFIG_ARCH_CHIP_IMXRT=y +CONFIG_ARCH_CHIP_MIMXRT1052CVL5A=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_BOARD_LOOPSPERMSEC=92335 +CONFIG_BUILTIN=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_IMXRT_LPUART4=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_HOSTNAME="EC300" +CONFIG_LINE_MAX=64 +CONFIG_LPUART4_SERIAL_CONSOLE=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=524288 +CONFIG_RAM_START=0x20200000 +CONFIG_RAW_BINARY=y +CONFIG_START_DAY=15 +CONFIG_START_MONTH=10 +CONFIG_START_YEAR=2026 +CONFIG_SYSTEM_NSH=y diff --git a/boards/arm/imxrt/ddcnc-ec300/include/board.h b/boards/arm/imxrt/ddcnc-ec300/include/board.h new file mode 100644 index 00000000000..788484497ab --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/include/board.h @@ -0,0 +1,230 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/include/board.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_IMXRT_DDCNC_EC300_INCLUDE_BOARD_H +#define __BOARDS_ARM_IMXRT_DDCNC_EC300_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/* Do not include i.MXRT header files here */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Clocking *****************************************************************/ + +/* The Digital Dream EC300 is fitted with a MIMXRT1052CVL5B (industrial + * grade part), which is rated for a maximum core frequency of 528MHz. + * + * Set VDD_SOC to 1.25V + */ + +#define IMXRT_VDD_SOC (0x12) + +/* Set Arm PLL (PLL1) to fOut = (24Mhz * ARM_PLL_DIV_SELECT/2) / + * ARM_PODF_DIVISOR + * 528Mhz = (24Mhz * ARM_PLL_DIV_SELECT/2) / + * ARM_PODF_DIVISOR + * ARM_PLL_DIV_SELECT = 88 + * ARM_PODF_DIVISOR = 2 + * 528Mhz = (24Mhz * 88/2) / 2 + * + * AHB_CLOCK_ROOT = PLL1fOut / IMXRT_AHB_PODF_DIVIDER + * 1Hz to 528 MHz = 528Mhz / IMXRT_ARM_CLOCK_DIVIDER + * IMXRT_ARM_CLOCK_DIVIDER = 1 + * 528Mhz = 528Mhz / 1 + * + * PRE_PERIPH_CLK_SEL = PRE_PERIPH_CLK_SEL_PLL1 + * PERIPH_CLK_SEL = 1 (0 select PERIPH_CLK2_PODF, + * 1 select PRE_PERIPH_CLK_SEL_PLL1) + * PERIPH_CLK = 528Mhz + * + * IPG_CLOCK_ROOT = AHB_CLOCK_ROOT / IMXRT_IPG_PODF_DIVIDER + * IMXRT_IPG_PODF_DIVIDER = 4 + * 132Mhz = 528Mhz / 4 + * + * PERCLK_CLOCK_ROOT = IPG_CLOCK_ROOT / + * IMXRT_PERCLK_PODF_DIVIDER + * IMXRT_PERCLK_PODF_DIVIDER = 9 + * 14.6Mhz = 132Mhz / 9 + * + * SEMC_CLK_ROOT = 528Mhz / IMXRT_SEMC_PODF_DIVIDER + * (labeled AIX_PODF in 18.2) + * IMXRT_SEMC_PODF_DIVIDER = 8 + * 66Mhz = 528Mhz / 8 + * + * Set Sys PLL (PLL2) to fOut = (24Mhz * (20+(2*(DIV_SELECT))) + * 528Mhz = (24Mhz * (20+(2*(1))) + * + * Set USB1 PLL (PLL3) to fOut = (24Mhz * 20) + * 480Mhz = (24Mhz * 20) + * + * Set LPSPI PLL3 PFD0 to fOut = (480Mhz / 12 * 18) + * 720Mhz = (480Mhz / 12 * 18) + * 90Mhz = (720Mhz / LSPI_PODF_DIVIDER) + * + * Set LPI2C PLL3 / 8 to fOut = (480Mhz / 8) + * 60Mhz = (480Mhz / 8) + * 12Mhz = (60Mhz / LSPI_PODF_DIVIDER) + * + * The ENET PLL (PLL6) is configured by the common i.MX RT clock logic to + * generate the 50MHz RMII reference clock that is driven out on the + * ENET_REF_CLK pin (GPIO_B1_10) to the LAN8720A PHY. + */ + +#define BOARD_XTAL_FREQUENCY 24000000 +#define IMXRT_PRE_PERIPH_CLK_SEL CCM_CBCMR_PRE_PERIPH_CLK_SEL_PLL1 +#define IMXRT_PERIPH_CLK_SEL CCM_CBCDR_PERIPH_CLK_SEL_PRE_PERIPH +#define IMXRT_ARM_PLL_DIV_SELECT 88 +#define IMXRT_ARM_PODF_DIVIDER 2 +#define IMXRT_AHB_PODF_DIVIDER 1 +#define IMXRT_IPG_PODF_DIVIDER 4 +#define IMXRT_PERCLK_CLK_SEL CCM_CSCMR1_PERCLK_CLK_SEL_IPG_CLK_ROOT +#define IMXRT_PERCLK_PODF_DIVIDER 9 +#define IMXRT_SEMC_PODF_DIVIDER 8 + +#define IMXRT_LPSPI_CLK_SELECT CCM_CBCMR_LPSPI_CLK_SEL_PLL3_PFD0 +#define IMXRT_LSPI_PODF_DIVIDER 8 + +#define IMXRT_LPI2C_CLK_SELECT CCM_CSCDR2_LPI2C_CLK_SEL_PLL3_60M +#define IMXRT_LSI2C_PODF_DIVIDER 5 + +#define IMXRT_USDHC1_CLK_SELECT CCM_CSCMR1_USDHC1_CLK_SEL_PLL2_PFD0 +#define IMXRT_USDHC1_PODF_DIVIDER 2 + +#define IMXRT_SYS_PLL_SELECT CCM_ANALOG_PLL_SYS_DIV_SELECT_22 + +#define IMXRT_USB1_PLL_DIV_SELECT CCM_ANALOG_PLL_USB1_DIV_SELECT_20 + +#define BOARD_CPU_FREQUENCY \ + (BOARD_XTAL_FREQUENCY * (IMXRT_ARM_PLL_DIV_SELECT / 2)) / IMXRT_ARM_PODF_DIVIDER + +/* LED definitions **********************************************************/ + +/* There are three LED indicators located on the EC300 front panel: + * + * - POWER: Main power supply (hardware controlled) + * - IO: IO power supply (hardware controlled) + * - CONN: Communication status, connected to GPIO_SD_B1_00 + * (GPIO3_IO00). Low illuminates. + * + * Only the CONN LED is under software control. + */ + +/* LED index values for use with board_userled() */ + +#define BOARD_USERLED 0 +#define BOARD_NLEDS 1 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_USERLED_BIT (1 << BOARD_USERLED) + +/* This LED is not used by the board port unless CONFIG_ARCH_LEDS is + * defined. In that case, the usage by the board port is defined in + * include/board.h and src/imxrt_autoleds.c. The CONN LED is used to + * encode OS-related events as follows: + * + * ------------------- ----------------------- ------ + * SYMBOL Meaning LED + * ------------------- ----------------------- ------ + */ + +#define LED_STARTED 0 /* NuttX has been started OFF */ +#define LED_HEAPALLOCATE 0 /* Heap has been allocated OFF */ +#define LED_IRQSENABLED 0 /* Interrupts enabled OFF */ +#define LED_STACKCREATED 1 /* Idle stack created ON */ +#define LED_INIRQ 2 /* In an interrupt N/C */ +#define LED_SIGNAL 2 /* In a signal handler N/C */ +#define LED_ASSERTION 2 /* An assertion failed N/C */ +#define LED_PANIC 3 /* The system has crashed FLASH */ +#undef LED_IDLE /* Not used */ + +/* Thus if the LED is statically on, NuttX has successfully booted and is, + * apparently, running normally. If the LED is flashing at approximately + * 2Hz, then a fatal error has been detected and the system has halted. + */ + +/* Ethernet *****************************************************************/ + +/* The EC300 uses a SMSC/Microchip LAN8720A RMII PHY. The i.MX RT provides + * the 50MHz reference clock to the PHY (CONFIG_IMXRT_MAC_PROVIDES_TXC). + * + * The PHY is strapped to answer at MDIO address 0, but the i.MX RT ENET + * driver hard-codes address 1 for CONFIG_ETH0_PHY_LAN8720. So the + * CONFIG_ETH0_PHY_MULTI run-time PHY selection is used instead, which + * allows the board to provide the PHY description below. + */ + +#define BOARD_ETH0_PHY_LIST \ + { \ + MII_LAN8720_NAME, \ + MII_PHYID1_LAN8720, \ + MII_PHYID2_LAN8720, \ + MII_LAN8720_SCSR, \ + 0, \ + 0xffff, \ + MII_LAN8720_SPSCR_10MBPS, \ + MII_LAN8720_SPSCR_100MBPS, \ + MII_LAN8720_SPSCR_DUPLEX, \ + 22, \ + 0, \ + 0 \ + } + +/* ETH Disambiguation *******************************************************/ + +#define GPIO_ENET_TX_DATA00 (GPIO_ENET_TX_DATA00_1| \ + IOMUX_ENET_DATA_DEFAULT) /* GPIO_B1_07 */ +#define GPIO_ENET_TX_DATA01 (GPIO_ENET_TX_DATA01_1| \ + IOMUX_ENET_DATA_DEFAULT) /* GPIO_B1_08 */ +#define GPIO_ENET_RX_DATA00 (GPIO_ENET_RX_DATA00_1| \ + IOMUX_ENET_DATA_DEFAULT) /* GPIO_B1_04 */ +#define GPIO_ENET_RX_DATA01 (GPIO_ENET_RX_DATA01_1| \ + IOMUX_ENET_DATA_DEFAULT) /* GPIO_B1_05 */ +#define GPIO_ENET_MDIO (GPIO_ENET_MDIO_1|IOMUX_ENET_MDIO_DEFAULT) /* GPIO_B1_15 */ +#define GPIO_ENET_MDC (GPIO_ENET_MDC_1|IOMUX_ENET_MDC_DEFAULT) /* GPIO_B1_14 */ +#define GPIO_ENET_RX_EN (GPIO_ENET_RX_EN_1|IOMUX_ENET_EN_DEFAULT) /* GPIO_B1_06 */ +#define GPIO_ENET_RX_ER (GPIO_ENET_RX_ER_1|IOMUX_ENET_RXERR_DEFAULT) /* GPIO_B1_11 */ +#define GPIO_ENET_TX_CLK (GPIO_ENET_REF_CLK_2|\ + IOMUX_ENET_TX_CLK_DEFAULT) /* GPIO_B1_10 */ +#define GPIO_ENET_TX_EN (GPIO_ENET_TX_EN_1|IOMUX_ENET_EN_DEFAULT) /* GPIO_B1_09 */ + +/* PIO Disambiguation *******************************************************/ + +/* LPUARTs + * + * LPUART4 is used as the debug console. LPUART5 is connected to the + * MPG port (NVMPG pendant). + */ + +#define GPIO_LPUART4_RX (GPIO_LPUART4_RX_1|IOMUX_UART_DEFAULT) /* GPIO_B1_01 */ +#define GPIO_LPUART4_TX (GPIO_LPUART4_TX_1|IOMUX_UART_DEFAULT) /* GPIO_B1_00 */ +#define GPIO_LPUART5_RX (GPIO_LPUART5_RX_1|IOMUX_UART_DEFAULT) /* GPIO_B1_13 */ +#define GPIO_LPUART5_TX (GPIO_LPUART5_TX_1|IOMUX_UART_DEFAULT) /* GPIO_B1_12 */ + +#endif /* __BOARDS_ARM_IMXRT_DDCNC_EC300_INCLUDE_BOARD_H */ diff --git a/boards/arm/imxrt/ddcnc-ec300/scripts/Make.defs b/boards/arm/imxrt/ddcnc-ec300/scripts/Make.defs new file mode 100644 index 00000000000..49f3d2873d3 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/scripts/Make.defs @@ -0,0 +1,38 @@ +############################################################################ +# boards/arm/imxrt/ddcnc-ec300/scripts/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/arch/arm/src/armv7-m/Toolchain.defs + +LDSCRIPT = flash-ocram.ld + +ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 diff --git a/boards/arm/imxrt/ddcnc-ec300/scripts/flash-ocram.ld b/boards/arm/imxrt/ddcnc-ec300/scripts/flash-ocram.ld new file mode 100644 index 00000000000..8905bffb06b --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/scripts/flash-ocram.ld @@ -0,0 +1,142 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/scripts/flash-ocram.ld + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* Specify the memory areas */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x60000000, LENGTH = 0x00400000 + sram (rwx) : ORIGIN = 0x20200000, LENGTH = 0x00080000 + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 0x00020000 + dtcm (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000 +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +EXTERN(g_flash_config) +EXTERN(g_image_vector_table) +EXTERN(g_boot_data) + +ENTRY(_stext) + +SECTIONS +{ + /* Image Vector Table and Boot Data for booting from external flash */ + + .boot_hdr : ALIGN(4) + { + FILL(0xff) + __boot_hdr_start__ = ABSOLUTE(.) ; + KEEP(*(.boot_hdr.conf)) + . = 0x1000 ; + KEEP(*(.boot_hdr.ivt)) + . = 0x1020 ; + KEEP(*(.boot_hdr.boot_data)) + . = 0x1030 ; + KEEP(*(.boot_hdr.dcd_data)) + __boot_hdr_end__ = ABSOLUTE(.) ; + . = 0x2000 ; + } >flash + + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : + { + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .ctors)) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : + { + *(.ARM.extab*) + } > flash + + .ARM.exidx : + { + __exidx_start = ABSOLUTE(.); + *(.ARM.exidx*) + __exidx_end = ABSOLUTE(.); + } > flash + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .ramfunc ALIGN(4): + { + _sramfuncs = ABSOLUTE(.); + *(.ramfunc .ramfunc.*) + _eramfuncs = ABSOLUTE(.); + } > sram AT > flash + + _framfuncs = LOADADDR(.ramfunc); + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/imxrt/ddcnc-ec300/src/CMakeLists.txt b/boards/arm/imxrt/ddcnc-ec300/src/CMakeLists.txt new file mode 100644 index 00000000000..5585edbfda1 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/CMakeLists.txt @@ -0,0 +1,39 @@ +# ############################################################################## +# boards/arm/imxrt/ddcnc-ec300/src/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +set(SRCS imxrt_boot.c imxrt_flexspi_nor_boot.c imxrt_flexspi_nor_flash.c + imxrt_bringup.c) + +if(CONFIG_IMXRT_ENET) + list(APPEND SRCS imxrt_ethernet.c) +endif() + +if(CONFIG_ARCH_LEDS) + list(APPEND SRCS imxrt_autoleds.c) +else() + list(APPEND SRCS imxrt_userleds.c) +endif() + +target_sources(board PRIVATE ${SRCS}) + +set_property(GLOBAL PROPERTY LD_SCRIPT + "${NUTTX_BOARD_DIR}/scripts/flash-ocram.ld") diff --git a/boards/arm/imxrt/ddcnc-ec300/src/Makefile b/boards/arm/imxrt/ddcnc-ec300/src/Makefile new file mode 100644 index 00000000000..3c9b29a9fd2 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/Makefile @@ -0,0 +1,38 @@ +############################################################################ +# boards/arm/imxrt/ddcnc-ec300/src/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/Make.defs + +CSRCS = imxrt_boot.c imxrt_flexspi_nor_boot.c imxrt_flexspi_nor_flash.c +CSRCS += imxrt_bringup.c + +ifeq ($(CONFIG_IMXRT_ENET),y) +CSRCS += imxrt_ethernet.c +endif + +ifeq ($(CONFIG_ARCH_LEDS),y) +CSRCS += imxrt_autoleds.c +else +CSRCS += imxrt_userleds.c +endif + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/imxrt/ddcnc-ec300/src/ddcnc-ec300.h b/boards/arm/imxrt/ddcnc-ec300/src/ddcnc-ec300.h new file mode 100644 index 00000000000..ada5c6fd1cb --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/ddcnc-ec300.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/ddcnc-ec300.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_IMXRT_DDCNC_EC300_SRC_DDCNC_EC300_H +#define __BOARDS_ARM_IMXRT_DDCNC_EC300_SRC_DDCNC_EC300_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <stdbool.h> + +#include <arch/irq.h> +#include <nuttx/irq.h> + +#include "imxrt_gpio.h" +#include "imxrt_iomuxc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* EC300 GPIO Pin Definitions ***********************************************/ + +/* LEDs + * + * The CONN LED is connected to GPIO_SD_B1_00 (GPIO3_IO00). It is lit when + * the pin is driven low. + */ + +#define GPIO_LED (GPIO_OUTPUT | IOMUX_LED_DEFAULT | \ + GPIO_OUTPUT_ONE | GPIO_PORT3 | GPIO_PIN0) /* SD_B1_00 */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt_bringup + * + * Description: + * Bring up board features + * + ****************************************************************************/ + +#if defined(CONFIG_BOARDCTL) || defined(CONFIG_BOARD_LATE_INITIALIZE) +int imxrt_bringup(void); +#endif + +/**************************************************************************** + * Name: imxrt_autoled_initialize + * + * Description: + * Initialize NuttX-controlled LED logic + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_LEDS +void imxrt_autoled_initialize(void); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM_IMXRT_DDCNC_EC300_SRC_DDCNC_EC300_H */ diff --git a/boards/arm/imxrt/ddcnc-ec300/src/imxrt_autoleds.c b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_autoleds.c new file mode 100644 index 00000000000..6d8d11d3663 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_autoleds.c @@ -0,0 +1,163 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/imxrt_autoleds.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* There are three LED indicators located on the EC300 front panel: + * + * - POWER: Main power supply (hardware controlled) + * - IO: IO power supply (hardware controlled) + * - CONN: Communication status, GPIO_SD_B1_00 (GPIO3_IO00) + * + * Only the CONN LED is under software control. Low illuminates. + * + * This LED is not used by the board port unless CONFIG_ARCH_LEDS is + * defined. In that case, the usage by the board port is defined in + * include/board.h and src/imxrt_autoleds.c. The LED is used to encode + * OS-related events as follows: + * + * -------------------- ----------------------- ------ + * SYMBOL Meaning LED + * -------------------- ----------------------- ------ + * + * LED_STARTED 0 NuttX has been started OFF + * LED_HEAPALLOCATE 0 Heap has been allocated OFF + * LED_IRQSENABLED 0 Interrupts enabled OFF + * LED_STACKCREATED 1 Idle stack created ON + * LED_INIRQ 2 In an interrupt N/C + * LED_SIGNAL 2 In a signal handler N/C + * LED_ASSERTION 2 An assertion failed N/C + * LED_PANIC 3 The system has crashed FLASH + * LED_IDLE Not used + * + * Thus if the LED is statically on, NuttX has successfully booted and is, + * apparently, running normally. If the LED is flashing at approximately + * 2Hz, then a fatal error has been detected and the system has halted. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/board.h> + +#include "imxrt_gpio.h" +#include "imxrt_iomuxc.h" +#include "ddcnc-ec300.h" + +#include <arch/board/board.h> + +#ifdef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt_autoled_initialize + * + * Description: + * Initialize NuttX-controlled LED logic + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void imxrt_autoled_initialize(void) +{ + /* Configure LED GPIO for output */ + + imxrt_config_gpio(GPIO_LED); +} + +/**************************************************************************** + * Name: board_autoled_on + * + * Description: + * Turn on the "logical" LED state + * + * Input Parameters: + * led - Identifies the "logical" LED state (see definitions in + * include/board.h) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_on(int led) +{ + bool ledoff = false; + + switch (led) + { + case 0: /* LED Off */ + ledoff = true; + break; + + case 2: /* LED No change */ + return; + + case 1: /* LED On */ + case 3: /* LED On */ + break; + } + + imxrt_gpio_write(GPIO_LED, ledoff); /* Low illuminates */ +} + +/**************************************************************************** + * Name: board_autoled_off + * + * Description: + * Turn off the "logical" LED state + * + * Input Parameters: + * led - Identifies the "logical" LED state (see definitions in + * include/board.h) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_off(int led) +{ + switch (led) + { + case 0: /* LED Off */ + case 1: /* LED Off */ + case 3: /* LED Off */ + break; + + case 2: /* LED No change */ + return; + } + + imxrt_gpio_write(GPIO_LED, true); /* Low illuminates */ +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/arm/imxrt/ddcnc-ec300/src/imxrt_boot.c b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_boot.c new file mode 100644 index 00000000000..c0df8bd648b --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_boot.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/imxrt_boot.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/board.h> +#include <arch/board/board.h> + +#include "imxrt_start.h" +#include "ddcnc-ec300.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt_boardinitialize + * + * Description: + * All i.MX RT architectures must provide the following entry point. This + * entry point is called early in the initialization -- after clocking and + * memory have been configured but before caches have been enabled and + * before any devices have been initialized. + * + ****************************************************************************/ + +void imxrt_boardinitialize(void) +{ + /* Configure on-board LEDs if LED support has been selected. */ + +#ifdef CONFIG_ARCH_LEDS + imxrt_autoled_initialize(); +#endif +} + +/**************************************************************************** + * Name: board_late_initialize + * + * Description: + * If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional + * initialization call will be performed in the boot-up sequence to a + * function called board_late_initialize(). board_late_initialize() will be + * called immediately after up_intitialize() is called and just before the + * initial application is started. This additional initialization phase + * may be used, for example, to initialize board-specific device drivers. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ + /* Perform board initialization */ + + imxrt_bringup(); +} +#endif /* CONFIG_BOARD_LATE_INITIALIZE */ diff --git a/boards/arm/imxrt/ddcnc-ec300/src/imxrt_bringup.c b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_bringup.c new file mode 100644 index 00000000000..4050751df96 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_bringup.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/imxrt_bringup.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <syslog.h> + +#include <nuttx/fs/fs.h> + +#include "ddcnc-ec300.h" + +#include <arch/board/board.h> /* Must always be included last */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt_bringup + * + * Description: + * Bring up board features + * + ****************************************************************************/ + +int imxrt_bringup(void) +{ + int ret; + +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = nx_mount(NULL, "/proc", "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount procfs at /proc: %d\n", ret); + } +#endif + + /* If we got here then perhaps not all initialization was successful, but + * at least enough succeeded to bring-up NSH with perhaps reduced + * capabilities. + */ + + UNUSED(ret); + return OK; +} diff --git a/boards/arm/imxrt/ddcnc-ec300/src/imxrt_ethernet.c b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_ethernet.c new file mode 100644 index 00000000000..4e29bce004d --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_ethernet.c @@ -0,0 +1,173 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/imxrt_ethernet.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <string.h> +#include <assert.h> +#include <errno.h> + +#include <nuttx/arch.h> +#include <nuttx/clock.h> +#include <nuttx/debug.h> +#include <nuttx/irq.h> +#include <nuttx/wdog.h> + +#include "ddcnc-ec300.h" + +#if defined(CONFIG_IMXRT_ENET) && defined(CONFIG_ARCH_PHY_INTERRUPT) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IMXRT_ENET_DEVNAME "eth0" + +/* The LAN8720A interrupt output is not connected to the MCU, so the PHY + * interrupt is emulated: while it is enabled, the handler is called + * periodically and the client (usually the NETINIT monitor thread) reads + * the PHY status registers to detect link changes. + */ + +#define PHY_POLL_TICKS MSEC2TICK(CONFIG_DDCNC_EC300_PHY_POLL_MSEC) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static xcpt_t g_phy_handler; +static void *g_phy_arg; +static struct wdog_s g_phy_wdog; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt_enet_phy_poll + * + * Description: + * Watchdog timer callback that emulates the PHY interrupt. + * + ****************************************************************************/ + +static void imxrt_enet_phy_poll(wdparm_t arg) +{ + xcpt_t handler = g_phy_handler; + + if (handler != NULL) + { + handler(0, NULL, g_phy_arg); + } +} + +/**************************************************************************** + * Name: imxrt_enet_phy_enable + ****************************************************************************/ + +static void imxrt_enet_phy_enable(bool enable) +{ + if (enable && g_phy_handler != NULL) + { + wd_start(&g_phy_wdog, PHY_POLL_TICKS, imxrt_enet_phy_poll, 0); + } + else + { + wd_cancel(&g_phy_wdog); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arch_phy_irq + * + * Description: + * This function may be called to register an interrupt handler that will + * be called when a PHY interrupt occurs. This function both attaches + * the interrupt handler and enables the interrupt if 'handler' is non- + * NULL. If handler is NULL, then the interrupt is detached and disabled + * instead. + * + * The PHY interrupt is always disabled upon return. The caller must + * call back through the enable function point to control the state of + * the interrupt. + * + * The EC300 has no PHY interrupt line, so the interrupt is emulated by + * calling the handler every CONFIG_DDCNC_EC300_PHY_POLL_MSEC + * milliseconds while it is enabled. + * + * Input Parameters: + * intf - Identifies the network interface. For example "eth0". + * handler - The client interrupt handler to be invoked when the PHY + * asserts an interrupt. A value of NULL can be passed in order + * to detach and disable the PHY interrupt. + * arg - The argument that will accompany the interrupt + * enable - A function pointer that be used to enable or disable the + * PHY interrupt. + * + * Returned Value: + * Zero (OK) returned on success; a negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int arch_phy_irq(const char *intf, xcpt_t handler, void *arg, + phy_enable_t *enable) +{ + irqstate_t flags; + + DEBUGASSERT(intf); + + ninfo("%s: handler=%p\n", intf, handler); + + if (strcmp(intf, IMXRT_ENET_DEVNAME) != 0) + { + nerr("ERROR: Unsupported interface: %s\n", intf); + return -EINVAL; + } + + flags = enter_critical_section(); + + /* Return with the (emulated) interrupt disabled in either case */ + + wd_cancel(&g_phy_wdog); + + g_phy_handler = handler; + g_phy_arg = arg; + + if (enable) + { + *enable = handler != NULL ? imxrt_enet_phy_enable : NULL; + } + + leave_critical_section(flags); + return OK; +} + +#endif /* CONFIG_IMXRT_ENET && CONFIG_ARCH_PHY_INTERRUPT */ diff --git a/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.c b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.c new file mode 100644 index 00000000000..f87dd60d130 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "imxrt_flexspi_nor_boot.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +locate_data(".boot_hdr.ivt") +const struct ivt_s g_image_vector_table = +{ + IVT_HEADER, /* IVT Header */ + 0x60002000, /* Image Entry Function */ + IVT_RSVD, /* Reserved = 0 */ + (uint32_t)DCD_ADDRESS, /* Address where DCD information is stored */ + (uint32_t)BOOT_DATA_ADDRESS, /* Address where BOOT Data Structure is stored */ + (uint32_t)&g_image_vector_table, /* Pointer to IVT Self (absolute address */ + (uint32_t)CSF_ADDRESS, /* Address where CSF file is stored */ + IVT_RSVD /* Reserved = 0 */ +}; + +locate_data(".boot_hdr.boot_data") +const struct boot_data_s g_boot_data = +{ + FLASH_BASE, /* boot start location */ + (FLASH_END - FLASH_BASE), /* size */ + PLUGIN_FLAG, /* Plugin flag */ + 0xffffffff /* empty - extra data word */ +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.h b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.h new file mode 100644 index 00000000000..6074115e0b7 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.h @@ -0,0 +1,138 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_boot.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_IMXRT_DDCNC_EC300_SRC_IMXRT_FLEXSPI_NOR_BOOT_H +#define __BOARDS_ARM_IMXRT_DDCNC_EC300_SRC_IMXRT_FLEXSPI_NOR_BOOT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <stdint.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* IVT Data */ + +#define IVT_MAJOR_VERSION 0x4 +#define IVT_MAJOR_VERSION_SHIFT 0x4 +#define IVT_MAJOR_VERSION_MASK 0xf +#define IVT_MINOR_VERSION 0x1 +#define IVT_MINOR_VERSION_SHIFT 0x0 +#define IVT_MINOR_VERSION_MASK 0xf + +#define IVT_VERSION(major, minor) \ + ((((major) & IVT_MAJOR_VERSION_MASK) << IVT_MAJOR_VERSION_SHIFT) | \ + (((minor) & IVT_MINOR_VERSION_MASK) << IVT_MINOR_VERSION_SHIFT)) + +#define IVT_TAG_HEADER (0xd1) /* Image Vector Table */ +#define IVT_SIZE 0x2000 +#define IVT_PAR IVT_VERSION(IVT_MAJOR_VERSION, IVT_MINOR_VERSION) + +#define IVT_HEADER (IVT_TAG_HEADER | (IVT_SIZE << 8) | (IVT_PAR << 24)) +#define IVT_RSVD (uint32_t)(0x00000000) + +/* DCD Data */ + +#define DCD_TAG_HEADER (0xd2) +#define DCD_TAG_HEADER_SHIFT (24) +#define DCD_VERSION (0x40) +#define DCD_ARRAY_SIZE 1 + +#define FLASH_BASE 0x60000000 +#define FLASH_END 0x7f7fffff +#define SCLK 1 + +/* The EC300 has no external SDRAM, so no DCD is needed */ + +#define DCD_ADDRESS 0 + +#define BOOT_DATA_ADDRESS &g_boot_data +#define CSF_ADDRESS 0 +#define PLUGIN_FLAG (uint32_t)0 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* IVT Data */ + +struct ivt_s +{ + /* Header with tag #HAB_TAG_IVT, length and HAB version fields + * (see data) + */ + + uint32_t hdr; + + /* Absolute address of the first instruction to execute from the + * image + */ + + uint32_t entry; + + /* Reserved in this version of HAB: should be NULL. */ + + uint32_t reserved1; + + /* Absolute address of the image DCD: may be NULL. */ + + uint32_t dcd; + + /* Absolute address of the Boot Data: may be NULL, but not interpreted + * any further by HAB + */ + + uint32_t boot_data; + + /* Absolute address of the IVT. */ + + uint32_t self; + + /* Absolute address of the image CSF. */ + + uint32_t csf; + + /* Reserved in this version of HAB: should be zero. */ + + uint32_t reserved2; +}; + +/* Boot Data */ + +struct boot_data_s +{ + uint32_t start; /* boot start location */ + uint32_t size; /* size */ + uint32_t plugin; /* plugin flag - 1 if downloaded application is plugin */ + uint32_t placeholder; /* placeholder to make even 0x10 size */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern const struct boot_data_s g_boot_data; + +#endif /* __BOARDS_ARM_IMXRT_DDCNC_EC300_SRC_IMXRT_FLEXSPI_NOR_BOOT_H */ diff --git a/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_flash.c b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_flash.c new file mode 100644 index 00000000000..2bbc6e1d5c8 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_flash.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_flash.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "imxrt_flexspi_nor_flash.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* FlexSPI NOR configuration block used by the i.MX RT ROM bootloader. + * + * The EC300 boots from a 4MiB Quad SPI NOR flash (Winbond W25Q32 style + * command set) connected to FlexSPI port A1. The LUT sequence indices + * follow the layout expected by the ROM: + * + * 0: Quad I/O Fast Read (0xeb) + * 1: Read Status Register (0x05) + * 3: Write Enable (0x06) + * 5: Sector Erase 4KiB (0x20) + * 8: Block Erase 64KiB (0xd8) + * 9: Page Program (0x02) + * 11: Chip Erase (0x60) + */ + +locate_data(".boot_hdr.conf") +const struct flexspi_nor_config_s g_flash_config = +{ + .mem_config = + { + .tag = FLEXSPI_CFG_BLK_TAG, + .version = FLEXSPI_CFG_BLK_VERSION, + .read_sample_clksrc = FLASH_READ_SAMPLE_CLK_LOOPBACK_FROM_DQSPAD, + .cs_hold_time = 3u, + .cs_setup_time = 3u, + .controller_misc_option = + (1u << FLEXSPIMISC_OFFSET_SAFECONFIG_FREQ_EN), + .device_type = FLEXSPI_DEVICE_TYPE_SERIAL_NOR, + .sflash_pad_type = SERIAL_FLASH_4PADS, + .serial_clk_freq = FLEXSPI_SERIAL_CLKFREQ_133MHz, + .sflash_a1size = 4u * 1024u * 1024u, + .lookup_table = + { + /* 0 Quad I/O Fast Read */ + + FLEXSPI_LUT_SEQ(CMD_SDR, + FLEXSPI_1PAD, 0xeb, RADDR_SDR, FLEXSPI_4PAD, 0x18), + FLEXSPI_LUT_SEQ(DUMMY_SDR, + FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04), + 0x00000000, + 0x00000000, + + /* 1 Read Status */ + + FLEXSPI_LUT_SEQ(CMD_SDR, + FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04), + 0x00000000, + 0x00000000, + 0x00000000, + + /* 2 */ + + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + /* 3 Write Enable */ + + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0x0), + 0x00000000, + 0x00000000, + 0x00000000, + + /* 4 */ + + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + /* 5 Erase Sector (4KiB) */ + + FLEXSPI_LUT_SEQ(CMD_SDR, + FLEXSPI_1PAD, 0x20, RADDR_SDR, FLEXSPI_1PAD, 0x18), + 0x00000000, + 0x00000000, + 0x00000000, + + /* 6 */ + + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + /* 7 */ + + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + /* 8 Erase Block (64KiB) */ + + FLEXSPI_LUT_SEQ(CMD_SDR, + FLEXSPI_1PAD, 0xd8, RADDR_SDR, FLEXSPI_1PAD, 0x18), + 0x00000000, + 0x00000000, + 0x00000000, + + /* 9 Page Program */ + + FLEXSPI_LUT_SEQ(CMD_SDR, + FLEXSPI_1PAD, 0x02, RADDR_SDR, FLEXSPI_1PAD, 0x18), + FLEXSPI_LUT_SEQ(WRITE_SDR, + FLEXSPI_1PAD, 0x04, STOP, FLEXSPI_1PAD, 0x0), + 0x00000000, + 0x00000000, + + /* 10 */ + + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + /* 11 Chip Erase */ + + FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60, STOP, FLEXSPI_1PAD, 0x0), + 0x00000000, + 0x00000000, + 0x00000000, + }, + }, + + .page_size = 256u, + .sector_size = 4u * 1024u, + .ipcmd_serial_clkfreq = 1u, + .is_uniform_blocksize = false, + .blocksize = 64u * 1024u, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_flash.h b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_flash.h new file mode 100644 index 00000000000..7b573293799 --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_flash.h @@ -0,0 +1,352 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/imxrt_flexspi_nor_flash.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_IMXRT_DDCNC_EC300_SRC_IMXRT_FLEXSPI_NOR_FLASH_H +#define __BOARDS_ARM_IMXRT_DDCNC_EC300_SRC_IMXRT_FLEXSPI_NOR_FLASH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <stdint.h> +#include <stdbool.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* FLEXSPI memory config block related definitions */ + +#define FLEXSPI_CFG_BLK_TAG (0x42464346ul) +#define FLEXSPI_CFG_BLK_VERSION (0x56010400ul) +#define FLEXSPI_CFG_BLK_SIZE (512) + +/* FLEXSPI Feature related definitions */ + +#define FLEXSPI_FEATURE_HAS_PARALLEL_MODE 1 + +/* Lookup table related definitions */ + +#define CMD_INDEX_READ 0 +#define CMD_INDEX_READSTATUS 1 +#define CMD_INDEX_WRITEENABLE 2 +#define CMD_INDEX_WRITE 4 + +#define CMD_LUT_SEQ_IDX_READ 0 +#define CMD_LUT_SEQ_IDX_READSTATUS 1 +#define CMD_LUT_SEQ_IDX_WRITEENABLE 3 +#define CMD_LUT_SEQ_IDX_WRITE 9 + +#define CMD_SDR 0x01 +#define CMD_DDR 0x21 +#define RADDR_SDR 0x02 +#define RADDR_DDR 0x22 +#define CADDR_SDR 0x03 +#define CADDR_DDR 0x23 +#define MODE1_SDR 0x04 +#define MODE1_DDR 0x24 +#define MODE2_SDR 0x05 +#define MODE2_DDR 0x25 +#define MODE4_SDR 0x06 +#define MODE4_DDR 0x26 +#define MODE8_SDR 0x07 +#define MODE8_DDR 0x27 +#define WRITE_SDR 0x08 +#define WRITE_DDR 0x28 +#define READ_SDR 0x09 +#define READ_DDR 0x29 +#define LEARN_SDR 0x0a +#define LEARN_DDR 0x2a +#define DATSZ_SDR 0x0b +#define DATSZ_DDR 0x2b +#define DUMMY_SDR 0x0c +#define DUMMY_DDR 0x2c +#define DUMMY_RWDS_SDR 0x0d +#define DUMMY_RWDS_DDR 0x2d +#define JMP_ON_CS 0x1f +#define STOP 0 + +#define FLEXSPI_1PAD 0 +#define FLEXSPI_2PAD 1 +#define FLEXSPI_4PAD 2 +#define FLEXSPI_8PAD 3 + +#define FLEXSPI_LUT_OPERAND0_MASK (0xffu) +#define FLEXSPI_LUT_OPERAND0_SHIFT (0U) +#define FLEXSPI_LUT_OPERAND0(x) (((uint32_t) \ + (((uint32_t)(x)) << FLEXSPI_LUT_OPERAND0_SHIFT)) & \ + FLEXSPI_LUT_OPERAND0_MASK) +#define FLEXSPI_LUT_NUM_PADS0_MASK (0x300u) +#define FLEXSPI_LUT_NUM_PADS0_SHIFT (8u) +#define FLEXSPI_LUT_NUM_PADS0(x) (((uint32_t) \ + (((uint32_t)(x)) << FLEXSPI_LUT_NUM_PADS0_SHIFT)) & \ + FLEXSPI_LUT_NUM_PADS0_MASK) +#define FLEXSPI_LUT_OPCODE0_MASK (0xfc00u) +#define FLEXSPI_LUT_OPCODE0_SHIFT (10u) +#define FLEXSPI_LUT_OPCODE0(x) (((uint32_t) \ + (((uint32_t)(x)) << FLEXSPI_LUT_OPCODE0_SHIFT)) & \ + FLEXSPI_LUT_OPCODE0_MASK) +#define FLEXSPI_LUT_OPERAND1_MASK (0xff0000u) +#define FLEXSPI_LUT_OPERAND1_SHIFT (16U) +#define FLEXSPI_LUT_OPERAND1(x) (((uint32_t) \ + (((uint32_t)(x)) << FLEXSPI_LUT_OPERAND1_SHIFT)) & \ + FLEXSPI_LUT_OPERAND1_MASK) +#define FLEXSPI_LUT_NUM_PADS1_MASK (0x3000000u) +#define FLEXSPI_LUT_NUM_PADS1_SHIFT (24u) +#define FLEXSPI_LUT_NUM_PADS1(x) (((uint32_t) \ + (((uint32_t)(x)) << FLEXSPI_LUT_NUM_PADS1_SHIFT)) & \ + FLEXSPI_LUT_NUM_PADS1_MASK) +#define FLEXSPI_LUT_OPCODE1_MASK (0xfc000000u) +#define FLEXSPI_LUT_OPCODE1_SHIFT (26u) +#define FLEXSPI_LUT_OPCODE1(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_OPCODE1_SHIFT)) & \ + FLEXSPI_LUT_OPCODE1_MASK) + +#define FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \ + (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | \ + FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) | \ + FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1)) + +#define NOR_CMD_INDEX_READ CMD_INDEX_READ +#define NOR_CMD_INDEX_READSTATUS CMD_INDEX_READSTATUS +#define NOR_CMD_INDEX_WRITEENABLE CMD_INDEX_WRITEENABLE +#define NOR_CMD_INDEX_ERASESECTOR 3 +#define NOR_CMD_INDEX_PAGEPROGRAM CMD_INDEX_WRITE +#define NOR_CMD_INDEX_CHIPERASE 5 +#define NOR_CMD_INDEX_DUMMY 6 +#define NOR_CMD_INDEX_ERASEBLOCK 7 + +/* READ LUT sequence id in lookupTable stored in config block */ + +#define NOR_CMD_LUT_SEQ_IDX_READ CMD_LUT_SEQ_IDX_READ + +/* Read Status LUT sequence id in lookupTable stored in config block */ + +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS CMD_LUT_SEQ_IDX_READSTATUS + +/* 2 Read status DPI/QPI/OPI sequence id in lookupTable stored in config + * block + */ + +#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI 2 + +/* 3 Write Enable sequence id in lookupTable stored in config block */ + +#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE CMD_LUT_SEQ_IDX_WRITEENABLE + +/* 4 Write Enable DPI/QPI/OPI sequence id in lookupTable stored in config + * block + */ + +#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE_XPI 4 + +/* 5 Erase Sector sequence id in lookupTable stored in config block */ + +#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 5 + +/* 8 Erase Block sequence id in lookupTable stored in config block */ + +#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 8 + +/* 9 Program sequence id in lookupTable stored in config block */ + +#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM CMD_LUT_SEQ_IDX_WRITE + +/* 11 Chip Erase sequence in lookupTable id stored in config block */ + +#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 + +/* 13 Read SFDP sequence in lookupTable id stored in config block */ + +#define NOR_CMD_LUT_SEQ_IDX_READ_SFDP 13 + +/* 14 Restore 0-4-4/0-8-8 mode sequence id in lookupTable stored in config + * block + */ + +#define NOR_CMD_LUT_SEQ_IDX_RESTORE_NOCMD 14 + +/* 15 Exit 0-4-4/0-8-8 mode sequence id in lookupTable stored in config + * blobk + */ + +#define NOR_CMD_LUT_SEQ_IDX_EXIT_NOCMD 15 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Definitions for FlexSPI Serial Clock Frequency */ + +enum flexspi_serial_clkfreq_e +{ + FLEXSPI_SERIAL_CLKFREQ_30MHz = 1, + FLEXSPI_SERIAL_CLKFREQ_50MHz = 2, + FLEXSPI_SERIAL_CLKFREQ_60MHz = 3, + FLEXSPI_SERIAL_CLKFREQ_75MHz = 4, + FLEXSPI_SERIAL_CLKFREQ_80MHz = 5, + FLEXSPI_SERIAL_CLKFREQ_100MHz = 6, + FLEXSPI_SERIAL_CLKFREQ_133MHz = 7, + FLEXSPI_SERIAL_CLKFREQ_166MHz = 8, + FLEXSPI_SERIAL_CLKFREQ_200MHz = 9, +}; + +/* FlexSPI clock configuration type */ + +enum flexspi_serial_clockmode_e +{ + FLEXSPI_CLKMODE_SDR, + FLEXSPI_CLKMODE_DDR, +}; + +/* FlexSPI Read Sample Clock Source definition */ + +enum flash_read_sample_clk_e +{ + FLASH_READ_SAMPLE_CLK_LOOPBACK_INTERNELLY = 0, + FLASH_READ_SAMPLE_CLK_LOOPBACK_FROM_DQSPAD = 1, + FLASH_READ_SAMPLE_CLK_LOOPBACK_FROM_SCKPAD = 2, + FLASH_READ_SAMPLE_CLK_EXT_INPUT_FROM_DQSPAD = 3, +}; + +/* Misc feature bit definitions */ + +enum flash_misc_feature_e +{ + FLEXSPIMISC_OFFSET_DIFFCLKEN = 0, /* Bit for Differential clock enable */ + FLEXSPIMISC_OFFSET_CK2EN = 1, /* Bit for CK2 enable */ + FLEXSPIMISC_OFFSET_PARALLELEN = 2, /* Bit for Parallel mode enable */ + FLEXSPIMISC_OFFSET_WORD_ADDRESSABLE_EN = 3, /* Bit for Word Addressable enable */ + FLEXSPIMISC_OFFSET_SAFECONFIG_FREQ_EN = 4, /* Bit for Safe Configuration Frequency enable */ + FLEXSPIMISC_OFFSET_PAD_SETTING_OVERRIDE_EN = 5, /* Bit for Pad setting override enable */ + FLEXSPIMISC_OFFSET_DDR_MODE_EN = 6, /* Bit for DDR clock configuration indication. */ +}; + +/* Flash Type Definition */ + +enum flash_flash_type_e +{ + FLEXSPI_DEVICE_TYPE_SERIAL_NOR = 1, /* Flash devices are Serial NOR */ + FLEXSPI_DEVICE_TYPE_SERIAL_NAND = 2, /* Flash devices are Serial NAND */ + FLEXSPI_DEVICE_TYPE_SERIAL_RAM = 3, /* Flash devices are Serial RAM/HyperFLASH */ + FLEXSPI_DEVICE_TYPE_MCP_NOR_NAND = 0x12, /* Flash device is MCP device, A1 is Serial NOR, A2 is Serial NAND */ + FLEXSPI_DEVICE_TYPE_MCP_NOR_RAM = 0x13, /* Flash device is MCP device, A1 is Serial NOR, A2 is Serial RAMs */ +}; + +/* Flash Pad Definitions */ + +enum flash_flash_pad_e +{ + SERIAL_FLASH_1PAD = 1, + SERIAL_FLASH_2PADS = 2, + SERIAL_FLASH_4PADS = 4, + SERIAL_FLASH_8PADS = 8, +}; + +/* Flash Configuration Command Type */ + +enum flash_config_cmd_e +{ + DEVICE_CONFIG_CMD_TYPE_GENERIC, /* Generic command, for example: configure dummy cycles, drive strength, etc */ + DEVICE_CONFIG_CMD_TYPE_QUADENABLE, /* Quad Enable command */ + DEVICE_CONFIG_CMD_TYPE_SPI2XPI, /* Switch from SPI to DPI/QPI/OPI mode */ + DEVICE_CONFIG_CMD_TYPE_XPI2SPI, /* Switch from DPI/QPI/OPI to SPI mode */ + DEVICE_CONFIG_CMD_TYPE_SPI2NO_CMD, /* Switch to 0-4-4/0-8-8 mode */ + DEVICE_CONFIG_CMD_TYPE_RESET, /* Reset device command */ +}; + +/* FlexSPI LUT Sequence structure */ + +struct flexspi_lut_seq_s +{ + uint8_t seq_num; /* Sequence Number, valid number: 1-16 */ + uint8_t seq_id; /* Sequence Index, valid number: 0-15 */ + uint16_t reserved; +}; + +/* FlexSPI Memory Configuration Block */ + +struct flexspi_mem_config_s +{ + uint32_t tag; + uint32_t version; + uint32_t reserved0; + uint8_t read_sample_clksrc; + uint8_t cs_hold_time; + uint8_t cs_setup_time; + uint8_t column_address_width; /* [0x00f-0x00f] Column Address with, for + * HyperBus protocol, it is fixed to 3, For + * Serial NAND, need to refer to datasheet + */ + uint8_t device_mode_cfg_enable; + uint8_t device_mode_type; + uint16_t wait_time_cfg_commands; + struct flexspi_lut_seq_s device_mode_seq; + uint32_t device_mode_arg; + uint8_t config_cmd_enable; + uint8_t config_mode_type[3]; + struct flexspi_lut_seq_s config_cmd_seqs[3]; + uint32_t reserved1; + uint32_t config_cmd_args[3]; + uint32_t reserved2; + uint32_t controller_misc_option; + uint8_t device_type; + uint8_t sflash_pad_type; + uint8_t serial_clk_freq; + uint8_t lut_custom_seq_enable; + uint32_t reserved3[2]; + uint32_t sflash_a1size; + uint32_t sflash_a2size; + uint32_t sflash_b1size; + uint32_t sflash_b2size; + uint32_t cspad_setting_override; + uint32_t sclkpad_setting_override; + uint32_t datapad_setting_override; + uint32_t dqspad_setting_override; + uint32_t timeout_in_ms; + uint32_t command_interval; + uint16_t data_valid_time[2]; + uint16_t busy_offset; + uint16_t busybit_polarity; + uint32_t lookup_table[64]; + struct flexspi_lut_seq_s lut_customseq[12]; + uint32_t reserved4[4]; +}; + +/* Serial NOR configuration block */ + +struct flexspi_nor_config_s +{ + struct flexspi_mem_config_s mem_config; /* Common memory configuration info via FlexSPI */ + uint32_t page_size; /* Page size of Serial NOR */ + uint32_t sector_size; /* Sector size of Serial NOR */ + uint8_t ipcmd_serial_clkfreq; /* Clock frequency for IP command */ + uint8_t is_uniform_blocksize; /* Sector/Block size is the same */ + uint8_t reserved0[2]; /* Reserved for future use */ + uint8_t serial_nor_type; /* Serial NOR Flash type: 0/1/2/3 */ + uint8_t need_exit_nocmdmode; /* Need to exit NoCmd mode before other IP command */ + uint8_t halfclk_for_nonreadcmd; /* Half the Serial Clock for non-read command: true/false */ + uint8_t need_restore_nocmdmode; /* Need to Restore NoCmd mode after IP command execution */ + uint32_t blocksize; /* Block size */ + uint32_t reserve2[11]; /* Reserved for future use */ +}; + +#endif /* __BOARDS_ARM_IMXRT_DDCNC_EC300_SRC_IMXRT_FLEXSPI_NOR_FLASH_H */ diff --git a/boards/arm/imxrt/ddcnc-ec300/src/imxrt_userleds.c b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_userleds.c new file mode 100644 index 00000000000..c3f26816bae --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/src/imxrt_userleds.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * boards/arm/imxrt/ddcnc-ec300/src/imxrt_userleds.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* There are three LED indicators located on the EC300 front panel: + * + * - POWER: Main power supply (hardware controlled) + * - IO: IO power supply (hardware controlled) + * - CONN: Communication status, GPIO_SD_B1_00 (GPIO3_IO00) + * + * Only the CONN LED is under software control. Low illuminates. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include "imxrt_gpio.h" +#include "imxrt_iomuxc.h" +#include "ddcnc-ec300.h" + +#include <arch/board/board.h> + +#if !defined(CONFIG_ARCH_LEDS) && defined(GPIO_LED) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_userled_initialize + ****************************************************************************/ + +uint32_t board_userled_initialize(void) +{ + /* Configure LED GPIO for output */ + + imxrt_config_gpio(GPIO_LED); + return BOARD_NLEDS; +} + +/**************************************************************************** + * Name: board_userled + ****************************************************************************/ + +void board_userled(int led, bool ledon) +{ + imxrt_gpio_write(GPIO_LED, !ledon); /* Low illuminates */ +} + +/**************************************************************************** + * Name: board_userled_all + ****************************************************************************/ + +void board_userled_all(uint32_t ledset) +{ + /* Low illuminates */ + + imxrt_gpio_write(GPIO_LED, (ledset & BOARD_USERLED_BIT) == 0); +} + +#endif /* !CONFIG_ARCH_LEDS */ diff --git a/boards/arm/imxrt/ddcnc-ec300/tools/ddcnc-ec300.cfg b/boards/arm/imxrt/ddcnc-ec300/tools/ddcnc-ec300.cfg new file mode 100644 index 00000000000..754dd0f09bb --- /dev/null +++ b/boards/arm/imxrt/ddcnc-ec300/tools/ddcnc-ec300.cfg @@ -0,0 +1,621 @@ +# +# boards/arm/imxrt/ddcnc-ec300/tools/ddcnc-ec300.cfg +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +# OpenOCD configuration for the Digital Dream EC300 (i.MX RT1052) with an +# ST-Link (or any other HLA/SWD) debug probe. +# +# OpenOCD has no flash driver for the i.MX RT FlexSPI controller, so this +# file implements one in Tcl. The QSPI NOR flash is accessed through +# FlexSPI IP commands using standard single-bit SPI NOR commands, so it does +# not depend on how the boot ROM or the running firmware configured the +# controller. +# +# Usage examples: +# +# Backup the whole flash: +# openocd -f ddcnc-ec300.cfg -c "init; ec300_flash_dump backup.bin; shutdown" +# +# Program NuttX (raw binary, linked at 0x60000000) and reboot: +# openocd -f ddcnc-ec300.cfg -c "init; ec300_program nuttx.bin; shutdown" +# +# Other commands (run after "init"): +# ec300_flash_info JEDEC ID and status registers +# ec300_flash_erase <offset> <length> Erase (rounded to 4 KiB sectors) +# ec300_flash_write <file> [offset] Program a raw binary file +# ec300_flash_verify <file> [offset] Compare flash with a binary file +# ec300_flash_erase_all Erase the whole 4 MiB flash +# +# Offsets are relative to the start of the flash (0x60000000). + +if { [info exists INTERFACE] } { + source [find interface/$INTERFACE.cfg] +} else { + source [find interface/stlink.cfg] +} + +transport select hla_swd +adapter speed 1800 + +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +set _CHIPNAME imxrt +set _TARGETNAME $_CHIPNAME.cpu + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id 0x0bd11477 +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap + +$_TARGETNAME configure -work-area-phys 0x20200000 \ + -work-area-size 0x4000 \ + -work-area-backup 0 + +# Flash geometry + +set EC300_FLASH_BASE 0x60000000 +set EC300_FLASH_SIZE 0x00400000 +set EC300_PAGE_SIZE 256 +set EC300_SECTOR_SIZE 0x1000 +set EC300_BLOCK_SIZE 0x10000 + +# OCRAM buffer used to stage the image before programming + +set EC300_BUF_ADDR 0x20200000 +set EC300_BUF_SIZE 0x10000 + +# Registers + +set FLEXSPI 0x402a8000 +set FLEXSPI_MCR0 [expr {$FLEXSPI + 0x000}] +set FLEXSPI_MCR1 [expr {$FLEXSPI + 0x004}] +set FLEXSPI_MCR2 [expr {$FLEXSPI + 0x008}] +set FLEXSPI_AHBCR [expr {$FLEXSPI + 0x00c}] +set FLEXSPI_INTR [expr {$FLEXSPI + 0x014}] +set FLEXSPI_LUTKEY [expr {$FLEXSPI + 0x018}] +set FLEXSPI_LUTCR [expr {$FLEXSPI + 0x01c}] +set FLEXSPI_FLSHA1CR0 [expr {$FLEXSPI + 0x060}] +set FLEXSPI_FLSHA2CR0 [expr {$FLEXSPI + 0x064}] +set FLEXSPI_FLSHB1CR0 [expr {$FLEXSPI + 0x068}] +set FLEXSPI_FLSHB2CR0 [expr {$FLEXSPI + 0x06c}] +set FLEXSPI_FLSHCR1A1 [expr {$FLEXSPI + 0x070}] +set FLEXSPI_FLSHCR2A1 [expr {$FLEXSPI + 0x080}] +set FLEXSPI_IPCR0 [expr {$FLEXSPI + 0x0a0}] +set FLEXSPI_IPCMD [expr {$FLEXSPI + 0x0b0}] +set FLEXSPI_IPRXFCR [expr {$FLEXSPI + 0x0b8}] +set FLEXSPI_IPTXFCR [expr {$FLEXSPI + 0x0bc}] +set FLEXSPI_DLLACR [expr {$FLEXSPI + 0x0c0}] +set FLEXSPI_STS0 [expr {$FLEXSPI + 0x0e0}] +set FLEXSPI_STS1 [expr {$FLEXSPI + 0x0e4}] +set FLEXSPI_RFDR [expr {$FLEXSPI + 0x100}] +set FLEXSPI_TFDR [expr {$FLEXSPI + 0x180}] +set FLEXSPI_LUT [expr {$FLEXSPI + 0x200}] + +set CCM_CSCMR1 0x400fc01c +set CCM_CCGR6 0x400fc080 +set CCM_ANALOG_PFD_528 0x400d8100 + +set IOMUXC_SW_MUX_SD_B1_05 0x401f81e8 +set IOMUXC_SW_PAD_SD_B1_05 0x401f83d8 + +set WDOG1_WMCR 0x400b8008 +set WDOG2_WMCR 0x400d0008 +set RTWDOG_CS 0x400bc000 +set RTWDOG_CNT 0x400bc004 +set RTWDOG_TOVAL 0x400bc008 + +set SCB_CCR 0xe000ed14 + +# FlexSPI LUT sequences +# +# Each LUT instruction is (opcode << 10) | (pads << 8) | operand, and every +# sequence has four 32-bit words with two instructions each. Sequences that +# need a write enable are preceded by a WREN sequence so both can be issued +# with a single IP command (ISEQNUM = 1). + +set LUT_SEQ_READ 0 ;# 0x0b fast read, used for AHB (XIP) reads +set LUT_SEQ_RDSR 1 ;# 0x05 read status register 1 +set LUT_SEQ_PP 2 ;# 0x06 + 0x02 page program +set LUT_SEQ_SE 4 ;# 0x06 + 0x20 4 KiB sector erase +set LUT_SEQ_BE 6 ;# 0x06 + 0xd8 64 KiB block erase +set LUT_SEQ_RDID 8 ;# 0x9f read JEDEC ID +set LUT_SEQ_RESET 9 ;# 0x66 + 0x99 software reset +set LUT_SEQ_RDSR2 11 ;# 0x35 read status register 2 + +proc _lut_instr {opcode pads operand} { + return [expr {($opcode << 10) | ($pads << 8) | $operand}] +} + +proc _lut_word {i0 {i1 0}} { + return [expr {$i0 | ($i1 << 16)}] +} + +proc _lut_cmd {cmd} { + return [_lut_instr 0x01 0 $cmd] +} + +# INTR flags cleared before and after an IP command: IPCMDDONE, IPCMDGE, +# AHBCMDGE, IPCMDERR, AHBCMDERR and SEQTIMEOUT. IPRXWA and IPTXWE must not +# be written here: writing them pops/pushes the IP RX/TX FIFOs. + +set FLEXSPI_INTR_CMD 0x81f + +set LUT_ADDR24 [_lut_instr 0x02 0 24] +set LUT_DUMMY8 [_lut_instr 0x0c 0 8] +set LUT_READ [_lut_instr 0x09 0 4] +set LUT_WRITE [_lut_instr 0x08 0 4] + +proc _flexspi_wait_idle {} { + global FLEXSPI_STS0 + + for {set i 0} {$i < 1000} {incr i} { + if {([read_memory $FLEXSPI_STS0 32 1] & 0x3) == 0x3} { + return + } + } + + error "FlexSPI: controller is not idle" +} + +proc _flexspi_load_lut {} { + global FLEXSPI_LUTKEY FLEXSPI_LUTCR FLEXSPI_LUT + global LUT_ADDR24 LUT_DUMMY8 LUT_READ LUT_WRITE + + set seqs [dict create \ + 0 [list [_lut_word [_lut_cmd 0x0b] $LUT_ADDR24] \ + [_lut_word $LUT_DUMMY8 $LUT_READ] 0 0] \ + 1 [list [_lut_word [_lut_cmd 0x05] $LUT_READ] 0 0 0] \ + 2 [list [_lut_word [_lut_cmd 0x06]] 0 0 0] \ + 3 [list [_lut_word [_lut_cmd 0x02] $LUT_ADDR24] \ + [_lut_word $LUT_WRITE] 0 0] \ + 4 [list [_lut_word [_lut_cmd 0x06]] 0 0 0] \ + 5 [list [_lut_word [_lut_cmd 0x20] $LUT_ADDR24] 0 0 0] \ + 6 [list [_lut_word [_lut_cmd 0x06]] 0 0 0] \ + 7 [list [_lut_word [_lut_cmd 0xd8] $LUT_ADDR24] 0 0 0] \ + 8 [list [_lut_word [_lut_cmd 0x9f] $LUT_READ] 0 0 0] \ + 9 [list [_lut_word [_lut_cmd 0x66]] 0 0 0] \ + 10 [list [_lut_word [_lut_cmd 0x99]] 0 0 0] \ + 11 [list [_lut_word [_lut_cmd 0x35] $LUT_READ] 0 0 0]] + + # Unlock the LUT, write the sequences and lock it again + + mww $FLEXSPI_LUTKEY 0x5af05af0 + mww $FLEXSPI_LUTCR 0x2 + + dict for {seq words} $seqs { + write_memory [expr {$FLEXSPI_LUT + $seq * 16}] 32 $words + } + + mww $FLEXSPI_LUTKEY 0x5af05af0 + mww $FLEXSPI_LUTCR 0x1 +} + +# Issue an IP command. The data size is in bytes and nseq is the number of +# additional sequences to execute after the first one. + +proc _flexspi_ip_start {seq addr {size 0} {nseq 0}} { + global FLEXSPI_INTR FLEXSPI_INTR_CMD FLEXSPI_IPCR0 FLEXSPI_IPCMD + + mww $FLEXSPI_INTR $FLEXSPI_INTR_CMD + write_memory $FLEXSPI_IPCR0 32 \ + [list $addr [expr {($nseq << 24) | ($seq << 16) | $size}]] + mww $FLEXSPI_IPCMD 0x1 +} + +proc _flexspi_ip_wait {} { + global FLEXSPI_INTR FLEXSPI_INTR_CMD FLEXSPI_STS1 + + for {set i 0} {$i < 1000} {incr i} { + set intr [read_memory $FLEXSPI_INTR 32 1] + + # IPCMDERR (bit 3) or SEQTIMEOUT (bit 11) + + if {$intr & 0x808} { + set sts1 [read_memory $FLEXSPI_STS1 32 1] + mww $FLEXSPI_INTR $FLEXSPI_INTR_CMD + error [format "FlexSPI: IP command failed, INTR=0x%08x STS1=0x%08x" \ + $intr $sts1] + } + + # IPCMDDONE (bit 0) + + if {$intr & 0x1} { + mww $FLEXSPI_INTR 0x1 + return + } + } + + error "FlexSPI: IP command timeout" +} + +proc _flexspi_ip_cmd {seq {addr 0} {nseq 0}} { + _flexspi_ip_start $seq $addr 0 $nseq + _flexspi_ip_wait +} + +# Execute a read sequence and return up to 8 bytes as a list of words + +proc _flexspi_ip_read {seq size {addr 0}} { + global FLEXSPI_IPRXFCR FLEXSPI_RFDR + + mww $FLEXSPI_IPRXFCR 0x1 + _flexspi_ip_start $seq $addr $size + _flexspi_ip_wait + + set data [read_memory $FLEXSPI_RFDR 32 [expr {($size + 3) / 4}]] + mww $FLEXSPI_IPRXFCR 0x1 + return $data +} + +proc _nor_read_status {} { + global LUT_SEQ_RDSR + return [expr {[lindex [_flexspi_ip_read $LUT_SEQ_RDSR 1] 0] & 0xff}] +} + +proc _nor_wait_ready {{timeout_ms 5000}} { + set start [ms] + while {[_nor_read_status] & 0x1} { + if {[ms] - $start > $timeout_ms} { + error "QSPI NOR: timeout waiting for the flash to be ready" + } + } +} + +# Program one page (up to 256 bytes) from a list of 32-bit words + +proc _nor_program_page {offset words} { + global FLEXSPI_INTR FLEXSPI_IPTXFCR FLEXSPI_TFDR LUT_SEQ_PP + + set size [expr {[llength $words] * 4}] + + # Clear the TX FIFO and set the watermark to 128 bytes + + mww $FLEXSPI_IPTXFCR [expr {(15 << 2) | 0x1}] + + _flexspi_ip_start $LUT_SEQ_PP $offset $size 1 + + for {set i 0} {$i < [llength $words]} {incr i 32} { + for {set j 0} {$j < 1000} {incr j} { + if {[read_memory $FLEXSPI_INTR 32 1] & 0x40} { + break + } + } + + # Fill the FIFO and push the data with IPTXWE (bit 6) + + set chunk [lrange $words $i [expr {$i + 31}]] + while {[llength $chunk] < 32} { + lappend chunk 0xffffffff + } + + write_memory $FLEXSPI_TFDR 32 $chunk + mww $FLEXSPI_INTR 0x40 + } + + _flexspi_ip_wait + _nor_wait_ready +} + +proc _ec300_disable_watchdogs {} { + global WDOG1_WMCR WDOG2_WMCR RTWDOG_CS RTWDOG_CNT RTWDOG_TOVAL + + # Disable the WDOG1/WDOG2 power down counters. WDOG1/WDOG2 themselves + # cannot be disabled once enabled. + + mwh $WDOG1_WMCR 0 + mwh $WDOG2_WMCR 0 + + # Disable RTWDOG (WDOG3) if it is enabled and can be updated + + set cs [read_memory $RTWDOG_CS 32 1] + if {($cs & 0x80) && ($cs & 0x20)} { + mww $RTWDOG_CNT 0xd928c520 + mww $RTWDOG_TOVAL 0xffff + mww $RTWDOG_CS [expr {($cs & ~0x80) | 0x20}] + } +} + +# Halt the CPU and configure FlexSPI for the programming commands + +proc ec300_flash_init {} { + global FLEXSPI_MCR0 FLEXSPI_MCR1 FLEXSPI_MCR2 FLEXSPI_AHBCR + global FLEXSPI_FLSHA1CR0 FLEXSPI_FLSHA2CR0 FLEXSPI_FLSHB1CR0 + global FLEXSPI_FLSHB2CR0 FLEXSPI_FLSHCR1A1 FLEXSPI_FLSHCR2A1 + global FLEXSPI_DLLACR FLEXSPI_INTR FLEXSPI_INTR_CMD + global CCM_CSCMR1 CCM_CCGR6 CCM_ANALOG_PFD_528 + global IOMUXC_SW_MUX_SD_B1_05 IOMUXC_SW_PAD_SD_B1_05 + global SCB_CCR LUT_SEQ_RESET EC300_FLASH_SIZE + + halt + wait_halt 1000 + + # The firmware may have enabled the caches. Disable them so that debug + # reads of the flash memory map see the new contents. Nothing is + # written back: the chip is reset after programming. + + mww $SCB_CCR [expr {[read_memory $SCB_CCR 32 1] & ~0x30000}] + + _ec300_disable_watchdogs + + # Disable FlexSPI before changing its clock + + _flexspi_wait_idle + mww $FLEXSPI_MCR0 [expr {[read_memory $FLEXSPI_MCR0 32 1] | 0x2}] + + # FlexSPI clock: PLL2 PFD2 = 528 MHz * 18 / 35 = 271.5 MHz, divided by + # 8 = 34 MHz. The PFD is only used by SEMC/uSDHC, which the EC300 + # doesn't use, and it is reconfigured by the next boot anyway. + + mmw $CCM_CCGR6 0 [expr {0x3 << 10}] + mmw $CCM_ANALOG_PFD_528 [expr {35 << 16}] [expr {0xbf << 16}] + mmw $CCM_CSCMR1 [expr {(2 << 29) | (7 << 23)}] \ + [expr {(3 << 29) | (7 << 23)}] + mmw $CCM_CCGR6 [expr {0x3 << 10}] 0 + + # FlexSPI pins: GPIO_SD_B1_05..11 in ALT1 with the boot ROM pad + # settings. DQS is not used (the read strobe is looped back + # internally), but it is configured the same way the boot ROM does. + + for {set i 0} {$i < 7} {incr i} { + mww [expr {$IOMUXC_SW_MUX_SD_B1_05 + $i * 4}] 0x1 + mww [expr {$IOMUXC_SW_PAD_SD_B1_05 + $i * 4}] 0x10f1 + } + + # Module configuration (still disabled): maximum grant wait, internal + # dummy read strobe, single 4 MiB flash on port A1. + + mww $FLEXSPI_MCR0 0xffff0002 + mww $FLEXSPI_MCR1 0xffffffff + mww $FLEXSPI_MCR2 0x200001f7 + mww $FLEXSPI_AHBCR 0x00000078 + mww $FLEXSPI_FLSHA1CR0 [expr {$EC300_FLASH_SIZE / 1024}] + mww $FLEXSPI_FLSHA2CR0 0 + mww $FLEXSPI_FLSHB1CR0 0 + mww $FLEXSPI_FLSHB2CR0 0 + mww $FLEXSPI_FLSHCR1A1 0x00000063 + mww $FLEXSPI_FLSHCR2A1 0x00000000 + + # The clock is below 100 MHz: bypass the DLL + + mww $FLEXSPI_DLLACR 0x00000100 + + # Enable the module and perform a software reset + + mww $FLEXSPI_MCR0 0xffff0000 + mww $FLEXSPI_MCR0 0xffff0001 + for {set i 0} {$i < 1000} {incr i} { + if {([read_memory $FLEXSPI_MCR0 32 1] & 0x1) == 0} { + break + } + } + + mww $FLEXSPI_INTR $FLEXSPI_INTR_CMD + _flexspi_load_lut + + # Reset the flash to make sure it is not in a continuous read mode + + _flexspi_ip_cmd $LUT_SEQ_RESET 0 1 + sleep 1 + _nor_wait_ready +} + +proc _flexspi_flush_ahb {} { + global FLEXSPI_MCR0 + + # Software reset clears the AHB RX buffers, so AHB reads return the new + # contents of the flash + + mww $FLEXSPI_MCR0 [expr {[read_memory $FLEXSPI_MCR0 32 1] | 0x1}] + for {set i 0} {$i < 1000} {incr i} { + if {([read_memory $FLEXSPI_MCR0 32 1] & 0x1) == 0} { + return + } + } +} + +proc ec300_flash_info {} { + global LUT_SEQ_RDID LUT_SEQ_RDSR2 + + ec300_flash_init + + set id [lindex [_flexspi_ip_read $LUT_SEQ_RDID 3] 0] + set sr1 [_nor_read_status] + set sr2 [expr {[lindex [_flexspi_ip_read $LUT_SEQ_RDSR2 1] 0] & 0xff}] + + echo [format "QSPI NOR: manufacturer 0x%02x, device 0x%02x%02x" \ + [expr {$id & 0xff}] [expr {($id >> 8) & 0xff}] \ + [expr {($id >> 16) & 0xff}]] + echo [format "QSPI NOR: SR1 0x%02x, SR2 0x%02x" $sr1 $sr2] + + if {$sr1 & 0x7c} { + echo "QSPI NOR: WARNING: block protection bits are set" + } +} + +proc _ec300_check_range {offset length} { + global EC300_FLASH_SIZE + + if {$offset < 0 || $length <= 0 || \ + $offset + $length > $EC300_FLASH_SIZE} { + error [format "Invalid flash range 0x%x + 0x%x" $offset $length] + } +} + +proc _ec300_erase {offset length} { + global EC300_SECTOR_SIZE EC300_BLOCK_SIZE LUT_SEQ_SE LUT_SEQ_BE + + _ec300_check_range $offset $length + + set end [expr {($offset + $length + $EC300_SECTOR_SIZE - 1) & \ + ~($EC300_SECTOR_SIZE - 1)}] + set addr [expr {$offset & ~($EC300_SECTOR_SIZE - 1)}] + + echo [format "Erasing 0x%06x..0x%06x" $addr [expr {$end - 1}]] + + while {$addr < $end} { + if {($addr & ($EC300_BLOCK_SIZE - 1)) == 0 && \ + $addr + $EC300_BLOCK_SIZE <= $end} { + _flexspi_ip_cmd $LUT_SEQ_BE $addr 1 + incr addr $EC300_BLOCK_SIZE + } else { + _flexspi_ip_cmd $LUT_SEQ_SE $addr 1 + incr addr $EC300_SECTOR_SIZE + } + + _nor_wait_ready + } +} + +proc ec300_flash_erase {offset length} { + ec300_flash_init + _ec300_erase $offset $length + _flexspi_flush_ahb +} + +proc ec300_flash_erase_all {} { + global EC300_FLASH_SIZE + ec300_flash_erase 0 $EC300_FLASH_SIZE +} + +proc _ec300_write {file offset} { + global EC300_BUF_ADDR EC300_BUF_SIZE EC300_PAGE_SIZE + + set size [file size $file] + _ec300_check_range $offset $size + + if {$offset % $EC300_PAGE_SIZE} { + error "The offset must be aligned to the page size" + } + + set start [ms] + set blank [lrepeat [expr {$EC300_PAGE_SIZE / 4}] 0xffffffff] + + echo [format "Programming %d bytes at 0x%06x" $size $offset] + + for {set win 0} {$win < $size} {incr win $EC300_BUF_SIZE} { + set len [expr {$size - $win}] + if {$len > $EC300_BUF_SIZE} { + set len $EC300_BUF_SIZE + } + + # Load this window of the file into OCRAM, padded with 0xff + + set nwords [expr {($len + $EC300_PAGE_SIZE - 1) / 4 & \ + ~($EC300_PAGE_SIZE / 4 - 1)}] + write_memory $EC300_BUF_ADDR 32 [lrepeat $nwords 0xffffffff] + load_image $file [expr {$EC300_BUF_ADDR - $win}] bin \ + $EC300_BUF_ADDR $len + + for {set page 0} {$page < $len} {incr page $EC300_PAGE_SIZE} { + set words [read_memory [expr {$EC300_BUF_ADDR + $page}] 32 \ + [expr {$EC300_PAGE_SIZE / 4}]] + + if {$words ne $blank} { + _nor_program_page [expr {$offset + $win + $page}] $words + } + } + + echo [format " 0x%06x / 0x%06x" [expr {$win + $len}] $size] + } + + echo [format "Programmed %d bytes in %.1f s" $size \ + [expr {([ms] - $start) / 1000.0}]] +} + +proc ec300_flash_write {file {offset 0}} { + ec300_flash_init + _ec300_write $file $offset + _flexspi_flush_ahb +} + +# Compare the flash with a file. This does not use verify_image, which runs +# a CRC algorithm on the CPU: the file is staged in OCRAM and both copies are +# read back through the debug port. + +proc ec300_flash_verify {file {offset 0}} { + global EC300_FLASH_BASE EC300_BUF_ADDR EC300_BUF_SIZE + + set size [file size $file] + _ec300_check_range $offset $size + + ec300_flash_init + _flexspi_flush_ahb + + for {set win 0} {$win < $size} {incr win $EC300_BUF_SIZE} { + set len [expr {$size - $win}] + if {$len > $EC300_BUF_SIZE} { + set len $EC300_BUF_SIZE + } + + # Compare whole words, the last one padded with 0xff + + set nwords [expr {($len + 3) / 4}] + write_memory $EC300_BUF_ADDR 32 [lrepeat $nwords 0xffffffff] + load_image $file [expr {$EC300_BUF_ADDR - $win}] bin \ + $EC300_BUF_ADDR $len + + set expected [read_memory $EC300_BUF_ADDR 32 $nwords] + set actual [read_memory \ + [expr {$EC300_FLASH_BASE + $offset + $win}] 32 $nwords] + + if {$expected ne $actual} { + for {set i 0} {$i < $nwords} {incr i} { + if {[lindex $expected $i] != [lindex $actual $i]} { + break + } + } + + error [format "Verify failed at 0x%06x: 0x%08x != 0x%08x" \ + [expr {$offset + $win + $i * 4}] \ + [lindex $actual $i] [lindex $expected $i]] + } + } + + echo [format "Verified %d bytes at 0x%06x" $size $offset] +} + +proc ec300_flash_dump {file {offset 0} {length 0}} { + global EC300_FLASH_BASE EC300_FLASH_SIZE + + if {$length == 0} { + set length [expr {$EC300_FLASH_SIZE - $offset}] + } + + _ec300_check_range $offset $length + + ec300_flash_init + _flexspi_flush_ahb + dump_image $file [expr {$EC300_FLASH_BASE + $offset}] $length +} + +# Erase, program, verify and reboot + +proc ec300_program {file {offset 0}} { + ec300_flash_init + _ec300_erase $offset [file size $file] + _ec300_write $file $offset + ec300_flash_verify $file $offset + reset run +} + +# The i.MX RT does not halt with SRST. Without SRST, the HLA layer resets +# the chip with SYSRESETREQ, which reboots it through the boot ROM. + +reset_config none
