大神驾到 发表于 2022-7-17 20:55:10

【开源】对迪文屏的数据文件实现在线升级的一种方法

背景:
目前迪文屏升级一共有两种方式:插卡和上位机通过串口升级,两者不足之处有 :1、批量生产升级效率慢且繁琐(当升级时,每个设备需要单独去插卡或者用电脑上位机升级) ,并且增加了人工成本。2、自己的项目中无法实现对迪文屏在线升级(当产品已发出需要修复BUG时,无法在线修复)。3、无法判断新老版本(当数据文件没有变化时执行了重复升级)。
设计:
基于以上不足,通过在自己的项目中嵌套一种方法实现对迪文屏数据文件的升级,弥补以上的不足。

实现效果的视频链接 https://b23.tv/3jOTtOW
https://www.bilibili.com/video/BV1c34y1n7ya/
以下是部分实现流程,具体请点击下载项目工程进行参考

/**
@brief获取norflash和本地文件夹的版本号以及通过文件名称前面的序号计算出外部flash更新的以32K BYTE为单位的地址
@parampUpgradeDgusUpgradeDgus_t 结构体指针
@return 无
*/
void get_VersionAnd32KByteAddr_ByFileName(UpgradeDgus_t *pUpgradeDgus)
{
      int i=0;
      uint8_t fileBuff;
      uint8_t readNorFlashBuff;
      char *pstr=NULL;
      char *str=NULL;
      char numStr;
      memset(numStr,0,sizeof(numStr));
      
      for(i=0;i<2;i++)//取文件序号
      {
                if(pUpgradeDgus->File<=0x39&&pUpgradeDgus->File>=0x30)
                {
                        numStr = pUpgradeDgus->File;
                }
      }
      
      pUpgradeDgus->addrTo32KBytes = atoi(numStr);
      
      pUpgradeDgus->addrTo32KBytes*=256;
      pUpgradeDgus->addrTo32KBytes/=32;//计算要存放外部flash的位置
      
      pstr = strstr(pUpgradeDgus->File,USER_DEFINE_VERSION_KEY_WORD);
      str = strstr(pUpgradeDgus->File,".");
      if(str!=NULL&&pstr!=NULL)
      {
                strncpy(pUpgradeDgus->CurrVer,pstr,str-pstr);
      }
      readDgusNorFlash_ByAddr(DGUS_USER_RAM_ADDR,DGUS_NOR_FLASH_ADDR,DGUS_USER_DEFINE_VERSION_NORFLASH_SIZE/2);//从NorFlash中读老版本到DGUS RAM
      Dgus_Dealyms(100);
      readDgusRam_ByAddr(DGUS_USER_RAM_ADDR,readNorFlashBuff,DGUS_USER_DEFINE_VERSION_NORFLASH_SIZE);//从DGUS RAM取出数据
      
      //下面主要是取版本号的操作
      if(strstr((char *)readNorFlashBuff,pstr)==NULL)
      {
                memset(fileBuff,0,sizeof(fileBuff));
                pstr = strstr(pUpgradeDgus->File,USER_DEFINE_VERSION_KEY_WORD);
                strncpy((char *)fileBuff,pUpgradeDgus->File,pstr - pUpgradeDgus->File);
                strcat((char *)fileBuff,USER_DEFINE_VERSION_KEY_WORD);
                pstr = strstr((char *)readNorFlashBuff,(char *)fileBuff);
                if(pstr!=NULL)
                {
                        str = (char *)readNorFlashBuff + (pstr - (char *)readNorFlashBuff);
                        pstr = strstr(str,".");
                        memset(fileBuff,0,sizeof(fileBuff));
                        if(pstr!=NULL)
                        {
                              strncpy((char *)fileBuff,str,pstr-str);
                              pstr = strstr((char *)fileBuff,USER_DEFINE_VERSION_KEY_WORD);
                              if(pstr!=NULL)
                              {
                                        strcpy(pUpgradeDgus->LasTVer,pstr);
                              }                              
                        }      
                }
                else
                {
                        strcpy(pUpgradeDgus->LasTVer," ");
                }
      }
      else
      {
                pstr = strstr((char *)readNorFlashBuff,pUpgradeDgus->File);
                if(pstr!=NULL)
                {
                        str = (char *)readNorFlashBuff + (pstr - (char *)readNorFlashBuff);
                        pstr = strstr(str,".");
                        memset(fileBuff,0,sizeof(fileBuff));
                        if(pstr!=NULL)
                        {
                              strncpy((char *)fileBuff,str,pstr-str);
                              pstr = strstr((char *)fileBuff,USER_DEFINE_VERSION_KEY_WORD);
                              if(pstr!=NULL)
                              {
                                        strcpy(pUpgradeDgus->LasTVer,pstr);
                              }                              
                        }      
                }               
      }
}

/**   
@brief将一个文件升级到DGUS 外部FLASH指定位置
pUpgradeDgusUpgradeDgus_t 结构体指针
@return false / true
*/
bool upgradeFiles(UpgradeDgus_t *pUpgradeDgus)
{
      FIL dgusFile;
      FRESULT uRet;
      char filePath;
      UINT br;
      uint16_t addrTo32KBytes=0;
      uint8_t readBuff;
      memset(filePath,0,sizeof(filePath));
      strcpy(filePath,DWIN_SET_PASTH);
      strcat(filePath,pUpgradeDgus->File);
      uRet = f_open(&dgusFile,filePath,FA_READ);
      
      addrTo32KBytes = pUpgradeDgus->addrTo32KBytes;
      if(!uRet)
      {
                        DGUS_ShowStrDesctibe_t Desctibe;
                        Desctibe.textAddr = 0x1800;
                        Desctibe.textColor = 0x00;
                        Desctibe.font0Id=0;
                        Desctibe.font1Id=7;
                        Desctibe.fontXDots = 24;
                        Desctibe.fontYDots = 26;
                        Desctibe.encodeMode = 0xC0; //居中对齐,8bit编码
                        Desctibe.HorDis=2;
                        Desctibe.VerDis=1;
                        show_StrInit(&Desctibe,0x8000);
                        show_StrByAddr(Desctibe.textAddr,filePath,100);
               
                        while(1)
                        {
                              memset(readBuff,0,sizeof(readBuff));
                              uRet = f_read(&dgusFile,readBuff,sizeof(readBuff),&br);
                              
                              if(!uRet)
                              {
                                        writeDgusRam_ByAddr(DGUS_USER_RAM_ADDR,(uint8_t *)readBuff,sizeof(readBuff));
                                        writeDgussFlash_ByAddr(DGUS_USER_RAM_ADDR,addrTo32KBytes,5);
                                        addrTo32KBytes++;
                                        if(br<sizeof(readBuff))
                                                break;
                              }
                              else
                              {
                                        return false;
                              }
                        }
                        return true;
      }
      return false;
}

/**
@brief升级DGUS除内核以外的所有数据文件
@paramdgusFilePathDWIN_SET的路径
@return 无
*/
void upgradeDgusFiles(char* dgusFilePath)
{
      int i=0;
      char *pstr=NULL;
      uint16_t isUpgradeCount=0;
      uint16_t okFileCount=0;
      uint16_t Len=0;
      uint16_t outPathLen=0;
      char strBuff;
      char outFileBuff;
      char fileVersionBuff;
      uint16_t fileNum=0;
      memset(outFileBuff,0,sizeof(outFileBuff));
      get_DgusDirsFileName(dgusFilePath,outFileBuff,&fileNum);
      
      outPathLen=0;
      okFileCount=0;
      for(i=0;i<fileNum;i++)
      {
                Len=strlen(outFileBuff+outPathLen)+1;
                strcpy(UpgradeDgus.File,outFileBuff+outPathLen);
                outPathLen+=Len;
               
                if(checkFileName(UpgradeDgus.File))
                        okFileCount++;
      }
      
      for(i=0;i<okFileCount;i++)
      {
                get_VersionAnd32KByteAddr_ByFileName(&UpgradeDgus);
      }
      
      isUpgradeCount=0;
      memset(fileVersionBuff,0,sizeof(fileVersionBuff));
      for(i=0;i<okFileCount;i++)
      {
                if(strcmp(UpgradeDgus.CurrVer,UpgradeDgus.LasTVer)!=0)
                {
                        //需要升级
                        show_JumpPageById(0x0001);      
                        strcat(fileVersionBuff,UpgradeDgus.File);
                        upgradeFiles(&UpgradeDgus);
                        isUpgradeCount++;
                }
                else
                {
                        memset(strBuff,0,sizeof(strBuff));
                        pstr =strstr(UpgradeDgus.File,USER_DEFINE_VERSION_KEY_WORD);
                        strncpy(strBuff,UpgradeDgus.File,pstr - UpgradeDgus.File );
                        strcat(strBuff,UpgradeDgus.LasTVer);
                        strcat(strBuff,strstr(UpgradeDgus.File,"."));
                        strcat(fileVersionBuff,strBuff);
                }
      }
      
      if(isUpgradeCount!=0)
      {
                writeDgusRam_ByAddr(DGUS_USER_RAM_ADDR,(uint8_t *)fileVersionBuff,DGUS_USER_DEFINE_VERSION_NORFLASH_SIZE);
                writeDgusNorFlash_ByAddr(DGUS_USER_RAM_ADDR,DGUS_NOR_FLASH_ADDR,DGUS_USER_DEFINE_VERSION_NORFLASH_SIZE);
                Dgus_Dealyms(100);
                resetDgus();//复位Dgus
                Dgus_Dealyms(DGUS_RESET_DELAY);
                NVIC_SystemReset();//mcu复位
      }
      else
      {
                        show_JumpPageById(0x0001);      
                        DGUS_ShowStrDesctibe_t Desctibe;
                        Desctibe.textAddr = 0x1800;
                        Desctibe.textColor = 0x00;
                        Desctibe.font0Id=0;
                        Desctibe.font1Id=7;
                        Desctibe.fontXDots = 24;
                        Desctibe.fontYDots = 26;
                        Desctibe.encodeMode = 0xC0; //居中对齐,8bit编码
                        Desctibe.HorDis=2;
                        Desctibe.VerDis=1;
                        show_StrInit(&Desctibe,0x8000);
                        show_StrByAddr(Desctibe.textAddr,"No files need to be upgraded",100);               
      }
}





wangyuxiang 发表于 2022-7-18 10:04:29

感谢楼主分享,赞一个

DWIN_LZ 发表于 2022-7-18 10:04:37

非常不错,顶一个!

long-------- 发表于 2022-7-18 10:28:02

感谢楼主分享

15231197670 发表于 2022-7-18 10:55:50

感谢楼主分享

大神驾到 发表于 2022-7-18 16:17:59

后续测试发现有丢数据的现象,原因在于写的时候没有延时,因此需要改动一下
                                        writeDgusRam_ByAddr(DGUS_USER_RAM_ADDR,(uint8_t *)readBuff,sizeof(readBuff));
                                        writeDgussFlash_ByAddr(DGUS_USER_RAM_ADDR,addrTo32KBytes,50);
                                        Dgus_Dealyms(50);这几段代码改成这样就好了

大神驾到 发表于 2022-7-18 16:28:53

其实最严谨的做法应该把已经写入迪文屏外部flash中的数据以32K BYTE为单位再读回来与写入的数据做一下比较或者开启CRC校验,但是这样会影响会影响升级的速度

大神驾到 发表于 2022-7-18 21:26:50

helloworld 发表于 2022-7-18 10:04
感谢分享

大家一起共同进步{:2_31:}

大神驾到 发表于 2022-7-18 21:28:40

DWIN_LZ 发表于 2022-7-18 10:04
非常不错,顶一个!

{:3_52:}感谢支持

大神驾到 发表于 2022-7-18 21:30:05

wangyuxiang 发表于 2022-7-18 10:04
感谢楼主分享,赞一个

感谢宝子们的支持
页: [1] 2 3
查看完整版本: 【开源】对迪文屏的数据文件实现在线升级的一种方法