解决stm32f103的flash写出错、升级一半就会失败问题

项目中使用stm32f407与stm32f103通过I2C升级。

STM32F407作为主机,外接4个从机103,根据地址的不同进行升级。

本人发现在测试中,利用stm32自带的硬件I2C功能进行升级。

过程中发现,407能与103正常通信,但是由于升级数据比较大,写到%10随机的一个数据后,就会报错,经单步调试发现,

写进去的数据跟读出来的数据不一样,再判断发现根本没写进flash里去。flash_unlock();也启用了,但是仍旧有这个问题。

一直以为是STM32自身的I2C有问题,但实际上发现,链路是通的,103的确可以收到数据。虽然众多网友反映它的I2C不好使,但在升级这里还是可以的。

排除I2C链路造成的干扰,还是把重点放在写flash这一块。


之前也做过写flash作为用户数据,保存一些少量的数据作为掉电不丢失来用,只要flash地址没有被占用,读写保存数据还是可以用的。

那问题出在哪里?

公布一点源码

这是升级的分析函数

u8 buffer[270];

void arm_update_handler(unsigned char * receive,unsigned char * transfer)
{
    uint16_t PageSize = PAGE_SIZE;
    uint32_t RamSource;
    int ret, EraseCounter, j;
       memcpy(buffer,receive,270);(后来添加原来这里的指针溢出,开辟一个空间解决问题)
    switch (buffer,receive[11])
    {
    case PREPARE:
        TPI_EDID_PRINT("PREPARE\n");
        update_state = UPDATE_OK;
        break;
        
    case  ERASE ://擦除应用包程序
        update_state = UPDATE_BUSY;
        FlashDestination = ApplicationAddress;
        
        for (EraseCounter = 0; EraseCounter < NBROFPAGE; EraseCounter++)
        {
            ret = FLASH_ErasePage(FlashDestination + (PageSize * EraseCounter));
            if(ret != FLASH_COMPLETE)
            {
                update_state = UPDATE_ERROR;
                return;
            }
        }
        
        update_state = UPDATE_OK;
        
        break;
        
    case  WRITE_BLOCK0:
        update_state = UPDATE_BUSY;
        TPI_EDID_PRINT("WRITE_BLOCK0\n");
   
      //  RamSource = (uint32_t)&receive[12];//不能使用这种指针方式来升级,因为数据过大,内存溢出的话  数据就会出错
        
          RamSource = (uint32_t)&buffer[12];//必须用这种数组的方式  
        for (j = 0;(j < PACKETLEN) && (FlashDestination <  0x803ffff); j += 4)
        {
            /* Program the data received into STM32F10x Flash */
            FLASH_ProgramWord(FlashDestination, *(uint32_t*)RamSource);//烧写4个字节
          
             if (*(uint32_t*)FlashDestination != *(uint32_t*)RamSource)
            {//判断读出来的数据是否一样
                /* End session */
             FlashDestination = ApplicationAddress;
               update_state = UPDATE_ERROR;
               return;
            }
            FlashDestination += 4;
            RamSource += 4;
        }
        update_state=UPDATE_OK;
        break;
        
    case  WRITE_CONTINUE_BLOCK:
        update_state = UPDATE_BUSY;
   
     //   RamSource = (uint32_t)&receive[12];// receive 是一个指针    这里的I2C   buffe竟然开辟了512个字节 其实用不了r
          RamSource = (uint32_t)&buffer[12];
        for (j = 0; (j < PACKETLEN) && (FlashDestination <  0x0803ffff); j += 4)
        {
            /* Program the data received into STM32F10x Flash */
            FLASH_ProgramWord(FlashDestination, *(uint32_t*)RamSource);
            //  Delay_ms(1);
            tempdata=*(uint32_t*)RamSource;
            tempdata2=*(uint32_t*)FlashDestination;
            if (tempdata2 != tempdata)        
            {
        /*       FLASH_ErasePage(FlashDestination);
             
               FLASH_ProgramWord(FlashDestination, *(uint32_t*)RamSource);
             // Delay_ms(5);
              */
           //  if (*(uint32_t*)FlashDestination != *(uint32_t*)RamSource)        
            {
                
                FlashDestination = ApplicationAddress;
               update_state = UPDATE_ERROR;
              return;
            }
            }
          
            FlashDestination += 4;
            RamSource += 4;
        }
        update_state = UPDATE_OK;
        break;
        
    case  END:
        update_state = UPDATE_BUSY;
        TPI_EDID_PRINT("END\n");
        FlashDestination = ApplicationAddress;             
        
        update_state = UPDATE_OK;
        Delay_ms(1000);
        
        JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
        
        /* Jump to user application */
        Jump_To_Application = (pFunction) JumpAddress;
        /* Initialize user application's Stack Pointer */
        __set_MSP(*(__IO uint32_t*) ApplicationAddress);
        Jump_To_Application();
        

        break;
        
    default:
        break;
    }
}
经过上述描述,是由于I2C的内存开的过大。而这里使用一个 未知的* receive 做指针,并靠它来读取数据导致失败。将有用到的数据copy到一个已知的静态buffer里,这样的他的地址其实就已经固定了,不会乱套。

sitemap