1.说到OTA功能,实际上 往flash 指定区域写 数据, 拷贝数据,然后 跳转, 必要时 注意单片机的偏移量。
2.不多说废话,进入正题,区别这两款 单片机的在读写flash的 不同点. go
在写本文时,L233支持单字写入,而L235只有双字写入. 一个写入地址+4 一个写入地址+8
在单片机里面表示 大概是 address += sizeof(uint32_t) address += sizeof(uint64_t)
下面是写入flash 代码:
记得在写入前 擦除
cpp
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 //GD32L233
uint32_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 GD32L235
uint32_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去实现,看自己需求
cpp
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上的读取
cpp
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 )
cpp
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 //GD32L233
address += 4;
#endif
}
}