在全球缺芯的大背景下,为产品中使用到的芯片寻找兼容的代替型号的工作迫在眉睫。若不未雨绸缪,产品很有可能就会因为热门芯片的短缺或者价格暴涨而被迫停产,就如同华为手机一样。
公司有一款产品用到了STM32F103CBT6,这款芯片比较热门,近期价格翻倍了,交期还特别长。网传国产GigaDevice的GD32F103CBT6能够完美兼容STM32F103CBT6,开发环境都不用变。于是马上申请了样品,做了替换验证。结果是在这个设计中,GD32F103CBT6无法直接替换STM32F103CBT6。原因是GD32F103CBT6和STM32F103CBT6的SPI通信口存在差异,GD32F103CBT6通过SPI初始化外围DSP失败。该问题现象在百度搜索中没有搜索到相关结果,因此借此文进行总结,下文详细描述了问题现象和解决办法(其实GD32F103CBT6和STM32F103CBT6的UART通信口也存在差异,关于UART口通信的问题百度能搜索到相关结果在此不复述)。
一、可替换性初步评估
图1 规格书截图
如图1所示,左侧是GD32F103CBT6,右侧是STM32F103CBT6,它们封装同为LQFP48,引脚分布pin2pin,具备了做替换验证的前提。事实上它们的寄存器地址映射也是相同的,这个为它们能够使用同一个程序提供了前提,具体可以参考规格书。
二、替换
图2 PCBA图
只需要替换MCU,外围器件参数保持不变。
三、问题分析
替换之后,发现板卡不能正常工作,外围的DSP初始化失败。因为DSP是由GD32F103CBT6通过SPI接口进行初始化,所以初步定位问题在SPI通信上。使用逻辑分析仪捕捉SPI信号线上的波形,如下:
图3 异常波形
图4 正常波形
对比正常波形容易看出,异常波形的时候,在SPI Enable已经上升之后(Disable),SPI Clock以及数据传送SPI MOSI还在持续,于是SPI Device(在这个通信中MCU是SPI Host,DSP是SPI Device)就丢失了一个字节数据0x2D。
以上时序对应程序的以下几句:
for(i=0; i<sizeof(SS_CMD_END_BUFFER); i++)
{
HAL_SPI_Transmit(&hspi2, &SS_CMD_END_BUFFER[i], 1, 100);
delay_us(2);
}
delay_us(2);
HAL_GPIO_WritePin(DSP_CS_GPIO_Port, DSP_CS_Pin, GPIO_PIN_SET);
代码原本的想法是,在发送完BUFFER里面的数据之后稍作延时delay_us(2),就拉高SPI Enable(对应DSP_CS引脚)。代码用在STM32F103CBT6上没有问题,但是用在GD32F103CBT6上,意想不到的现象出现了,此时程序好像不再是顺序执行了,也就是发送完了数据之后,再执行IO拉高操作,而是数据发送和IO控制变成了并行操作,数据发送和IO拉高同时进行,而且数据发送的动作比IO拉高的动作要慢,于是就导致了异常波形的出现。(有点像DMA数据传输)。
四、解决办法
导致问题的根本原因是,GD32F103CBT6不能使用 SPI_I2S_FLAG_BSY位来判断SPI数据是否发送完成,GD32F103CBT6的SPI BUSY标志位,只有在数据发送第一个位后才置1,这个和STM32F103CBT6不一样。从逻辑分析仪抓取的异常波形也可以看出,CS是在数据发送第一个位以后被置高。因此,通过强制延时就能使程序工作正常,修改代码如下:
for(i=0; i<sizeof(SS_CMD_END_BUFFER); i++)
{
HAL_SPI_Transmit(&hspi2, &SS_CMD_END_BUFFER[i], 1, 100);
delay_us(2);
}
delay_us(100);
HAL_GPIO_WritePin(DSP_CS_GPIO_Port, DSP_CS_Pin, GPIO_PIN_SET);
在发送BUFFER里面的数据之后增加延时delay_us(100),确保数据发送完成之后再进行IO上拉操作即可。
结语,GD32F103CBT6和STM32F103CBT6存在一些差异,在使用到SPI通信和UART通信的时候,不能够直接替换,还需要程序上进行适配,不过从实践经验来看,移植的工作量并不大。(这次实践完全是在STM32F103CBT6的开发环境中进行,底层库也是STM32的库,网传GD32F103CBT6有自己的底层库,对GD32兼容性更好,有待尝试)。
联系客服