本帖最后由 IFXJone 于 2024-7-18 14:30 编辑
问:与PSoC 3/5不同,PSoC4的codeexample中Flash在线升级擦除和编程调用的是同一个函数CySysFlashWriteRow(),这个函数的Erase和Program 无法分割,所以没有独立的Erase和Program功能。那么该怎么实现Erase和Program分割呢?
答:以下是具体步骤: (基于CY8CKIT-149的开发板、UART Bootloader 的例程,工程已上传附件):
1:首先在桌面拷贝两个一模一样的工程,demo板为CY8CKIT-149。
2:打开其中Bootloader2URAT工程
3:打开Components组件,选择Import Component
4:Import fromproject/library选择Downloads(4.4), Source component选择cy_boot_v6_10 ,Target project选择Design01(注意:这里是选择您的bootloader工程),最后点击OK
5:Import fromproject/library选择CyComponentLibrary, Source component选择Bootloader_v1_1_60 ,Target project选择Design01(注意:这里是选择您的bootloader工程),最后点击OK
6:将Bootloader.c的代码修改为如下(目的是自定义CySysFlashProgramRow() 函数):
代码如下:
// ackCode =(CYRET_SUCCESS != CySysFlashWriteRow((uint32) row, dataBuffer)) \ // ?`$INSTANCE_NAME`_ERR_ROW \ // :CYRET_SUCCESS;
if(Bootloader_1_COMMAND_PROGRAM== packetBuffer[Bootloader_1_CMD_ADDR]) { ackCode =(CYRET_SUCCESS != CySysFlashProgramRow((uint32) row, dataBuffer)) \ ? `$INSTANCE_NAME`_ERR_ROW\ :CYRET_SUCCESS; } else if(Bootloader_1_COMMAND_ERASE== packetBuffer[Bootloader_1_CMD_ADDR]) { /*data buffer is set to 0, write row only ececute erase process */ ackCode =(CYRET_SUCCESS != CySysFlashWriteRow((uint32) row, dataBuffer)) \ ? `$INSTANCE_NAME`_ERR_ROW\ :CYRET_SUCCESS; }
7:在flash.h中添加如下代码
8:在flash.c中添加如下代码,点击保存
具体代码如下:
/******************************************************************************* * Function Name:CySysFlashWriteRow ****************************************************************************//** * * programsa a rowof Flash with the new data.*/ uint32CySysFlashProgramRow(uint32 rowNum, const uint8 rowData[]) { volatile uint32 retValue= CY_SYS_FLASH_SUCCESS; volatile uint32clkCnfRetValue = CY_SYS_FLASH_SUCCESS; volatile uint32parameters[(CY_FLASH_SIZEOF_ROW + CY_FLASH_SRAM_ROM_DATA) / sizeof(uint32)]; uint8 interruptState;
#if(CY_FLASH_CHECKSUM_WORKAROUND) uint32 needChecksumWorkaround = 0u; uint32 savedIndex = 0u; uint32 savedValue = 0u; uint32 checksum = 0u; uint32 bits = 0u; uint32 i; #endif /* (CY_FLASH_CHECKSUM_WORKAROUND)*/
if ((rowNum <CY_FLASH_NUMBER_ROWS) && (rowData != 0u)) { /* Copy data tobe written into internal variable */ (void)memcpy((void*)¶meters[2u], rowData, CY_FLASH_SIZEOF_ROW);
#if(CY_FLASH_CHECKSUM_WORKAROUND)
for (i =2u; i < ((CY_FLASH_SIZEOF_ROW / sizeof(uint32)) + 2u);i++) { uint32 tmp = parameters; if (tmp!= 0u) { checksum += tmp; bits |= tmp; savedIndex = i; } }
needChecksumWorkaround = ((checksum== 0u) && (bits != 0u)) ? 1u : 0u; if(needChecksumWorkaround != 0u) { savedValue =parameters[savedIndex]; parameters[savedIndex] = 0u; } #endif /* (CY_FLASH_CHECKSUM_WORKAROUND)*/
/* Load FlashBytes */ parameters[0u] = (uint32)(CY_FLASH_GET_MACRO_FROM_ROW(rowNum) << CY_FLASH_PARAM_MACRO_SEL_OFFSET) | (uint32)(CY_FLASH_PAGE_LATCH_START_ADDR << CY_FLASH_PARAM_ADDR_OFFSET ) | (uint32)(CY_FLASH_KEY_TWO(CY_FLASH_API_OPCODE_LOAD) <<CY_FLASH_PARAM_KEY_TWO_OFFSET ) | CY_FLASH_KEY_ONE; parameters[1u] = CY_FLASH_SIZEOF_ROW -1u;
CY_FLASH_CPUSS_SYSARG_REG = (uint32)¶meters[0u]; CY_FLASH_CPUSS_SYSREQ_REG =CY_FLASH_CPUSS_REQ_START | CY_FLASH_API_OPCODE_LOAD; CY_NOP; retValue = CY_FLASH_API_RETURN;
if(retValue== CY_SYS_FLASH_SUCCESS) { /*************************************************************** * Mask all the exceptions toguarantee that Flash write will * occur in the atomic way. It willnot affect system call * execution (flash row write) sinceit is executed in the NMI * context. ***************************************************************/ interruptState =CyEnterCriticalSection();
clkCnfRetValue =CySysFlashClockBackup();
#if(CY_IP_SPCIF_SYNCHRONOUS) if(clkCnfRetValue== CY_SYS_FLASH_SUCCESS) { retValue =CySysFlashClockConfig(); } #endif /* (CY_IP_SPCIF_SYNCHRONOUS) */
if(retValue== CY_SYS_FLASH_SUCCESS) { /* Write Row */ parameters[0u] = (uint32) (((uint32)CY_FLASH_KEY_TWO(CY_FLASH_API_OPCODE_PROGRAM_ROW) << CY_FLASH_PARAM_KEY_TWO_OFFSET) |CY_FLASH_KEY_ONE); parameters[0u] |=(uint32)(rowNum << 16u);
CY_FLASH_CPUSS_SYSARG_REG =(uint32) ¶meters[0u]; CY_FLASH_CPUSS_SYSREQ_REG =CY_FLASH_CPUSS_REQ_START | CY_FLASH_API_OPCODE_PROGRAM_ROW; CY_NOP; retValue = CY_FLASH_API_RETURN; }
#if(CY_FLASH_CHECKSUM_WORKAROUND)
if((retValue == CYRET_SUCCESS) && (needChecksumWorkaround != 0u)) { (void)memset((void*)¶meters[2u], 0, CY_FLASH_SIZEOF_ROW); parameters[savedIndex] =savedValue;
/* Load FlashBytes */ parameters[0u] = (uint32)(CY_FLASH_GET_MACRO_FROM_ROW(rowNum) << CY_FLASH_PARAM_MACRO_SEL_OFFSET) | (uint32)(CY_FLASH_PAGE_LATCH_START_ADDR << CY_FLASH_PARAM_ADDR_OFFSET ) | (uint32)(CY_FLASH_KEY_TWO(CY_FLASH_API_OPCODE_LOAD) <<CY_FLASH_PARAM_KEY_TWO_OFFSET ) | CY_FLASH_KEY_ONE; parameters[1u] =CY_FLASH_SIZEOF_ROW - 1u;
CY_FLASH_CPUSS_SYSARG_REG =(uint32) ¶meters[0u]; CY_FLASH_CPUSS_SYSREQ_REG =CY_FLASH_CPUSS_REQ_START | CY_FLASH_API_OPCODE_LOAD; CY_NOP; retValue =CY_FLASH_API_RETURN;
if(retValue== CY_SYS_FLASH_SUCCESS) { /*Program Row */ parameters[0u] = (uint32) (((uint32)CY_FLASH_KEY_TWO(CY_FLASH_API_OPCODE_PROGRAM_ROW) << CY_FLASH_PARAM_KEY_TWO_OFFSET) | CY_FLASH_KEY_ONE); parameters[0u] |=(uint32)(rowNum << 16u);
CY_FLASH_CPUSS_SYSARG_REG = (uint32) ¶meters[0u]; CY_FLASH_CPUSS_SYSREQ_REG = CY_FLASH_CPUSS_REQ_START |CY_FLASH_API_OPCODE_PROGRAM_ROW; CY_NOP; retValue =CY_FLASH_API_RETURN; } } #endif /* (CY_FLASH_CHECKSUM_WORKAROUND)*/
if(clkCnfRetValue== CY_SYS_FLASH_SUCCESS) { clkCnfRetValue =CySysFlashClockRestore();
if(clkCnfRetValue!= CY_SYS_FLASH_SUCCESS) { retValue = clkCnfRetValue; } }
CyExitCriticalSection(interruptState); } } else { retValue = CY_SYS_FLASH_INVALID_ADDR; }
return (retValue); } 9:在Bootloader_v1_60的Component中右击选择Export Component->Create New Archive,然后在桌面新建一个文件夹,将文件保存在桌面的文件夹中。
10:在cy_boot_v6_10的Component中右击选择Export Component->Create New Archive,然后在桌面新建一个文件夹,将文件保存在桌面的文件夹中(注意修改下.cycomp的文件名)。
11:保存完两个文件夹之后,关闭当前Bootloader2URAT的工程,并打开另外一个Bootloader2URAT1的工程
12:右击Design01工程,选择Import Component,在对话框中选择Import from archive,依次选择comp_archive1.cycomp,comp_archive2.cycomp,Target Project选择Design01(注意:这里是选择您的bootloader工程)
13:导入之后将第二个工程(即Design02)设置为Set As Active Project
14:打开bootloadable_1组件,将Application ID改为0x0001(注意:该步骤修改的目的是我们官方的bootloader程序有一点错误,实际用的时候Erase再烧录是没有问题的,所以实际应用该步骤可省去),改好之后编译Design02工程(注意:一定不可省略),
15:Design02工程编译完之后将Design01设置为Set As Active Project,编译并烧录到MCU中,
16:打开Bootloader Host组件,选择Application的Design02.cyacd文件,点击Program即可烧录成功。
|