打印
[STM32F0]

STM32F070 UNCLED-F070RB开发板TF卡IAP升级

[复制链接]
2667|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yklstudent|  楼主 | 2015-11-16 13:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
因为公司项目功能需求,网上购买了UNCLED-F070RB开发板,摸索实现TF卡IAP升级用户程序。拿到UNCLED-F070RB开发板后,参考官网的库文件,很快就调通了TF卡和移植了FatFs文件系统;
并在官网USART串口IAP范例下,也很快就实现了TF卡IAP升级用户程序。
接下来就大概介绍下实现过程:
1、UNCLED-F070RB开发板由于自带ST-LINK,所以给PC电脑安装ST-LINK驱动(备注:驱动KEIL 5安装路径下就有);
2、参照官网库工程,设置好硬件SPI的初始化设置,基本设置如下所示:
        GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;

        /*!< Enable the SPI clock */
        SPI_CLK_INIT(SPI_CLK, ENABLE);

        /*!< Enable GPIO clocks */
        RCC_AHBPeriphClockCmd_Boot(SPI_SCK_GPIO_CLK  | SPI_MISO_GPIO_CLK |
                                                   SPI_MOSI_GPIO_CLK | SPI_CS_GPIO_CLK, ENABLE);

        /*!< SPI pins configuration *************************************************/

        /*!< Connect SPI pins to AF6 */
        GPIO_PinAFConfig_Boot(SPI_SCK_GPIO_PORT, SPI_SCK_SOURCE, SPI_SCK_AF);
        GPIO_PinAFConfig_Boot(SPI_MISO_GPIO_PORT, SPI_MISO_SOURCE, SPI_MISO_AF);
        GPIO_PinAFConfig_Boot(SPI_MOSI_GPIO_PORT, SPI_MOSI_SOURCE, SPI_MOSI_AF);

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;

        /*!< SPI SCK pin configuration */
        GPIO_InitStructure.GPIO_Pin = SPI_SCK_PIN;
        GPIO_Init_Boot(SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

        /*!< SPI MOSI pin configuration */
        GPIO_InitStructure.GPIO_Pin =  SPI_MOSI_PIN;
        GPIO_Init_Boot(SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

        /*!< SPI MISO pin configuration */
        GPIO_InitStructure.GPIO_Pin =  SPI_MISO_PIN;
        GPIO_Init_Boot(SPI_MISO_GPIO_PORT, &GPIO_InitStructure);

        /*!< Configure sd Card CS pin in output pushpull mode ********************/
        GPIO_InitStructure.GPIO_Pin = SPI_CS_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init_Boot(SPI_CS_GPIO_PORT, &GPIO_InitStructure);

        SPI_StructInit_Boot(&SPI_InitStructure);
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitStructure.SPI_CRCPolynomial = 7;
        SPI_Init_Boot(SPI, &SPI_InitStructure);

        SPI_RxFIFOThresholdConfig_Boot(SPI, SPI_RxFIFOThreshold_QF);
       
        //< Enable the sFLASH_SPI
        SPI_Cmd_Boot(SPI, ENABLE);

其中加粗部分是需要跟STM32F207/STM32F407不同,需要注意的。
3、TF卡初始化等操作部分直接移植的官网的(可直接参考官方代码);
4、移植FatFs文件系统,修改底层diskio.C文件内的disk_initialize、disk_read和disk_write函数,具体如下所示:
DSTATUS disk_initialize (
        BYTE pdrv                                /* Physical drive nmuber to identify the drive */
)
{
        INT8U res=0;

        switch (pdrv)
        {
                case SD_CARD://SD¿¨
                        res = SD_Initialize();//SD_Initialize()
                         if(res)//STM32 SPIµÄbug,ÔÚsd¿¨²Ù×÷ʧ°ÜµÄʱºòÈç¹û²»Ö´ÐÐÏÂÃæµÄÓï¾ä,¿ÉÄܵ¼ÖÂSPI¶ÁдÒì³£
                        {
                                SD_SPI_SpeedLow();
                                SD_SPI_ReadWriteByte(0xff);//Ìṩ¶îÍâµÄ8¸öʱÖÓ
                                SD_SPI_SpeedHigh();
                        }
                          break;

                default:
                        break;
        }

        if(res==0x00)
        return RES_OK;   
    else
        return RES_ERROR;
}

DRESULT disk_read (
        BYTE pdrv,                /* Physical drive nmuber to identify the drive */
        BYTE *buff,                /* Data buffer to store read data */
        DWORD sector,        /* Sector address in LBA */
        UINT count                /* Number of sectors to read */
)
{
        INT8U res=0;
    if (!count)
        return RES_PARERR;//count²»ÄܵÈÓÚ0£¬·ñÔò·µ»Ø²ÎÊý´íÎó        

        switch (pdrv)
        {
                case SD_CARD://SD¿¨
                        res=SD_ReadDisk(buff,sector,count);         
                         if(res)//STM32 SPIµÄbug,ÔÚsd¿¨²Ù×÷ʧ°ÜµÄʱºòÈç¹û²»Ö´ÐÐÏÂÃæµÄÓï¾ä,¿ÉÄܵ¼ÖÂSPI¶ÁдÒì³£
                        {
                                SD_SPI_SpeedLow();
                                SD_SPI_ReadWriteByte(0xff);//Ìṩ¶îÍâµÄ8¸öʱÖÓ
                                SD_SPI_SpeedHigh();
                        }
                        break;

                default:
                        break;
        }

    if(res==0x00)
        return RES_OK;   
    else
        return RES_ERROR;
}

DRESULT disk_write (
        BYTE pdrv,                        /* Physical drive nmuber to identify the drive */
        const BYTE *buff,        /* Data to be written */
        DWORD sector,                /* Sector address in LBA */
        UINT count                        /* Number of sectors to write */
)
{
    INT8U res=0;  
    if (!count)
        return RES_PARERR;//count²»ÄܵÈÓÚ0£¬·ñÔò·µ»Ø²ÎÊý´íÎó        

        switch (pdrv)
        {
                case SD_CARD:
                        res=SD_WriteDisk((INT8U*)buff,sector,count);
                        res = RES_OK;
                        break;
                default:
                        break;
        }

        if(res==0x00)
        return RES_OK;   
    else
        return RES_ERROR;
}

5、接下来就是移植IAP部分的FLASH擦除和烧录操作,具体如下所示:
static INT8U sIAPUpdate(void)
{
        INT8U lubRecv = 1;
        INT8U lucArray[12];
        INT8U i;
        INT32U lulData;
       
        switch( lubTaskID )
        {
                case 0:
                {
                        if( sCreateFileSystem() )
                        {
                                lubTaskID = 1;
                        }
                        break;
                }
                case 1:
                {
                        if( sCheckUpdateFile() )
                        {
                                lubTaskID = 2;
                        }
                        else
                        {
                                lubTaskID = 6;
                        }
                        break;
                }
                case 2:
                {
                        if( sOpenUpdateFile1(cAppFileName1String) )
                        {
                                FLASH_Unlock();
                                FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR | FLASH_FLAG_BSY);
                                for(i = PAGE_START; i < PAGE_NUM; i++)
                                {
                                        if(FLASH_ErasePage(0x8000000 + i * PAGE_SIZE) != FLASH_COMPLETE)
                                        {
                                                FLASH_Lock();
                                                NVIC_SystemReset_Boot();
                                        }
                                }
                                FLASH_Lock();
                                lubTaskID = 3;
                        }
                        else
                        {
                                lubTaskID = 6;
                        }
                        break;
                }
                case 3:
                {
                        if( sProgramFlashFromUpdateFile() )
                        {
                                lubTaskID = 4;
                        }
                        else
                        {
                                lubTaskID = 3;
                        }
                        break;
                }
                case 4:
                {
                        if( sOpenUpdateFile2(cAppFileName2String) )
                        {
                                lulDataAddr = cAppSecondAddr;
                                lubTaskID = 5;
                        }
                        else
                        {
                                FLASH_Unlock();
                                FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR | FLASH_FLAG_BSY);
                                for(i = PAGE_START; i < PAGE_NUM; i++)
                                {
                                        if(FLASH_ErasePage(0x8000000 + i * PAGE_SIZE) != FLASH_COMPLETE)
                                        {
                                                FLASH_Lock();
                                                NVIC_SystemReset_Boot();
                                        }
                                }
                                FLASH_Lock();
                                NVIC_SystemReset_Boot();
                        }
                        break;
                }
                case 5:
                {
                        if( sProgramFlashFromUpdateFile() )
                        {
                                lulDataAddr = cAppAddress;
                                FLASH_Unlock();
                                FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR | FLASH_FLAG_BSY);
                                for(i = 0;i < 0x40;i++)
                                {
                                        lulData  = (INT32U)lubFirstAppData[4 * i + 3] << 24;
                                        lulData += (INT32U)lubFirstAppData[4 * i + 2] << 16;
                                        lulData += (INT32U)lubFirstAppData[4 * i + 1] << 8;
                                        lulData += (INT32U)lubFirstAppData[4 * i];                               
                                        lubFaultCnt = 0;                               
                                        while(FLASH_ProgramWord(lulDataAddr,lulData) != FLASH_COMPLETE)
                                        {
                                                if(++lubFaultCnt >= 5)
                                                {
                                                        FLASH_Lock();
                                                        NVIC_SystemReset_Boot();
                                                }
                                        }
                                        lulDataAddr += 4;
                                }
                                FLASH_Lock();
                                NVIC_SystemReset_Boot();
                        }
                        lubTaskID = 5;
                        break;
                }
                case 6:
                {
                        sDeleteFileSystem();
                        lubRecv = 0;
                        break;
                }
                default:
                        break;
        }
       
        return (lubRecv);
}

IAP实现步骤描述具体为:
第一步:SPI和TF卡初始化,并创建文件系统;
第二步:扫描判断TF卡内是否存在待升级文件(BIN格式);
第三步:打开升级文件,并擦除用户区FLASH;
第四步:读取升级文件内容,烧录到用户区FLASH内;
第五步:烧录完成关闭文件系统;
第六步:跳转到用户区FLASH内运行;

第一次整理,各位见谅描述的可能粗糙了。
沙发
cybers| | 2017-3-17 18:01 | 只看该作者
谢谢楼主分享!我先保存着,有时间研究下

使用特权

评论回复
板凳
cybers| | 2017-3-17 18:15 | 只看该作者
有一部分看不明白,有待研究

使用特权

评论回复
地板
hudi008| | 2017-3-17 21:38 | 只看该作者
这个竟然能够外部升级程序。

使用特权

评论回复
5
hudi008| | 2017-3-17 21:42 | 只看该作者
有使用蓝牙升级程序的吗?

使用特权

评论回复
6
yklstudent|  楼主 | 2017-3-18 10:08 | 只看该作者
hudi008 发表于 2017-3-17 21:42
有使用蓝牙升级程序的吗?

你用串口转蓝牙模块,搞定数据收发后;你要有配套的软件,都可以实现你想实现的功能

使用特权

评论回复
7
yongwong99| | 2017-4-8 21:45 | 只看该作者
mark!

使用特权

评论回复
8
ghuca| | 2017-4-8 23:16 | 只看该作者
TF卡直接升级程序,厉害。

使用特权

评论回复
9
ghuca| | 2017-4-8 23:17 | 只看该作者
这个最好能够通过TF插入直接升级,省了串口下载了。

使用特权

评论回复
10
minzisc| | 2017-4-9 17:08 | 只看该作者
看到有人实现了离线下载了。

使用特权

评论回复
11
minzisc| | 2017-4-9 17:11 | 只看该作者
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:本人熟悉STM32、PIC、AVR等嵌入式软件开发;联系方式:524716771.

39

主题

3256

帖子

22

粉丝