话说使用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,成功。
|