完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
问题的背景:公司的一个客户,应该算是一家创业企业,偶尔会让我们帮他们下stm32的驱动程序,具体的应用产需还是在自己写的。驱动基本都写好了,也都交付给他们了。最近他们在写应用程序的使用遇到了一个问题。
问题描述:申请了一个很大的全局数组,如下: #define MAXDOORNUMBER 220 DOOR_INFO doorInfo[MAXDOORNUMBER]; 程序运行起来会莫名死机,或者会被看门狗咬死。 开始分析: 1,怀疑程序内存不足,留给静态存储区的空间不足导致。 内存会划分几个区,该程序中回涉及到三个,静态存储区,堆区,栈区。静态存储区主要存放程序的全局变量,例如上边代码里的全局数组就存放在该区中,堆里存放的是程序动态分配的内存,例如用malloc分配的;栈里存放的是局部变量,函数调用现场的保存。从本例的map文件中,的Global Symbols中可以看出,全局数据区到0x20003090+2070,堆是从0x200038a8到0x20004aa8(堆是从小内存往大内存地址增长的),栈是从0x20006aa8开始到0x20004aa8,(栈是从小内存空间往大内存空间增长的,0x20006aa8为栈顶,入栈数据会向4aa8方向增长)。 对于本例来说,103vct6 的总内存大小为48K,就是从20000000-2000C000一个空间内,在魔术棒的target RAM1的设置里也可以看到。对于这个内存空间中的区域是如何分配和使用的在编译生成的map文件中都有详细的描述。本例可以查看 map文件中的 Global Symbols 中 看到全局变量doorInfo 从内存0x20000ff4开始,占用了3080个字节。 理论上说,不存在内存不够的问题,难道是全局数组的大小编译器有限制? 2,从改变数据存储区的方向来解决问题, DOOR_INFO * doorInfo = NULL; //不用数组了,将其定义为指针。 doorInfo = (DOOR_INFO *)malloc(MAXDOORNUMBER*sizeof(DOOR_INFO)); //在程序开始的时候用malloc来分配空间。 经过以上的修改,相当于将该数据存储区域从内存中的全局数据区,移到了堆里边存储了,并在*.s文件中将堆的大小进行适当的增大。这是一种方法,但是并不能解决问题,只是往这个方向上做了研究。 3,客户那边的开发领导也找到了一种方法,就是将大的全局数组一分为二,这样也避免了问题,程序也不会死了,真没想通是什么原因。 4,最后的尝试找到了解决方法,用keil 5的debug功能,执行代码发现是卡在了如下的地方: int fputc(int ch, FILE *f){ USART_SendData(DEBUG_USARTx, (uint8_t) ch); //利用keil的debug功能,卡在了这一句,是printf的相应中断没有清导致的。 while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return (ch);} 终于发现是死在printf里边了,可以知道应该是打印中断的标志没有清对,在如下的函数中添加清除标志的处理,如下所示。 int fputc(int ch, FILE *f) { USART_SendData(DEBUG_USARTx, (uint8_t) ch); //利用keil的debug功能,卡在了这一句,是printf的相应中断没有清导致的。 while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return (ch); } 终于发现是死在printf里边了,可以知道应该是打印中断的标志没有清对,在如下的函数中添加清除标志的处理,如下所示。 void USART3_IRQHandler(void) { uint8_t ucTemp; if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET) { USART_ClearITPendingBit(USART3,USART_IT_RXNE); //收的地方可能会遇到相同问题,同样需要清标志。 ucTemp = USART_ReceiveData(USART3); UARTIOInfo[2].buf[UARTIOInfo[2].write_pos++] = ucTemp; UARTIOInfo[2].write_pos %= RB_BUFFER_SIZE; UARTIOInfo[2].data_count ++; UARTIOInfo[2].bUartRcvActing = 1U; UARTIOInfo[2].u16UartRcvTimer = u16_UART_FRAME_INTERVAL_MS; } //发的地方清标志 if(USART_GetFlagStatus(USART3,USART_FLAG_ORE) == SET) { USART_ClearFlag(USART3,USART_FLAG_ORE); USART_ReceiveData(USART3); } } 标记上边的代码,红框里的代码就是为了清标志所添加的代码。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1649 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1566 浏览 1 评论
994 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
693 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1613 浏览 2 评论
1872浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
656浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
526浏览 3评论
543浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
515浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 16:56 , Processed in 0.640539 second(s), Total 45, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号