RT1020 —— BootLoader 中烧写 APP 到指定位置的方法

前言

        本篇博文将介绍如何实现在 BootLoader 中烧写代码数据到 Flash 的指定位置,并跳转到代码位置运行:

        正常实现升级的方式是通过各种通信接口如:UART、CAN、USB、Ethernet...,通信接口把需要升级的代码传送给 BootLoader,BootLoader 写代码数据到 Flash 并跳转到代码位置执行。

        本篇博文将不使用通信接口获取数据,而是把需要烧录到 Flash 的数据放到 Flash 当中,在 BootLoader 中把 Flash 数据读取到 RAM 当中,通过 FlexSPI 把 RAM 中的数据写到 Flash 的指定位置。

        把数组数据放到指定的 Flash 自定义 section 中:

        数组定义与声明:

        1. 对把数组需要放到的 section 进行 __attribute__ 修饰;

#define LOCATION_EXTFLASH_ATTRIBUTE __attribute__ ((section ("Myapp"))) __attribute__ ((aligned(4)))

const unsigned char _aclwip_ping_bm[0x12880] LOCATION_EXTFLASH_ATTRIBUTE = {
0, 0, 0,
};

        2. 修改 scf 文件:

  • 自定义 block,定义 block 的起始和结束地址。
  • 加载 block 段,在其中声明数据放到的 section 段 *.o(Myapp)。
;Define new block m_text_data, place it at the beginning of the scf file
#define m_text_data_start              0x60030000
#define m_text_data_size               0x00013000


;Place at the end of the scf file, as a new block of m_text_data
LR_m_data_text m_text_data_start m_text_data_size{ 
  ER_m_data_text m_text_data_start FIXED m_text_data_size { ; load address = execution address
	*.o(Myapp)
  }
}

        添加 flexspi 操作函数文件到工程中。

        在主函数所在文件中添加:

#include "fsl_flexspi.h"
#include "app.h"
#include "fsl_cache.h"
/************************************************FlexSPI********************************************************************/
//add FlexSPI Functions
/* Program data buffer should be 4-bytes alignment, which can avoid busfault due to this memory region is configured as
   Device Memory by MPU. */
SDK_ALIGN(static uint8_t s_nor_program_buffer[256], 4);
static uint8_t s_nor_read_buffer[256];

extern status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
extern status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src);
extern status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId);
extern status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base);
extern status_t flexspi_nor_erase_chip(FLEXSPI_Type *base);
extern void flexspi_nor_flash_init(FLEXSPI_Type *base);
/*******************************************************************************
 * Code
 ******************************************************************************/
flexspi_device_config_t deviceconfig = {
    .flexspiRootClk       = 133000000,
    .flashSize            = FLASH_SIZE,
    .CSIntervalUnit       = kFLEXSPI_CsIntervalUnit1SckCycle,
    .CSInterval           = 2,
    .CSHoldTime           = 3,
    .CSSetupTime          = 3,
    .dataValidTime        = 0,
    .columnspace          = 0,
    .enableWordAddress    = 0,
    .AWRSeqIndex          = 0,
    .AWRSeqNumber         = 0,
    .ARDSeqIndex          = NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD,
    .ARDSeqNumber         = 1,
    .AHBWriteWaitUnit     = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
    .AHBWriteWaitInterval = 0,
};

const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
    /* Normal read mode -SDR */
    /* Normal read mode -SDR */
    [4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x03, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
    [4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 1] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

    /* Fast read mode - SDR */
    [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0B, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
    [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST + 1] = FLEXSPI_LUT_SEQ(
        kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x08, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

    /* Fast read quad mode - SDR */
    [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xEB, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18),
    [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] = FLEXSPI_LUT_SEQ(
        kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x06, kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04),

    /* Read extend parameters */
    [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUS] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x81, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

    /* Write Enable */
    [4 * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

    /* Erase Sector  */
    [4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x20, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

    /* Page Program - single mode */
    [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
    [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE + 1] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

    /* Page Program - quad mode */
    [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
    [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD + 1] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

    /* Read ID */
    [4 * NOR_CMD_LUT_SEQ_IDX_READID] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

    /* Enable Quad mode */
    [4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),

    /* Enter QPI mode */
    [4 * NOR_CMD_LUT_SEQ_IDX_ENTERQPI] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x35, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

    /* Exit QPI mode */
    [4 * NOR_CMD_LUT_SEQ_IDX_EXITQPI] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_4PAD, 0xF5, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

    /* Read status register */
    [4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

    /* Erase whole chip */
    [4 * NOR_CMD_LUT_SEQ_IDX_ERASECHIP] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xC7, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
};


/************************************************FlexSPI********************************************************************/

uint8_t flespi_test()
{
	/************************************************FlexSPI********************************************************************/	
	uint32_t i = 0;
    status_t status;
    uint8_t vendorID = 0;
	flexspi_nor_flash_init(EXAMPLE_FLEXSPI);

    PRINTF("\r\nFLEXSPI example1 started!\r\n");

    /* Get vendor ID. */
    status = flexspi_nor_get_vendor_id(EXAMPLE_FLEXSPI, &vendorID);
    if (status != kStatus_Success)
    {
        return status;
    }
    PRINTF("Vendor ID: 0x%x\r\n", vendorID);

	PRINTF("Enter quad mode 1\n");
    /* Enter quad mode. */
    status = flexspi_nor_enable_quad_mode(EXAMPLE_FLEXSPI);
    if (status != kStatus_Success)
    {
        return status;
    }
	PRINTF("Enter quad mode 2\n");

		for(int i = 0; i<= sizeof(_aclwip_ping_bm)/SECTOR_SIZE; i++)
		{
			/* Erase sectors. */
			PRINTF("Erasing Serial NOR over FlexSPI...\r\n");
			status = flexspi_nor_flash_erase_sector(EXAMPLE_FLEXSPI, APP_BASE_ADDRESS + SECTOR_SIZE * i);
			if (status != kStatus_Success)
			{
					PRINTF("Erase sector failure !\r\n");
					return -1;
			}
		}
		
		
		for(int j = 0; j<= sizeof(_aclwip_ping_bm)/FLASH_PAGE_SIZE; j++)
		{
			if(j>sizeof(_aclwip_ping_bm)/256-1)
			{
				memset(s_nor_program_buffer, 0xFFU, sizeof(s_nor_program_buffer));
				DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + APP_BASE_ADDRESS + FLASH_PAGE_SIZE * j, FLASH_PAGE_SIZE);
				memcpy(s_nor_program_buffer, &_aclwip_ping_bm[(j)*256], sizeof(_aclwip_ping_bm)%256);
			}
			else
			{
				DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + APP_BASE_ADDRESS + FLASH_PAGE_SIZE * j, FLASH_PAGE_SIZE);
				memcpy(s_nor_program_buffer, &_aclwip_ping_bm[(j)*256], sizeof(s_nor_program_buffer));
			}
			status =
					flexspi_nor_flash_page_program(EXAMPLE_FLEXSPI, APP_BASE_ADDRESS + FLASH_PAGE_SIZE*(j), (void *)s_nor_program_buffer);
			if (status != kStatus_Success)
			{
				PRINTF("Page program failure !\r\n");
				return -1;
			}
		}
		return 0;
}
/************************************************FlexSPI********************************************************************/

 跳转函数代码:

/*******************************************Jump Function********************************************************/
#define APP_ADDR 0x60010000	//APP1 : 0x60010000 APP2 : 0x60030000

typedef void (*pFunc)(void);

volatile uint32_t AppAddr;
volatile uint32_t app_start_address;
pFunc JumpToApp;

void jump_to_application(uint32_t applicationAddress)
{
	app_start_address = applicationAddress + 0x00002000;
	PRINTF("App Start Address : 0x%x\r\n",app_start_address);
	SCB->VTOR = app_start_address;
	AppAddr = *(uint32_t*)app_start_address;
	PRINTF("App Top of Stack : 0x%x\r\n",AppAddr);
	__set_MSP(AppAddr);
	AppAddr = *(uint32_t*)(app_start_address + 4);
	JumpToApp = (pFunc)AppAddr;
	JumpToApp();
}
/*******************************************Jump Function********************************************************/

 主函数:

/*!
 * @brief Main function
 */
int main(void)
{
    char ch;

    /* Init board hardware. */
    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitDebugConsole();

    /* Just enable the trace clock, leave coresight initialization to IDE debugger */
    SystemCoreClockUpdate();
    CLOCK_EnableClock(kCLOCK_Trace);

    PRINTF("hello world.\r\n");
	PRINTF("0x = %x\r\n",_aclwip_ping_bm[0]);
	flespi_test();
	jump_to_application(APP_ADDR);

    while (1)
    {
    }
}
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值