发新帖本帖赏金 20.00元(功能说明)我要提问
返回列表
打印
[APM32F1]

APM32F103_IAP的简单实现_3 flash编程基础

[复制链接]
1246|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
WuKaiLi|  楼主 | 2022-10-9 23:27 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 WuKaiLi 于 2022-10-9 23:27 编辑

#申请原创#
@21小跑堂

前言

最近拿到了一块APM32F103VC的MINI开发板,在学习了一段时间后发现其有非常丰富的外设资源,主频能达到96Mhz。最近在项目中使用到了IAP(In Application Programming)功能,特来评估一下APM32F103的IAP实现方式。

在应用编程IAP(In-Application Programming)是应用在Flash程序存储器的一种编程模式。它可以在应用程序正常运行的情况下,通过调用特定的IAP程序对另外一段程序Flash空间进行读/写操作,甚至可以控制对某段、某页甚至某个字节的读/写操作,这为数据存储和固件的现场升级带来了更大的灵活性。

话接上回,我们提及到了 程序跳转运行就是修改PC指针至我们的APP程序,然后修改我们的中断向量寄存器以使得我们的APP程序能够正确相应中断。

那我们本章节就在IAP实现的第三部分内容,Flash编程的基础进行梳理。


1 为什么要编程Flash?

众所周知,MCU的Flash保存着我们的程序,一般情况下我们在生产或者调试的时候是通过我们的烧录器或者仿真器对MCU的Flash进行编程。在这个过程中我们无需关系Flash的编程流程,仅需要通过工具即可完成对Flash的编程操作。


那为什么做IAP需要关心Flash编程呢?因为IAP的一个关键因素就能够通过BootLoader去编程我们的APP区域的内容。

即我们需要实现对MCU的Flash编程操作。

2 Flash的编程流程

在APM32F103的手册,我们可以看到Flash编程一共分为解锁,擦除,编程,上锁的四个步骤。下面我们一步步看一下我们需要完成哪些操作。



2.1 Flash解锁与上锁

Flash是我们程序保存的地方,需要编程FLash必须是“确定的”,而不是我们“一时兴起”。所以涉及较为繁琐的“解锁”步骤,以防我们重要的程序内容被改动。



APM32F1的标准库函数如下所示:
/*!
* [url=home.php?mod=space&uid=247401]@brief[/url]     Unlocks the FMC Program Erase Controller
*
* @param     None
*
* @retval    None
*/
void FMC_Unlock(void)
{
    FMC->KEY = 0x45670123;
    FMC->KEY = 0xCDEF89AB;
}

/*!
* [url=home.php?mod=space&uid=247401]@brief[/url]     Locks the FMC Program Erase Controller.
*
* @param     None
*
* @retval    None
*/
void FMC_Lock(void)
{
    FMC->CTRL2_B.LOCK = BIT_SET;
}


2.2 Flash的擦除

由于APM32F1 的Flash的特性,对Flash写入数据的地址内容必须是0xFFFF,打个比方来说,我们要在一张纸上画一幅精彩的画作,那我们的纸张必须要是空白的,这样子才能不受纸张上的污渍影响我们。

那对于APM32F1的Flash来说,0xFFFF是“空白”状态,这个状态下我们才能尽情的“书写”内容。

那Flash的擦除操作,便是把Flash变回“空白”的操作。

擦除有分“全擦除”和“页擦除”,由于我们的BootLoader也是存储于Flash中的,我们若是使用“全擦除”操作我们的BootLoader程序也会被擦除掉,使得MCU处于“空片”状态。所以我们会使用“页擦除”完成对APP存储的区域进行擦除操作。



APM32F1的标准库函数如下所示:

/*!
* @brief     Erases a specified FMC page.
*
* @param     pageAddr: The page address to be erased.
*
* @retval    Returns the flash state.It can be one of value:
*                 [url=home.php?mod=space&uid=2817080]@ARG[/url] FMC_STATUS_BUSY
*                 [url=home.php?mod=space&uid=2817080]@ARG[/url] FMC_STATUS_ERROR_PG
*                 @arg FMC_STATUS_ERROR_WRP
*                 @arg FMC_STATUS_COMPLETE
*                 @arg FMC_STATUS_TIMEOUT
*/
FMC_STATUS_T FMC_ErasePage(uint32_t pageAddr)
{
    FMC_STATUS_T status = FMC_STATUS_COMPLETE;

    status = FMC_WaitForLastOperation(0x000B0000);
    if(status == FMC_STATUS_COMPLETE)
    {
        FMC->CTRL2_B.PAGEERA = BIT_SET;
        FMC->ADDR = pageAddr;
        FMC->CTRL2_B.STA = BIT_SET;

        status = FMC_WaitForLastOperation(0x000B0000);
        FMC->CTRL2_B.PAGEERA = BIT_RESET;
    }
    return status;
}

/*!
* @brief     Erases all FMC pages.
*
* @param     None
*
* @retval    Returns the flash state.It can be one of value:
*                 @arg FMC_STATUS_ERROR_PG
*                 @arg FMC_STATUS_ERROR_WRP
*                 @arg FMC_STATUS_COMPLETE
*                 @arg FMC_STATUS_TIMEOUT
*/
FMC_STATUS_T FMC_EraseAllPage(void)
{
    FMC_STATUS_T status = FMC_STATUS_COMPLETE;

    status = FMC_WaitForLastOperation(0x000B0000);
    if(status == FMC_STATUS_COMPLETE)
    {
        FMC->CTRL2_B.MASSERA = BIT_SET;
        FMC->CTRL2_B.STA = BIT_SET;

        status = FMC_WaitForLastOperation(0x000B0000);
        FMC->CTRL2_B.MASSERA = BIT_RESET;
    }
    return status;
}


2.3 Flash的编程

在上面我们完成对目标区域的擦除操作后,便可以对Flash进行编程操作了。


在APM32F1的标准库函数中给我们提供了字编程与半字编程操作。

/*!
* @brief     Programs a word at a specified address.
*
* @param     address:the address to be programmed.
*
* @param     data: the data to be programmed.
*
* @retval    Returns the flash state.It can be one of value:
*                 @arg FMC_STATUS_ERROR_PG
*                 @arg FMC_STATUS_ERROR_WRP
*                 @arg FMC_STATUS_COMPLETE
*                 @arg FMC_STATUS_TIMEOUT
*/
FMC_STATUS_T FMC_ProgramWord(uint32_t address, uint32_t data)
{
    FMC_STATUS_T status = FMC_STATUS_COMPLETE;
    __IOM uint32_t temp = 0;

    #ifdef APM32F10X_HD
          __set_PRIMASK(1);
    #endif

    status = FMC_WaitForLastOperation(0x000B0000);

    if(status == FMC_STATUS_COMPLETE)
    {
        FMC->CTRL2_B.PG = BIT_SET;

        *(__IOM uint16_t *)address = data;

        status = FMC_WaitForLastOperation(0x000B0000);

        if(status == FMC_STATUS_COMPLETE)
        {
            temp = address + 2;

            *(__IOM uint16_t*) temp = data >> 16;

            status = FMC_WaitForLastOperation(0x000B0000);
            FMC->CTRL2_B.PG = BIT_RESET;
        }
        else
        {
            FMC->CTRL2_B.PG = BIT_RESET;
        }
    }

    #ifdef APM32F10X_HD
        __set_PRIMASK(0);
    #endif

    return status;
}

/*!
* @brief     Programs a half word at a specified address.
*
* @param     address:the address to be programmed.
*
* @param     data: the data to be programmed.
*
* @retval    Returns the flash state.It can be one of value:
*                 @arg FMC_STATUS_ERROR_PG
*                 @arg FMC_STATUS_ERROR_WRP
*                 @arg FMC_STATUS_COMPLETE
*                 @arg FMC_STATUS_TIMEOUT
*/
FMC_STATUS_T FMC_ProgramHalfWord(uint32_t address, uint16_t data)
{
    FMC_STATUS_T status = FMC_STATUS_COMPLETE;

    #ifdef APM32F10X_HD
        __set_PRIMASK(1);
    #endif

    status = FMC_WaitForLastOperation(0x000B0000);

    if(status == FMC_STATUS_COMPLETE)
    {
        FMC->CTRL2_B.PG = BIT_SET;
        *(__IOM uint16_t *)address = data;
        status = FMC_WaitForLastOperation(0x000B0000);
        FMC->CTRL2_B.PG = BIT_RESET;
    }

    #ifdef APM32F10X_HD
        __set_PRIMASK(0);
    #endif

    return status;
}


3 Flash的读取

完成对目标区域的Flash的编程后,我们一般情况下都需要进行校验,校验我们写入到Flash的实际内容与我们的期望内容是否一致。

我们可以使用直接读取比较,或者CRC校验的方式进行校验。校验的方法多种多样,但是都离不开Flash的读取。APM32F1的Flash读取较为简单,可以直接使用地址指针直接读取相应地址的内容。
data =  *(__IOM uint16_t *)address;

data =  *(__IOM uint32_t *)address;




  

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 20.00 元 2022-10-14
理由:恭喜通过原创审核

评论
21小跑堂 2022-10-14 10:55 回复TA
FLASH的操作,每家的MCU都有自己的库函数来进行操作,难度相对降低。重点在于理解FLASH的读写流程,已经注意事项。作者对比进行了较为详细的阐述,内容较为完整,条理较为清晰。但是缺少实战演练,有相应的实验支撑可能会获得更高打赏哦! 
沙发
昨天| | 2022-10-10 10:17 | 只看该作者
开发板不可以显示出来吗?没有显示屏??。

使用特权

评论回复
评论
WuKaiLi 2022-10-10 10:42 回复TA
开发板没有屏幕,需要显示什么?其实使用串口打印就可以了。 
板凳
kai迪皮| | 2022-10-10 22:26 | 只看该作者
学到了,谢谢楼主

使用特权

评论回复
地板
linfelix| | 2023-2-4 16:18 | 只看该作者
这个怎么修改BootLoader ?

使用特权

评论回复
5
i1mcu| | 2023-2-4 20:36 | 只看该作者
IAP可以通过哪些方式实现?              

使用特权

评论回复
6
beacherblack| | 2023-2-4 23:21 | 只看该作者
是否可以通过can总线实现数据传输?

使用特权

评论回复
7
pl202| | 2023-2-7 21:08 | 只看该作者
APM32F103跟stm32f103一样的吧?

使用特权

评论回复
8
ingramward| | 2023-2-8 18:18 | 只看该作者
使用的是ymodem的协议吗?              

使用特权

评论回复
9
ulystronglll| | 2023-2-8 20:28 | 只看该作者
APM32F103_IAP是兼容st的芯片的吗?

使用特权

评论回复
评论
WuKaiLi 2023-11-20 21:29 回复TA
兼容的 
发新帖 本帖赏金 20.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

39

帖子

1

粉丝