GD32F4替代STM32F4注意事项

  • 前言
  • 一、开发环境
  • 二、移植步骤
    • 1.安装GD的支持包。
    • 2.修改32固件库的时钟
    • 3.FLASH修改
      • 3.1 F1的处理
      • 3.2 F4的Flash修改
    • 4.其他修改
      • 4.1 函数中的变量定义
      • 4.2 串口发送
      • 4.3 中断服务函数中不能有printf
  • 总结

前言

近期在项目中采用了GD32F407VET6替换原项目中的STM32F407VET6,网传GD的兼容性很好,之前也用F1系统的替换了一下,按照CSND各位大佬的经验一步步改进了代码,测试直接通过,现在也一直在项目中实际应用了,一直没有出问题。
所以这SMT时,嘉立创没有STM的货果断换成了GD,可换时简单,到手之后,搜索了一大圈,并没有发现F4像F1一样有大把的经验可以抄。可能是我的搜索水平有限;也有可能是F4相较于F1,其成本优势并没有比F1强很多,替换的人就少了。
还好经过几天的摸索还是搞定了F4的程序替换,下面就个人经验分享给大家,提前声明一下,个人经验有限,本文只阐述本人的开发过程,目前程序运行正常,如果有其他不兼容的地方,还请各位网友自行解决。
另外,如果你是新开发程序,还是建议采用GD的库,毕竟原厂的库更有保障,我这里是因为程序都开发完成了,再移植到GD的库中,很多地方都有修改。

一、开发环境

本人使用Keil5,编写的程序,其他开发环境如:IAR等,可参考修改。工程模板及大部分驱动代码借鉴正点原子F4系列。

二、移植步骤

1.安装GD的支持包。

GD的程序芯片可以选择STM32的替代,但是烧录的时候Flash必须选择GD的,所以安装支持包是必须的。
官网pack包下载链接:https://www.keil.com/dd2/pack/
1.进入KEIL官网下载pack包(链接 **https://www.keil.com/dd2/pack/)


2.找到GigaDevice -> GD32F4xx pack包 -> 点击下载,等待下载完成。

3. 下载完成后,点击安装包,默认安装就好了。
4. 安装完成之后可以打开工程文件,点击魔术棒\Device ,选择对应的GD的芯片就可以了。

注意:重选芯片,会让工程的代码起始位置和大小变成默认值,如果你的程序有OTA或者其他更改程序起始位置和大小的设计,请自行在Target中修改。

5.然后 点击魔术棒\Debug\Settings\Flash Download\Add,如果看到下图这个GD的Flash就ok了。

还有,代码的起始位置和大小,按照自己的程序来改,没有修改就默认即可,我这里是BootLoader程序,所以程序大小就比默认的小很多。

6. 完成上面的操作之后就重新编译一下工程即可。

2.修改32固件库的时钟

在V3.x的库,启动时间宏定义在xxx32f10x.h头文件中;在V3.0以前的库,其启动时间宏定义在xxx32f10x_rcc.c中(HSEStartUp_TimeOut)。搜索一下就找到了。

//修改前:
#define HSE_STARTUP_TIMEOUT    ((uint16_t)0x05000)   /*!< Time out for HSE start up */
//修改后:
#define HSE_STARTUP_TIMEOUT    ((uint16_t)0xFFFF)   /*!< Time out for HSE start up */

GD和STM32的晶振部分电路设计存在一定的差异,修改HSE_STARTUP_TIMEOUT宏定义可以保证晶振能够正常起振。

3.FLASH修改

由于GD的Flash采用了其专利技术,所以GD 的Flash 和STM 的Flash 有些许差异。GD 的擦除时间会一些。对于Falsh的移植要重视,如果程序中有对FLASH的操作(主要是写Flash),则应该进行修改。
这里我们参考F1系列的修改。

3.1 F1的处理

在F1的移植中需要对4个函数进行修改

FLASH_Status FLASH_EraseOptionBytes(void)
FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data)
FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages)
FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState)

上面这个这四个函数里面都有下面这一句代码:

key( FLASH->OPTKEYR = FLASH_KEY1;FLASH->OPTKEYR = FLASH_KEY2;)

在以上4个函数中在写完KEY 序列以后,需要读该位,确认key 已生效。所以我们在这里应该插入
While( ! (FLASH->CR & 0x200 ) ); // Wait OPTWRE 或可简单插入两个NOP。
比如,改成以下这样。

/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
while( ! (FLASH->CR & 0x200 ) );// Wait OPTWRE

或者

/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
__NOP();
__NOP();

3.2 F4的Flash修改

由于我代码里对Flash的操作使用的是正点原子的驱动文件,并未使用ST官方库函数stm32f4xx_flash.c,尝试搜索key( FLASH->OPTKEYR = FLASH_KEY1;FLASH->OPTKEYR = FLASH_KEY2;),并无匹配项,于是尝试搜索FLASH_KEY1,这时匹配到下面那个函数:

//解锁STM32的FLASH
void STMFLASH_Unlock(void)
{FLASH->KEYR=FLASH_KEY1;    //写入解锁序列.FLASH->KEYR=FLASH_KEY2;
}

于是便在其后面加了一个延时查询指令:while( ! (FLASH->CR & 0x200 ) );// Wait OPTWRE
但在后面的测试中,发现有较大概率会卡死在这个while循环中,于是只能采取加两个空延时的方式实现,具体是什么问题暂时还没有查出来。目前该函数改成以下这样:

//解锁STM32的FLASH
void STMFLASH_Unlock(void)
{FLASH->KEYR=FLASH_KEY1;    //写入解锁序列.FLASH->KEYR=FLASH_KEY2; __NOP();__NOP();
//  while(!(FLASH->CR & 0x200));// Wait OPTWRE
}

此外在F1的帖子里,提到GD的延时时间比ST的短,出于保险起见,我在flash的操作中也延长了其等待时间,其函数的等待因为是可以break循环而提前退出,所以我也不知道这部分代码是否起到作用,但是加上应该不会有问题。我是将STMFLASH_WaitDone这个函数的参数扩大为原来的2倍,修改的函数如下:

//擦除扇区
//sectoraddr:扇区地址,范围是:0~11.
//0~3,16K扇区;4,64K扇区;5~11,128K扇区.
//返回值:执行情况
u8 STMFLASH_EraseSector(u32 sectoraddr)
{u8 res=0;//res=STMFLASH_WaitDone(200000);//等待上次操作结束,最大2sres=STMFLASH_WaitDone(400000);//等待上次操作结束,最大2sif(res==0){ FLASH->CR&=~(3<<8);    //清除PSIZE原来的设置FLASH->CR|=2<<8;    //设置为32bit宽,确保VCC=2.7~3.6V之间!!FLASH->CR&=~(0X1F<<3);//清除原来的设置FLASH->CR|=sectoraddr<<3;//设置要擦除的扇区 FLASH->CR|=1<<1;    //扇区擦除 FLASH->CR|=1<<16;  //开始擦除        //res=STMFLASH_WaitDone(200000);//等待上次操作结束,最大2sres=STMFLASH_WaitDone(400000);//等待操作结束,最大2s  if(res!=1)         //非忙{FLASH->CR&=~(1<<1);//清除扇区擦除标志.}}return res;
}
//在FLASH指定地址写一个字
//faddr:指定地址(此地址必须为4的倍数!!)
//dat:要写入的数据
//返回值:0,写入成功
//    其他,写入失败
u8 STMFLASH_WriteWord(u32 faddr, u32 dat)
{u8 res;          //res=STMFLASH_WaitDone(0xFF);res=STMFLASH_WaitDone(0X200);if(res==0)//OK{FLASH->CR&=~(3<<8);   //清除PSIZE原来的设置FLASH->CR|=2<<8;    //设置为32bit宽,确保VCC=2.7~3.6V之间!!FLASH->CR|=1<<0;   //编程使能*(vu32*)faddr=dat;   //写入数据//res=STMFLASH_WaitDone(0XFF);//等待操作完成,一个字编程,最多100us.res=STMFLASH_WaitDone(0X200);//等待操作完成,一个字编程,最多100us.//0xffif(res!=1)//操作成功{FLASH->CR&=~(1<<0);//清除PG位.}} return res;
}

4.其他修改

本来我以为修改以上几点就可以完美兼容代码,可现实给我一个大大的教训,现在想来可能是GD的芯片代码要更加规范,所以如果移植出问题了,可能要在代码的规范上重视。
还有就是GD的MCU和ST的相比在连续串口发送的时候会多一个IDLE bit,但是在F1中,这个差异对于大多数程序并不影响执行,所以就没有重视这个问题。

4.1 函数中的变量定义

在函数中的变量必须先定义,再进行其他操作,当我的芯片改为GD之后,keil编译一遍程序之后,出现了几个报错,百度了一下,发现就是有一个变量的声明在函数的中间,将其声明改到函数前面之后就正常了。

4.2 串口发送

在串口发送数据时,要先发送再等待相应的标志位变化,如果先查询标志位那么程序就会一直在这个while循环中运行,直到我的看门狗将程序复位。
比如,我修改前的串口3发送代码如下:

/*-------------------------------------------------*/
/*函数名:串口3发送缓冲区中的数据                  */
/*参  数:data:数据                               */
/*返回值:无                                       */
/*-------------------------------------------------*/
void u3_TxData(unsigned char *data)
{int    i;  while((USART3->SR&0X40)==0);for(i = 1;i <= data[0];i ++){           USART3->DR = data[i];while((USART3->SR&0X40)==0);  }
}

修改之后为,就正常了。

/*-------------------------------------------------*/
/*函数名:串口3发送缓冲区中的数据                  */
/*参  数:data:数据                               */
/*返回值:无                                       */
/*-------------------------------------------------*/
void u3_TxData(unsigned char *data)
{int    i;
//  while((USART3->SR&0X40)==0);for(i = 1;i <= data[0];i ++){
//      USART3->DR = data[i];
//      while((USART3->SR&0X40)==0);   USART_SendData(USART3,data[i]);while( USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET );}
}

4.3 中断服务函数中不能有printf

其实这个问题,是大部分做单片机开发的一个常识,这个是我之前在ST调试时留下的一条调试信息,只输出了一个数字,(因为我也知道中断中最好不能printf),在ST中正常,后面程序就忘了删,就埋了一个雷,浪费了许多时间。
这也是我说GD的代码要规范的原因,可能他的容错性还是低于ST的,还有其他的例子,但是我一时想不起来了,只能把我记得的bug写出来,以后调试出现问题,要着重查查代码规范性。


总结

以上就是我在移植中的一个小小记录,也可以给大家一个参考。

GD32F4移植STM32F4相关推荐

  1. RTX 移植STM32F4之基础配置

    RTX_Config_CM.c 在使用RTX的嵌入式应用程序中,必须先对RTX内核进行基础配置 配置选项如下: 1.指定当前运行任务的数目,即除停止状态以外的其他状态的总数,如,运行.挂起或就绪. 关 ...

  2. 基于STM32F4移植W5500官方驱动库ioLibrary_Driver(转)

    源: 基于STM32F4移植W5500官方驱动库ioLibrary_Driver 参考: 基于STM32+W5500 的Ethernet和Internet移植 Upgrade W5500 Throug ...

  3. 文件系统应用笔记之一:FatFS在STM32F4上的移植

      在实现如U盘文件读写,SD卡的文件读写等工作时,我们往往需要一个文件系统来支持我们的工作.特别在一些MCU应用中,文件系统的加入能明显改善系统交互的友好性.在这一篇中,我们就来讨论FatFS文件系 ...

  4. 基于STM32F4的CANOpen移植教程(超级详细)

    CANopen移植到STM32F4平台 前言 1 物品准备 2 相关软件安装 2.1 CAN上位机 2.2 对象字典生成工具objdictedit环境配置 3 将CANopen移植到STM32F407 ...

  5. STM32F4+FreeRTOS+FreeRTosTcpIp移植教程

    花了几天时间完成了FreeRTOS自带的TCP/IP协议栈在stm32F407上的移植,在此记录并分享,第一次写这个,写的不好的地方见谅. 硬件是stm32F407最小系统(内带phy控制器),所以还 ...

  6. 从零开始创建GD32F4系列单片机工程模板移植涂鸦MCU-SDK

    从零开始创建GD32F4系列单片机工程模板&移植涂鸦MCU-SDK  兆易创新的GD32单片机在中国MCU厂商市场中一直有着不算太小的份额.最近由于ST系列单片机的大幅度涨价,国产MCU凭借价 ...

  7. STM32F4基础工程移植FreeRTOS

    本篇目标:基于上一篇的基础工程(stm32f4_first_demo)上,移植freertos,建立移植工程(stm32f4_freertos). 资料准备: Freertos源文件 最后工程:项目工 ...

  8. lua移植到STM32F4全过程

    基于之前了解到的Lua脚本开发功能,尝试过多次都没有很认真的做到底.之前的尝试都没能很好的应用到自己的工程里. elua东西太多并且是在linux下编译的,我很不适应,当然liunx涉及的不深. 本次 ...

  9. MPU6050(读取原数据、移植DMP、stm32f4、HAL库、KEIL5)

    记录一下自己遇到的问题及解决方法,希望能帮助到一些人. 第一步,读取芯片的原始数据.需要注意两点:1.对HAL库提供的IIC读取写入函数进行再包装.(千万不要觉的这步多此一举,后面移植DMP时用得到) ...

最新文章

  1. laravel ajax vue6,详解用vue.js和laravel实现微信支付
  2. 数据结构 排序(希尔排序)
  3. linux php ldap扩展,php_ldap域集成模块安装-159
  4. UVa11100 The Trip,2007(贪心)
  5. Andriod 测试 day1​andriod 工具介绍
  6. 微信能远程控制电脑吗_牛皮!微信远程控制电脑这个神器太厉害了!
  7. linux网卡口闪烁,LINUX 下网卡口绑定整理
  8. DOM-13 【实战】输入及状态改变事件、京东搜索框
  9. ubuntu20.10上搭建hadoop3.2.2伪分布式
  10. mysql Innodb参数配置
  11. 修改npm安装的全局路径和配置环境变量的坑
  12. 【交换机】配置RNStrack的功能原理是什么?
  13. 报表性能优化方案之多种报表服务器内存修改方法
  14. linux 进程的pid分配策略——pid位图算法
  15. 免费的数据恢复软件 恢复丢失的数据
  16. bzoj 1603 打谷机
  17. 使用MCT6.0工具和fontconver制作MTK字库文件
  18. 29 岁成为阿里巴巴 P8,工作前 5 年完成晋升 3 连跳,他如何做到?
  19. OFDM系统中的信号检测算法分类和详解
  20. C++面向对象小练习:几何图形类

热门文章

  1. RS232/RS485的关系与区别
  2. 前端-解除事件的绑定
  3. Python — 爬取饿了么外卖店信息
  4. 字节面试复盘:大厂究竟会问些什么呢?
  5. 苏春园:跟车品觉老师吃了顿早茶,让我明白了什么是数据的本质
  6. 如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧
  7. 前端自学笔记(五)ES6 - (1)
  8. 东华大学计算机学院推免生面试难吗,东华大学接收推免生复试与录取办法
  9. Flutter——在Android平台上的启动流程浅析
  10. 传感器课程作业 车载激光雷达