0、NXP没有提供S32R274的bootloader试例程序,网上也没有找到,不过NXP MPC5XXX系列芯片有bootloader的例子可以借鉴,它们都是用的z4启动核心,而且都是用的C55 FLASH。
1、开发环境是NXP官方的S32DS最新版,建立一个z4的单核工程,bootloader和用户程序要在不同的flash块,建立工程的时候地址都是从0x01000000开始,启动代码必须放到boot location块,下面是s32r274 flash相关资料
可以把bootloader放到0x00F98000,S32DS自动生成的项目起始地址是0x01000000,只能通过flash配置文件linker_flash.ld改地址,启动配置半字从F98000开始,代码起始地址从F99000开始,大小为156K,一般bootloader很小,我用到了lwip模块和串口模块,自动生成的代码有点大。
//linker_flash.ld
/* define heap and stack size */
__HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x00000400;
__STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x00004000;
/* Define FLASH */
//启动配置半字RCHW需要占用8个字节,所以代码地址从F99000开始,大小为156K
FLASH_BASE_ADDR = DEFINED(__flash_base_addr__) ? __flash_base_addr__ : 0x00F99000;
FLASH_SIZE = DEFINED(__flash_size__) ? __flash_size__ : 156K;
/* Define SRAM */
SRAM_BASE_ADDR = DEFINED(__sram_base_addr__) ? __sram_base_addr__ : 0x40000000;
SRAM_SIZE = DEFINED(__sram_size__) ? __sram_size__ : 256K;
/* Define local data memory */
LOCAL_DMEM_BASE_ADDR = DEFINED(__local_dmem_base_addr__) ? __local_dmem_base_addr__ : 0x50800000;
LOCAL_DMEM_SIZE = DEFINED(__local_dmem_size__) ? __local_dmem_size__ : 64K;
MEMORY
{
//启动配置半字
flash_rchw : org = 0x00F98000, len = 0x4
cpu0_reset_vec : org = 0x00F98000+0x04, len = 0x4
m_text : org = FLASH_BASE_ADDR, len = FLASH_SIZE
m_data : org = SRAM_BASE_ADDR, len = SRAM_SIZE
local_dmem : org = LOCAL_DMEM_BASE_ADDR, len = LOCAL_DMEM_SIZE
}
...
2、flash C55模块,需要在工程内添加flash_C55模块,它提供了读写flash的接口函数,初始化、格式化、写flash代码都是官网或网上能找到的,就直接贴文件了flash.c,ProgramFlash是写烧录文件的函数,S19格式的,一条一条写
/*
* flash.c
*
* Created on: 2020年7月6日
* Author:
*/
#include "flash.h"
#include "flash_c55_driver.h"
#include "Srec.h"
#include "net_conn.h"
uint32_t g_usrCnt = 0U;
flash_context_data_t pCtxData;
static uint32_t pflash_pfcr1, pflash_pfcr2;
void UserCallBack(void)
{
/* increase g_usrCnt */
g_usrCnt++;
}
/**************************************************************
* Disable Flash Cache *
***************************************************************/
void DisableFlashControllerCache(uint32_t flashConfigReg,
uint32_t disableVal,
uint32_t *origin_pflash_pfcr)
{
/* Read the values of the register of flash configuration */
*origin_pflash_pfcr = REG_READ32(FLASH_FMC + flashConfigReg);
/* Disable Caches */
REG_BIT_CLEAR32(FLASH_FMC + flashConfigReg, disableVal);
}
/*****************************************************************
* Restore configuration register of FCM *
******************************************************************/
void RestoreFlashControllerCache(uint32_t flashConfigReg,
uint32_t pflash_pfcr)
{
REG_WRITE32(FLASH_FMC + flashConfigReg, pflash_pfcr);
}
void disable_flash_cache()
{
DisableFlashControllerCache(FLASH_PFCR1, FLASH_FMC_BFEN_MASK, &pflash_pfcr1);
DisableFlashControllerCache(FLASH_PFCR2, FLASH_FMC_BFEN_MASK, &pflash_pfcr2);
}
void restore_flash_cache()
{
if(pflash_pfcr1 != 0 && pflash_pfcr2 != 0) {
RestoreFlashControllerCache(FLASH_PFCR1, pflash_pfcr1);
RestoreFlashControllerCache(FLASH_PFCR2, pflash_pfcr2);
}
}
status_t FlashInit()
{
status_t ret = STATUS_SUCCESS;
uint32_t blkLockState;
/* Flash Initialization */
ret = FLASH_DRV_Init();
DEV_ASSERT(ret == STATUS_SUCCESS);
/**************************************************************************/
/* Lock to protect UTest address space */
/**************************************************************************/
ret = FLASH_DRV_GetLock(C55_BLOCK_UTEST, &blkLockState);
if (!(blkLockState & 0x00000001U))
{
ret = FLASH_DRV_SetLock(C55_BLOCK_UTEST, 0x1U);
if (STATUS_SUCCESS != ret)
{
return ret;
}
}
/**************************************************************************/
/* Unlock all blocks in low address space */
/**************************************************************************/
ret = FLASH_DRV_SetLock(C55_BLOCK_LOW, UNLOCK_LOW_BLOCKS);
if (STATUS_SUCCESS != ret)
{
return ret;
}
/**************************************************************************/
/* Unlock all blocks in mid address space */
/**************************************************************************/
ret = FLASH_DRV_SetLock(C55_BLOCK_MID, UNLOCK_MID_BLOCKS);
if (STATUS_SUCCESS != ret)
{
return ret;
}
/**************************************************************************/
/* Unlock all blocks in 256K blocks */
/**************************************************************************/
ret = FLASH_DRV_SetLock(C55_BLOCK_256K_FIRST, UNLOCK_FIRST256_BLOCKS);
return ret;
}
status_t EraseFlash()
{
status_t ret = STATUS_SUCCESS;
flash_block_select_t blockSelect;
flash_state_t opResult;
//选择需要擦除的块,是用户代码块0x01000000开始
blockSelect.lowBlockSelect = 0x0U;
blockSelect.midBlockSelect = 0x0U;
blockSelect.highBlockSelect = 0x0U;
blockSelect.first256KBlockSelect = 0x3U;
blockSelect.second256KBlockSelect = 0x0U;
ret = FlashInit();
if (STATUS_SUCCESS != ret)
{
return ret;
}
/* Erase block */
ret = FLASH_DRV_Erase(ERS_OPT_MAIN_SPACE, &blockSelect);
if (STATUS_SUCCESS == ret)
{
do
{
/* The user can do any tasks while check status function is still in progress */
UserCallBack();
ret = FLASH_DRV_CheckEraseStatus(&opResult);
}while(ret == STATUS_FLASH_INPROGRESS);
}
return ret;
}
status_t ProgramFlash(int sock, char * data, uint32_t len)
{
status_t ret = STATUS_SUCCESS;
flash_block_select_t blockSelect;
flash_state_t opResult;
uint32_t numOfWordCycle;
uint32_t sum;
uint32_t failedAddress;
uint32_t dest; /* destination address */
uint32_t size; /* size applicable */
uint32_t source; /* source address for program and verify */
SRecDataRec ProgSRec;
/* go get an S-Record, return if there was an error */
uint8_t Error = RcvSRecord(sock, &ProgSRec, data, len);
if (Error != 0) {
return Error;
}
if (ProgSRec.RecType == EndRec) /* S7, S8 or S9 record? */
{
restore_flash_cache();
return (0x006U); /* yes. return */
}
else if (ProgSRec.RecType == HeaderRec) /* S0 record? */
{
return STATUS_SUCCESS; /* yes. just ignore it */
}
/* a data record was received */
else
{
//write(sock, ProgSRec.Data, MaxSRecLen);
if ((ProgSRec.LoadAddr & 0x0000000FUL) != 0) /* S-Record address aligned? */
{
return(101); /* address not aligned. return */
}
if (ProgSRec.NumBytes != 16)/* S-Record constant length 16? */
{
return(102); /* length different from 16. Return */
}
/* Prepare data for programming */
dest = ProgSRec.LoadAddr;
source = (uint32_t)ProgSRec.Data;
size = 16;
ret = FLASH_DRV_Program(&pCtxData,dest, size, source);
if (STATUS_SUCCESS == ret)
{
do
{
/* The user can do any tasks while check status function is still in progress */
UserCallBack();
ret = FLASH_DRV_CheckProgramStatus(&pCtxData, &opResult);
}while(ret == STATUS_FLASH_INPROGRESS);
}
if (STATUS_SUCCESS != ret)
{
return ret;
}
numOfWordCycle = NUMBER_OF_WORD_PGM_VERIFY;
/* Program verify */
ret = FLASH_DRV_ProgramVerify(dest,
size,
source,
numOfWordCycle,
&failedAddress,
NULL_CALLBACK);
if (STATUS_SUCCESS != ret)
{
return ret;
}
numOfWordCycle = NUMBER_OF_WORD_CHECK_SUM;
/* Check sum */
ret = FLASH_DRV_CheckSum(dest,
size,
numOfWordCycle,
&sum,
NULL_CALLBACK);
if ((STATUS_SUCCESS != ret) && (sum != 0U))
{
return ret;
}
}
return ret;
}