打印
[PSoC™]

PSOC4 Flash Row 的Erase和 Program分割技巧

[复制链接]
177|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
IFXJone|  楼主 | 2024-7-18 14:24 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 IFXJone 于 2024-7-18 14:30 编辑

问:PSoC 3/5不同,PSoC4codeexampleFlash在线升级擦除和编程调用的是同一个函数CySysFlashWriteRow(),这个函数的EraseProgram 无法分割,所以没有独立的EraseProgram功能。那么该怎么实现EraseProgram分割呢?


答:以下是具体步骤: (基于CY8CKIT-149的开发板、UART Bootloader 的例程,工程已上传附件)
1:首先在桌面拷贝两个一模一样的工程,demo板为CY8CKIT-149。

                              

2:打开其中Bootloader2URAT工程


3:打开Components组件,选择Import Component



4Import fromproject/library选择Downloads(4.4) Source component选择cy_boot_v6_10 Target project选择Design01(注意:这里是选择您的bootloader工程),最后点击OK




5Import 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即可烧录成功。









Bootloader2 UART.zip

4.44 MB

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

22

帖子

0

粉丝