Merge pull request #49 from adafruit/rt10xx-followup-pr41

rt10xx link2ram followup
This commit is contained in:
Ha Thach 2020-12-31 23:17:42 +07:00 committed by GitHub
commit e43e10a04e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 1133 additions and 797 deletions

View file

@ -1,16 +1,14 @@
UF2_FAMILY_ID = 0x2abc77ec
CROSS_COMPILE = arm-none-eabi-
# List of git submodules that is included as part of the UF2 version
GIT_SUBMODULES = nxp tinyusb
include ../make.mk
MCU_DIR = lib/nxp/sdk/devices/$(MCU)
LD_FILES ?= $(MCU_DIR)/gcc/$(MCU_CORE)_flash.ld
# Version
GIT_VERSION := $(shell git describe --dirty --always --tags)
GIT_SUBMODULE_VERSIONS := $(shell git submodule status $(addprefix ../../lib/, tinyusb) | cut -d" " -f3,4 | paste -s -d" " -)
GIT_SUBMODULE_VERSIONS := $(subst ../../lib/,,$(GIT_SUBMODULE_VERSIONS))
# Port Compiler Flags
CFLAGS += \
-flto \
@ -19,9 +17,7 @@ CFLAGS += \
-mcpu=cortex-m33 \
-mfloat-abi=hard \
-mfpu=fpv5-sp-d16 \
-DCFG_TUSB_MCU=OPT_MCU_LPC55XX \
-DBOARD_UF2_FAMILY_ID=$(UF2_FAMILY_ID) \
-DUF2_VERSION='"$(GIT_VERSION) - $(GIT_SUBMODULE_VERSIONS)"'
-DCFG_TUSB_MCU=OPT_MCU_LPC55XX
# suppress warning caused by vendor mcu driver
CFLAGS += -Wno-error=unused-parameter -Wno-error=float-equal
@ -62,7 +58,11 @@ SELF_ASFLAGS = $(ASFLAGS)
include ../self_update.mk
# required for uf2 conversion
# self-update uf2 file
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).uf2: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex
@echo CREATE $@
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).elf
@echo CREATE $@
@$(OBJCOPY) -O ihex $^ $@

View file

@ -41,6 +41,13 @@ endif
BUILD = _build/$(BOARD)
BIN = _bin/$(BOARD)
OUTNAME = tinyuf2-$(BOARD)
# UF2 version with git tag and submodules
GIT_VERSION := $(shell git describe --dirty --always --tags)
GIT_SUBMODULE_VERSIONS := $(shell git submodule status $(addprefix ../../lib/,$(GIT_SUBMODULES)) | cut -d" " -f3,4 | paste -s -d" " -)
GIT_SUBMODULE_VERSIONS := $(subst ../../lib/,,$(GIT_SUBMODULE_VERSIONS))
#-------------- Source files and compiler flags --------------
# PORT is directory name containing the Makefile
@ -94,7 +101,9 @@ CFLAGS += \
-Wsign-compare \
-Wmissing-format-attribute \
-Wunreachable-code \
-Wcast-align
-Wcast-align \
-DBOARD_UF2_FAMILY_ID=$(UF2_FAMILY_ID) \
-DUF2_VERSION='"$(GIT_VERSION) - $(GIT_SUBMODULE_VERSIONS)"'
# Debugging/Optimization
ifeq ($(DEBUG), 1)

View file

@ -1,15 +1,16 @@
UF2_FAMILY_ID = 0x4fb2d5bd
CROSS_COMPILE = arm-none-eabi-
# List of git submodules that is included as part of the UF2 version
GIT_SUBMODULES = nxp tinyusb
# For flash-pyocd-bin target
FLASH_BIN_ADDR = 0x60000400
include ../make.mk
MCU_DIR = lib/nxp/sdk/devices/$(MCU)
LD_FILES ?= $(PORT_DIR)/linker/$(MCU)_nor.ld $(PORT_DIR)/linker/memory.ld $(PORT_DIR)/linker/common.ld
# Version
GIT_VERSION := $(shell git describe --dirty --always --tags)
GIT_SUBMODULE_VERSIONS := $(shell git submodule status $(addprefix ../../lib/,nxp tinyusb) | cut -d" " -f3,4 | paste -s -d" " -)
GIT_SUBMODULE_VERSIONS := $(subst ../../lib/,,$(GIT_SUBMODULE_VERSIONS))
LD_FILES ?= $(PORT_DIR)/linker/$(MCU)_ram.ld $(PORT_DIR)/linker/memory.ld $(PORT_DIR)/linker/common.ld
# Port Compiler Flags
CFLAGS += \
@ -21,9 +22,7 @@ CFLAGS += \
-D__ARMVFP__=0 -D__ARMFPV5__=0 \
-DXIP_EXTERNAL_FLASH=1 \
-DXIP_BOOT_HEADER_ENABLE=1 \
-DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX \
-DBOARD_UF2_FAMILY_ID=$(UF2_FAMILY_ID) \
-DUF2_VERSION='"$(GIT_VERSION) - $(GIT_SUBMODULE_VERSIONS)"'
-DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX
# mcu driver cause following warnings
CFLAGS += -Wno-error=unused-parameter
@ -58,22 +57,54 @@ INC += \
include ../rules.mk
#-------------- Self-update --------------
SELF_CFLAGS = $(CFLAGS) -DTINYUF2_SELF_UPDATE
SELF_LDFLAGS = $(LDFLAGS)
SELF_LD_FILES ?= $(PORT_DIR)/linker/$(MCU)_nor.ld $(PORT_DIR)/linker/self_update_memory.ld $(PORT_DIR)/linker/common.ld
SELF_ASFLAGS = $(ASFLAGS)
#------------- Load to SRAM using sdphost -------------
# Note: you may need to give the sdphost binary executable permission first.
#---------------------------------------------------------
SDP_MIMXRT1011_PID = 0x0145
SDP_MIMXRT1011_WRITE_ADDR = 0x20206400
SDP_MIMXRT1011_JUMP_ADDR = 0x20207000
SDP_MIMXRT1021_PID = 0x0130
SDP_MIMXRT1021_WRITE_ADDR = 0x0400
SDP_MIMXRT1021_JUMP_ADDR = 0x1000
SDP_MIMXRT1062_PID = 0x0135
SDP_MIMXRT1062_WRITE_ADDR = 0x0400
SDP_MIMXRT1062_JUMP_ADDR = 0x1000
ifeq ($(OS),Windows_NT)
SDPHOST = sdphost/win/sdphost.exe
else
UNAME_S := $(shell uname -s)
UNAME_I := $(shell uname -i)
ifeq ($(UNAME_S),Darwin)
SDPHOST = sdphost/mac/sdphost
endif
ifeq ($(UNAME_S),Linux)
ifeq ($(UNAME_I),x86_64)
SDPHOST = sdphost/linux/amd64/sdphost
endif
ifeq ($(UNAME_I),i386)
SDPHOST = sdphost/linux/i386/sdphost
endif
endif
endif
flash-sdp: $(BUILD)/$(OUTNAME).bin
$(SDPHOST) -u 0x1fc9,$(SDP_$(MCU)_PID) -- write-file $(SDP_$(MCU)_WRITE_ADDR) $<
$(SDPHOST) -u 0x1fc9,$(SDP_$(MCU)_PID) -- jump-address $(SDP_$(MCU)_JUMP_ADDR)
#-------------- Self-update --------------
# RT10xx run entire bootloader from SRAM and
# can directly flash the bootloader region
# without using self-update app as other port
#--------------------------------------------
include ../self_update.mk
# required for uf2 conversion
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).elf
# self-update uf2 file
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).uf2: $(BUILD)/$(OUTNAME).bin $(SELF_OBJ_DIRS)
@echo CREATE $@
@$(OBJCOPY) -O ihex -R .flash_config -R .ivt $^ $@
# required for self-update elf compile
$(SELF_BUILD_OBJ)/self_update/$(OUTNAME).c: $(SELF_BUILD_OBJ)/self_update/$(OUTNAME)-textonly.bin
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py --carray $^ -o $@
$(SELF_BUILD_OBJ)/self_update/$(OUTNAME)-textonly.bin: $(BUILD)/$(OUTNAME).elf
@$(OBJCOPY) -O binary -R .flash_config -R .ivt $^ $@
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x60000400 -c -o $@ $<

View file

@ -0,0 +1,42 @@
# TinyUF for iMXRT
TinyUF2 port of iMXRT runs entirely on SRAM which is not only super fast but also easy to perform self-update. After powering on, if TinyUF2 already exists on external flash, it will be loaded to internal SRAM and start executing from there.
## Initial Flash
To initially flash TinyUF2 on your blank board or board that is shipped with other bootlaoder. You could either use external debugger or BootROM
### External Debugger
jlink or pyocd can be used to program .bin file to appropriate address on external flash which is typically **0x60000400**. This can be done with `flash-jlink-bin` or `flash-pyocd-bin` make target.
```
make BOARD=metro_m7_1011 flash-jlink-bin
```
### Serial Download Mode with BootROM
iMXRT has built-in BootROM that implements the Serial Download Protocol (SDP), which can be used to load & execute TinyUF2 to SRAM with `spdhost` tool via USB. You need to
1. Power up your board with the Boot Mode switch set to `BOOT_MODE[1:0]=01` to enter Serial Download mode. Note Serial Download mode also automatically run with blank flash, therefore you don't have to manual change it in your production run.
2. Run `flash-sdp` make target which in turn uses the `sdphost` with correct address and arguments to load TinyUF2
```
make BOARD=imxrt1010_evk flash-sdp
```
3. (Optional) Drag and drop `update-tinyuf2_BOARD.uf2` to program the external flash. This step is optional for blank chip since TinyUF2 will automatically check the external flash to see if it has a valid Flash Configure Block (FCFB), if not TinyUF2 will program the external flash with its SRAM's image.
Note: `sdphost` executable binaries for common platforms (windows/mac/linux) are included in sdphost folder. If you have issue with executable permission, just manually give it permission to run. The source code for sdphost tool is also included just in case binaries for your host platform is not included (e.g ARM, RISC-V etc ...)
Note2: Since SDP with BootROM doesn't requires external debugger and always exists regardless of the external flash, this method can also be used to de-brick your board should it needs.
## Update to newer version
Double tap to enter bootloader mode, then simply drag & drop `update-tinyuf2_BOARD.uf2` into BOOT drive to update. The update file can be generated by running make with `self-update` target or simply download it from [release page](https://github.com/adafruit/tinyuf2/releases).
## Supported Boards
- Adafruit Metro M7 1011
- [MIMX RT1010 Evaluation Kit](https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1010-evaluation-kit:MIMXRT1010-EVK)
- [MIMX RT1020 Evaluation Kit](https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/i.mx-rt1020-evaluation-kit:MIMXRT1020-EVK)
- [MIMX RT1060 Evaluation Kit](https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/mimxrt1060-evk-i.mx-rt1060-evaluation-kit:MIMXRT1060-EVK)

View file

@ -124,9 +124,9 @@ enum
//!@brief FlexSPI Read Sample Clock Source definition
typedef enum _FlashReadSampleClkSource
{
kFlexSPIReadSampleClk_LoopbackInternally = 0,
kFlexSPIReadSampleClk_LoopbackFromDqsPad = 1,
kFlexSPIReadSampleClk_LoopbackFromSckPad = 2,
kFlexSPIReadSampleClk_LoopbackInternally = 0,
kFlexSPIReadSampleClk_LoopbackFromDqsPad = 1,
kFlexSPIReadSampleClk_LoopbackFromSckPad = 2,
kFlexSPIReadSampleClk_ExternalInputFromDqsPad = 3,
} flexspi_read_sample_clk_t;
@ -156,32 +156,32 @@ enum _flexspi_status
//!@brief Misc feature bit definitions
enum
{
kFlexSpiMiscOffset_DiffClkEnable = 0, //!< Bit for Differential clock enable
kFlexSpiMiscOffset_Ck2Enable = 1, //!< Bit for CK2 enable
kFlexSpiMiscOffset_ParallelEnable = 2, //!< Bit for Parallel mode enable
kFlexSpiMiscOffset_WordAddressableEnable = 3, //!< Bit for Word Addressable enable
kFlexSpiMiscOffset_SafeConfigFreqEnable = 4, //!< Bit for Safe Configuration Frequency enable
kFlexSpiMiscOffset_DiffClkEnable = 0, //!< Bit for Differential clock enable
kFlexSpiMiscOffset_Ck2Enable = 1, //!< Bit for CK2 enable
kFlexSpiMiscOffset_ParallelEnable = 2, //!< Bit for Parallel mode enable
kFlexSpiMiscOffset_WordAddressableEnable = 3, //!< Bit for Word Addressable enable
kFlexSpiMiscOffset_SafeConfigFreqEnable = 4, //!< Bit for Safe Configuration Frequency enable
kFlexSpiMiscOffset_PadSettingOverrideEnable = 5, //!< Bit for Pad setting override enable
kFlexSpiMiscOffset_DdrModeEnable = 6, //!< Bit for DDR clock confiuration indication.
kFlexSpiMiscOffset_UseValidTimeForAllFreq = 7, //!< Bit for DLLCR settings under all modes
kFlexSpiMiscOffset_SecondPinMux = 8, //!< Bit for Second Pinmux group
kFlexSpiMiscOffset_SecondDqsPinMux = 9, //!< Bit for Second DQS Pinmux
kFlexSpiMiscOffset_DdrModeEnable = 6, //!< Bit for DDR clock confiuration indication.
kFlexSpiMiscOffset_UseValidTimeForAllFreq = 7, //!< Bit for DLLCR settings under all modes
kFlexSpiMiscOffset_SecondPinMux = 8, //!< Bit for Second Pinmux group
kFlexSpiMiscOffset_SecondDqsPinMux = 9, //!< Bit for Second DQS Pinmux
};
//!@brief Flash Type Definition
enum
{
kFlexSpiDeviceType_SerialNOR = 1, //!< Flash devices are Serial NOR
kFlexSpiDeviceType_SerialNAND = 2, //!< Flash devices are Serial NAND
kFlexSpiDeviceType_SerialRAM = 3, //!< Flash devices are Serial RAM/HyperFLASH
kFlexSpiDeviceType_SerialNOR = 1, //!< Flash devices are Serial NOR
kFlexSpiDeviceType_SerialNAND = 2, //!< Flash devices are Serial NAND
kFlexSpiDeviceType_SerialRAM = 3, //!< Flash devices are Serial RAM/HyperFLASH
kFlexSpiDeviceType_MCP_NOR_NAND = 0x12, //!< Flash device is MCP device, A1 is Serial NOR, A2 is Serial NAND
kFlexSpiDeviceType_MCP_NOR_RAM = 0x13, //!< Flash deivce is MCP device, A1 is Serial NOR, A2 is Serial RAMs
kFlexSpiDeviceType_MCP_NOR_RAM = 0x13, //!< Flash deivce is MCP device, A1 is Serial NOR, A2 is Serial RAMs
};
//!@brief Flash Pad Definitions
enum
{
kSerialFlash_1Pad = 1,
kSerialFlash_1Pad = 1,
kSerialFlash_2Pads = 2,
kSerialFlash_4Pads = 4,
kSerialFlash_8Pads = 8,

View file

@ -41,8 +41,10 @@
#define FLEXSPI_INSTANCE 0
#define FCFB_START_ADDRESS (FlexSPI_AMBA_BASE + 0x400U)
// Flash Configuration Structure
extern flexspi_nor_config_t qspiflash_config;
extern flexspi_nor_config_t const qspiflash_config;
static uint32_t _flash_page_addr = NO_CACHE;
static uint8_t _flash_cache[SECTOR_SIZE] __attribute__((aligned(4)));
@ -50,7 +52,24 @@ static uint8_t _flash_cache[SECTOR_SIZE] __attribute__((aligned(4)));
void board_flash_init(void)
{
flexspi_nor_flash_init(FLEXSPI_INSTANCE, &qspiflash_config);
flexspi_nor_flash_init(FLEXSPI_INSTANCE, (flexspi_nor_config_t*) &qspiflash_config);
// Check for FCFB and copy bootloader to flash if not present
if ( *(uint32_t*) FCFB_START_ADDRESS != FLEXSPI_CFG_BLK_TAG )
{
uint8_t const* image_data = (uint8_t const *) &qspiflash_config;
uint32_t flash_addr = FCFB_START_ADDRESS;
TU_LOG1("FCFB not present. Copying image to flash.\r\n");
while ( flash_addr < (FlexSPI_AMBA_BASE + BOARD_BOOT_LENGTH) )
{
board_flash_write(flash_addr, image_data, FLASH_PAGE_SIZE);
flash_addr += FLASH_PAGE_SIZE;
image_data += FLASH_PAGE_SIZE;
}
board_flash_flush();
TU_LOG1("TinyUF2 copied to flash.\r\n");
}
}
uint32_t board_flash_size(void)
@ -80,7 +99,7 @@ void board_flash_flush(void)
uint32_t const sector_addr = (_flash_page_addr - FlexSPI_AMBA_BASE);
__disable_irq();
status = flexspi_nor_flash_erase(FLEXSPI_INSTANCE, &qspiflash_config, sector_addr, SECTOR_SIZE);
status = flexspi_nor_flash_erase(FLEXSPI_INSTANCE, (flexspi_nor_config_t*) &qspiflash_config, sector_addr, SECTOR_SIZE);
__enable_irq();
SCB_InvalidateDCache_by_Addr((uint32_t *)sector_addr, SECTOR_SIZE);
@ -97,7 +116,7 @@ void board_flash_flush(void)
void* page_data = _flash_cache + i * FLASH_PAGE_SIZE;
__disable_irq();
status = flexspi_nor_flash_page_program(FLEXSPI_INSTANCE, &qspiflash_config, page_addr, (uint32_t*) page_data);
status = flexspi_nor_flash_page_program(FLEXSPI_INSTANCE, (flexspi_nor_config_t*) &qspiflash_config, page_addr, (uint32_t*) page_data);
__enable_irq();
if ( status != kStatus_Success )
@ -131,39 +150,3 @@ void board_flash_write (uint32_t addr, void const *src, uint32_t len)
// Overwrite part or all of the page cache with the src data.
memcpy(_flash_cache + (addr & (SECTOR_SIZE - 1)), src, len);
}
#ifdef TINYUF2_SELF_UPDATE
#define SELF_UPDATE_ADDRESS (FlexSPI_AMBA_BASE + 0x2000)
void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len)
{
board_flash_init();
//------------- Flash new bootloader -------------//
uint32_t addr = SELF_UPDATE_ADDRESS;
while (bootloader_len)
{
uint32_t const count = (bootloader_len < SECTOR_SIZE) ? bootloader_len : SECTOR_SIZE;
board_flash_write(addr, bootloader_bin, count);
addr += count;
bootloader_len -= count;
bootloader_bin += count;
}
board_flash_flush();
//------------- Self destruct -------------//
extern uint32_t __VECTOR_TABLE[]; // defined by linker
uint32_t const isr_addr = ((uint32_t) __VECTOR_TABLE) - FlexSPI_AMBA_BASE;
__disable_irq();
flexspi_nor_flash_erase_sector(FLEXSPI, isr_addr);
SCB_InvalidateDCache_by_Addr((uint32_t *)isr_addr, SECTOR_SIZE);
NVIC_SystemReset();
}
#endif

View file

@ -364,8 +364,6 @@ int board_uart_write(void const * buf, int len)
//--------------------------------------------------------------------+
// USB Interrupt Handler
//--------------------------------------------------------------------+
#ifndef TINYUF2_SELF_UPDATE
void USB_OTG1_IRQHandler(void)
{
#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST
@ -387,5 +385,3 @@ void USB_OTG2_IRQHandler(void)
tud_int_handler(1);
#endif
}
#endif

View file

@ -36,8 +36,14 @@
#include "fsl_device_registers.h"
#include "board.h"
// Flash Start Address of Application
#define BOARD_FLASH_APP_START 0x6000C000 // FlexSPI_AMBA_BASE + 0xC000
// _fcfb_origin is defined in linker script
extern uint32_t _fcfb_origin[];
#define BOARD_BOOT_START (((uint32_t) _fcfb_origin) - 0x400)
#define BOARD_BOOT_LENGTH (0x8800)
// Flash Start Address of Application, typically 0x6000C000
#define BOARD_FLASH_APP_START (FlexSPI_AMBA_BASE + 0xC000)
// Double Reset tap to enter DFU
#define USE_DFU_DOUBLE_TAP 1

View file

@ -28,13 +28,8 @@
#ifndef BOARD_H_
#define BOARD_H_
// required since iMX RT10xx SDK include this file for board size
// Size of on-board external flash
#define BOARD_FLASH_SIZE (0x1000000U)
#define BOARD_BOOT_START (0x20206000U)
#define BOARD_BOOT_LENGTH (0xA000U)
#define BOARD_FLEXSPI_INSTANCE (uint32_t)0x0
#define BOARD_FLEXSPI_PARALLEL 0
//--------------------------------------------------------------------+
// LED

View file

@ -8,5 +8,5 @@ JLINK_DEVICE = MIMXRT1011DAE5A
PYOCD_TARGET = mimxrt1010
# flash using pyocd
flash: flash-pyocd
flash: flash-pyocd-bin
erase: erase-pyocd

View file

@ -12,14 +12,14 @@
__attribute__((section(".boot_hdr.ivt")))
/*************************************
* IVT Data for Load to RAM from flash
* IVT Data
*************************************/
const ivt image_vector_table = {
IVT_HEADER, /* IVT Header */
IMAGE_ENTRY_ADDRESS, /* Image Entry Function */
IVT_RSVD, /* Reserved = 0 */
(uint32_t)DCD_ADDRESS, /* Address where DCD information is stored */
(uint32_t)&boot_data, /* Address where BOOT Data Structure is stored */
(uint32_t)BOOT_DATA_ADDRESS, /* Address where BOOT Data Structure is stored */
(uint32_t)&image_vector_table, /* Pointer to IVT Self (absolute address) */
(uint32_t)CSF_ADDRESS, /* Address where CSF file is stored */
IVT_RSVD /* Reserved = 0 */

View file

@ -0,0 +1,69 @@
/*
* Copyright 2017-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "bl_api.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
#define g_bootloaderTree ((bootloader_api_entry_t *)*(uint32_t *)0x0020001c)
#define api_flexspi_nor_erase_sector \
((status_t(*)(uint32_t instance, flexspi_nor_config_t * config, uint32_t address))0x0021055d)
#define api_flexspi_nor_erase_block \
((status_t(*)(uint32_t instance, flexspi_nor_config_t * config, uint32_t address))0x002104a9)
/*******************************************************************************
* Codes
******************************************************************************/
/*******************************************************************************
* FlexSPI NOR driver
******************************************************************************/
//#if BL_FEATURE_HAS_FLEXSPI_NOR_ROMAPI
status_t flexspi_nor_flash_init(uint32_t instance, flexspi_nor_config_t *config)
{
return g_bootloaderTree->flexSpiNorDriver->init(instance, config);
}
status_t flexspi_nor_flash_page_program(uint32_t instance,
flexspi_nor_config_t *config,
uint32_t dstAddr,
const uint32_t *src)
{
return g_bootloaderTree->flexSpiNorDriver->program(instance, config, dstAddr, src);
}
status_t flexspi_nor_flash_erase(uint32_t instance, flexspi_nor_config_t *config, uint32_t start, uint32_t length)
{
return g_bootloaderTree->flexSpiNorDriver->erase(instance, config, start, length);
}
status_t flexspi_nor_flash_erase_sector(uint32_t instance, flexspi_nor_config_t *config, uint32_t start)
{
return api_flexspi_nor_erase_sector(instance, config, start);
}
status_t flexspi_nor_flash_erase_block(uint32_t instance, flexspi_nor_config_t *config, uint32_t start)
{
return api_flexspi_nor_erase_block(instance, config, start);
}
status_t flexspi_command_xfer(uint32_t instance, flexspi_xfer_t *xfer)
{
return g_bootloaderTree->flexSpiNorDriver->xfer(instance, xfer);
}
void flexspi_clear_cache(uint32_t instance)
{
g_bootloaderTree->flexSpiNorDriver->clear_cache(instance);
}
//#endif // BL_FEATURE_HAS_FLEXSPI_NOR_ROMAPI

View file

@ -0,0 +1,47 @@
/*
* Copyright 2017-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BL_API_H__
#define __BL_API_H__
#include <string.h>
#include "bl_flexspi.h"
#include "flexspi_nor_flash.h"
#include "fsl_device_registers.h"
/*******************************************************************************
* Definitions
******************************************************************************/
typedef struct
{
uint32_t version;
status_t (*init)(uint32_t instance, flexspi_nor_config_t *config);
status_t (*program)(uint32_t instance, flexspi_nor_config_t *config, uint32_t dst_addr, const uint32_t *src);
uint32_t reserved0;
status_t (*erase)(uint32_t instance, flexspi_nor_config_t *config, uint32_t start, uint32_t lengthInBytes);
uint32_t reserved1;
void (*clear_cache)(uint32_t instance);
status_t (*xfer)(uint32_t instance, flexspi_xfer_t *xfer);
uint32_t reserved2;
uint32_t reserved3;
} flexspi_nor_driver_interface_t;
enum
{
kFlexSpiNorDriver_Version_1_5 = MAKE_VERSION(1, 4, 0),
};
typedef struct
{
void (*runBootloader)(void *arg); //!< Function to start the bootloader executing
const uint32_t version; //!< Bootloader version number
const char *copyright; //!< Bootloader Copyright
const uint32_t reserved0;
const flexspi_nor_driver_interface_t *flexSpiNorDriver; //!< FlexSPI NOR Flash API
} bootloader_api_entry_t;
#endif //__BL_API_H__

View file

@ -28,8 +28,8 @@
#ifndef BOARD_H_
#define BOARD_H_
// required since iMX RT10xx SDK include this file for board size
#define BOARD_FLASH_SIZE (0x800000U)
// Size of on-board external flash
#define BOARD_FLASH_SIZE (0x800000U)
//--------------------------------------------------------------------+
// LED

View file

@ -8,7 +8,7 @@ JLINK_DEVICE = MIMXRT1021DAG5A
PYOCD_TARGET = mimxrt1020
# flash using pyocd
flash: flash-pyocd
flash: flash-pyocd-bin
erase: erase-pyocd
# flash: flash-jlink

View file

@ -5,7 +5,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "flexspi_nor_config.h"
#include "flexspi_nor_flash.h"
#include "fsl_flexspi_nor_boot.h"
#include "boards.h"
@ -30,8 +30,8 @@ __attribute__((section(".boot_hdr.boot_data")))
* Boot Data
*************************************/
const BOOT_DATA_T boot_data = {
FLASH_BASE, /* boot start location */
FLASH_SIZE, /* size */
BOARD_BOOT_START, /* boot start location */
BOARD_BOOT_LENGTH, /* bootloader size 48K */
PLUGIN_FLAG, /* Plugin flag*/
0xFFFFFFFF /* empty - extra data word */
};

View file

@ -28,12 +28,8 @@
#ifndef BOARD_H_
#define BOARD_H_
// required since iMX RT10xx SDK include this file for board size
// Size of on-board external flash
#define BOARD_FLASH_SIZE (0x800000U)
#define BOARD_BOOT_START (0x0U)
#define BOARD_BOOT_LENGTH (0xC000U)
#define BOARD_FLEXSPI_INSTANCE (uint32_t)0x0
//--------------------------------------------------------------------+
// LED

View file

@ -8,5 +8,5 @@ JLINK_DEVICE = MIMXRT1062xxx6A
PYOCD_TARGET = mimxrt1060
# flash using pyocd
flash: flash-pyocd
flash: flash-pyocd-bin
erase: erase-pyocd

View file

@ -5,7 +5,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "flexspi_nor_config.h"
#include "flexspi_nor_flash.h"
#include "fsl_flexspi_nor_boot.h"
#include "boards.h"
@ -20,7 +20,7 @@ const ivt image_vector_table = {
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)&image_vector_table, /* Pointer to IVT Self (absolute address */
(uint32_t)&image_vector_table, /* Pointer to IVT Self (absolute address) */
(uint32_t)CSF_ADDRESS, /* Address where CSF file is stored */
IVT_RSVD /* Reserved = 0 */
};

View file

@ -28,11 +28,8 @@
#ifndef BOARD_H_
#define BOARD_H_
// required since iMX RT10xx SDK include this file for board size
// Size of on-board external flash
#define BOARD_FLASH_SIZE (2*1024*1024)
#define BOARD_BOOT_START (0x0U)
#define BOARD_BOOT_LENGTH (0x8000U)
//--------------------------------------------------------------------+
// LED

View file

@ -8,5 +8,5 @@ JLINK_DEVICE = MIMXRT1011DAE5A
PYOCD_TARGET = mimxrt1010
# flash using pyocd
flash: flash-pyocd
flash: flash-pyocd-bin
erase: erase-pyocd

View file

@ -19,7 +19,7 @@ const ivt image_vector_table = {
IMAGE_ENTRY_ADDRESS, /* Image Entry Function */
IVT_RSVD, /* Reserved = 0 */
(uint32_t)DCD_ADDRESS, /* Address where DCD information is stored */
(uint32_t)&boot_data, /* Address where BOOT Data Structure is stored */
(uint32_t)BOOT_DATA_ADDRESS, /* Address where BOOT Data Structure is stored */
(uint32_t)&image_vector_table, /* Pointer to IVT Self (absolute address) */
(uint32_t)CSF_ADDRESS, /* Address where CSF file is stored */
IVT_RSVD /* Reserved = 0 */

View file

@ -1,277 +0,0 @@
/*
* Copyright 2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __FLEXSPI_NOR_CONFIG__
#define __FLEXSPI_NOR_CONFIG__
#include <stdint.h>
#include <stdbool.h>
#include "fsl_common.h"
/*! @name Driver version */
/*@{*/
/*! @brief XIP_BOARD driver version 2.0.0. */
#define FSL_XIP_BOARD_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/* FLEXSPI memory config block related defintions */
#define FLEXSPI_CFG_BLK_TAG (0x42464346UL) // ascii "FCFB" Big Endian
#define FLEXSPI_CFG_BLK_VERSION (0x56010400UL) // V1.4.0
#define FLEXSPI_CFG_BLK_SIZE (512)
/* FLEXSPI Feature related definitions */
#define FLEXSPI_FEATURE_HAS_PARALLEL_MODE 1
/* Lookup table related defintions */
#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_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))
//!@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,
#if defined(MIMXRT1011_SERIES) || defined(MIMXRT1064_SERIES) || defined(MIMXRT1062_SERIES)
kFlexSpiSerialClk_120MHz = 7,
kFlexSpiSerialClk_133MHz = 8,
kFlexSpiSerialClk_166MHz = 9,
#elif defined(MIMXRT1015_SERIES) || defined(MIMXRT1021_SERIES) || defined(MIMXRT1052_SERIES)
kFlexSpiSerialClk_133MHz = 7,
kFlexSpiSerialClk_166MHz = 8,
kFlexSpiSerialClk_200MHz = 9,
#else
#error This series is not supported
#endif
} flexspi_serial_clk_freq_t;
//!@brief FlexSPI clock configuration type
enum
{
kFlexSpiClk_SDR, //!< Clock configure for SDR mode
kFlexSpiClk_DDR, //!< Clock configurat for DDR mode
};
//!@brief FlexSPI Read Sample Clock Source definition
typedef enum _FlashReadSampleClkSource
{
kFlexSPIReadSampleClk_LoopbackInternally = 0,
kFlexSPIReadSampleClk_LoopbackFromDqsPad = 1,
kFlexSPIReadSampleClk_LoopbackFromSckPad = 2,
kFlexSPIReadSampleClk_ExternalInputFromDqsPad = 3,
} flexspi_read_sample_clk_t;
//!@brief Misc feature bit definitions
enum
{
kFlexSpiMiscOffset_DiffClkEnable = 0, //!< Bit for Differential clock enable
kFlexSpiMiscOffset_Ck2Enable = 1, //!< Bit for CK2 enable
kFlexSpiMiscOffset_ParallelEnable = 2, //!< Bit for Parallel mode enable
kFlexSpiMiscOffset_WordAddressableEnable = 3, //!< Bit for Word Addressable enable
kFlexSpiMiscOffset_SafeConfigFreqEnable = 4, //!< Bit for Safe Configuration Frequency enable
kFlexSpiMiscOffset_PadSettingOverrideEnable = 5, //!< Bit for Pad setting override enable
kFlexSpiMiscOffset_DdrModeEnable = 6, //!< Bit for DDR clock confiuration indication.
};
//!@brief Flash Type Definition
enum
{
kFlexSpiDeviceType_SerialNOR = 1, //!< Flash devices are Serial NOR
kFlexSpiDeviceType_SerialNAND = 2, //!< Flash devices are Serial NAND
kFlexSpiDeviceType_SerialRAM = 3, //!< Flash devices are Serial RAM/HyperFLASH
kFlexSpiDeviceType_MCP_NOR_NAND = 0x12, //!< Flash device is MCP device, A1 is Serial NOR, A2 is Serial NAND
kFlexSpiDeviceType_MCP_NOR_RAM = 0x13, //!< Flash deivce is MCP device, A1 is Serial NOR, A2 is Serial RAMs
};
//!@brief Flash Pad Definitions
enum
{
kSerialFlash_1Pad = 1,
kSerialFlash_2Pads = 2,
kSerialFlash_4Pads = 4,
kSerialFlash_8Pads = 8,
};
//!@brief FlexSPI LUT Sequence structure
typedef struct _lut_sequence
{
uint8_t seqNum; //!< Sequence Number, valid number: 1-16
uint8_t seqId; //!< Sequence Index, valid number: 0-15
uint16_t reserved;
} flexspi_lut_seq_t;
//!@brief Flash Configuration Command Type
enum
{
kDeviceConfigCmdType_Generic, //!< Generic command, for example: configure dummy cycles, drive strength, etc
kDeviceConfigCmdType_QuadEnable, //!< Quad Enable command
kDeviceConfigCmdType_Spi2Xpi, //!< Switch from SPI to DPI/QPI/OPI mode
kDeviceConfigCmdType_Xpi2Spi, //!< Switch from DPI/QPI/OPI to SPI mode
kDeviceConfigCmdType_Spi2NoCmd, //!< Switch to 0-4-4/0-8-8 mode
kDeviceConfigCmdType_Reset, //!< Reset device command
};
//!@brief FlexSPI Memory Configuration Block
typedef struct _FlexSPIConfig
{
uint32_t tag; //!< [0x000-0x003] Tag, fixed value 0x42464346UL
uint32_t version; //!< [0x004-0x007] Version,[31:24] -'V', [23:16] - Major, [15:8] - Minor, [7:0] - bugfix
uint32_t reserved0; //!< [0x008-0x00b] Reserved for future use
uint8_t readSampleClkSrc; //!< [0x00c-0x00c] Read Sample Clock Source, valid value: 0/1/3
uint8_t csHoldTime; //!< [0x00d-0x00d] CS hold time, default value: 3
uint8_t csSetupTime; //!< [0x00e-0x00e] CS setup time, default value: 3
uint8_t columnAddressWidth; //!< [0x00f-0x00f] Column Address with, for HyperBus protocol, it is fixed to 3, For
//! Serial NAND, need to refer to datasheet
uint8_t deviceModeCfgEnable; //!< [0x010-0x010] Device Mode Configure enable flag, 1 - Enable, 0 - Disable
uint8_t deviceModeType; //!< [0x011-0x011] Specify the configuration command type:Quad Enable, DPI/QPI/OPI switch,
//! Generic configuration, etc.
uint16_t waitTimeCfgCommands; //!< [0x012-0x013] Wait time for all configuration commands, unit: 100us, Used for
//! DPI/QPI/OPI switch or reset command
flexspi_lut_seq_t deviceModeSeq; //!< [0x014-0x017] Device mode sequence info, [7:0] - LUT sequence id, [15:8] - LUt
//! sequence number, [31:16] Reserved
uint32_t deviceModeArg; //!< [0x018-0x01b] Argument/Parameter for device configuration
uint8_t configCmdEnable; //!< [0x01c-0x01c] Configure command Enable Flag, 1 - Enable, 0 - Disable
uint8_t configModeType[3]; //!< [0x01d-0x01f] Configure Mode Type, similar as deviceModeTpe
flexspi_lut_seq_t
configCmdSeqs[3]; //!< [0x020-0x02b] Sequence info for Device Configuration command, similar as deviceModeSeq
uint32_t reserved1; //!< [0x02c-0x02f] Reserved for future use
uint32_t configCmdArgs[3]; //!< [0x030-0x03b] Arguments/Parameters for device Configuration commands
uint32_t reserved2; //!< [0x03c-0x03f] Reserved for future use
uint32_t controllerMiscOption; //!< [0x040-0x043] Controller Misc Options, see Misc feature bit definitions for more
//! details
uint8_t deviceType; //!< [0x044-0x044] Device Type: See Flash Type Definition for more details
uint8_t sflashPadType; //!< [0x045-0x045] Serial Flash Pad Type: 1 - Single, 2 - Dual, 4 - Quad, 8 - Octal
uint8_t serialClkFreq; //!< [0x046-0x046] Serial Flash Frequencey, device specific definitions, See System Boot
//! Chapter for more details
uint8_t lutCustomSeqEnable; //!< [0x047-0x047] LUT customization Enable, it is required if the program/erase cannot
//! be done using 1 LUT sequence, currently, only applicable to HyperFLASH
uint32_t reserved3[2]; //!< [0x048-0x04f] Reserved for future use
uint32_t sflashA1Size; //!< [0x050-0x053] Size of Flash connected to A1
uint32_t sflashA2Size; //!< [0x054-0x057] Size of Flash connected to A2
uint32_t sflashB1Size; //!< [0x058-0x05b] Size of Flash connected to B1
uint32_t sflashB2Size; //!< [0x05c-0x05f] Size of Flash connected to B2
uint32_t csPadSettingOverride; //!< [0x060-0x063] CS pad setting override value
uint32_t sclkPadSettingOverride; //!< [0x064-0x067] SCK pad setting override value
uint32_t dataPadSettingOverride; //!< [0x068-0x06b] data pad setting override value
uint32_t dqsPadSettingOverride; //!< [0x06c-0x06f] DQS pad setting override value
uint32_t timeoutInMs; //!< [0x070-0x073] Timeout threshold for read status command
uint32_t commandInterval; //!< [0x074-0x077] CS deselect interval between two commands
uint16_t dataValidTime[2]; //!< [0x078-0x07b] CLK edge to data valid time for PORT A and PORT B, in terms of 0.1ns
uint16_t busyOffset; //!< [0x07c-0x07d] Busy offset, valid value: 0-31
uint16_t busyBitPolarity; //!< [0x07e-0x07f] Busy flag polarity, 0 - busy flag is 1 when flash device is busy, 1 -
//! busy flag is 0 when flash device is busy
uint32_t lookupTable[64]; //!< [0x080-0x17f] Lookup table holds Flash command sequences
flexspi_lut_seq_t lutCustomSeq[12]; //!< [0x180-0x1af] Customizable LUT Sequences
uint32_t reserved4[4]; //!< [0x1b0-0x1bf] Reserved for future use
} flexspi_mem_config_t;
/* */
#define NOR_CMD_INDEX_READ CMD_INDEX_READ //!< 0
#define NOR_CMD_INDEX_READSTATUS CMD_INDEX_READSTATUS //!< 1
#define NOR_CMD_INDEX_WRITEENABLE CMD_INDEX_WRITEENABLE //!< 2
#define NOR_CMD_INDEX_ERASESECTOR 3 //!< 3
#define NOR_CMD_INDEX_PAGEPROGRAM CMD_INDEX_WRITE //!< 4
#define NOR_CMD_INDEX_CHIPERASE 5 //!< 5
#define NOR_CMD_INDEX_DUMMY 6 //!< 6
#define NOR_CMD_INDEX_ERASEBLOCK 7 //!< 7
#define NOR_CMD_LUT_SEQ_IDX_READ CMD_LUT_SEQ_IDX_READ //!< 0 READ LUT sequence id in lookupTable stored in config block
#define NOR_CMD_LUT_SEQ_IDX_READSTATUS \
CMD_LUT_SEQ_IDX_READSTATUS //!< 1 Read Status LUT sequence id in lookupTable stored in config block
#define NOR_CMD_LUT_SEQ_IDX_READSTATUS_XPI \
2 //!< 2 Read status DPI/QPI/OPI sequence id in lookupTable stored in config block
#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE \
CMD_LUT_SEQ_IDX_WRITEENABLE //!< 3 Write Enable sequence id in lookupTable stored in config block
#define NOR_CMD_LUT_SEQ_IDX_WRITEENABLE_XPI \
4 //!< 4 Write Enable DPI/QPI/OPI sequence id in lookupTable stored in config block
#define NOR_CMD_LUT_SEQ_IDX_ERASESECTOR 5 //!< 5 Erase Sector sequence id in lookupTable stored in config block
#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 8 //!< 8 Erase Block sequence id in lookupTable stored in config block
#define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM \
CMD_LUT_SEQ_IDX_WRITE //!< 9 Program sequence id in lookupTable stored in config block
#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11 //!< 11 Chip Erase sequence in lookupTable id stored in config block
#define NOR_CMD_LUT_SEQ_IDX_READ_SFDP 13 //!< 13 Read SFDP sequence in lookupTable id stored in config block
#define NOR_CMD_LUT_SEQ_IDX_RESTORE_NOCMD \
14 //!< 14 Restore 0-4-4/0-8-8 mode sequence id in lookupTable stored in config block
#define NOR_CMD_LUT_SEQ_IDX_EXIT_NOCMD \
15 //!< 15 Exit 0-4-4/0-8-8 mode sequence id in lookupTable stored in config blobk
/*
* Serial NOR configuration block
*/
typedef struct _flexspi_nor_config
{
flexspi_mem_config_t memConfig; //!< Common memory configuration info via FlexSPI
uint32_t pageSize; //!< Page size of Serial NOR
uint32_t sectorSize; //!< Sector size of Serial NOR
uint8_t ipcmdSerialClkFreq; //!< Clock frequency for IP command
uint8_t isUniformBlockSize; //!< Sector/Block size is the same
uint8_t reserved0[2]; //!< Reserved for future use
uint8_t serialNorType; //!< Serial NOR Flash type: 0/1/2/3
uint8_t needExitNoCmdMode; //!< Need to exit NoCmd mode before other IP command
uint8_t halfClkForNonReadCmd; //!< Half the Serial Clock for non-read command: true/false
uint8_t needRestoreNoCmdMode; //!< Need to Restore NoCmd mode after IP commmand execution
uint32_t blockSize; //!< Block size
uint32_t reserve2[11]; //!< Reserved for future use
} flexspi_nor_config_t;
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* __FLEXSPI_NOR_CONFIG__ */

View file

@ -1,13 +0,0 @@
m_flash_base = 0x60000000;
m_itcm_base = 0x00000000;
m_itcm_size = 32K;
m_dtcm_base = 0x20000000;
m_dtcm_size = 32K;
m_ocram_base = 0x20200000;
m_ocram_size = 64K;
m_fcfb_origin = 0x20206400;
m_ivt_origin = 0x20207000;
m_int_origin = 0x20207400;
m_txt_origin = 0x20207800;
m_txt_length = 0x00008800;
m_data_length = 32K;

View file

@ -0,0 +1,10 @@
_itcm_base = 0x00000000;
_itcm_size = 32K;
_dtcm_base = 0x20000000;
_dtcm_size = 32K;
_ocram_base = 0x20200000;
_ocram_size = 64K;
_fcfb_origin = 0x20206400;

View file

@ -1,36 +0,0 @@
/*
** ###################################################################
** Processors: MIMXRT1011CAE4A
** MIMXRT1011DAE5A
**
** Compiler: GNU C Compiler
** Reference manual: IMXRT1010RM Rev.A, 03/2019
** Version: rev. 0.1, 2019-02-14
** Build: b190716
**
** Abstract:
** Linker file for the GNU C Compiler
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2019 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** ###################################################################
*/
/* Specify the memory areas */
MEMORY
{
m_ivt (RX) : ORIGIN = 0x20205800, LENGTH = 0x00000800 /* use OC RAM past boot ROM */
m_interrupts (RX) : ORIGIN = 0x20206000, LENGTH = 0x00000400
m_text (RX) : ORIGIN = 0x20206400, LENGTH = 0x20210000-0x20206400
m_data (RW) : ORIGIN = 0x20000000, LENGTH = 0x00008000 - 4 /* double tap */
m_data2 (RW) : ORIGIN = 0x20210000, LENGTH = 0x00000000
}
INCLUDE "rt10xx_common.ld"

View file

@ -1,3 +0,0 @@
m_flash_base = 0x60000000;
m_flash_config_origin = 0x60000000;
m_data_length = 64K;

View file

@ -0,0 +1,10 @@
_itcm_base = 0x00000000;
_itcm_size = 64K;
_dtcm_base = 0x20000000;
_dtcm_size = 64K;
_ocram_base = 0x20200000;
_ocram_size = 128K;
_fcfb_origin = 0x00000400;

View file

@ -1,13 +0,0 @@
m_flash_base = 0x60000000;
m_itcm_base = 0x00000000;
m_itcm_size = 128K;
m_dtcm_base = 0x20000000;
m_dtcm_size = 128K;
m_ocram_base = 0x20200000;
m_ocram_size = 256K;
m_fcfb_origin = 0x00000400;
m_ivt_origin = 0x00001000;
m_int_origin = 0x00001400;
m_txt_origin = 0x00001800;
m_txt_length = 0x0000A800;
m_data_length = 128K;

View file

@ -0,0 +1,10 @@
_itcm_base = 0x00000000;
_itcm_size = 128K;
_dtcm_base = 0x20000000;
_dtcm_size = 128K;
_ocram_base = 0x20200000;
_ocram_size = 256K;
_fcfb_origin = 0x00000400;

View file

@ -1,10 +1,25 @@
_fcfb_length = 0x0C00;
/* offset 0x1000 */
_ivt_origin = _fcfb_origin + _fcfb_length;
_ivt_length = 0x0400;
/* offset 0x1400 */
_interrupts_origin = _ivt_origin + _ivt_length;
_interrupts_length = 0x0400;
/* offset 0x1800 */
_text_origin = _interrupts_origin + _interrupts_length;
_text_length = 0x8800;
/* Specify the memory areas */
MEMORY
{
m_flash_config (RX) : ORIGIN = m_fcfb_origin, LENGTH = 0x00000C00 /* fcfb */
m_ivt (RX) : ORIGIN = m_ivt_origin, LENGTH = 0x00000400
m_interrupts (RX) : ORIGIN = m_int_origin, LENGTH = 0x00000400
m_text (RX) : ORIGIN = m_txt_origin, LENGTH = m_txt_length
m_data (RW) : ORIGIN = m_dtcm_base, LENGTH = m_dtcm_size - 4 /* double tap */
m_data2 (RW) : ORIGIN = m_ocram_base, LENGTH = m_ocram_size /* ocram */
m_flash_config (RX) : ORIGIN = _fcfb_origin , LENGTH = _fcfb_length
m_ivt (RX) : ORIGIN = _ivt_origin , LENGTH = _ivt_length
m_interrupts (RX) : ORIGIN = _interrupts_origin , LENGTH = _interrupts_length
m_text (RX) : ORIGIN = _text_origin , LENGTH = _text_length
m_data (RW) : ORIGIN = _dtcm_base , LENGTH = _dtcm_size - 4 /* 4 bytes for double tap */
m_data2 (RW) : ORIGIN = _ocram_base , LENGTH = _ocram_size
}

View file

@ -1,241 +0,0 @@
/*
** ###################################################################
** Compiler: GNU C Compiler
** Reference manual: IMXRT1010RM Rev.A, 03/2019
** Version: rev. 0.1, 2019-02-14
** Build: b190716
**
** Abstract:
** Linker file for the GNU C Compiler
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2019 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** ###################################################################
*/
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400;
VECTOR_RAM_SIZE = DEFINED(__ram_vector_table__) ? 0x00000400 : 0;
_board_dfu_dbl_tap = ORIGIN(m_data) + LENGTH(m_data);
/* Define output sections */
SECTIONS
{
__NCACHE_REGION_START = ORIGIN(m_data2);
__NCACHE_REGION_SIZE = 0;
ivt_begin = ORIGIN(m_ivt);
.ivt : AT(ivt_begin)
{
. = ALIGN(4);
__FLASH_BASE = .;
KEEP(* (.boot_hdr.ivt)) /* ivt section */
KEEP(* (.boot_hdr.boot_data)) /* boot section */
KEEP(* (.boot_hdr.dcd_data)) /* dcd section */
. = ALIGN(4);
} > m_ivt
/* The startup code goes first into internal RAM */
.interrupts :
{
__VECTOR_TABLE = .;
__Vectors = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} > m_interrupts
/* The program code and other data goes into internal RAM */
.text :
{
. = ALIGN(4);
/* all text section except flexspi files */
*(EXCLUDE_FILE(*flexspi_nor_flash_ops.o) .text*)
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > m_text
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > m_text
.ctors :
{
__CTOR_LIST__ = .;
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
} > m_text
.dtors :
{
__DTOR_LIST__ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
} > m_text
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} > m_text
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} > m_text
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} > m_text
__etext = .; /* define a global symbol at end of code */
__DATA_ROM = .; /* Symbol is used by startup for data initialization */
.interrupts_ram :
{
. = ALIGN(4);
__VECTOR_RAM__ = .;
__interrupts_ram_start__ = .; /* Create a global symbol at data start */
*(.m_interrupts_ram) /* This is a user defined section */
. += VECTOR_RAM_SIZE;
. = ALIGN(4);
__interrupts_ram_end__ = .; /* Define a global symbol at data end */
} > m_data
__VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts);
__RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0;
.data : AT(__DATA_ROM)
{
. = ALIGN(4);
__DATA_RAM = .;
__data_start__ = .; /* create a global symbol at data start */
*(m_usb_dma_init_data)
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*flexspi_nor_flash_ops.o(.text*)
KEEP(*(.jcr*))
. = ALIGN(4);
__data_end__ = .; /* define a global symbol at data end */
} > m_data
__NDATA_ROM = __DATA_ROM + (__data_end__ - __data_start__);
.ncache.init : AT(__NDATA_ROM)
{
__noncachedata_start__ = .; /* create a global symbol at ncache data start */
*(NonCacheable.init)
. = ALIGN(4);
__noncachedata_init_end__ = .; /* create a global symbol at initialized ncache data end */
} > m_data
. = __noncachedata_init_end__;
.ncache :
{
*(NonCacheable)
. = ALIGN(4);
__noncachedata_end__ = .; /* define a global symbol at ncache data end */
} > m_data
__DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__);
text_end = ORIGIN(m_text) + LENGTH(m_text);
ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data")
/* Uninitialized data section */
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
. = ALIGN(4);
__START_BSS = .;
__bss_start__ = .;
*(m_usb_dma_noninit_data)
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__END_BSS = .;
} > m_data
.heap :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
__heap_limit = .; /* Add for _sbrk */
} > m_data
.stack :
{
. = ALIGN(8);
. += STACK_SIZE;
} > m_data
/* Initializes stack on the end of block */
__StackTop = ORIGIN(m_data) + LENGTH(m_data);
__StackLimit = __StackTop - STACK_SIZE;
PROVIDE(__stack = __StackTop);
.ARM.attributes 0 : { *(.ARM.attributes) }
ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap")
}

View file

@ -1,10 +0,0 @@
/* Specify the memory areas */
MEMORY
{
/* m_flash_config (RX) : ORIGIN = m_flash_config_origin, LENGTH = 0x00000C00 */
m_ivt (RX) : ORIGIN = m_ocram_rom_safe_origin, LENGTH = 0x00000400
m_interrupts (RX) : ORIGIN = m_ocram_rom_safe_origin + 0x400, LENGTH = 0x00000400
m_text (RX) : ORIGIN = m_ocram_rom_safe_origin + 0x800, LENGTH = 40K
m_data (RW) : ORIGIN = 0x20000000, LENGTH = m_data_length - 4 /* double tap */
m_data2 (RW) : ORIGIN = 0x00000000, LENGTH = 0x00008000 /* itcm */
}

View file

@ -1,47 +0,0 @@
# iMXRT10XX Load to RAM
The serial download protocol (SDP) implemented in the RT10xx ROM does not have the abilty natively load flash, so a flashloader image needs to be loaded to run from RAM. The boot ROM supports eXecute In Place (XIP), and load to RAM images, so the same flashloader that is designed to be loaded through the serial download protocol, can also be copied into external flash to be loaded at boot.
## Load Image Through SDP using sdphost
1. Power down RT1011 and switch to Serial Downloader Boot Type (BOOT_MODE[1:0]=01)
2. Power up RT1011 and connect USB cable
3. Copy flashloader into RAM using sdphost
MIMXRT1011
sdphost.exe -u 0x1fc9,0x0145 -V -- write-file 0x20206400 "tinyuf2-imxrt1010_evk.bin"
MIMXRT1062
sdphost.exe -u 0x1fc9,0x0135 -V -- write-file 0x400 "tinyuf2-imxrt1060_evk.bin"
4. Launch flashloader
MIMXRT1011
sdphost.exe -u 0x1fc9,0x0145 -V -- jump-address 0x20207000
MIMXRT1062
sdphost.exe -u 0x1fc9,0x0135 -V -- jump-address 0x1000
## Copy Image to flash with UF2
1. Generate UF2 file from binary image using `uf2conv.py`
MIMXRT1011
uf2conv.py -b 0x60000400 -o imxrt1010_evk-bl.uf2 -f MIMXRT10XX tinyuf2-imxrt1010_evk.bin
MIMXRT1062
uf2conv.py -b 0x60000400 -o imxrt1060_evk-bl.uf2 -f MIMXRT10XX tinyuf2-imxrt1060_evk.bin
2. Get board into UF2 mode by loading the image through SDP or double pressing the reset button if it is already present in flash
3. Drag-N-Drop `imxrt1010_evk-bl.uf2` onto `RT1010BOOT` drive.
## To Be Developed
1. Convert additonal mimxrt10xx boards to work using load-to-RAM
2. Implement bootloader version, so when the image is loaded through SDP, it will self copy to flash if there is no flashloader or an older flashloader image in flash. It simply needs to copy itself to flash.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,209 @@
#-----------------------------------------------
# Make command:
# make build=<build> all
# <build>: debug or release, release by default.
#-----------------------------------------------
#-----------------------------------------------
# setup variables
# ----------------------------------------------
BOOT_ROOT := $(abspath ../../..)
OUTPUT_ROOT := $(abspath ./)
APP_NAME = sdphost
#-----------------------------------------------
# Debug or Release
# Release by default
#-----------------------------------------------
build ?= release
include $(BOOT_ROOT)/mk/common.mk
#-----------------------------------------------
# Include path. Add the include paths like this:
# INCLUDES += ./include/
#-----------------------------------------------
INCLUDES += $(BOOT_ROOT)/validation/sdphost/sdphost \
$(BOOT_ROOT)/src \
$(BOOT_ROOT)/src/include \
$(BOOT_ROOT)/src/blfwk \
$(BOOT_ROOT)/src/sbloader \
$(BOOT_ROOT)/src/bootloader \
$(BOOT_ROOT)/src/crc \
$(BOOT_ROOT)/src/packet \
$(BOOT_ROOT)/src/property \
$(BOOT_ROOT)/src/drivers/common \
$(BOOT_ROOT)/src/bm_usb
CXXFLAGS := -D LINUX -D BOOTLOADER_HOST -Wno-narrowing -std=c++11
CFLAGS := -std=c99 -D LINUX -D BOOTLOADER_HOST -D _GNU_SOURCE
LD := g++
SOURCES := $(BOOT_ROOT)/tools/sdphost/sdphost/sdphost.cpp \
$(BOOT_ROOT)/src/blfwk/src/Blob.cpp \
$(BOOT_ROOT)/src/blfwk/src/Bootloader.cpp \
$(BOOT_ROOT)/src/blfwk/src/BusPal.cpp \
$(BOOT_ROOT)/src/blfwk/src/BusPalPeripheral.cpp \
$(BOOT_ROOT)/src/blfwk/src/Command.cpp \
$(BOOT_ROOT)/src/blfwk/src/DataSource.cpp \
$(BOOT_ROOT)/src/blfwk/src/DataSourceImager.cpp \
$(BOOT_ROOT)/src/blfwk/src/DataTarget.cpp \
$(BOOT_ROOT)/src/blfwk/src/ELFSourceFile.cpp \
$(BOOT_ROOT)/src/blfwk/src/ExcludesListMatcher.cpp \
$(BOOT_ROOT)/src/blfwk/src/format_string.cpp \
$(BOOT_ROOT)/src/blfwk/src/GHSSecInfo.cpp \
$(BOOT_ROOT)/src/blfwk/src/GlobMatcher.cpp \
$(BOOT_ROOT)/src/blfwk/src/hid-linux.c \
$(BOOT_ROOT)/src/blfwk/src/jsoncpp.cpp \
$(BOOT_ROOT)/src/blfwk/src/Logging.cpp \
$(BOOT_ROOT)/src/blfwk/src/options.cpp \
$(BOOT_ROOT)/src/blfwk/src/SBSourceFile.cpp \
$(BOOT_ROOT)/src/blfwk/src/SDPCommand.cpp \
$(BOOT_ROOT)/src/blfwk/src/SDPUsbHidPacketizer.cpp \
$(BOOT_ROOT)/src/blfwk/src/SearchPath.cpp \
$(BOOT_ROOT)/src/blfwk/src/serial.c \
$(BOOT_ROOT)/src/blfwk/src/SerialPacketizer.cpp \
$(BOOT_ROOT)/src/blfwk/src/SourceFile.cpp \
$(BOOT_ROOT)/src/blfwk/src/SRecordSourceFile.cpp \
$(BOOT_ROOT)/src/blfwk/src/IntelHexSourceFile.cpp \
$(BOOT_ROOT)/src/blfwk/src/StELFFile.cpp \
$(BOOT_ROOT)/src/blfwk/src/StExecutableImage.cpp \
$(BOOT_ROOT)/src/blfwk/src/StSRecordFile.cpp \
$(BOOT_ROOT)/src/blfwk/src/StIntelHexFile.cpp \
$(BOOT_ROOT)/src/blfwk/src/Updater.cpp \
$(BOOT_ROOT)/src/blfwk/src/UartPeripheral.cpp \
$(BOOT_ROOT)/src/blfwk/src/UsbHidPacketizer.cpp \
$(BOOT_ROOT)/src/blfwk/src/UsbHidPeripheral.cpp \
$(BOOT_ROOT)/src/blfwk/src/utils.cpp \
$(BOOT_ROOT)/src/blfwk/src/Value.cpp \
$(BOOT_ROOT)/src/crc/src/crc16.c \
$(BOOT_ROOT)/src/crc/src/crc32.c \
INCLUDES := $(foreach includes, $(INCLUDES), -I $(includes))
ifeq "$(build)" "debug"
DEBUG_OR_RELEASE := Debug
CFLAGS += -g
CXXFLAGS += -g
LDFLAGS += -g
else
DEBUG_OR_RELEASE := Release
endif
TARGET_OUTPUT_ROOT := $(OUTPUT_ROOT)/$(DEBUG_OR_RELEASE)
MAKE_TARGET := $(TARGET_OUTPUT_ROOT)/$(APP_NAME)
OBJS_ROOT = $(TARGET_OUTPUT_ROOT)/obj
# Strip sources.
SOURCES := $(strip $(SOURCES))
# Convert sources list to absolute paths and root-relative paths.
SOURCES_ABS := $(foreach s,$(SOURCES),$(abspath $(s)))
SOURCES_REL := $(subst $(BOOT_ROOT)/,,$(SOURCES_ABS))
# Get a list of unique directories containing the source files.
SOURCE_DIRS_ABS := $(sort $(foreach f,$(SOURCES_ABS),$(dir $(f))))
SOURCE_DIRS_REL := $(subst $(BOOT_ROOT)/,,$(SOURCE_DIRS_ABS))
OBJECTS_DIRS := $(addprefix $(OBJS_ROOT)/,$(SOURCE_DIRS_REL))
# Filter source files list into separate source types.
C_SOURCES = $(filter %.c,$(SOURCES_REL))
CXX_SOURCES = $(filter %.cpp,$(SOURCES_REL))
ASM_s_SOURCES = $(filter %.s,$(SOURCES_REL))
ASM_S_SOURCES = $(filter %.S,$(SOURCES_REL))
# Convert sources to objects.
OBJECTS_C := $(addprefix $(OBJS_ROOT)/,$(C_SOURCES:.c=.o))
OBJECTS_CXX := $(addprefix $(OBJS_ROOT)/,$(CXX_SOURCES:.cpp=.o))
OBJECTS_ASM := $(addprefix $(OBJS_ROOT)/,$(ASM_s_SOURCES:.s=.o))
OBJECTS_ASM_S := $(addprefix $(OBJS_ROOT)/,$(ASM_S_SOURCES:.S=.o))
# Complete list of all object files.
OBJECTS_ALL := $(sort $(OBJECTS_C) $(OBJECTS_CXX) $(OBJECTS_ASM) $(OBJECTS_ASM_S))
#-------------------------------------------------------------------------------
# Default target
#-------------------------------------------------------------------------------
# Note that prerequisite order is important here. The subdirectories must be built first, or you
# may end up with files in the current directory not getting added to libraries. This would happen
# if subdirs modified the library file after local files were compiled but before they were added
# to the library.
.PHONY: all
all: $(MAKE_TARGET)
## Recipe to create the output object file directories.
$(OBJECTS_DIRS) :
$(at)mkdir -p $@
# Object files depend on the directories where they will be created.
#
# The dirs are made order-only prerequisites (by being listed after the '|') so they won't cause
# the objects to be rebuilt, as the modification date on a directory changes whenver its contents
# change. This would cause the objects to always be rebuilt if the dirs were normal prerequisites.
$(OBJECTS_ALL): | $(OBJECTS_DIRS)
#-------------------------------------------------------------------------------
# Pattern rules for compilation
#-------------------------------------------------------------------------------
# We cd into the source directory before calling the appropriate compiler. This must be done
# on a single command line since make calls individual recipe lines in separate shells, so
# '&&' is used to chain the commands.
#
# Generate make dependencies while compiling using the -MMD option, which excludes system headers.
# If system headers are included, there are path problems on cygwin. The -MP option creates empty
# targets for each header file so that a rebuild will be forced if the file goes missing, but
# no error will occur.
# Compile C sources.
$(OBJS_ROOT)/%.o: $(BOOT_ROOT)/%.c
@$(call printmessage,c,Compiling, $(subst $(BOOT_ROOT)/,,$<))
$(at)$(CC) $(CFLAGS) $(SYSTEM_INC) $(INCLUDES) $(DEFINES) -MMD -MF $(basename $@).d -MP -o $@ -c $<
# Compile C++ sources.
$(OBJS_ROOT)/%.o: $(BOOT_ROOT)/%.cpp
@$(call printmessage,cxx,Compiling, $(subst $(BOOT_ROOT)/,,$<))
$(at)$(CXX) $(CXXFLAGS) $(SYSTEM_INC) $(INCLUDES) $(DEFINES) -MMD -MF $(basename $@).d -MP -o $@ -c $<
# For .S assembly files, first run through the C preprocessor then assemble.
$(OBJS_ROOT)/%.o: $(BOOT_ROOT)/%.S
@$(call printmessage,asm,Assembling, $(subst $(BOOT_ROOT)/,,$<))
$(at)$(CPP) -D__LANGUAGE_ASM__ $(INCLUDES) $(DEFINES) -o $(basename $@).s $< \
&& $(AS) $(ASFLAGS) $(INCLUDES) -MD $(OBJS_ROOT)/$*.d -o $@ $(basename $@).s
# Assembler sources.
$(OBJS_ROOT)/%.o: $(BOOT_ROOT)/%.s
@$(call printmessage,asm,Assembling, $(subst $(BOOT_ROOT)/,,$<))
$(at)$(AS) $(ASFLAGS) $(INCLUDES) -MD $(basename $@).d -o $@ $<
#------------------------------------------------------------------------
# Build the tagrget
#------------------------------------------------------------------------
# Wrap the link objects in start/end group so that ld re-checks each
# file for dependencies. Otherwise linking static libs can be a pain
# since order matters.
$(MAKE_TARGET): $(OBJECTS_ALL)
@$(call printmessage,link,Linking, $(APP_NAME))
$(at)$(LD) $(LDFLAGS) \
$(OBJECTS_ALL) \
-lc -lstdc++ -lm -ludev \
-o $@
@echo "Output binary:" ; echo " $(APP_NAME)"
#-------------------------------------------------------------------------------
# Clean
#-------------------------------------------------------------------------------
.PHONY: clean cleanall
cleanall: clean
clean:
$(at)rm -rf $(OBJECTS_ALL) $(OBJECTS_DIRS) $(MAKE_TARGET) $(APP_NAME)
# Include dependency files.
-include $(OBJECTS_ALL:.o=.d)

View file

@ -0,0 +1,504 @@
/*
* Copyright (c) 2013-2015 Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <cstring>
#include "blfwk/options.h"
#include "blfwk/Logging.h"
#include "blfwk/host_types.h"
#include "blfwk/utils.h"
#include "blfwk/Command.h"
#include "blfwk/SDPCommand.h"
#include "blfwk/UsbHidPeripheral.h"
#include "blfwk/SDPUsbHidPacketizer.h"
#include "blfwk/UartPeripheral.h"
#include "blfwk/SDPUartPacketizer.h"
#if defined(WIN32)
#include "windows.h"
#include "stdafx.h"
#elif defined(LINUX) || defined(MACOSX)
#include "signal.h"
#endif
using namespace blfwk;
using namespace std;
////////////////////////////////////////////////////////////////////////////////
// Variables
////////////////////////////////////////////////////////////////////////////////
//! @brief The tool's name.
const char k_toolName[] = "sdphost";
//! @brief Current version number for the tool.
const char k_version[] = "1.0.0";
//! @brief Copyright string.
const char k_copyright[] = "Copyright (c) 2016 Freescale Semiconductor, Inc.\nAll rights reserved.";
//! @brief Command line option definitions.
static const char *k_optionsDefinition[] = { "?|help", "v|version", "p:port <name>[,<speed>]",
"u?usb [[<vid>,]<pid>]", "V|verbose", "d|debug", "j|json",
"t:timeout <ms>", NULL };
//! @brief Usage text.
const char k_optionUsage[] =
"\nOptions:\n\
-?/--help Show this help\n\
-v/--version Display tool version\n\
-p/--port <name>[,<speed>] Connect to target over UART. Specify COM port\n\
and optionally baud rate\n\
(default=COM1,115200)\n\
If -b, then port is BusPal port\n\
-u/--usb [[[<vid>,]<pid>] | [<path>]]\n\
Connect to target over USB HID device denoted by\n\
vid/pid (default=0x15a2,0x0083) or device path\n\
-V/--verbose Print extra detailed log information\n\
-d/--debug Print really detailed log information\n\
-j/--json Print output in JSON format to aid automation.\n\
The last -V/-d/-j takes precedence.\n\
-t/--timeout <ms> Set packet timeout in milliseconds\n\
(default=5000)\n";
//! @brief Trailer usage text that gets appended after the options descriptions.
static const char *usageTrailer = "-- command <args...>";
//! @brief Command usage string.
const char k_commandUsage[] =
"Commands:\n\
read-register <addr> [<format> [<count> [<file>]]]\n\
Read one or more registers at address.\n\
Format must be 8, 16, or 32;\n\
default format is 32.\n\
Count is number of bytes to read;\n\
default count is sizeof format\n\
(i.e. one register).\n\
Output file is binary;\n\
default is hex display on stdout.\n\
write-register <addr> <format> <data>\n\
Write one register at address.\n\
Format must be 8, 16, or 32.\n\
Data is data value to write.\n\
write-file <addr> <file> [<count>]\n\
Write file at address.\n\
Count is size of data to write in bytes;\n\
size of file will be used by default.\n\
error-status Read error status of last command.\n\
dcd-write <addr> <file> Send DCD table from file.\n\
<addr> must point to a valid\n\
temporary storage area.\n\
skip-dcd-header Ignore DCD table in image.\n\
jump-address <addr> Jump to entry point of image\n\
with IVT at specified address.\n\
\n";
/*!
* \brief Class that encapsulates the sdp tool.
*
* A single global logger instance is created during object construction. It is
* never freed because we need it up to the last possible minute, when an
* exception could be thrown.
*/
class SDPHost
{
public:
/*!
* Constructor.
*
* Creates the singleton logger instance.
*/
SDPHost(int argc, char *argv[])
: m_argc(argc)
, m_argv(argv)
, m_cmdv()
, m_comPort("COM1")
, m_comSpeed(115200)
, m_logger(NULL)
, m_useUsb(false)
, m_useUart(false)
, m_usbVid(UsbHidPeripheral::kDefault_Vid)
, m_usbPid(UsbHidPeripheral::kK32H_Pid)
, m_packetTimeoutMs(5000)
{
// create logger instance
m_logger = new StdoutLogger();
m_logger->setFilterLevel(Logger::kInfo);
Log::setLogger(m_logger);
#if defined(WIN32)
// set ctrl handler for Ctrl + C and Ctrl + Break signal
SetConsoleCtrlHandler((PHANDLER_ROUTINE)ctrlHandler, TRUE);
#elif defined(LINUX)
// set ctrl handler for Ctrl + C signal, Ctrl + Break doesnot take effect under LINUX system.
signal(SIGINT, ctrlPlusCHandler);
#endif
}
//! @brief Destructor.
virtual ~SDPHost() {}
//! @brief Run the application.
int run();
protected:
//! @brief Process command line options.
int processOptions();
//! @brief Handler for Ctrl signals.
#if defined(WIN32)
static BOOL ctrlHandler(DWORD ctrlType);
#elif defined(LINUX)
static void ctrlPlusCHandler(int msg);
#endif
//! @brief Show transfer progress.
static void displayProgress(int percentage, int segmentIndex, int segmentCount);
protected:
int m_argc; //!< Number of command line arguments.
char **m_argv; //!< Command line arguments.
string_vector_t m_cmdv; //!< Command line argument vector.
string m_comPort; //!< COM port to use.
int m_comSpeed; //!< COM port speed.
bool m_useUsb; //!< Connect over USB HID.
bool m_useUart; //!< Connect over UART.
uint16_t m_usbVid; //!< USB VID of the target HID device
uint16_t m_usbPid; //!< USB PID of the target HID device
string m_usbPath; //!< USB PATH of the target HID device
uint32_t m_packetTimeoutMs; //!< Packet timeout in milliseconds.
StdoutLogger *m_logger; //!< Singleton logger instance.
};
////////////////////////////////////////////////////////////////////////////////
// Code
////////////////////////////////////////////////////////////////////////////////
//! @brief Print command line usage.
static void printUsage()
{
printf(k_optionUsage);
printf(k_commandUsage);
}
#if defined(WIN32)
BOOL SDPHost::ctrlHandler(DWORD ctrlType)
{
switch (ctrlType)
{
// Trap both of Ctrl + C and Ctrl + Break signal.
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
Log::warning(
"\nWarning: Operation canceled!\n- The target device must be reset before sending any further "
"commands.\n");
return false;
default:
return false;
}
}
#elif defined(LINUX)
void SDPHost::ctrlPlusCHandler(int msg)
{
if (msg == SIGINT)
{
Log::warning(
"\nWarning: Operation canceled!\n- The target device must be reset before sending any further commands.\n");
exit(0);
}
}
#endif
void SDPHost::displayProgress(int percentage, int segmentIndex, int segmentCount)
{
Log::info("\r(%d/%d)%d%%", segmentIndex, segmentCount, percentage);
if (percentage >= 100)
{
Log::info(" Completed!\n");
}
}
int SDPHost::processOptions()
{
Options options(*m_argv, k_optionsDefinition);
// If there are no arguments print the usage.
if (m_argc == 1)
{
options.usage(std::cout, usageTrailer);
printUsage();
return 0;
}
OptArgvIter iter(--m_argc, ++m_argv);
// Process command line options.
int optchar;
const char *optarg;
while ((optchar = options(iter, optarg)))
{
switch (optchar)
{
case '?':
options.usage(std::cout, usageTrailer);
printUsage();
return 0;
case 'v':
printf("%s %s\n%s\n", k_toolName, k_version, k_copyright);
return 0;
break;
case 'p':
{
if (m_useUsb)
{
Log::error("Error: You cannot specify both -u and -p options.\n");
options.usage(std::cout, usageTrailer);
printUsage();
return 0;
}
#if defined(WIN32)
if (optarg && (string(optarg)[0] == 'c' || string(optarg)[0] == 'C'))
#else
if (optarg)
#endif
{
string_vector_t params = utils::string_split(optarg, ',');
m_comPort = params[0];
if (params.size() == 2)
{
int speed = atoi(params[1].c_str());
if (speed <= 0)
{
Log::error("Error: You must specify a valid baud rate with the -p/--port option.\n");
options.usage(std::cout, usageTrailer);
printUsage();
return 0;
}
m_comSpeed = speed;
}
}
else
{
Log::error("Error: You must specify the COM port identifier string with the -p/--port option.\n");
options.usage(std::cout, usageTrailer);
printUsage();
return 0;
}
m_useUart = true;
break;
}
case 'u':
{
if (m_useUart)
{
Log::error("Error: You cannot specify both -u and -p options.\n");
options.usage(std::cout, usageTrailer);
printUsage();
return 0;
}
if (optarg)
{
string_vector_t params = utils::string_split(optarg, ',');
uint32_t tempId = 0;
bool useDefaultVid = true;
bool useDefaultPid = true;
uint16_t vid = 0, pid = 0;
string path;
if (params.size() == 1)
{
if (utils::stringtoui(params[0].c_str(), tempId) && tempId < 0x00010000)
{
pid = (uint16_t)tempId;
useDefaultPid = false;
}
else
{
path = params[0];
}
}
else if (params.size() == 2)
{
if (utils::stringtoui(params[0].c_str(), tempId) && tempId < 0x00010000)
{
vid = (uint16_t)tempId;
useDefaultVid = false;
}
else
{
Log::error("Error: %s is not valid vid for option -u.\n", params[0].c_str());
return 0;
}
if (utils::stringtoui(params[1].c_str(), tempId) && tempId < 0x00010000)
{
pid = (uint16_t)tempId;
useDefaultPid = false;
}
else
{
Log::error("Error: %s is not valid pid for option -u.\n", params[1].c_str());
return 0;
}
}
if (!useDefaultPid)
{
m_usbPid = pid;
}
if (!useDefaultVid)
{
m_usbVid = vid;
}
m_usbPath = path;
}
m_useUsb = true;
break;
}
case 'V':
Log::getLogger()->setFilterLevel(Logger::kDebug);
break;
case 'd':
Log::getLogger()->setFilterLevel(Logger::kDebug2);
break;
case 'j':
Log::getLogger()->setFilterLevel(Logger::kJson);
break;
case 't':
if (optarg)
{
uint32_t timeout = 0;
if (utils::stringtoui(optarg, timeout))
{
m_packetTimeoutMs = timeout;
}
else
{
Log::error("Error: %s is not valid for option -t/--timeout.\n", optarg);
options.usage(std::cout, usageTrailer);
printUsage();
return 0;
}
}
break;
// All other cases are errors.
default:
return 1;
}
}
// Treat the rest of the command line as a single bootloader command,
// possibly with arguments.
if (iter.index() == m_argc)
{
options.usage(std::cout, usageTrailer);
printUsage();
return 0;
}
// Save command name and arguments.
for (int i = iter.index(); i < m_argc; ++i)
{
m_cmdv.push_back(m_argv[i]);
}
// All is well.
return -1;
}
int SDPHost::run()
{
// Read command line options.
int optionsResult;
if ((optionsResult = processOptions()) != -1)
{
return optionsResult;
}
int result = 0;
SDPCommand *cmd = NULL;
Progress *progress = NULL;
try
{
if (m_cmdv.size())
{
// Check for any passed commands and validate command.
cmd = SDPCommand::create(&m_cmdv);
if (!cmd)
{
std::string msg = format_string("Error: invalid command or arguments '%s", m_cmdv.at(0).c_str());
string_vector_t::iterator it = m_cmdv.begin();
for (++it; it != m_cmdv.end(); ++it)
{
msg.append(format_string(" %s", (*it).c_str()));
}
msg.append("'\n");
throw std::runtime_error(msg);
}
progress = new Progress(displayProgress, NULL);
cmd->registerProgress(progress);
}
else
{
throw std::runtime_error("Internal error: no command\n");
}
Packetizer *hostPacketizer;
if (m_useUsb)
{
std::string usbHidSerialNumber;
UsbHidPeripheral *peripheral = new UsbHidPeripheral(m_usbVid, m_usbPid, usbHidSerialNumber.c_str(), m_usbPath.c_str());
hostPacketizer = new SDPUsbHidPacketizer(peripheral, m_packetTimeoutMs);
}
else // use UART
{
UartPeripheral *peripheral = new UartPeripheral(m_comPort.c_str(), m_comSpeed);
hostPacketizer = new SDPUartPacketizer(peripheral, m_packetTimeoutMs);
}
// Send the command.
cmd->sendTo(*hostPacketizer);
if (cmd->getResponseValues()->size() > 0)
{
// Print command response values.
cmd->logResponses();
// Only thing we consider an error is NoResponse
if (cmd->getResponseValues()->at(0) == SDPCommand::kStatus_NoResponse)
{
result = SDPCommand::kStatus_NoResponse;
}
}
}
catch (exception &e)
{
Log::error(e.what());
result = 1; // return non-zero error code to shell
}
if (progress)
{
delete progress;
}
return result;
}
//! @brief Application entry point.
int main(int argc, char *argv[], char *envp[])
{
return SDPHost(argc, argv).run();
}

View file

@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// sdphost.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View file

@ -0,0 +1,16 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <stdint.h>
// TODO: reference additional headers your program requires here

View file

@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

Binary file not shown.

View file

@ -2,8 +2,6 @@
# Common make rules for all
# ---------------------------------------
OUTNAME = tinyuf2-$(BOARD)
PYTHON3 ?= python3
MKDIR = mkdir
SED = sed
@ -109,6 +107,7 @@ endif
JLINK_IF ?= swd
# Flash hex file using jlink
$(BUILD)/$(BOARD).jlink: $(BUILD)/$(OUTNAME).hex
@echo halt > $@
@echo r >> $@
@ -117,10 +116,21 @@ $(BUILD)/$(BOARD).jlink: $(BUILD)/$(OUTNAME).hex
@echo go >> $@
@echo exit >> $@
# Flash using jlink
flash-jlink: $(BUILD)/$(BOARD).jlink
$(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -JTAGConf -1,-1 -speed auto -CommandFile $<
# Flash bin file with jlink
$(BUILD)/$(BOARD)-bin.jlink: $(BUILD)/$(OUTNAME).bin
@echo halt > $@
@echo r >> $@
@echo loadfile $< $(FLASH_BIN_ADDR) >> $@
@echo r >> $@
@echo go >> $@
@echo exit >> $@
flash-jlink-bin: $(BUILD)/$(BOARD)-bin.jlink
$(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -JTAGConf -1,-1 -speed auto -CommandFile $<
# Erase with jlink
$(BUILD)/$(BOARD)-erase.jlink:
@echo halt > $@
@ -140,9 +150,16 @@ erase-stlink:
STM32_Programmer_CLI --connect port=swd --erase all
#-------------------- Flash with pyocd --------------------
# Flash hex file using pyocd
flash-pyocd: $(BUILD)/$(OUTNAME).hex
pyocd flash -t $(PYOCD_TARGET) $<
pyocd reset -t $(PYOCD_TARGET)
# Flash bin file using pyocd
flash-pyocd-bin: $(BUILD)/$(OUTNAME).hex
pyocd flash -t $(PYOCD_TARGET) -a $(FLASH_BIN_ADDR) $<
pyocd reset -t $(PYOCD_TARGET)
erase-pyocd:
pyocd erase -t $(PYOCD_TARGET) -c

View file

@ -13,12 +13,10 @@ $(SELF_OBJ): | $(SELF_OBJ_DIRS)
$(SELF_OBJ_DIRS):
@$(MKDIR) -p $@
# self-update uf2 target is defined by port Makefile
self-update: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).uf2
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).uf2: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex
@echo CREATE $@
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^
# self-update elf require self_update/$(OUTPNAME0.c which is defined by port Makefile
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).elf: $(SELF_OBJ)
@echo LINK $@
@$(CC) -o $@ $(SELF_LDFLAGS) $(addprefix $(LD_SCRIPT_FLAG), $(SELF_LD_FILES)) $^ -Wl,--start-group $(LIBS) -Wl,--end-group

View file

@ -5,12 +5,10 @@ ST_HAL_DRIVER = lib/st/stm32f4xx_hal_driver
ST_CMSIS = lib/st/cmsis_device_f4
CMSIS_5 = lib/CMSIS_5
include ../make.mk
# List of git submodules that is included as part of the UF2 version
GIT_SUBMODULES = CMSIS_5 st tinyusb
# Version
GIT_VERSION := $(shell git describe --dirty --always --tags)
GIT_SUBMODULE_VERSIONS := $(shell git submodule status $(addprefix ../../lib/,CMSIS_5 st tinyusb) | cut -d" " -f3,4 | paste -s -d" " -)
GIT_SUBMODULE_VERSIONS := $(subst ../../lib/,,$(GIT_SUBMODULE_VERSIONS))
include ../make.mk
# Port Compiler Flags
CFLAGS += \
@ -21,9 +19,7 @@ CFLAGS += \
-mfloat-abi=hard \
-mfpu=fpv4-sp-d16 \
-nostdlib -nostartfiles \
-DCFG_TUSB_MCU=OPT_MCU_STM32F4 \
-DBOARD_UF2_FAMILY_ID=$(UF2_FAMILY_ID) \
-DUF2_VERSION='"$(GIT_VERSION) - $(GIT_SUBMODULE_VERSIONS)"'
-DCFG_TUSB_MCU=OPT_MCU_STM32F4
# suppress warning caused by vendor mcu driver
CFLAGS += -Wno-error=cast-align -Wno-error=unused-parameter
@ -66,7 +62,11 @@ SELF_ASFLAGS = $(ASFLAGS)
include ../self_update.mk
# required for uf2 conversion
# self-update uf2 file
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).uf2: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex
@echo CREATE $@
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).elf
@echo CREATE $@
@$(OBJCOPY) -O ihex $^ $@

View file

@ -1,12 +1,10 @@
UF2_FAMILY_ID = 0x00000000
CROSS_COMPILE = arm-none-eabi-
include ../make.mk
# List of git submodules that is included as part of the UF2 version
GIT_SUBMODULES = tinyusb
# Version
GIT_VERSION := $(shell git describe --dirty --always --tags)
GIT_SUBMODULE_VERSIONS := $(shell git submodule status $(addprefix ../../lib/, tinyusb) | cut -d" " -f3,4 | paste -s -d" " -)
GIT_SUBMODULE_VERSIONS := $(subst ../../lib/,,$(GIT_SUBMODULE_VERSIONS))
include ../make.mk
# Port Compiler Flags
CFLAGS += \
@ -14,9 +12,7 @@ CFLAGS += \
-mthumb \
-mabi=aapcs \
-mcpu=cortex-m3 \
-DCFG_TUSB_MCU=OPT_MCU_NONE \
-DBOARD_UF2_FAMILY_ID=$(UF2_FAMILY_ID) \
-DUF2_VERSION='"$(GIT_VERSION) - $(GIT_SUBMODULE_VERSIONS)"'
-DCFG_TUSB_MCU=OPT_MCU_NONE
# suppress warning caused by vendor mcu driver
CFLAGS += -Wno-error=cast-align -Wno-error=unused-parameter
@ -46,7 +42,11 @@ SELF_ASFLAGS = $(ASFLAGS)
include ../self_update.mk
# required for uf2 conversion
# self-update uf2 file
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).uf2: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex
@echo CREATE $@
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^
$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).elf
@echo CREATE $@
@$(OBJCOPY) -O ihex $^ $@