简介:
感谢社区提供的评测机会,本次评测的板卡为 STM32H7S78-DK先来张上电运行图片。



该板卡有着丰富的外设资源,主要特性如下:
-这款开发板基于 Arm® Cortex®-M7 的 STM32H7S7L8H6H 微控制器,采用 TFBGA225 封装,具有 64KB 闪存和 620KB SRAM。
- 带电容式触摸屏的 5 英寸 LCD 模块
- 带 USB 2.0 HS 接口的 USB Type-C®
- USB Type-C®,带 USB 2.0 FS 接口
- 以太网符合 IEEE-802.3-2002 标准
- I2S 音频编
- 一个 ST-MEMS 数字麦克风
- 1-Gbit Octo-SPI NOR FLASH
- 256-Mbit Hexadeca-SPI PSRAM
- 附带 Wi-Fi® 模块(符合 802.11 b/g/n 标准)
- 四个用户 LED 指示灯
- 用户和复位按钮
- 两个 USB Type-C
- 以太网 RJ45
- 摄像头接口: FPC 连接器
- microSD™ 卡
- 立体声耳机插孔,包括模拟麦克风输入
- 音频 MEMS 子板扩展连接器
- ARDUINO® Uno V3 扩展连接器
- STMod+ 扩展连接器
- Pmod™ 扩展连接器
芯片的主要外设资源说明如下:

芯片内部只有64KB 的flash 资源,该芯片可以用来开发大型的MCU 程序,显然如果程序都放在片内flash 运行是放不下的,板卡上通过XSPI 模块分别挂载了1-Gbit Octo-SPI NOR FLASH(128MB 的nor flash), 256-Mbit Hexadeca-SPI PSRAM (32MB)的RAM资源,这下才是运行大型嵌入式程序及GUI 该有的资源配置, 芯片是支持XIP模式运行在nor flash 上的,本次的主题就是检讨如何将程序存储在NOR FLASH 上运行。
XIP 配置
对于XIP的 运行方式,ST 的HAL 软件包 STM32Cube_FW_H7RS_V1.1.0\Projects\STM32H7S78-DK\Templates\Template_XIP 路径下提供了IAR/MDK/CUBEIDE 的工程模板来方便我们直接XIP方式运行程序,在开始探讨XIP运行方式前我们先看下XIP 像款的user flash/xspi1/xspi2 这三段外设的地址映射空间。
user flash 映射到芯片的-0x08000000~0x0800ffff
xspi1(RAM)映射到芯片 -0x90000000~0x9fffffff
xspi2(NOR flash)映射到芯片-0x70000000~0x7fffffff

STM32Cube_FW_H7RS_V1.1.0\Projects\STM32H7S78-DK\Templates\Template_XIP 模板路径下可以看到一个boot工程和Appli工程,boot 工程会编译出一个运行在user flash的镜像该镜像会完成完成XSPI1 和 XSPI2 的初始化将app 工程使用的RAM及ROM映射到上述的地址空间,然后跳转到appi 运行,本次试用IAR环境运行XIP工程,我们查看boot 工程代码来验证上述的XIP运行方式。
以下是boot 工程对应的IAR 化境的linkfile(stm32h7s7xx_flash.icf)

从上述link 文件的layout 可知boot 程序运行于user flash,堆栈空间存放在Dtcm。
从boot 工程的如下代码可以看出boot 工程会配置对应的pin 脚为xspi 功能,并对其进行初始化。
/**
* @brief XSPI MSP Initialization
* This function configures the hardware resources used in this example
* @param hxspi: XSPI handle pointer
* @retval None
*/
void HAL_XSPI_MspInit(XSPI_HandleTypeDef* hxspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(hxspi->Instance==XSPI1)
{
/* USER CODE BEGIN XSPI1_MspInit 0 */
/* USER CODE END XSPI1_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_XSPI1;
PeriphClkInit.Xspi1ClockSelection = RCC_XSPI1CLKSOURCE_PLL2S;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/* Peripheral clock enable */
HAL_RCC_XSPIM_CLK_ENABLED++;
if(HAL_RCC_XSPIM_CLK_ENABLED==1){
__HAL_RCC_XSPIM_CLK_ENABLE();
}
__HAL_RCC_XSPI1_CLK_ENABLE();
__HAL_RCC_GPIOO_CLK_ENABLE();
__HAL_RCC_GPIOP_CLK_ENABLE();
/**XSPI1 GPIO Configuration
PO3 ------> XSPIM_P1_DQS1
PP10 ------> XSPIM_P1_IO10
PP12 ------> XSPIM_P1_IO12
PP14 ------> XSPIM_P1_IO14
PP2 ------> XSPIM_P1_IO2
PP5 ------> XSPIM_P1_IO5
PO2 ------> XSPIM_P1_DQS0
PP1 ------> XSPIM_P1_IO1
PP11 ------> XSPIM_P1_IO11
PP15 ------> XSPIM_P1_IO15
PP3 ------> XSPIM_P1_IO3
PP0 ------> XSPIM_P1_IO0
PP7 ------> XSPIM_P1_IO7
PP8 ------> XSPIM_P1_IO8
PP13 ------> XSPIM_P1_IO13
PP4 ------> XSPIM_P1_IO4
PO4 ------> XSPIM_P1_CLK
PP6 ------> XSPIM_P1_IO6
PO0 ------> XSPIM_P1_NCS1
PP9 ------> XSPIM_P1_IO9
*/
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_XSPIM_P1;
HAL_GPIO_Init(GPIOO, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_12|GPIO_PIN_14|GPIO_PIN_2
|GPIO_PIN_5|GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_15
|GPIO_PIN_3|GPIO_PIN_0|GPIO_PIN_7|GPIO_PIN_8
|GPIO_PIN_13|GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_XSPIM_P1;
HAL_GPIO_Init(GPIOP, &GPIO_InitStruct);
/* USER CODE BEGIN XSPI1_MspInit 1 */
/* USER CODE END XSPI1_MspInit 1 */
}
else if(hxspi->Instance==XSPI2)
{
/* USER CODE BEGIN XSPI2_MspInit 0 */
/* USER CODE END XSPI2_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_XSPI2;
PeriphClkInit.Xspi2ClockSelection = RCC_XSPI2CLKSOURCE_PLL2S;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/* Peripheral clock enable */
HAL_RCC_XSPIM_CLK_ENABLED++;
if(HAL_RCC_XSPIM_CLK_ENABLED==1){
__HAL_RCC_XSPIM_CLK_ENABLE();
}
__HAL_RCC_XSPI2_CLK_ENABLE();
__HAL_RCC_GPION_CLK_ENABLE();
/**XSPI2 GPIO Configuration
PN1 ------> XSPIM_P2_NCS1
PN3 ------> XSPIM_P2_IO1
PN0 ------> XSPIM_P2_DQS0
PN11 ------> XSPIM_P2_IO7
PN10 ------> XSPIM_P2_IO6
PN9 ------> XSPIM_P2_IO5
PN2 ------> XSPIM_P2_IO0
PN6 ------> XSPIM_P2_CLK
PN8 ------> XSPIM_P2_IO4
PN4 ------> XSPIM_P2_IO2
PN5 ------> XSPIM_P2_IO3
*/
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_0|GPIO_PIN_11
|GPIO_PIN_10|GPIO_PIN_9|GPIO_PIN_2|GPIO_PIN_6
|GPIO_PIN_8|GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_XSPIM_P2;
HAL_GPIO_Init(GPION, &GPIO_InitStruct);
/* USER CODE BEGIN XSPI2_MspInit 1 */
/* USER CODE END XSPI2_MspInit 1 */
}
}
/**
* @brief XSPI MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hxspi: XSPI handle pointer
* @retval None
*/
void HAL_XSPI_MspDeInit(XSPI_HandleTypeDef* hxspi)
{
if(hxspi->Instance==XSPI1)
{
/* USER CODE BEGIN XSPI1_MspDeInit 0 */
/* USER CODE END XSPI1_MspDeInit 0 */
/* Peripheral clock disable */
HAL_RCC_XSPIM_CLK_ENABLED--;
if(HAL_RCC_XSPIM_CLK_ENABLED==0){
__HAL_RCC_XSPIM_CLK_DISABLE();
}
__HAL_RCC_XSPI1_CLK_DISABLE();
/**XSPI1 GPIO Configuration
PO3 ------> XSPIM_P1_DQS1
PP10 ------> XSPIM_P1_IO10
PP12 ------> XSPIM_P1_IO12
PP14 ------> XSPIM_P1_IO14
PP2 ------> XSPIM_P1_IO2
PP5 ------> XSPIM_P1_IO5
PO2 ------> XSPIM_P1_DQS0
PP1 ------> XSPIM_P1_IO1
PP11 ------> XSPIM_P1_IO11
PP15 ------> XSPIM_P1_IO15
PP3 ------> XSPIM_P1_IO3
PP0 ------> XSPIM_P1_IO0
PP7 ------> XSPIM_P1_IO7
PP8 ------> XSPIM_P1_IO8
PP13 ------> XSPIM_P1_IO13
PP4 ------> XSPIM_P1_IO4
PO4 ------> XSPIM_P1_CLK
PP6 ------> XSPIM_P1_IO6
PO0 ------> XSPIM_P1_NCS1
PP9 ------> XSPIM_P1_IO9
*/
HAL_GPIO_DeInit(GPIOO, GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_0);
HAL_GPIO_DeInit(GPIOP, GPIO_PIN_10|GPIO_PIN_12|GPIO_PIN_14|GPIO_PIN_2
|GPIO_PIN_5|GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_15
|GPIO_PIN_3|GPIO_PIN_0|GPIO_PIN_7|GPIO_PIN_8
|GPIO_PIN_13|GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_9);
/* USER CODE BEGIN XSPI1_MspDeInit 1 */
/* USER CODE END XSPI1_MspDeInit 1 */
}
else if(hxspi->Instance==XSPI2)
{
/* USER CODE BEGIN XSPI2_MspDeInit 0 */
/* USER CODE END XSPI2_MspDeInit 0 */
/* Peripheral clock disable */
HAL_RCC_XSPIM_CLK_ENABLED--;
if(HAL_RCC_XSPIM_CLK_ENABLED==0){
__HAL_RCC_XSPIM_CLK_DISABLE();
}
__HAL_RCC_XSPI2_CLK_DISABLE();
/**XSPI2 GPIO Configuration
PN1 ------> XSPIM_P2_NCS1
PN3 ------> XSPIM_P2_IO1
PN0 ------> XSPIM_P2_DQS0
PN11 ------> XSPIM_P2_IO7
PN10 ------> XSPIM_P2_IO6
PN9 ------> XSPIM_P2_IO5
PN2 ------> XSPIM_P2_IO0
PN6 ------> XSPIM_P2_CLK
PN8 ------> XSPIM_P2_IO4
PN4 ------> XSPIM_P2_IO2
PN5 ------> XSPIM_P2_IO3
*/
HAL_GPIO_DeInit(GPION, GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_0|GPIO_PIN_11
|GPIO_PIN_10|GPIO_PIN_9|GPIO_PIN_2|GPIO_PIN_6
|GPIO_PIN_8|GPIO_PIN_4|GPIO_PIN_5);
/* USER CODE BEGIN XSPI2_MspDeInit 1 */
/* USER CODE END XSPI2_MspDeInit 1 */
}
}以下代码段会对xspi 进行初始化配置。
/**
* @brief XSPI1 Initialization Function
* @param None
* @retval None
*/
static void MX_XSPI1_Init(void)
{
/* USER CODE BEGIN XSPI1_Init 0 */
/* USER CODE END XSPI1_Init 0 */
XSPIM_CfgTypeDef sXspiManagerCfg = {0};
/* USER CODE BEGIN XSPI1_Init 1 */
/* USER CODE END XSPI1_Init 1 */
/* XSPI1 parameter configuration*/
hxspi1.Instance = XSPI1;
hxspi1.Init.FifoThresholdByte = 2;
hxspi1.Init.MemoryMode = HAL_XSPI_SINGLE_MEM;
hxspi1.Init.MemoryType = HAL_XSPI_MEMTYPE_APMEM_16BITS;
hxspi1.Init.MemorySize = HAL_XSPI_SIZE_32GB;
hxspi1.Init.ChipSelectHighTimeCycle = 1;
hxspi1.Init.FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE;
hxspi1.Init.ClockMode = HAL_XSPI_CLOCK_MODE_0;
hxspi1.Init.WrapSize = HAL_XSPI_WRAP_NOT_SUPPORTED;
hxspi1.Init.ClockPrescaler = 0;
hxspi1.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_NONE;
hxspi1.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_ENABLE;
hxspi1.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_8KB;
hxspi1.Init.MaxTran = 0;
hxspi1.Init.Refresh = 0;
hxspi1.Init.MemorySelect = HAL_XSPI_CSSEL_NCS1;
if (HAL_XSPI_Init(&hxspi1) != HAL_OK)
{
Error_Handler();
}
sXspiManagerCfg.nCSOverride = HAL_XSPI_CSSEL_OVR_NCS1;
sXspiManagerCfg.IOPort = HAL_XSPIM_IOPORT_1;
if (HAL_XSPIM_Config(&hxspi1, &sXspiManagerCfg, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN XSPI1_Init 2 */
/* USER CODE END XSPI1_Init 2 */
}
/**
* @brief XSPI2 Initialization Function
* @param None
* @retval None
*/
static void MX_XSPI2_Init(void)
{
/* USER CODE BEGIN XSPI2_Init 0 */
/* USER CODE END XSPI2_Init 0 */
XSPIM_CfgTypeDef sXspiManagerCfg = {0};
/* USER CODE BEGIN XSPI2_Init 1 */
/* USER CODE END XSPI2_Init 1 */
/* XSPI2 parameter configuration*/
hxspi2.Instance = XSPI2;
hxspi2.Init.FifoThresholdByte = 4;
hxspi2.Init.MemoryMode = HAL_XSPI_SINGLE_MEM;
hxspi2.Init.MemoryType = HAL_XSPI_MEMTYPE_MACRONIX;
hxspi2.Init.MemorySize = HAL_XSPI_SIZE_32GB;
hxspi2.Init.ChipSelectHighTimeCycle = 2;
hxspi2.Init.FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE;
hxspi2.Init.ClockMode = HAL_XSPI_CLOCK_MODE_0;
hxspi2.Init.WrapSize = HAL_XSPI_WRAP_NOT_SUPPORTED;
hxspi2.Init.ClockPrescaler = 0;
hxspi2.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_NONE;
hxspi2.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_ENABLE;
hxspi2.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_NONE;
hxspi2.Init.MaxTran = 0;
hxspi2.Init.Refresh = 0;
hxspi2.Init.MemorySelect = HAL_XSPI_CSSEL_NCS1;
if (HAL_XSPI_Init(&hxspi2) != HAL_OK)
{
Error_Handler();
}
sXspiManagerCfg.nCSOverride = HAL_XSPI_CSSEL_OVR_NCS1;
sXspiManagerCfg.IOPort = HAL_XSPIM_IOPORT_2;
if (HAL_XSPIM_Config(&hxspi2, &sXspiManagerCfg, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN XSPI2_Init 2 */
/* USER CODE END XSPI2_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPION_CLK_ENABLE();
__HAL_RCC_GPIOO_CLK_ENABLE();
__HAL_RCC_GPIOP_CLK_ENABLE();
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}对xspi初始化完成后,调用该接口跳转到app 程序运行,跳转前配置跳转后的运行环境,然后跳转到XIP地址运行。
/**
* @addtogroup BOOT_XIP_Exported_Functions Boot XIP exported functions
* @{
*/
BOOTStatus_TypeDef BOOT_Application(void)
{
BOOTStatus_TypeDef retr;
/* mount the memory */
retr = MapMemory();
if (BOOT_OK == retr)
{
/* jump on the application */
retr = JumpToApplication();
}
return retr;
}
BOOTStatus_TypeDef JumpToApplication(void)
{
uint32_t primask_bit;
typedef void (*pFunction)(void);
pFunction JumpToApp;
uint32_t Application_vector;
if (EXTMEM_OK != EXTMEM_GetMapAddress(EXTMEM_MEMORY_BOOTXIP, &Application_vector))
{
return BOOT_ERROR_INCOMPATIBLEMEMORY;
}
/* Suspend SysTick */
HAL_SuspendTick();
/* Disable I-Cache---------------------------------------------------------*/
SCB_DisableICache();
/* Disable D-Cache---------------------------------------------------------*/
SCB_DisableDCache();
/* Initialize user application's Stack Pointer & Jump to user application */
primask_bit = __get_PRIMASK();
__disable_irq();
/* Apply offsets for image location and vector table offset */
Application_vector += EXTMEM_XIP_IMAGE_OFFSET + EXTMEM_HEADER_OFFSET;
SCB->VTOR = (uint32_t)Application_vector;
JumpToApp = (pFunction) (*(__IO uint32_t *)(Application_vector + 4u));
#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
(defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
(defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
/* on ARM v8m, set MSPLIM before setting MSP to avoid unwanted stack overflow faults */
__set_MSPLIM(0x00000000);
#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
__set_MSP(*(__IO uint32_t*) Application_vector);
/* Re-enable the interrupts */
__set_PRIMASK(primask_bit);
JumpToApp();
return BOOT_OK;
}app 程序使用的linkfile 的链接地址为xspi1和xspi2 对应的空间,程序需要加载在nor flash上运行。
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x70000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x70000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x77FFFFFF;
define symbol NONCACHEABLEBUFFER_size = 0x400;
define symbol __ICFEDIT_region_RAM_start__ = 0x24000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x24071FFF - NONCACHEABLEBUFFER_size;
define symbol NONCACHEABLEBUFFER_start = __ICFEDIT_region_RAM_end__ + 1;
define symbol NONCACHEABLEBUFFER_end = __ICFEDIT_region_RAM_end__ + NONCACHEABLEBUFFER_size;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x400;
define symbol __ICFEDIT_size_heap__ = 0x200;
/**** End of ICF editor section. ###ICF###*/
define symbol __region_ITCM_start__ = 0x00000000;
define symbol __region_ITCM_end__ = 0x0000FFFF;
define symbol __region_DTCM_start__ = 0x20000000;
define symbol __region_DTCM_end__ = 0x2000FFFF;
define symbol __region_SRAMAHB_start__ = 0x30000000;
define symbol __region_SRAMAHB_end__ = 0x30007FFF;
define symbol __region_BKPSRAM_start__ = 0x38800000;
define symbol __region_BKPSRAM_end__ = 0x38800FFF;
define symbol __region_EXTRAM_start__ = 0x90000000;
define symbol __region_EXTRAM_end__ = 0x91FFFFFF;
export symbol NONCACHEABLEBUFFER_start;
export symbol NONCACHEABLEBUFFER_size;
export symbol __ICFEDIT_region_ROM_start__;
export symbol __ICFEDIT_region_ROM_end__;
export symbol __region_EXTRAM_start__;
export symbol __region_EXTRAM_end__;
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define region EXTRAM_region = mem:[from __region_EXTRAM_start__ to __region_EXTRAM_end__];
define region NONCACHEABLE_region = mem:[from NONCACHEABLEBUFFER_start to NONCACHEABLEBUFFER_end];
define region ITCM_region = mem:[from __region_ITCM_start__ to __region_ITCM_end__];
define region DTCM_region = mem:[from __region_DTCM_start__ to __region_DTCM_end__];
define region SRAMAHB_region = mem:[from __region_SRAMAHB_start__ to __region_SRAMAHB_end__];
define region BKPSRAM_region = mem:[from __region_BKPSRAM_start__ to __region_BKPSRAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit, section noncacheable_buffer };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place in RAM_region { readwrite };
place in NONCACHEABLE_region { section noncacheable_buffer };
place in DTCM_region { block CSTACK, block HEAP };IAR app 工程在debug时会同时将boot 工程的image 下载到user flash ,从而在上电时先运行user flash 的boot程序准备xip运行环境然后跳转到xip 运行。

IAR debug 运行appI 程序发现程序运行的地址为0x70000000 的地址空间,外挂的RAM 也可以正常访问。

从debug log 窗口也可以看出,IAR 在现在app 程序后会把boot 程序下载到user flash

后续在XIP工程基础上继续验证其他功能。

我要赚赏金
