1.说到OTA功能,实际上 往flash 指定区域写 数据, 拷贝数据,然后 跳转, 必要时 注意单片机的偏移量。
2.不多说废话,进入正题,区别这两款 单片机的在读写flash的 不同点. go
在写本文时,L233支持单字写入,而L235只有双字写入. 一个写入地址+4 一个写入地址+8
在单片机里面表示 大概是 address += sizeof(uint32_t) address += sizeof(uint64_t)
下面是写入flash 代码:
记得在写入前 擦除
void fmc_flags_clear(void)
{fmc_flag_clear(FMC_FLAG_END);fmc_flag_clear(FMC_FLAG_WPERR);fmc_flag_clear(FMC_FLAG_PGAERR);fmc_flag_clear(FMC_FLAG_PGERR);
}
void WriteFlash(uint32_t address,const uint8_t *pBuffer,uint32_t Numlengh)
{#ifdef GD32E230 //GD32L233uint32_t i,temp;fmc_unlock();for(i = 0; i < Numlengh;i+= 4){temp = (uint32_t)pBuffer[i+3]<<24;temp |= (uint32_t)pBuffer[i+2]<<16;temp |= (uint32_t)pBuffer[i+1]<<8;temp |= (uint32_t)pBuffer[i];fmc_word_program(address+i,temp);fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR);}fmc_lock();#endif#ifdef GD32L235uint32_t i;uint32_t temp1,temp2;uint64_t temp_v;fmc_unlock();for(i = 0; i < Numlengh;i+=8){temp1 = (uint32_t)pBuffer[i+3]<<24;temp1 |= (uint32_t)pBuffer[i+2]<<16;temp1 |= (uint32_t)pBuffer[i+1]<<8;temp1 |= (uint32_t)pBuffer[i];temp2 = (uint32_t)pBuffer[i+7]<<24;temp2 |= (uint32_t)pBuffer[i+6]<<16;temp2 |= (uint32_t)pBuffer[i+5]<<8;temp2 |= (uint32_t)pBuffer[i+4];temp_v = ((uint64_t)temp2) << 32 | temp1;fmc_doubleword_program(address+i,temp_v);fmc_flags_clear();}fmc_lock();#endif
}
这个是 自己写的擦除一页 数据,当然可以参考 提供的demo去实现,看自己需求
uint8_t EarseFlash_1K(uint32_t address){//PR_INFO("begin_earse,0x%X\r\n",address);fmc_state_enum fmc_state;if(address % 1024 == 0){fmc_unlock();fmc_flags_clear();fmc_state = fmc_page_erase(address);if(fmc_state == FMC_READY){PR_INFO("erase_ok\r\n");}else{PR_ERR("erase_fail\r\n");}fmc_flags_clear();fmc_lock();}else{PR_NOTICE("without_EarseFlash_1K\r\n");return 0;}return 1;
}
接下来是 读取 双字,也就是在L235上的读取
void ReadFlashTwoWorld(uint32_t address,uint8_t *Nbuffer,uint32_t length){uint64_t temp = 0;uint32_t count = 0;while(count < length){temp = *((volatile uint64_t *)address);*Nbuffer++ = (temp & 0xff);count++;if(count >= length)break;*Nbuffer++ = (temp >> 8) & 0xff;count++;if(count >= length)break;*Nbuffer++ = (temp >> 16) & 0xff;count++;if(count >= length)break;*Nbuffer++ = (temp >> 24) & 0xff;count++;if(count >= length)break;*Nbuffer++ = (temp >> 32) & 0xff;count++;if(count >= length)break;*Nbuffer++ = (temp >> 40) & 0xff;count++;if(count >= length)break;*Nbuffer++ = (temp >> 48) & 0xff;count++;if(count >= length)break;*Nbuffer++ = (temp >> 56) & 0xff;count++;if(count >= length)break;address += sizeof(uint64_t);}
}
以及 下面的 读取单字的 ( GD32L233 以及 GD32E230 )
void ReadFlash(uint32_t address,uint8_t *Nbuffer,uint32_t length)
{uint32_t temp = 0;uint32_t count = 0;while(count < length){temp = *((volatile uint32_t *)address);*Nbuffer++ = (temp & 0xff);count++;if(count >= length)break;*Nbuffer++ = (temp >> 8) & 0xff;count++;if(count >= length)break;*Nbuffer++ = (temp >> 16) & 0xff;count++;if(count >= length)break;*Nbuffer++ = (temp >> 24) & 0xff;count++;if(count >= length)break;#ifdef GD32E230 //GD32L233address += 4;#endif}
}