打印
[STM32F7]

NUCLEO-F767】 cubeMX生成虚拟串口出错原因分析与解决

[复制链接]
2538|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
话说使用STM32 CUBEMX这种初始化代码神器,估计大多数人都会了,但是生成的代码出了问题,去追踪分析问题并且解决的朋友可能就不会了。

在这里,笔者分享一下自己使用cubeMX生成虚拟串口,然后出错不能用并解决的方法。

如何生成代码的过程就不介绍了,直接进入主题。

出错现象:编译成功,下载成功,但是电脑提示设备无法启动,如下图所示。

思考1:跟大多数网友一样,第一反映肯定想到:驱动不对,重新安装一下就好了。
验证:作者在L432KC是使用过虚拟串口的,是可以用的,电脑上的驱动是没问题的,推翻思考1。

思考2:cubeMX生成的代码有问题。
验证:目前只有两种可能了,那就追踪一下代码,看看是哪里出错了。

打开代码分析一下,main函数没什么特别,调用一些HAL和时钟的和USB的初始化。
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

使用调试仿真一下,运气很好,一下子就发现异常了,如下图所示。


这里给 pdev->pClassData 自动分配内存,分配失败,所以返回NULL了。
  pdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));
  
  if(pdev->pClassData == NULL)
  {
    ret = 1;
  }
很好,找到问题点,那就好解决了。

计算一下USBD_CDC_HandleTypeDef这个结构体的size。

#define <font color="#ff0000">CDC_DATA_HS_MAX_PACKET_SIZE </font>                512  /* Endpoint IN & OUT Packet size */
#define CDC_DATA_FS_MAX_PACKET_SIZE                 64  /* Endpoint IN & OUT Packet size */
#define CDC_CMD_PACKET_SIZE                         8  /* Control Endpoint Packet size */
typedef struct
{
  uint32_t data[<font color="#ff0000">CDC_DATA_HS_MAX_PACKET_SIZE</font>/4];      /* Force 32bits alignment */
  uint8_t  CmdOpCode;
  uint8_t  CmdLength;   
  uint8_t  *RxBuffer;
  uint8_t  *TxBuffer;   
  uint32_t RxLength;
  uint32_t TxLength;   

  __IO uint32_t TxState;     
  __IO uint32_t RxState;   
}
USBD_CDC_HandleTypeDef;
512+1+1+4+4+4+4+4+4=538
是这样算的么,其实不对的,这里要考虑的内存字节对齐,uint8_t CmdOpCode;uint8_t CmdLength;只占了2字节,但是需要4字节对齐,所以编译器会自动在后面补2字节
所以是:512+4+4+4+4+4+4+4=540




下面说说stack和heap的区别,以下内容摘自:http://blog.csdn.net/slj_win/article/details/16906141
(1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等,其操作方式类似
于数据结构中的栈。
(2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。分配
方式类似于数据结构中的链表。



使用malloc分配的内存是在heap上的,可以判断,初始化的时候,分配的heap太小了,导致上面的内存分配失败。
查看一下startup_stm32f767xx.s文件,可以看到分配给heap的大小只有0x200字节,也就是512字节,那明显是不够的,上面的结构体就占了540字节了。


解决方法:在startup_stm32f767xx.s加大分配给heap的字节大小。Heap_Size    加大为     0x400
重新编译下载,OK,成功。




评分
参与人数 1威望 +5 收起 理由
mmuuss586 + 5 很给力!
沙发
mmuuss586| | 2016-8-7 12:37 | 只看该作者
不错;

使用特权

评论回复
板凳
changing753| | 2019-1-19 17:50 | 只看该作者
碰到和楼主一样的问题了。解决了,非常感谢楼主大佬分享

使用特权

评论回复
地板
colin2135|  楼主 | 2019-1-19 20:44 | 只看该作者
changing753 发表于 2019-1-19 17:50
碰到和楼主一样的问题了。解决了,非常感谢楼主大佬分享

哈哈,能帮你解决问题,很好。

使用特权

评论回复
5
zhang..yb| | 2019-2-2 09:31 | 只看该作者
在 407 板子上可以, 在 H750 板子上还是不行
电脑显示:由于该设备有问题,Windows 已将其停止。 (代码 43)

使用特权

评论回复
6
xtoolbox| | 2019-2-3 00:44 | 只看该作者
zhang..yb 发表于 2019-2-2 09:31
在 407 板子上可以, 在 H750 板子上还是不行
电脑显示:由于该设备有问题,Windows 已将其停止。 (代码 43 ...

官方有几个demo确实需要做一些修改才能使用
不过你还可以偿试一下非官方的demo
code.tusb.org

407的demo有现成的,H750的你得修改一下teeny_usb_platform.h文件,把H750的相关头文件加进去

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

144

主题

533

帖子

8

粉丝