【转】GD32芯片移植完全攻略

[复制链接]
4440|13
 楼主| sunmeat 发表于 2015-1-27 15:08 | 显示全部楼层 |阅读模式
GD32是国产兆易创新公司生产的完全兼容STM32系列的Cortex-M3处理器,具有几大亮点:
1,高主频108MHz。性能提升30%以上,可超频到120MHz
2,Flash零等待。STM32的72MHz需要两个等待,其实兆易创新公司本来就是做Flash起家的,具有gFlash专利
3,采用ARM Cortex-M3新内核R2p1。STM32采用R1p1,带有一些缺陷
4,性价比高。GD32比对应的STM32芯片一般便宜20%,某些芯片便宜30%以上

 楼主| sunmeat 发表于 2015-1-27 15:09 | 显示全部楼层
收到样片GD32F103VET6后,替换STM32F103VET6,写入最新版本TinyBooter和MF固件,以及MF测试例程,全部一次性通过!
兼容性非常好。
不过我们不能满足于此,MF固件默认跑在72MHz主频,Flash还是使用两个等待,我们需要测试更高速度!
于是根据官方的资料,修改主频为108MHz,Flash为零等待。
  1. RCC->CFGR |= (uint32_t)(0x08000000 | RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL12);
修改以后发现USB无法识别,串口一团糟!
上面是网上能找到的最多的资料,意思是HSE/2*(12+15),除以2和12都可以理解,15哪里冒出来的就实在不懂了。
 楼主| sunmeat 发表于 2015-1-27 15:10 | 显示全部楼层
请求官方技术支持,几分钟后得到邮件回复。
大意是108MHz无法分频得到USB所需要的48MHz,STM32本来支持1分频和1.5分配,然后GD32在这方面扩展了2分频和2.5分配。所以,如果想要使用USB,要么降频到96MHz,要么超频到120MHz,这样分别使用2分频和2.5分配即可得到USB所需要的48MHz。
这就说明GD32无法在标准108MHz下使用USB,好杯具!!!
 楼主| sunmeat 发表于 2015-1-27 15:10 | 显示全部楼层
另外,关于串口乱码的问题,给我的答复是修改RCC_GetClocksFreq函数:
  1. void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
  2. {
  3.   uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0;

  4.   /* Get SYSCLK source -------------------------------------------------------*/
  5.   tmp = RCC->CFGR & CFGR_SWS_Mask;

  6.   switch (tmp)
  7.   {
  8.     case 0x00:  /* HSI used as system clock */
  9.       RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
  10.       break;
  11.     case 0x04:  /* HSE used as system clock */
  12.       RCC_Clocks->SYSCLK_Frequency = HSE_VALUE;
  13.       break;
  14.     case 0x08:  /* PLL used as system clock */

  15.       /* Get PLL clock source and multiplication factor ----------------------*/
  16.       pllmull = RCC->CFGR &((uint32_t)0x203C0000);
  17.       pllsource = RCC->CFGR & CFGR_PLLSRC_Mask;
  18.       
  19.     if(((pllmull)&(0x20000000)) != 0)
  20.           pllmull = (((pllmull)&(0x003C0000)) >> 18) + 17;
  21.       else
  22.           pllmull = ( pllmull >> 18) +2;
  23.       
  24.       if (pllsource == 0x00)
  25.       {/* HSI oscillator clock divided by 2 selected as PLL clock entry */
  26.         RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
  27.       }
  28.       else
  29.       {
  30.         /* HSE selected as PLL clock entry */
  31.         if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (uint32_t)RESET)
  32.         {/* HSE oscillator clock divided by 2 */
  33.           RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull;
  34.         }
  35.         else
  36.         {
  37.           RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull;
  38.         }
  39.       }
  40.       break;
  41.     default:
  42.       RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
  43.       break;
  44.   }

  45.   /* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/
  46.   /* Get HCLK prescaler */
  47.   tmp = RCC->CFGR & CFGR_HPRE_Set_Mask;
  48.   tmp = tmp >> 4;
  49.   presc = APBAHBPrescTable[tmp];
  50.   /* HCLK clock frequency */
  51.   RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc;
  52.   /* Get PCLK1 prescaler */
  53.   tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
  54.   tmp = tmp >> 8;
  55.   presc = APBAHBPrescTable[tmp];
  56.   /* PCLK1 clock frequency */
  57.   RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
  58.   /* Get PCLK2 prescaler */
  59.   tmp = RCC->CFGR & CFGR_PPRE2_Set_Mask;
  60.   tmp = tmp >> 11;
  61.   presc = APBAHBPrescTable[tmp];
  62.   /* PCLK2 clock frequency */
  63.   RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
  64.   /* Get ADCCLK prescaler */
  65.   tmp = RCC->CFGR & CFGR_ADCPRE_Set_Mask;
  66. tmp = (tmp >> 14)+(tmp >> 26);
  67.   presc = ADCPrescTable[tmp];
  68.   /* ADCCLK clock frequency */
  69.   RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc;
  70. }
 楼主| sunmeat 发表于 2015-1-27 15:10 | 显示全部楼层
大概意思是判断一个标识位,如果有那个标识位,则采用另一条公式来计算倍频。暂时猜测那个标识位是GD32专用。
但是这样解决不了我的问题,我们的MF系统采用的是寄存器设定波特率,根本就没有使用库函数。我就想理清思路搞清楚这里为什么要这样修改,然后我依葫芦画瓢同样操作寄存器。结果我失败了,这里的17跟上面的15同样莫名其妙,不过+17比下面原来的+2刚好多了15,看来有什么关系。
 楼主| sunmeat 发表于 2015-1-27 15:11 | 显示全部楼层
就以0x20000000作为切入口,查看它在RCC->CFGR中的用途。
QQ截图20150127151119.png
果然是GD32专用,0x20000000是第29位保留位。
小飞觉得这一位跟前面的15有关,那么我们尝试把前面分频使用的0x08000000改为0x20000000试试
  1. RCC->CFGR |= (uint32_t)(0x20000000 | RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL12);
 楼主| sunmeat 发表于 2015-1-27 15:12 | 显示全部楼层
这个时候系统跑起来了,串口没有乱码,但是USB口不能使用,当然了,USB在108MHz不能用呀。
这样子算是解决了串口乱码这个问题。
 楼主| sunmeat 发表于 2015-1-27 15:12 | 显示全部楼层
但是有个非常奇怪的问题,Keil调试看到系统时钟是48MHz,通过寄存器换算也是,百思不得其解!
花哥提醒,Keil的RCC调试界面是为STM32准备的,看GD32的特殊频率可能不准。
其实关键就在于这个29位,由于它的存在,导致RCC_GetClocksFreq函数计算108MHz分频时忽略了29位,从而得到48MHz,也就是8M/2*12,那个15不见了。
因此,GD32新手需要修改RCC_GetClocksFreq是为了让频率计算结果为108MHz,从而解决串口乱码问题。而我用0x0800000分频的时候,MCU实际工作在48MHz,然后在串口那里计算波特率的时候,我使用了108MHz。两者犯了不同的错误,导致了相同的结果,然后歪打正着解决了这个问题。
之前很多人让我等比例换算频率,108M是72M的1.5倍,然后在波特率那里也这样算。但是我不服气,因为F407是168M,也是这个公式。
结论表明:串口乱码的关键是计算波特率的频率必须与实际MCU频率相符!
 楼主| sunmeat 发表于 2015-1-27 15:13 | 显示全部楼层
对于MF系统来说,不能使用USB是不可原谅的,于是我们测试96MHz和120MHz,分别12倍频和15倍频,USB分别2分频和2.5分频,非常好算!
通过Keil调试发现系统成功工作在96MHz和120MHz,但是显示的USB频率有时是64MHz,有时是96MHz/80MHz/120MHz,很是莫名其妙!
PC无法发现USB设备,非常郁闷!
后来无意中清空一次芯片Flash后才明白,原来是TinyBooter工作在120MHz已经启动,但是TinyCLR还跑在72MHz,导致发现不了USB。
重新编译TinyCLR到120MHz后解决问题,发现USB。
并且,在刷写TinyCLR的时候,速度明显加快,大概100k Byte/s
 楼主| sunmeat 发表于 2015-1-27 15:13 | 显示全部楼层
实际上这些问题可能不是很难,但是官方没有统一的详细的文档(没有说清楚为什么那样子改)。
事后在网上发现一个信息:
QQ截图20150127151341.png
真是坑爹呀,有木有???

120MHz主频,加上Flash零等待,性能提升应该不止50%了吧,对于性能不足的MF来说,可是极大的利好!
至于是否稳定,咱不懂,直接装上流水线试试!
Mrjiang88178 发表于 2015-7-8 09:22 | 显示全部楼层
挺好,学习了
cowboy2014 发表于 2015-7-9 09:13 | 显示全部楼层
你的意思是把stm32替换掉吗
vivilzb1985 发表于 2015-7-11 09:48 | 显示全部楼层
主频的提升是一个亮点的。
comeon201208 发表于 2015-7-11 16:43 | 显示全部楼层
GD32的性价比是非常高的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

208

主题

2132

帖子

13

粉丝
快速回复 在线客服 返回列表 返回顶部