Compare commits

...

5 Commits

Author SHA1 Message Date
Peter van der Perk 7848b1dacc tropic-community: Don't use last 4kB of flash for storage 2025-06-29 14:34:45 +02:00
Peter van der Perk 6e0d744c51 tropic-community: Update SPI driver and basic hwver support 2025-06-29 14:07:28 +02:00
Peter van der Perk c3fbaf18f1 tropic-community: use ROM api for flash storage 2025-06-29 14:07:17 +02:00
Peter van der Perk 6c57ddc495 rt106x: Add romapi support and reboot to isp/bootloader 2025-06-26 09:11:54 +02:00
Peter van der Perk 496843dbad rt106x: Use platform SPI hal layer 2025-06-26 09:11:54 +02:00
24 changed files with 1035 additions and 619 deletions
@@ -14,6 +14,7 @@ CONFIG_DRIVERS_CAMERA_TRIGGER=y
CONFIG_DRIVERS_CDCACM_AUTOSTART=y
CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y
CONFIG_COMMON_DISTANCE_SENSOR=y
CONFIG_DRIVERS_DISTANCE_SENSOR_LIGHTWARE_SF45_SERIAL=y
CONFIG_DRIVERS_DSHOT=y
CONFIG_DRIVERS_GNSS_SEPTENTRIO=y
CONFIG_DRIVERS_GPS=y
@@ -7,7 +7,7 @@
"summary": "TROPIC Community",
"version": "0.1",
"image_size": 0,
"image_maxsize": 0,
"image_maxsize": 8126464,
"git_identity": "",
"board_revision": 0
}
@@ -61,7 +61,9 @@ CONFIG_FS_CROMFS=y
CONFIG_FS_FAT=y
CONFIG_FS_FATTIME=y
CONFIG_FS_LITTLEFS=y
CONFIG_FS_LITTLEFS_PROGRAM_SIZE_FACTOR=2
CONFIG_FS_LITTLEFS_CACHE_SIZE_FACTOR=2
CONFIG_FS_LITTLEFS_LOOKAHEAD_SIZE=64
CONFIG_FS_LITTLEFS_PROGRAM_SIZE_FACTOR=1
CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_MAX_TASKS=64
CONFIG_FS_PROCFS_REGISTER=y
@@ -83,8 +85,6 @@ CONFIG_IMXRT_ENET_NTXBUFFERS=8
CONFIG_IMXRT_ENET_PHYINIT=y
CONFIG_IMXRT_FLEXCAN3=y
CONFIG_IMXRT_FLEXCAN_TXMB=1
CONFIG_IMXRT_FLEXSPI1=y
CONFIG_IMXRT_FLEXSPI1_XIP=y
CONFIG_IMXRT_GPIO1_0_15_IRQ=y
CONFIG_IMXRT_GPIO1_16_31_IRQ=y
CONFIG_IMXRT_GPIO2_0_15_IRQ=y
@@ -20,7 +20,12 @@
*(.text.imxrt_enet_interrupt)
*(.text.imxrt_enet_interrupt_work)
*(.text.imxrt_interrupt)
*(.text.imxrt_gpio1_16_31_interrupt)
*(.text.imxrt_gpio2_0_15_interrupt)
*(.text.imxrt_gpio3_16_31_interrupt)
*(.text.imxrt_lpi2c_isr)
*(.text.imxrt_lpspi3select)
*(.text.imxrt_lpspi4select)
*(.text.imxrt_lpspi_exchange)
*(.text.imxrt_recvdma)
*(.text.imxrt_tcd_free)
@@ -115,18 +120,45 @@
*(.text.work_thread)
*(.text.work_queue)
/* Flash Storage */
*(.text.imxrt_flexspi_transfer_blocking)
*(.text.imxrt_flexspi_transfer_blocking_private)
*(.text.imxrt_flexspi_write_blocking)
*(.text.imxrt_flexspi_read_blocking)
*(.text.imxrt_flexspi_check_and_clear_error)
*(.text.imxrt_flexspi_get_bus_idle_status)
*(.text.imxrt_flexspi_configure_prefetch)
*(.text.imxrt_flexspi_configure_prefetch_private)
*(.text.imxrt_flexspi_storage_write_enable)
*(.text.imxrt_flexspi_storage_wait_bus_busy)
*(.text.imxrt_flexspi_storage_read_status)
*(.text.imxrt_flexspi_storage_erase)
*(.text.imxrt_flexspi_storage_bwrite)
*(.text.imxrt_flexspi_storage_page_program)
/* ICM45686 */
*(.text._ZN8ICM4568612ProcessAccelERKyPKN19InvenSense_ICM456864FIFO4DATAEh)
*(.text._ZN8ICM4568611ProcessGyroERKyPKN19InvenSense_ICM456864FIFO4DATAEh)
*(.text._ZN8ICM456868FIFOReadERKy)
*(.text._ZN8ICM456867RunImplEv)
*(.text._ZN8ICM4568618ProcessTemperatureEPKN19InvenSense_ICM456864FIFO4DATAEh)
*(.text._ZN12I2CSPIDriverI8ICM45686E3RunEv)
*(.text._ZN8ICM4568613FIFOReadCountEv)
/* BMI088 */
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer12RegisterReadENS1_8RegisterE)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer13FIFOReadCountEv)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer8FIFOReadERKyh)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer13RegisterCheckERKNS2_17register_config_tE)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer13RegisterWriteENS1_8RegisterEh)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer17UpdateTemperatureEv)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer23RegisterSetAndClearBitsENS1_8RegisterEhh)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer26DataReadyInterruptCallbackEiPvS3_)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer7RunImplEv)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_Accelerometer9DataReadyEv)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_AccelerometerD0Ev)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_AccelerometerD1Ev)
*(.text._ZN5Bosch6BMI08813Accelerometer20BMI088_AccelerometerD2Ev)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_Gyroscope12RegisterReadENS1_8RegisterE)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_Gyroscope13RegisterCheckERKNS2_17register_config_tE)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_Gyroscope13RegisterWriteENS1_8RegisterEh)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_Gyroscope23RegisterSetAndClearBitsENS1_8RegisterEhh)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_Gyroscope26DataReadyInterruptCallbackEiPvS3_)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_Gyroscope7RunImplEv)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_Gyroscope8FIFOReadERKyh)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_Gyroscope9DataReadyEv)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_GyroscopeD0Ev)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_GyroscopeD1Ev)
*(.text._ZN5Bosch6BMI0889Gyroscope16BMI088_GyroscopeD2Ev)
*(.text._ZN12I2CSPIDriverI6BMI088E3RunEv)
/* BMM350 */
*(.text._ZN12I2CSPIDriverI6BMM350E3RunEv)
*(.text._ZN6BMM3507RunImplEv)
*(.text._ZN6BMM35013RegisterWriteEN12Bosch_BMM3508RegisterEh)
*(.text._ZN6BMM35012RegisterReadEN12Bosch_BMM3508RegisterEPh)
*(.text._ZN6BMM35014ReadOutRawDataEPf)
@@ -80,6 +80,13 @@ SECTIONS
{
_stext = ABSOLUTE(.);
*(.vectors)
. = ALIGN(32);
/*
This signature provides the bootloader with a way to delay booting
*/
_bootdelay_signature = ABSOLUTE(.);
FILL(0xffecc2925d7d05c5)
. += 8;
*(.text .text.*)
*(.fixup)
*(.gnu.warning)
@@ -162,6 +169,10 @@ SECTIONS
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
_boot_loadaddr = ORIGIN(flash);
_boot_size = LENGTH(flash);
_ram_size = LENGTH(sram);
_sdtcm = ORIGIN(dtcm);
_edtcm = ORIGIN(dtcm) + LENGTH(dtcm);
}
+51 -22
View File
@@ -30,28 +30,57 @@
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
if("${PX4_BOARD_LABEL}" STREQUAL "bootloader")
add_compile_definitions(BOOTLOADER)
add_library(drivers_board
bootloader_main.c
init.c
usb.c
imxrt_flexspi_nor_boot.c
imxrt_flexspi_nor_flash.c
timer_config.cpp
)
target_link_libraries(drivers_board
PRIVATE
nuttx_arch # sdio
nuttx_drivers # sdio
px4_layer #gpio
arch_io_pins # iotimer
arch_board_romapi
bootloader
)
target_include_directories(drivers_board PRIVATE ${PX4_SOURCE_DIR}/platforms/nuttx/src/bootloader/common)
px4_add_library(drivers_board
i2c.cpp
init.c
sdhc.c
spi.cpp
timer_config.cpp
tropic_led_pwm.cpp
usb.c
imxrt_flexspi_nor_boot.c
imxrt_flexspi_nor_flash.c
imxrt_flexspi_storage.c
imxrt_ocram_initialize.c
)
else()
# Force compiler not to use builtin functions (like memcpy)
# to optimize for loops in init.c (imxrt_ocram_initialize)
set_source_files_properties(imxrt_ocram_initialize.c PROPERTIES COMPILE_FLAGS -fno-builtin)
px4_add_library(drivers_board
i2c.cpp
init.c
sdhc.c
spi.cpp
timer_config.cpp
tropic_led_pwm.cpp
usb.c
imxrt_flexspi_nor_boot.c
imxrt_flexspi_nor_flash.c
imxrt_flexspi_storage.c
imxrt_ocram_initialize.c
hw_rev_ver_tropic.c
manifest.c
)
target_link_libraries(drivers_board
PRIVATE
nuttx_arch # sdio
nuttx_drivers # sdio
px4_layer
)
# Force compiler not to use builtin functions (like memcpy)
# to optimize for loops in init.c (imxrt_ocram_initialize)
set_source_files_properties(imxrt_ocram_initialize.c PROPERTIES COMPILE_FLAGS -fno-builtin)
target_link_libraries(drivers_board
PRIVATE
arch_board_romapi
arch_spi
nuttx_arch # sdio
nuttx_drivers # sdio
px4_layer
)
endif()
+16 -1
View File
@@ -112,7 +112,6 @@
#define GPIO_DRDY_OFF_SPI4_DRDY7_EXTERNAL1 _PIN_OFF(GPIO_SPI4_DRDY7_EXTERNAL1)
#define ADC_IOMUX (IOMUX_CMOS_INPUT | IOMUX_PULL_NONE | IOMUX_DRIVE_HIZ)
#define ADC1_CH(n) (n)
@@ -262,6 +261,18 @@ static inline int board_read_usb2_vbus_state(void)
}
#define BOARD_ENABLE_CONSOLE_BUFFER
/* To detect IMU */
#define BOARD_HAS_HW_VERSIONING 1
#define BOARD_HAS_HW_SPLIT_VERSIONING 1
#define HW_INFO_INIT_PREFIX "TROPIC"
#define BOARD_NUM_SPI_CFG_HW_VERSIONS 3
// Base/FMUM
#define TROPIC_0 HW_FMUM_ID(0x0) // ICM42688
#define TROPIC_1 HW_FMUM_ID(0x1) // ICM42688
#define TROPIC_2 HW_FMUM_ID(0x2) // ICM45686
__BEGIN_DECLS
/****************************************************************************************************
@@ -316,6 +327,8 @@ extern int imxrt1062_spi_bus_initialize(void);
*
************************************************************************************/
extern void imxrt_spiinitialize(void);
extern int imxrt_usb_initialize(void);
extern void imxrt_usbinitialize(void);
@@ -326,6 +339,8 @@ extern void fmurt1062_timer_initialize(void);
#include <px4_platform_common/board_common.h>
void imxrt_flash_romapi_initialize(void);
int imxrt_flexspi_storage_initialize(void);
#endif /* __ASSEMBLY__ */
@@ -0,0 +1,61 @@
/****************************************************************************
*
* Copyright (c) 2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file bootloader_main.c
*
* FMU-specific early startup code for bootloader
*/
#include "board_config.h"
#include "bl.h"
#include <nuttx/config.h>
#include <nuttx/board.h>
#include <chip.h>
#include <arch/board/board.h>
#include "arm_internal.h"
#include <px4_platform_common/init.h>
extern int sercon_main(int c, char **argv);
void board_late_initialize(void)
{
sercon_main(0, NULL);
}
extern void sys_tick_handler(void);
void board_timerhook(void)
{
sys_tick_handler();
}
+130
View File
@@ -0,0 +1,130 @@
/*
* hw_config.h
*
* Created on: May 17, 2015
* Author: david_s5
*/
#ifndef HW_CONFIG_H_
#define HW_CONFIG_H_
/****************************************************************************
* 10-8--2016:
* To simplify the ripple effect on the tools, we will be using
* /dev/serial/by-id/<asterisk>PX4<asterisk> to locate PX4 devices. Therefore
* moving forward all Bootloaders must contain the prefix "PX4 BL "
* in the USBDEVICESTRING
* This Change will be made in an upcoming BL release
****************************************************************************/
/*
* Define usage to configure a bootloader
*
*
* Constant example Usage
* APP_LOAD_ADDRESS 0x08004000 - The address in Linker Script, where the app fw is org-ed
* BOOTLOADER_DELAY 5000 - Ms to wait while under USB pwr or bootloader request
* BOARD_FMUV2
* INTERFACE_USB 1 - (Optional) Scan and use the USB interface for bootloading
* INTERFACE_USART 1 - (Optional) Scan and use the Serial interface for bootloading
* USBDEVICESTRING "PX4 BL FMU v2.x" - USB id string
* USBPRODUCTID 0x0011 - PID Should match defconfig
* BOOT_DELAY_ADDRESS 0x000001a0 - (Optional) From the linker script from Linker Script to get a custom
* delay provided by an APP FW
* BOARD_TYPE 9 - Must match .prototype boad_id
* _FLASH_KBYTES (*(uint16_t *)0x1fff7a22) - Run time flash size detection
* BOARD_FLASH_SECTORS ((_FLASH_KBYTES == 0x400) ? 11 : 23) - Run time determine the physical last sector
* BOARD_FLASH_SECTORS 11 - Hard coded zero based last sector
* BOARD_FLASH_SIZE (_FLASH_KBYTES*1024)- Total Flash size of device, determined at run time.
* (1024 * 1024) - Hard coded Total Flash of device - The bootloader and app reserved will be deducted
* programmatically
*
* BOARD_FIRST_FLASH_SECTOR_TO_ERASE 2 - Optional sectors index in the flash_sectors table (F4 only), to begin erasing.
* This is to allow sectors to be reserved for app fw usage. That will NOT be erased
* during a FW upgrade.
* The default is 0, and selects the first sector to be erased, as the 0th entry in the
* flash_sectors table. Which is the second physical sector of FLASH in the device.
* The first physical sector of FLASH is used by the bootloader, and is not defined
* in the table.
*
* APP_RESERVATION_SIZE (BOARD_FIRST_FLASH_SECTOR_TO_ERASE * 16 * 1024) - Number of bytes reserved by the APP FW. This number plus
* BOOTLOADER_RESERVATION_SIZE will be deducted from
* BOARD_FLASH_SIZE to determine the size of the App FW
* and hence the address space of FLASH to erase and program.
* USBMFGSTRING "PX4 AP" - Optional USB MFG string (default is '3D Robotics' if not defined.)
* SERIAL_BREAK_DETECT_DISABLED - Optional prevent break selection on Serial port from entering or staying in BL
*
* * Other defines are somewhat self explanatory.
*/
/* Boot device selection list*/
#define USB0_DEV 0x01
#define SERIAL0_DEV 0x02
#define SERIAL1_DEV 0x04
#define APP_LOAD_ADDRESS 0x60020000
#define APP_VECTOR_OFFSET 0x2000
#define BOOTLOADER_DELAY 5000
#define INTERFACE_USB 1
#define INTERFACE_USB_CONFIG "/dev/ttyACM0"
//#define USE_VBUS_PULL_DOWN
#define INTERFACE_USART 1
#define INTERFACE_USART_CONFIG "/dev/ttyS0,1500000"
#define BOOT_DELAY_ADDRESS 0x00039FA0
#define BOARD_TYPE 37
// The board has a 8 Mb part with 2048, 4K secors
// as 1024, 4K sectors
#define BOARD_FLASH_SECTORS 1984 // 1024 * 4k sectors, 128k for bootloader, 128k for storage
#define BOARD_FIRST_FLASH_SECTOR_TO_ERASE 32 // We resreve 128K for the bootloader
#define BOARD_FLASH_SIZE (BOARD_FLASH_SECTORS * 4096)
#define OSC_FREQ 24
#define BOARD_PIN_LED_ACTIVITY GPIO_nLED_BLUE // BLUE
#define BOARD_PIN_LED_BOOTLOADER GPIO_nLED_GREEN // GREEN
#define BOARD_LED_ON 0
#define BOARD_LED_OFF 1
#define SERIAL_BREAK_DETECT_DISABLED 1
/*
* Uncommenting this allows to force the bootloader through
* a PWM output pin. As this can accidentally initialize
* an ESC prematurely, it is not recommended. This feature
* has not been used and hence defaults now to off.
*
* # define BOARD_FORCE_BL_PIN_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN14)
* # define BOARD_FORCE_BL_PIN_IN (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN11)
*
* # define BOARD_POWER_PIN_OUT (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4)
* # define BOARD_POWER_ON 1
* # define BOARD_POWER_OFF 0
* # undef BOARD_POWER_PIN_RELEASE // Leave pin enabling Power - un comment to release (disable power)
*
*/
#if !defined(ARCH_SN_MAX_LENGTH)
# define ARCH_SN_MAX_LENGTH 12
#endif
#if !defined(APP_RESERVATION_SIZE)
# define APP_RESERVATION_SIZE 0
#endif
#if !defined(BOARD_FIRST_FLASH_SECTOR_TO_ERASE)
# define BOARD_FIRST_FLASH_SECTOR_TO_ERASE 1
#endif
#if !defined(USB_DATA_ALIGN)
# define USB_DATA_ALIGN
#endif
#ifndef BOOT_DEVICES_SELECTION
# define BOOT_DEVICES_SELECTION USB0_DEV|SERIAL0_DEV|SERIAL1_DEV
#endif
#ifndef BOOT_DEVICES_FILTER_ONUSB
# define BOOT_DEVICES_FILTER_ONUSB USB0_DEV|SERIAL0_DEV|SERIAL1_DEV
#endif
#endif /* HW_CONFIG_H_ */
@@ -0,0 +1,165 @@
/****************************************************************************
*
* Copyright (C) 2025 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file hw_rev_ver_tropic.c
* Tropic-community Hardware Revision and Version ID API
*/
#include <drivers/drv_adc.h>
#include <px4_arch/adc.h>
#include <px4_platform_common/micro_hal.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform/board_determine_hw_info.h>
#include <stdio.h>
#include <board_config.h>
#include <drivers/drv_sensor.h>
#include <systemlib/px4_macros.h>
#include <nuttx/spi/spi.h>
#if defined(BOARD_HAS_HW_VERSIONING)
#define HW_INFO_SIZE HW_INFO_VER_DIGITS + HW_INFO_REV_DIGITS
/****************************************************************************
* Private Data
****************************************************************************/
static int hw_revision = 0;
static char hw_info[HW_INFO_SIZE] = {0};
#if defined(BOARD_HAS_HW_SPLIT_VERSIONING)
static char hw_base_info[HW_INFO_SIZE] = {0};
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/************************************************************************************
* Name: board_get_hw_type
*
* Description:
* Optional returns a 0 terminated string defining the HW type.
*
* Input Parameters:
* None
*
* Returned Value:
* a 0 terminated string defining the HW type. This my be a 0 length string ""
*
************************************************************************************/
__EXPORT const char *board_get_hw_type_name()
{
return (const char *) hw_info;
}
#if defined(BOARD_HAS_HW_SPLIT_VERSIONING)
/************************************************************************************
* Name: board_get_hw_base_type_name
*
* Description:
* Optional returns a 0 terminated string defining the base type.
*
* Input Parameters:
* None
*
* Returned Value:
* a 0 terminated string defining the HW type. This my be a 0 length string ""
*
************************************************************************************/
__EXPORT const char *board_get_hw_base_type_name()
{
return (const char *) hw_base_info;
}
#endif
/************************************************************************************
* Name: board_get_hw_version
*
* Description:
* Optional returns a integer HW version
*
* Input Parameters:
* None
*
* Returned Value:
* An integer value of this boards hardware version.
* A value of -1 is the default for boards not supporting the BOARD_HAS_VERSIONING API.
* A value of 0 is the default for boards supporting the API but not having version.
*
************************************************************************************/
__EXPORT int board_get_hw_version()
{
return 0;
}
/************************************************************************************
* Name: board_get_hw_revision
*
* Description:
* Optional returns a integer HW revision
*
* Input Parameters:
* None
*
* Returned Value:
* An integer value of this boards hardware revision.
* A value of -1 is the default for boards not supporting the BOARD_HAS_VERSIONING API.
* A value of 0 is the default for boards supporting the API but not having revision.
*
************************************************************************************/
__EXPORT int board_get_hw_revision()
{
return hw_revision;
}
/************************************************************************************
* Name: board_determine_hw_info
*
* Description:
* Uses FUSES to detect Version
*
************************************************************************************/
int board_determine_hw_info()
{
hw_revision = 0; //TODO Read fuses
sprintf(hw_info, "%03d", hw_revision);
return 0;
}
#endif
@@ -28,55 +28,71 @@
* Public Data
****************************************************************************/
enum {
/* SPI instructions */
READ_FAST = 0,
READ_STATUS_REG = 1,
WRITE_ENABLE = 3,
SECTOR_ERASE_4K = 5,
READ_FAST_QUAD_OUTPUT = 6,
PAGE_PROGRAM_QUAD_INPUT = 7,
ERASE_BLOCK = 8,
PAGE_PROGRAM = 9,
CHIP_ERASE = 11,
};
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_SCKPAD,
.cs_hold_time = 1u,
.cs_setup_time = 1u,
.column_address_width = 0u,
.device_type = FLEXSPI_DEVICE_TYPE_SERIAL_NOR,
.sflash_pad_type = SERIAL_FLASH_4PADS,
.serial_clk_freq = FLEXSPI_SERIAL_CLKFREQ_133MHz,
.sflash_a1size = 8u * 1024u * 1024u,
.data_valid_time =
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.read_sample_clksrc = FLASH_READ_SAMPLE_CLK_LOOPBACK_FROM_SCKPAD,
.cs_hold_time = 3u,
.cs_setup_time = 3u,
.column_address_width = 0u,
.device_type = FLEXSPI_DEVICE_TYPE_SERIAL_NOR,
.sflash_pad_type = SERIAL_FLASH_4PADS,
.serial_clk_freq = FLEXSPI_SERIAL_CLKFREQ_133MHz,
.sflash_a1size = 8u * 1024u * 1024u,
.lookup_table =
{
0u, 0u
},
.lookup_table =
{
/* Fast Read Quad I/O */
[0 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xeb,
RADDR_SDR, FLEXSPI_4PAD, 0x18),
[0 + 1] = FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06,
READ_SDR, FLEXSPI_4PAD, 0x04),
[4 * READ_FAST] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xeb,
RADDR_SDR, FLEXSPI_4PAD, 0x18),
[4 * READ_FAST + 1] = FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06,
READ_SDR, FLEXSPI_4PAD, 0x04),
/* Read Status Register-1 */
[4 * 1 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05,
READ_SDR, FLEXSPI_1PAD, 0x04),
[4 * READ_STATUS_REG] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05,
READ_SDR, FLEXSPI_1PAD, 0x04),
/* Write Status Register-1 */
[4 * 3 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01, STOP, FLEXSPI_1PAD, 0x0),
[4 * WRITE_ENABLE] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06,
STOP, FLEXSPI_1PAD, 0),
/* Sector Erase (4KB) */
[4 * 5 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20,
RADDR_SDR, FLEXSPI_1PAD, 0x18),
[4 * SECTOR_ERASE_4K] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20,
RADDR_SDR, FLEXSPI_1PAD, 0x18),
/* Block Erase (64KB) */
[4 * 8 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xd8,
RADDR_SDR, FLEXSPI_1PAD, 0x18),
[4 * CHIP_ERASE] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xc7,
STOP, FLEXSPI_1PAD, 0),
/* Page Program */
[4 * 9 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02,
RADDR_SDR, FLEXSPI_1PAD, 0x18),
[4 * 9 + 1] = FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04,
STOP, FLEXSPI_1PAD, 0x0),
[4 * ERASE_BLOCK] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xd8,
RADDR_SDR, FLEXSPI_1PAD, 0x18),
[4 * PAGE_PROGRAM] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02,
RADDR_SDR, FLEXSPI_1PAD, 0x18),
[4 * PAGE_PROGRAM + 1] = FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04,
STOP, FLEXSPI_1PAD, 0x0),
[4 * READ_FAST_QUAD_OUTPUT] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x6b,
RADDR_SDR, FLEXSPI_1PAD, 0x18),
[4 * READ_FAST_QUAD_OUTPUT + 1] = FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x08,
READ_SDR, FLEXSPI_4PAD, 0x04),
[4 * PAGE_PROGRAM_QUAD_INPUT] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32,
RADDR_SDR, FLEXSPI_1PAD, 0x18),
[4 * PAGE_PROGRAM_QUAD_INPUT + 1] = FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_4PAD, 0x04,
STOP, FLEXSPI_1PAD, 0),
/* Chip Erase */
[4 * 11 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60, STOP, FLEXSPI_1PAD, 0x0),
},
},
@@ -1,5 +1,5 @@
/****************************************************************************
* boards/px4/fmu-v6xrt/src/imxrt_flexspi_storage.c
* boards/nxp/tropic-community/src/imxrt_flexspi_storage.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -36,11 +36,11 @@
#include <px4_platform_common/px4_mtd.h>
#include "px4_log.h"
#include "imxrt_flexspi.h"
#include <px4_arch/imxrt_flexspi_nor_flash.h>
#include <px4_arch/imxrt_romapi.h>
#include "board_config.h"
#include "hardware/imxrt_pinmux.h"
#ifdef CONFIG_IMXRT_FLEXSPI
#include "barriers.h"
/* Used sectors must be multiple of the flash block size
* i.e. W25Q32JV has a block size of 64KB
@@ -50,90 +50,14 @@
#define NOR_TOTAL_SECTORS (0x0800U)
#define NOR_PAGE_SIZE (0x0100U) /* 256 bytes */
#define NOR_SECTOR_SIZE (0x1000U) /* 4KB */
#define NOR_START_SECTOR (NOR_TOTAL_SECTORS - NOR_USED_SECTORS)
#define NOR_START_SECTOR (NOR_TOTAL_SECTORS - NOR_USED_SECTORS - 1) /* Don't use the last 4kB somehow this gives trouble */
#define NOR_START_PAGE ((NOR_START_SECTOR * NOR_SECTOR_SIZE) / NOR_PAGE_SIZE)
#define NOR_STORAGE_ADDR (IMXRT_FLEXCIPHER_BASE + NOR_START_SECTOR * NOR_SECTOR_SIZE)
#define NOR_STORAGE_END (IMXRT_FLEXCIPHER_BASE + (NOR_START_SECTOR + NOR_TOTAL_SECTORS) * NOR_SECTOR_SIZE)
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
enum {
/* SPI instructions */
READ_FAST = 0,
READ_STATUS_REG = 1,
WRITE_STATUS_REG = 3,
WRITE_ENABLE = 4,
SECTOR_ERASE_4K = 5,
READ_FAST_QUAD_OUTPUT = 6,
PAGE_PROGRAM_QUAD_INPUT = 7,
PAGE_PROGRAM = 9,
CHIP_ERASE = 11,
};
static const uint32_t g_flexspi_nor_lut[][4] = {
[READ_FAST] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0xeb,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_DUMMY_SDR, FLEXSPI_4PAD, 0x06,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_4PAD, 0x04),
},
[READ_STATUS_REG] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x05,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04),
},
[WRITE_STATUS_REG] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x01,
FLEXSPI_COMMAND_WRITE_SDR, FLEXSPI_1PAD, 0x04),
},
[WRITE_ENABLE] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x06,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
[SECTOR_ERASE_4K] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x20,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
},
[CHIP_ERASE] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0xc7,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
[PAGE_PROGRAM] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x02,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_WRITE_SDR, FLEXSPI_1PAD, 0x04,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0x0),
},
[READ_FAST_QUAD_OUTPUT] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x6b,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_DUMMY_SDR, FLEXSPI_4PAD, 0x08,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_4PAD, 0x04),
},
[PAGE_PROGRAM_QUAD_INPUT] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x32,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_WRITE_SDR, FLEXSPI_4PAD, 0x04,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
};
extern struct flexspi_nor_config_s g_bootConfig;
/****************************************************************************
* Private Types
@@ -143,10 +67,7 @@ static const uint32_t g_flexspi_nor_lut[][4] = {
struct imxrt_flexspi_storage_dev_s {
struct mtd_dev_s mtd;
struct flexspi_dev_s *flexspi; /* Saved FlexSPI interface instance */
uint8_t *ahb_base;
enum flexspi_port_e port;
struct flexspi_device_config_s *config;
};
/****************************************************************************
@@ -178,26 +99,6 @@ static int imxrt_flexspi_storage_ioctl(struct mtd_dev_s *dev,
* Private Data
****************************************************************************/
static struct flexspi_device_config_s g_flexspi_device_config = {
.flexspi_root_clk = 4000000,
.is_sck2_enabled = 0,
.flash_size = NOR_USED_SECTORS * NOR_SECTOR_SIZE / 4,
.cs_interval_unit = FLEXSPI_CS_INTERVAL_UNIT1_SCK_CYCLE,
.cs_interval = 0,
.cs_hold_time = 3,
.cs_setup_time = 3,
.data_valid_time = 0,
.columnspace = 0,
.enable_word_address = 0,
.awr_seq_index = 0,
.awr_seq_number = 0,
.ard_seq_index = READ_FAST,
.ard_seq_number = 1,
.ahb_write_wait_unit = FLEXSPI_AHB_WRITE_WAIT_UNIT2_AHB_CYCLE,
.ahb_write_wait_interval = 0,
.rx_sample_clock = FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_FROM_DQS_PAD,
};
static struct imxrt_flexspi_storage_dev_s g_flexspi_nor = {
.mtd =
{
@@ -211,90 +112,17 @@ static struct imxrt_flexspi_storage_dev_s g_flexspi_nor = {
#endif
.name = "imxrt_flexspi_storage"
},
.flexspi = (void *)0,
.ahb_base = (uint8_t *) NOR_STORAGE_ADDR,
.port = FLEXSPI_PORT_A1,
.config = &g_flexspi_device_config
};
/* Ensure exclusive access to the driver */
static sem_t g_exclsem = SEM_INITIALIZER(1);
/****************************************************************************
* Private Functions
****************************************************************************/
static int imxrt_flexspi_storage_read_status(
const struct imxrt_flexspi_storage_dev_s *dev,
uint32_t *status)
{
int stat;
struct flexspi_transfer_s transfer = {
.device_address = 0,
.port = dev->port,
.cmd_type = FLEXSPI_READ,
.seq_number = 1,
.seq_index = READ_STATUS_REG,
.data = status,
.data_size = 1,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0) {
return -EIO;
}
return 0;
}
static int imxrt_flexspi_storage_write_enable(
const struct imxrt_flexspi_storage_dev_s *dev)
{
int stat;
struct flexspi_transfer_s transfer = {
.device_address = 0,
.port = dev->port,
.cmd_type = FLEXSPI_COMMAND,
.seq_number = 1,
.seq_index = WRITE_ENABLE,
.data = NULL,
.data_size = 0,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0) {
return -EIO;
}
return 0;
}
static int imxrt_flexspi_storage_erase_sector(
const struct imxrt_flexspi_storage_dev_s *dev,
off_t offset)
{
int stat;
struct flexspi_transfer_s transfer = {
.device_address = offset,
.port = dev->port,
.cmd_type = FLEXSPI_COMMAND,
.seq_number = 1,
.seq_index = SECTOR_ERASE_4K,
.data = NULL,
.data_size = 0,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0) {
return -EIO;
}
return 0;
}
static int imxrt_flexspi_storage_erase_chip(
const struct imxrt_flexspi_storage_dev_s *dev)
{
@@ -302,69 +130,38 @@ static int imxrt_flexspi_storage_erase_chip(
return -EINVAL;
}
static int imxrt_flexspi_storage_page_program(
const struct imxrt_flexspi_storage_dev_s *dev,
off_t offset,
const void *buffer,
size_t len)
{
int stat;
struct flexspi_transfer_s transfer = {
.device_address = offset,
.port = dev->port,
.cmd_type = FLEXSPI_WRITE,
.seq_number = 1,
.seq_index = PAGE_PROGRAM_QUAD_INPUT,
.data = (uint32_t *) buffer,
.data_size = len,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0) {
return -EIO;
}
return 0;
}
static int imxrt_flexspi_storage_wait_bus_busy(
const struct imxrt_flexspi_storage_dev_s *dev)
{
uint32_t status = 0;
int ret;
do {
ret = imxrt_flexspi_storage_read_status(dev, &status);
if (ret) {
return ret;
}
} while (status & 1);
return 0;
}
static ssize_t imxrt_flexspi_storage_read(struct mtd_dev_s *dev,
off_t offset,
size_t nbytes,
uint8_t *buffer)
{
ssize_t ret;
struct imxrt_flexspi_storage_dev_s *priv =
(struct imxrt_flexspi_storage_dev_s *)dev;
uint8_t *src;
finfo("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes);
if (priv->port >= FLEXSPI_PORT_COUNT) {
if (offset < 0) {
return -EIO;
}
src = priv->ahb_base + offset;
if (src + nbytes > (uint8_t *)NOR_STORAGE_END) {
return -EIO;
}
ret = nxsem_wait(&g_exclsem);
if (ret < 0) {
return ret;
}
memcpy(buffer, src, nbytes);
nxsem_post(&g_exclsem);
finfo("return nbytes: %d\n", (int)nbytes);
return (ssize_t)nbytes;
}
@@ -392,11 +189,14 @@ static ssize_t imxrt_flexspi_storage_bread(struct mtd_dev_s *dev,
return nbytes;
}
locate_code(".ramfunc")
static ssize_t imxrt_flexspi_storage_bwrite(struct mtd_dev_s *dev,
off_t startblock,
size_t nblocks,
const uint8_t *buffer)
{
ssize_t ret;
struct flexspi_nor_config_s *pConfig = &g_bootConfig;
struct imxrt_flexspi_storage_dev_s *priv =
(struct imxrt_flexspi_storage_dev_s *)dev;
size_t len = nblocks * NOR_PAGE_SIZE;
@@ -407,70 +207,84 @@ static ssize_t imxrt_flexspi_storage_bwrite(struct mtd_dev_s *dev,
#endif
int i;
if (((uintptr_t)buffer % 4) != 0) {
return -EINVAL; // Byte aligned write not supported
}
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
FLEXSPI_CONFIGURE_PREFETCH(priv->flexspi, false);
ret = nxsem_wait(&g_exclsem);
irqstate_t flags = enter_critical_section();
if (ret < 0) {
return ret;
}
while (len) {
i = MIN(NOR_PAGE_SIZE, len);
imxrt_flexspi_storage_write_enable(priv);
imxrt_flexspi_storage_page_program(priv, offset, src, i);
imxrt_flexspi_storage_wait_bus_busy(priv);
cpsid(); // Disable interrupts
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
volatile uint32_t status = ROM_FLEXSPI_NorFlash_ProgramPage(0, pConfig, offset, (const uint32_t *)src);
#pragma GCC diagnostic pop
cpsie(); // Enable interrupts
usleep(0); // Yield to scheduler
UNUSED(status);
offset += i;
src += i;
len -= i;
}
FLEXSPI_CONFIGURE_PREFETCH(priv->flexspi, true);
leave_critical_section(flags);
#ifdef CONFIG_ARMV7M_DCACHE
up_invalidate_dcache((uintptr_t)dst,
(uintptr_t)dst + nblocks * NOR_PAGE_SIZE);
#endif
nxsem_post(&g_exclsem);
return nblocks;
}
locate_code(".ramfunc")
static int imxrt_flexspi_storage_erase(struct mtd_dev_s *dev,
off_t startblock,
size_t nblocks)
{
struct flexspi_nor_config_s *pConfig = &g_bootConfig;
struct imxrt_flexspi_storage_dev_s *priv =
(struct imxrt_flexspi_storage_dev_s *)dev;
size_t blocksleft = nblocks;
#ifdef CONFIG_ARMV7M_DCACHE
uint8_t *dst = priv->ahb_base + startblock * NOR_SECTOR_SIZE;
#endif
ssize_t ret;
startblock += NOR_START_SECTOR;
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
FLEXSPI_CONFIGURE_PREFETCH(priv->flexspi, false);
ret = nxsem_wait(&g_exclsem);
irqstate_t flags = enter_critical_section();
if (ret < 0) {
return ret;
}
while (blocksleft-- > 0) {
/* Erase each sector */
imxrt_flexspi_storage_write_enable(priv);
imxrt_flexspi_storage_erase_sector(priv, startblock * NOR_SECTOR_SIZE);
imxrt_flexspi_storage_wait_bus_busy(priv);
cpsid(); // Disable interrupts
volatile uint32_t status = ROM_FLEXSPI_NorFlash_Erase(0, pConfig,
(startblock * NOR_SECTOR_SIZE), NOR_SECTOR_SIZE);
cpsie(); // Enable interrupts
usleep(0); // Yield to scheduler
UNUSED(status);
startblock++;
}
FLEXSPI_CONFIGURE_PREFETCH(priv->flexspi, true);
leave_critical_section(flags);
#ifdef CONFIG_ARMV7M_DCACHE
up_invalidate_dcache((uintptr_t)dst,
(uintptr_t)dst + nblocks * NOR_SECTOR_SIZE);
#endif
nxsem_post(&g_exclsem);
return (int)nblocks;
}
@@ -530,9 +344,7 @@ static int imxrt_flexspi_storage_ioctl(struct mtd_dev_s *dev,
case MTDIOC_BULKERASE: {
/* Erase the entire device */
imxrt_flexspi_storage_write_enable(priv);
imxrt_flexspi_storage_erase_chip(priv);
imxrt_flexspi_storage_wait_bus_busy(priv);
ret = OK;
}
break;
@@ -569,20 +381,6 @@ int imxrt_flexspi_storage_initialize(void)
struct mtd_dev_s *mtd_dev = &g_flexspi_nor.mtd;
int ret = -ENODEV;
/* Select FlexSPI1 */
g_flexspi_nor.flexspi = imxrt_flexspi_initialize(0);
if (g_flexspi_nor.flexspi) {
ret = OK;
FLEXSPI_UPDATE_LUT(g_flexspi_nor.flexspi,
0,
(const uint32_t *)g_flexspi_nor_lut,
sizeof(g_flexspi_nor_lut) / 4);
}
/* Register the MTD driver so that it can be accessed from the
* VFS.
*/
@@ -611,4 +409,3 @@ int imxrt_flexspi_storage_initialize(void)
return ret;
}
#endif /* CONFIG_IMXRT_FLEXSPI */
+41 -13
View File
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2024 PX4 Development Team. All rights reserved.
* Copyright (c) 2025 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -64,9 +64,9 @@
#include <nuttx/analog/adc.h>
#include <nuttx/mm/gran.h>
#include "arm_internal.h"
#include "arm_internal.h"
#include "imxrt_flexspi_nor_boot.h"
#include <px4_arch/imxrt_flexspi_nor_flash.h>
#include "imxrt_iomuxc.h"
#include "imxrt_flexcan.h"
#include "imxrt_enet.h"
@@ -84,9 +84,11 @@
#include <drivers/drv_board_led.h>
#include <systemlib/px4_macros.h>
#include <px4_arch/io_timer.h>
#include <px4_arch/imxrt_romapi.h>
#include <px4_platform_common/init.h>
#include <px4_platform/gpio.h>
#include <px4_platform/board_dma_alloc.h>
#include <px4_platform/board_determine_hw_info.h>
/* Configuration ************************************************************/
@@ -144,6 +146,30 @@ __EXPORT void board_on_reset(int status)
}
}
/****************************************************************************
* Name: imxrt_flash_romapi_initialize
*
* Description:
*
****************************************************************************/
struct flexspi_nor_config_s g_bootConfig;
locate_code(".ramfunc")
void imxrt_flash_romapi_initialize(void)
{
memcpy((struct flexspi_nor_config_s *)&g_bootConfig, &g_flash_config,
sizeof(struct flexspi_nor_config_s));
g_bootConfig.memConfig.tag = FLEXSPI_CFG_BLK_TAG;
ROM_API_Init();
ROM_FLEXSPI_NorFlash_Init(0, (struct flexspi_nor_config_s *)&g_bootConfig);
ROM_FLEXSPI_NorFlash_ClearCache(0);
ARM_DSB();
ARM_ISB();
ARM_DMB();
}
locate_code(".ramfunc")
void imxrt_flash_setup_prefetch_partition(void)
@@ -207,6 +233,8 @@ __EXPORT void imxrt_boardinitialize(void)
{
imxrt_flash_setup_prefetch_partition();
imxrt_flash_romapi_initialize();
board_on_reset(-1); /* Reset PWM first thing */
/* configure LEDs */
@@ -218,10 +246,6 @@ __EXPORT void imxrt_boardinitialize(void)
const uint32_t gpio[] = PX4_GPIO_INIT_LIST;
px4_gpio_init(gpio, arraySize(gpio));
/* configure SPI interfaces */
imxrt_spidev_initialize();
imxrt_usb_initialize();
fmurt1062_timer_initialize();
@@ -330,14 +354,20 @@ void imxrt_flexio_clocking(void)
****************************************************************************/
__EXPORT int board_app_initialize(uintptr_t arg)
{
int ret = OK;
#if !defined(BOOTLOADER)
imxrt_flexio_clocking();
/* Power on Interfaces */
board_spi_reset(10, 0xffff);
px4_platform_init();
imxrt_spiinitialize();
board_determine_hw_info();
/* configure the DMA allocator */
if (board_dma_alloc_init() < 0) {
@@ -350,14 +380,13 @@ __EXPORT int board_app_initialize(uintptr_t arg)
hrt_call_every(&serial_dma_call, 1000, 1000, (hrt_callout)imxrt_serial_dma_poll, NULL);
#endif
int ret = OK;
#if defined(CONFIG_IMXRT_USDHC)
ret = fmurt1062_usdhc_initialize();
#endif
/* Configure SPI-based devices */
imxrt_spiinitialize();
ret = imxrt1062_spi_bus_initialize();
board_spi_reset(10, 0xffff);
#ifdef CONFIG_IMXRT_ENET
imxrt_netinitialize(0);
@@ -367,7 +396,6 @@ __EXPORT int board_app_initialize(uintptr_t arg)
imxrt_caninitialize(3);
#endif
#ifdef CONFIG_IMXRT_FLEXSPI
ret = imxrt_flexspi_storage_initialize();
if (ret < 0) {
@@ -375,7 +403,7 @@ __EXPORT int board_app_initialize(uintptr_t arg)
"ERROR: imxrt_flexspi_nor_initialize failed: %d\n", ret);
}
#endif
#endif /* !defined(BOOTLOADER) */
return ret;
}
@@ -0,0 +1,79 @@
/****************************************************************************
*
* Copyright (c) 2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file manifest.c
*
* This module supplies the interface to the manifest of hardware that is
* optional and dependent on the HW REV and HW VER IDs
*
* The manifest allows the system to know whether a hardware option
* say for example the PX4IO is an no-pop option vs it is broken.
*
*/
/****************************************************************************
* Included Files
****************************************************************************/
#include <px4_platform_common/px4_config.h>
#include <stdbool.h>
#include <syslog.h>
#include "systemlib/px4_macros.h"
#include "px4_log.h"
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/************************************************************************************
* Name: board_query_manifest
*
* Description:
* Optional returns manifest item.
*
* Input Parameters:
* manifest_id - the ID for the manifest item to retrieve
*
* Returned Value:
* 0 - item is not in manifest => assume legacy operations
* pointer to a manifest item
*
************************************************************************************/
__EXPORT px4_hw_mft_item board_query_manifest(px4_hw_mft_item_id_t id)
{
return px4_hw_mft_unsupported;
}
+27 -249
View File
@@ -60,256 +60,34 @@
#include "board_config.h"
#include <systemlib/err.h>
#if defined(CONFIG_IMXRT_LPSPI3) || defined(CONFIG_IMXRT_LPSPI4)
constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = {
initSPIBus(SPI::Bus::LPSPI3, {
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::Port1, GPIO::Pin28}), /* GPIO_AD_B1_12 GPIO1_IO28 */
constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSIONS] = {
initSPIFmumID(TROPIC_0, {
initSPIBus(SPI::Bus::LPSPI3, {
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::Port1, GPIO::Pin28}), /* GPIO_AD_B1_12 GPIO1_IO28 */
}),
initSPIBus(SPI::Bus::LPSPI4, {
initSPIDevice(DRV_GYR_DEVTYPE_BMI088, SPI::CS{GPIO::Port2, GPIO::Pin18}), /* GPIO_B1_02 GPIO2_IO18 */
initSPIDevice(DRV_ACC_DEVTYPE_BMI088, SPI::CS{GPIO::Port2, GPIO::Pin0}), /* GPIO_B0_00 GPIO2_IO00 */
}),
}),
initSPIBus(SPI::Bus::LPSPI4, {
initSPIDevice(DRV_GYR_DEVTYPE_BMI088, SPI::CS{GPIO::Port2, GPIO::Pin18}), /* GPIO_B1_02 GPIO2_IO18 */
initSPIDevice(DRV_ACC_DEVTYPE_BMI088, SPI::CS{GPIO::Port2, GPIO::Pin0}), /* GPIO_B0_00 GPIO2_IO00 */
initSPIFmumID(TROPIC_1, {
initSPIBus(SPI::Bus::LPSPI3, {
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::Port1, GPIO::Pin28}), /* GPIO_AD_B1_12 GPIO1_IO28 */
}),
initSPIBus(SPI::Bus::LPSPI4, {
initSPIDevice(DRV_GYR_DEVTYPE_BMI088, SPI::CS{GPIO::Port2, GPIO::Pin18}), /* GPIO_B1_02 GPIO2_IO18 */
initSPIDevice(DRV_ACC_DEVTYPE_BMI088, SPI::CS{GPIO::Port2, GPIO::Pin0}), /* GPIO_B0_00 GPIO2_IO00 */
}),
}),
initSPIFmumID(TROPIC_2, {
initSPIBus(SPI::Bus::LPSPI3, {
initSPIDevice(DRV_IMU_DEVTYPE_ICM45686, SPI::CS{GPIO::Port1, GPIO::Pin28}), /* GPIO_AD_B1_12 GPIO1_IO28 */
}),
initSPIBus(SPI::Bus::LPSPI4, {
initSPIDevice(DRV_GYR_DEVTYPE_BMI088, SPI::CS{GPIO::Port2, GPIO::Pin18}), /* GPIO_B1_02 GPIO2_IO18 */
initSPIDevice(DRV_ACC_DEVTYPE_BMI088, SPI::CS{GPIO::Port2, GPIO::Pin0}), /* GPIO_B0_00 GPIO2_IO00 */
}),
}),
};
static constexpr bool unused = validateSPIConfig(px4_spi_buses);
#define _PIN_OFF(def) (((def) & (GPIO_PORT_MASK | GPIO_PIN_MASK)) | (GPIO_INPUT | IOMUX_PULL_DOWN_100K | IOMUX_CMOS_INPUT))
/************************************************************************************
* Public Functions
************************************************************************************/
/************************************************************************************
* Name: fmurt1062_spidev_initialize
*
* Description:
* Called to configure SPI chip select GPIO pins for the NXP FMUKRT1062-V1 board.
*
************************************************************************************/
void imxrt_spidev_initialize(void)
{
for (int bus = 0; bus < SPI_BUS_MAX_BUS_ITEMS; ++bus) {
for (int i = 0; i < SPI_BUS_MAX_DEVICES; ++i) {
if (px4_spi_buses[bus].devices[i].cs_gpio != 0) {
px4_arch_configgpio(px4_spi_buses[bus].devices[i].cs_gpio);
}
}
}
}
/************************************************************************************
* Name: imxrt_spi_bus_initialize
*
* Description:
* Called to configure SPI chip select GPIO pins for the NXP FMUKRT1062-V1 board.
*
************************************************************************************/
static const px4_spi_bus_t *_spi_bus3;
static const px4_spi_bus_t *_spi_bus4;
__EXPORT int imxrt1062_spi_bus_initialize(void)
{
for (int i = 0; i < SPI_BUS_MAX_BUS_ITEMS; ++i) {
switch (px4_spi_buses[i].bus) {
case 3: _spi_bus3 = &px4_spi_buses[i]; break;
case 4: _spi_bus4 = &px4_spi_buses[i]; break;
}
}
/* Configure SPI-based devices */
struct spi_dev_s *spi_icm = px4_spibus_initialize(3);
if (!spi_icm) {
PX4_ERR("[boot] FAILED to initialize SPI port %d\n", 1);
return -ENODEV;
}
/* Default bus 1 to 8MHz and de-assert the known chip selects.
*/
SPI_SETFREQUENCY(spi_icm, 8 * 1000 * 1000);
SPI_SETBITS(spi_icm, 8);
SPI_SETMODE(spi_icm, SPIDEV_MODE3);
/* Get the SPI port for the BMI088 */
struct spi_dev_s *spi_bmi = px4_spibus_initialize(4);
if (!spi_bmi) {
PX4_ERR("[boot] FAILED to initialize SPI port %d\n", 4);
return -ENODEV;
}
/* Default ext bus to 8MHz and de-assert the known chip selects.
*/
SPI_SETFREQUENCY(spi_bmi, 8 * 1000 * 1000);
SPI_SETBITS(spi_bmi, 8);
SPI_SETMODE(spi_bmi, SPIDEV_MODE3);
/* deselect all */
for (int bus = 0; bus < SPI_BUS_MAX_BUS_ITEMS; ++bus) {
for (int i = 0; i < SPI_BUS_MAX_DEVICES; ++i) {
if (px4_spi_buses[bus].devices[i].cs_gpio != 0) {
SPI_SELECT(spi_bmi, px4_spi_buses[bus].devices[i].devid, false);
}
}
}
return OK;
}
/****************************************************************************
* Name: imxrt_lpspi1/2/3select and imxrt_lpspi1/2/3status
*
* Description:
* The external functions, imxrt_lpspi1/2/3select and imxrt_lpspi1/2/3status must be
* provided by board-specific logic. They are implementations of the select
* and status methods of the SPI interface defined by struct spi_ops_s (see
* include/nuttx/spi/spi.h). All other methods (including imxrt_lpspibus_initialize())
* are provided by common STM32 logic. To use this common SPI logic on your
* board:
*
* 1. Provide logic in imxrt_boardinitialize() to configure SPI chip select
* pins.
* 2. Provide imxrt_lpspi1/2/3select() and imxrt_lpspi1/2/3status() functions in your
* board-specific logic. These functions will perform chip selection and
* status operations using GPIOs in the way your board is configured.
* 3. Add a calls to imxrt_lpspibus_initialize() in your low level application
* initialization logic
* 4. The handle returned by imxrt_lpspibus_initialize() may then be used to bind the
* SPI driver to higher level logic (e.g., calling
* mmcsd_spislotinitialize(), for example, will bind the SPI driver to
* the SPI MMC/SD driver).
*
****************************************************************************/
static inline void imxrt_spixselect(const px4_spi_bus_t *bus, struct spi_dev_s *dev, uint32_t devid, bool selected)
{
for (int i = 0; i < SPI_BUS_MAX_DEVICES; ++i) {
if (bus->devices[i].cs_gpio == 0) {
break;
}
if (devid == bus->devices[i].devid) {
// SPI select is active low, so write !selected to select the device
imxrt_gpio_write(bus->devices[i].cs_gpio, !selected);
}
}
}
#if defined(CONFIG_IMXRT_LPSPI3)
__EXPORT void imxrt_lpspi3select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected)
{
imxrt_spixselect(_spi_bus3, dev, devid, selected);
}
__EXPORT uint8_t imxrt_lpspi3status(FAR struct spi_dev_s *dev, uint32_t devid)
{
return SPI_STATUS_PRESENT;
}
#endif
#if defined(CONFIG_IMXRT_LPSPI4)
__EXPORT void imxrt_lpspi4select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected)
{
imxrt_spixselect(_spi_bus4, dev, devid, selected);
}
__EXPORT uint8_t imxrt_lpspi4status(FAR struct spi_dev_s *dev, uint32_t devid)
{
return SPI_STATUS_PRESENT;
}
#endif
/************************************************************************************
* Name: board_spi_reset
*
* Description:
*
*
************************************************************************************/
__EXPORT void board_spi_reset(int ms, int bus_mask)
{
#ifdef CONFIG_IMXRT_LPSPI1
/* Goal not to back feed the chips on the bus via IO lines */
for (int bus = 0; bus < SPI_BUS_MAX_BUS_ITEMS; ++bus) {
if (px4_spi_buses[bus].bus == 1 || px4_spi_buses[bus].bus == 3) {
for (int i = 0; i < SPI_BUS_MAX_DEVICES; ++i) {
if (px4_spi_buses[bus].devices[i].cs_gpio != 0) {
imxrt_config_gpio(_PIN_OFF(px4_spi_buses[bus].devices[i].cs_gpio));
}
if (px4_spi_buses[bus].devices[i].drdy_gpio != 0) {
imxrt_config_gpio(_PIN_OFF(px4_spi_buses[bus].devices[i].drdy_gpio));
}
}
}
}
imxrt_config_gpio(GPIO_SPI1_SCK_OFF);
imxrt_config_gpio(GPIO_SPI1_MISO_OFF);
imxrt_config_gpio(GPIO_SPI1_MOSI_OFF);
imxrt_config_gpio(GPIO_SPI3_SCK_OFF);
imxrt_config_gpio(GPIO_SPI3_MISO_OFF);
imxrt_config_gpio(GPIO_SPI3_MOSI_OFF);
imxrt_config_gpio(_PIN_OFF(GPIO_LPI2C3_SDA_RESET));
imxrt_config_gpio(_PIN_OFF(GPIO_LPI2C3_SCL_RESET));
/* set the sensor rail off */
imxrt_gpio_write(GPIO_VDD_3V3_SENSORS_EN, 0);
/* wait for the sensor rail to reach GND */
usleep(ms * 1000);
warnx("reset done, %d ms", ms);
/* re-enable power */
/* switch the sensor rail back on */
imxrt_gpio_write(GPIO_VDD_3V3_SENSORS_EN, 1);
/* wait a bit before starting SPI, different times didn't influence results */
usleep(100);
/* reconfigure the SPI pins */
for (int bus = 0; bus < SPI_BUS_MAX_BUS_ITEMS; ++bus) {
if (px4_spi_buses[bus].bus == 1 || px4_spi_buses[bus].bus == 3) {
for (int i = 0; i < SPI_BUS_MAX_DEVICES; ++i) {
if (px4_spi_buses[bus].devices[i].cs_gpio != 0) {
imxrt_config_gpio(px4_spi_buses[bus].devices[i].cs_gpio);
}
if (px4_spi_buses[bus].devices[i].drdy_gpio != 0) {
imxrt_config_gpio(px4_spi_buses[bus].devices[i].drdy_gpio);
}
}
}
}
imxrt_config_gpio(GPIO_LPSPI1_SCK);
imxrt_config_gpio(GPIO_LPSPI1_MISO);
imxrt_config_gpio(GPIO_LPSPI1_MOSI);
imxrt_config_gpio(GPIO_LPSPI3_SCK);
imxrt_config_gpio(GPIO_LPSPI3_MISO);
imxrt_config_gpio(GPIO_LPSPI3_MOSI);
imxrt_config_gpio(GPIO_LPI2C3_SDA);
imxrt_config_gpio(GPIO_LPI2C3_SCL);
#endif /* CONFIG_IMXRT_LPSPI1 */
}
#endif /* CONFIG_IMXRT_LPSPI3 || CONFIG_IMXRT_LPSPI4 */
static constexpr bool unused = validateSPIConfig(px4_spi_buses_all_hw);
@@ -35,9 +35,7 @@ px4_add_library(arch_board_reset
board_reset.cpp
)
if (CONFIG_ARCH_FAMILY_IMXRT117x)
target_link_libraries(arch_board_reset PRIVATE arch_board_romapi)
endif()
# up_systemreset
if (NOT DEFINED CONFIG_BUILD_FLAT)
@@ -45,6 +45,12 @@
#ifdef CONFIG_ARCH_FAMILY_IMXRT117x
#include <hardware/rt117x/imxrt117x_snvs.h>
#elif defined CONFIG_ARCH_FAMILY_IMXRT106x
# include <hardware/imxrt_snvs.h>
# define SNVS_LPCR_GPR_Z_DIS (1 << 24) /* Bit 24: General Purpose Registers Zeroization Disable */
#endif
#ifdef BOARD_HAS_ISP_BOOTLOADER
#include <px4_arch/imxrt_flexspi_nor_flash.h>
#include <px4_arch/imxrt_romapi.h>
#endif
@@ -59,13 +65,9 @@
static int board_reset_enter_bootloader()
{
#ifdef CONFIG_ARCH_FAMILY_IMXRT117x
uint32_t regvalue = BOOT_RTC_SIGNATURE;
modifyreg32(IMXRT_SNVS_LPCR, 0, SNVS_LPCR_GPR_Z_DIS);
putreg32(regvalue, PX4_IMXRT_RTC_REBOOT_REG_ADDRESS);
#elif defined(BOARD_HAS_TEENSY_BOOTLOADER)
asm("BKPT #251"); /* Enter Teensy MKL02 bootloader */
#endif
return OK;
}
@@ -75,15 +77,16 @@ int board_reset(int status)
board_reset_enter_bootloader();
}
#if defined(BOARD_HAS_ISP_BOOTLOADER)
else if (status == REBOOT_TO_ISP) {
#ifdef BOARD_HAS_TEENSY_BOOTLOADER
asm("BKPT #251"); /* Enter Teensy MKL02 bootloader */
#elif defined(BOARD_HAS_ISP_BOOTLOADER)
uint32_t arg = 0xeb100000;
ROM_API_Init();
ROM_RunBootloader(&arg);
#endif
}
#endif
#if defined(BOARD_HAS_ON_RESET)
board_on_reset(status);
@@ -138,18 +138,33 @@
(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))
#ifdef CONFIG_ARCH_FAMILY_IMXRT106x
//!@brief Definitions for FlexSPI Serial Clock Frequency
typedef enum _FlexSpiSerialClockFreq {
kFlexSpiSerialClk_30MHz = 1,
kFlexSpiSerialClk_50MHz = 2,
kFlexSpiSerialClk_60MHz = 3,
kFlexSpiSerialClk_75MHz = 4,
kFlexSpiSerialClk_80MHz = 5,
kFlexSpiSerialClk_100MHz = 6,
kFlexSpiSerialClk_120MHz = 7,
kFlexSpiSerialClk_133MHz = 8,
kFlexSpiSerialClk_166MHz = 9,
} flexspi_serial_clk_freq_t;
#elif defined(CONFIG_ARCH_FAMILY_IMXRT117x)
//!@brief Definitions for FlexSPI Serial Clock Frequency
typedef enum _FlexSpiSerialClockFreq {
kFlexSpiSerialClk_30MHz = 1,
kFlexSpiSerialClk_50MHz = 2,
kFlexSpiSerialClk_60MHz = 3,
kFlexSpiSerialClk_80MHz = 4,
kFlexSpiSerialClk_100MHz = 5,
kFlexSpiSerialClk_100MHz = 5,
kFlexSpiSerialClk_120MHz = 6,
kFlexSpiSerialClk_133MHz = 7,
kFlexSpiSerialClk_166MHz = 8,
kFlexSpiSerialClk_200MHz = 9,
} flexspi_serial_clk_freq_t;
#endif
//!@brief FlexSPI clock configuration type
enum {
@@ -239,7 +239,9 @@ status_t ROM_FLEXSPI_NorFlash_Erase(uint32_t instance, flexspi_nor_config_t *con
* @retval kStatus_ROM_FLEXSPI_SequenceExecutionTimeout Sequence Execution timeout.
* @retval kStatus_ROM_FLEXSPI_DeviceTimeout the device timeout
*/
#ifdef CONFIG_ARCH_FAMILY_IMXRT117x
status_t ROM_FLEXSPI_NorFlash_EraseSector(uint32_t instance, flexspi_nor_config_t *config, uint32_t start);
#endif
/*!
* @brief Erase one block specified by address
@@ -259,7 +261,9 @@ status_t ROM_FLEXSPI_NorFlash_EraseSector(uint32_t instance, flexspi_nor_config_
* @retval kStatus_ROM_FLEXSPI_SequenceExecutionTimeout Sequence Execution timeout.
* @retval kStatus_ROM_FLEXSPI_DeviceTimeout the device timeout
*/
#ifdef CONFIG_ARCH_FAMILY_IMXRT117x
status_t ROM_FLEXSPI_NorFlash_EraseBlock(uint32_t instance, flexspi_nor_config_t *config, uint32_t start);
#endif
/*!
* @brief Erase all the Serial NOR devices connected on FLEXSPI.
@@ -342,10 +346,12 @@ status_t ROM_FLEXSPI_NorFlash_UpdateLut(uint32_t instance,
* @retval kStatus_ROM_FLEXSPI_InvalidSequence A invalid Sequence is provided.
* @retval kStatus_ROM_FLEXSPI_DeviceTimeout Device timeout.
*/
#ifdef CONFIG_ARCH_FAMILY_IMXRT117x
status_t ROM_FLEXSPI_NorFlash_WaitBusy(uint32_t instance,
flexspi_nor_config_t *config,
bool isParallelMode,
uint32_t address);
#endif
/*@}*/
/*!
@@ -52,8 +52,29 @@ typedef union _standard_version {
#endif
} standard_version_t;
#ifdef CONFIG_ARCH_FAMILY_IMXRT106x
/*!
* @brief Interface for the ROM FLEXSPI NOR flash driver.
* @brief Interface for the IMXRT106X ROM FLEXSPI NOR flash driver.
*/
typedef struct {
uint32_t version;
status_t (*init)(uint32_t instance, flexspi_nor_config_t *config);
status_t (*page_program)(uint32_t instance, flexspi_nor_config_t *config, uint32_t dst_addr, const uint32_t *src);
status_t (*erase_all)(uint32_t instance, flexspi_nor_config_t *config);
status_t (*erase)(uint32_t instance, flexspi_nor_config_t *config, uint32_t start, uint32_t length);
status_t (*read)(uint32_t instance, flexspi_nor_config_t *config, uint32_t *dst, uint32_t start, uint32_t bytes);
void (*clear_cache)(uint32_t instance);
status_t (*xfer)(uint32_t instance, flexspi_xfer_t *xfer);
status_t (*update_lut)(uint32_t instance, uint32_t seqIndex, const uint32_t *lutBase, uint32_t numberOfSeq);
status_t (*get_config)(uint32_t instance, flexspi_nor_config_t *config, serial_nor_config_option_t *option);
} flexspi_nor_driver_interface_t;
#elif defined(CONFIG_ARCH_FAMILY_IMXRT117x)
/*!
* @brief Interface for the IMXRT117X ROM FLEXSPI NOR flash driver.
*/
typedef struct {
uint32_t version;
@@ -73,6 +94,33 @@ typedef struct {
const uint32_t reserved1[2]; /*!< Reserved */
} flexspi_nor_driver_interface_t;
#endif
#ifdef CONFIG_ARCH_FAMILY_IMXRT106x
/*!
* @brief Root of the bootloader api tree.
*
* An instance of this struct resides in read-only memory in the bootloader. It
* provides a user application access to APIs exported by the bootloader.
*
* @note The order of existing fields must not be changed.
*/
typedef struct {
const uint32_t version; //!< Bootloader version number
const char *copyright; //!< Bootloader Copyright
void (*runBootloader)(void *arg); //!< Function to start the bootloader executing
const uint32_t *reserved0; //!< Reserved
const flexspi_nor_driver_interface_t *flexSpiNorDriver; //!< FlexSPI NOR Flash API
const uint32_t *reserved1; //!< Reserved
const uint32_t *unused_rtwdogDriver;
const uint32_t *unused_wdogDriver;
const uint32_t *reserved2;
} bootloader_api_entry_t;
#elif defined(CONFIG_ARCH_FAMILY_IMXRT117x)
/*!
* @brief Root of the bootloader api tree.
*
@@ -89,6 +137,8 @@ typedef struct {
const uint32_t reserved[8]; /*!< Reserved */
} bootloader_api_entry_t;
#endif
/*******************************************************************************
* Variables
******************************************************************************/
@@ -104,6 +154,9 @@ static bootloader_api_entry_t *g_bootloaderTree = NULL;
locate_code(".ramfunc")
void ROM_API_Init(void)
{
#ifdef CONFIG_ARCH_FAMILY_IMXRT106x
g_bootloaderTree = ((bootloader_api_entry_t *) * (uint32_t *)0x0020001cU);
#else
if ((getreg32(IMXRT_ANADIG_MISC_MISC_DIFPROG) & ANADIG_MISC_MISC_DIFPROG_CHIPID(0x10U)) != 0U) {
g_bootloaderTree = ((bootloader_api_entry_t *) * (uint32_t *)0x0021001cU);
@@ -111,6 +164,8 @@ void ROM_API_Init(void)
} else {
g_bootloaderTree = ((bootloader_api_entry_t *) * (uint32_t *)0x0020001cU);
}
#endif
}
/*!
@@ -193,6 +248,8 @@ status_t ROM_FLEXSPI_NorFlash_Erase(uint32_t instance, flexspi_nor_config_t *con
return g_bootloaderTree->flexSpiNorDriver->erase(instance, config, start, length);
}
#ifdef CONFIG_ARCH_FAMILY_IMXRT117x
/*!
* @brief Erase one sector specified by address.
*
@@ -219,6 +276,8 @@ status_t ROM_FLEXSPI_NorFlash_EraseBlock(uint32_t instance, flexspi_nor_config_t
return g_bootloaderTree->flexSpiNorDriver->erase_block(instance, config, start);
}
#endif
/*! @brief Erase all the Serial NOR devices connected on FLEXSPI. */
locate_code(".ramfunc")
status_t ROM_FLEXSPI_NorFlash_EraseAll(uint32_t instance, flexspi_nor_config_t *config)
@@ -242,6 +301,19 @@ status_t ROM_FLEXSPI_NorFlash_UpdateLut(uint32_t instance,
return g_bootloaderTree->flexSpiNorDriver->update_lut(instance, seqIndex, lutBase, seqNumber);
}
#ifdef CONFIG_ARCH_FAMILY_IMXRT106x
/*! @brief Software reset for the FLEXSPI logic. */
locate_code(".ramfunc")
void ROM_FLEXSPI_NorFlash_ClearCache(uint32_t instance)
{
g_bootloaderTree->flexSpiNorDriver->clear_cache(instance);
}
#elif defined(CONFIG_ARCH_FAMILY_IMXRT117x)
/*! @brief Software reset for the FLEXSPI logic. */
locate_code(".ramfunc")
void ROM_FLEXSPI_NorFlash_ClearCache(uint32_t instance)
@@ -259,6 +331,9 @@ void ROM_FLEXSPI_NorFlash_ClearCache(uint32_t instance)
MISRA_CAST(clearCacheCommand_t, clearCacheCommand, uint32_t, clearCacheFunctionAddress);
(void)clearCacheCommand(instance);
}
#endif
#ifdef CONFIG_ARCH_FAMILY_IMXRT117x
/*! @brief Wait until device is idle*/
locate_code(".ramfunc")
@@ -269,3 +344,5 @@ status_t ROM_FLEXSPI_NorFlash_WaitBusy(uint32_t instance,
{
return g_bootloaderTree->flexSpiNorDriver->wait_busy(instance, config, isParallelMode, address);
}
#endif
@@ -36,11 +36,13 @@ add_subdirectory(../imxrt/adc adc)
add_subdirectory(../imxrt/board_critmon board_critmon)
add_subdirectory(../imxrt/board_hw_info board_hw_info)
add_subdirectory(../imxrt/board_reset board_reset)
add_subdirectory(../imxrt/romapi romapi)
add_subdirectory(../imxrt/dshot dshot)
add_subdirectory(../imxrt/hrt hrt)
add_subdirectory(../imxrt/led_pwm led_pwm)
add_subdirectory(../imxrt/io_pins io_pins)
add_subdirectory(../imxrt/tone_alarm tone_alarm)
add_subdirectory(../imxrt/version version)
add_subdirectory(../imxrt/spi spi)
add_subdirectory(px4io_serial)
@@ -0,0 +1,36 @@
/****************************************************************************
*
* Copyright (c) 2024 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include "../../../imxrt/include/px4_arch/imxrt_flexspi_nor_flash.h"
@@ -0,0 +1,36 @@
/****************************************************************************
*
* Copyright (c) 2024 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include "../../../imxrt/include/px4_arch/imxrt_romapi.h"
@@ -46,6 +46,58 @@
#define GENERAL_OUTPUT_IOMUX (IOMUX_CMOS_OUTPUT | IOMUX_PULL_KEEP | IOMUX_DRIVE_33OHM | IOMUX_SPEED_MEDIUM | IOMUX_SLEW_FAST)
constexpr bool validateSPIConfig(const px4_spi_bus_t spi_busses_conf[SPI_BUS_MAX_BUS_ITEMS])
{
const bool nuttx_enabled_spi_buses[] = {
#ifdef CONFIG_IMXRT_LPSPI1
true,
#else
false,
#endif
#ifdef CONFIG_IMXRT_LPSPI2
true,
#else
false,
#endif
#ifdef CONFIG_IMXRT_LPSPI3
true,
#else
false,
#endif
#ifdef CONFIG_IMXRT_LPSPI4
true,
#else
false,
#endif
#ifdef CONFIG_IMXRT_LPSPI5
true,
#else
false,
#endif
#ifdef CONFIG_IMXRT_LPSPI6
true,
#else
false,
#endif
};
for (unsigned i = 0; i < sizeof(nuttx_enabled_spi_buses) / sizeof(nuttx_enabled_spi_buses[0]); ++i) {
bool found_bus = false;
for (int j = 0; j < SPI_BUS_MAX_BUS_ITEMS; ++j) {
if (spi_busses_conf[j].bus == (int)i + 1) {
found_bus = true;
}
}
// Either the bus is enabled in NuttX and configured in spi_busses_conf, or disabled and not configured
constexpr_assert(found_bus == nuttx_enabled_spi_buses[i], "SPI bus config mismatch (CONFIG_STM32H7_SPIx)");
}
return false;
}
static inline constexpr px4_spi_bus_device_t initSPIDevice(uint32_t devid, SPI::CS cs_gpio, SPI::DRDY drdy_gpio = {})
{
px4_spi_bus_device_t ret{};
@@ -138,8 +190,57 @@ static inline constexpr SPI::bus_device_external_cfg_t initSPIConfigExternal(SPI
return ret;
}
constexpr bool validateSPIConfig(const px4_spi_bus_t spi_busses_conf[SPI_BUS_MAX_BUS_ITEMS])
struct px4_spi_bus_array_t {
px4_spi_bus_t item[SPI_BUS_MAX_BUS_ITEMS];
};
#if defined(BOARD_HAS_HW_SPLIT_VERSIONING)
static inline constexpr px4_spi_bus_all_hw_t initSPIFmumID(hw_fmun_id_t hw_fmun_id,
const px4_spi_bus_array_t &bus_items)
{
return true;
px4_spi_bus_all_hw_t ret{};
for (int i = 0; i < SPI_BUS_MAX_BUS_ITEMS; ++i) {
ret.buses[i] = bus_items.item[i];
}
ret.board_hw_fmun_id = hw_fmun_id;
return ret;
}
#else
static inline constexpr px4_spi_bus_all_hw_t initSPIHWVersion(int hw_version_revision,
const px4_spi_bus_array_t &bus_items)
{
px4_spi_bus_all_hw_t ret{};
for (int i = 0; i < SPI_BUS_MAX_BUS_ITEMS; ++i) {
ret.buses[i] = bus_items.item[i];
}
ret.board_hw_version_revision = hw_version_revision;
return ret;
}
#endif
constexpr bool validateSPIConfig(const px4_spi_bus_t spi_buses_conf[SPI_BUS_MAX_BUS_ITEMS]);
constexpr bool validateSPIConfig(const px4_spi_bus_all_hw_t spi_buses_conf[BOARD_NUM_SPI_CFG_HW_VERSIONS])
{
for (int ver = 0; ver < BOARD_NUM_SPI_CFG_HW_VERSIONS; ++ver) {
validateSPIConfig(spi_buses_conf[ver].buses);
}
for (int ver = 1; ver < BOARD_NUM_SPI_CFG_HW_VERSIONS; ++ver) {
for (int i = 0; i < SPI_BUS_MAX_BUS_ITEMS; ++i) {
const bool equal_power_enable_gpio = spi_buses_conf[ver].buses[i].power_enable_gpio == spi_buses_conf[ver -
1].buses[i].power_enable_gpio;
// currently board_control_spi_sensors_power_configgpio() depends on that - this restriction can be removed
// by ensuring board_control_spi_sensors_power_configgpio() is called after the hw version is determined
// and SPI config is initialized.
constexpr_assert(equal_power_enable_gpio, "All HW versions must define the same power enable GPIO");
}
}
return false;
}
#endif // CONFIG_SPI