我希望这是对我的问题的清晰解释,我已经在各种手册中运行了一个多星期,现在尝试解决这个问题:
最近我在对STM32 Nucleo-F334R8进行反馈和测试后,重新设计了一个班级项目的软件设计(我的初始代码充满了内存和时序错误)
目前我遇到两个主要错误:
(此问题已得到解决)
我一直在使用 sprintf 不考虑写入分配内存之外的尾随空字符。
在异步模式下以 115200 波特率使用 USART 1 处理 USART 数据时:
程序收到信号 SIGTRAP,跟踪/断点陷阱。memset()中的0x08002c08
程序收到信号 SIGTRAP,跟踪/断点陷阱。memset()中的0x08002c08
程序收到信号 SIGTRAP,跟踪/断点陷阱。memset()中的0x08002c08
程序收到信号 SIGTRAP,跟踪/断点陷阱。memset()中的0x08002c08
程序收到信号 SIGTRAP,跟踪/断点陷阱。std.isra () 中的 0x080056b4
存储在地址 0x08002c08 的值通常非常大,通常类似于十进制的 134228385。此外,如果我强行解决该问题,程序将继续正常运行并且再也不会遇到我发现奇怪的可能原因的问题?
更新:所以我已经跟踪了一下 memset 问题,发现它发生在我的
setOutputBuffer
方法中:String>,%5d,%8s,%3d,%3d,%3d,%4d,%4d,%4d,%10.6f,%11.6f,%7.1f,%3d,%3.1f\n",uptime,timeString,temperature,pressure,humidity,acc1,acc2,acc3,latitude,longitude,altitude,current,voltage); } ``` Which leads me to believe the issue lies in finding a value that is being used to set the Output buffer message. I would like advice on how to further troubleshoot these two issues and whether there is a chance that the memset error is related the later bss error. My String Tokenizing code(edited): ```c void tokenize(char* in){ const char *p = in; const char delim[] = ","; char *token = NULL; uint8_t n = 0; do{ size_t length = strcspn(p, delim); if(length > 0){ if(token == NULL){ token = malloc(sizeof(char)*length); // create memory space for the token memset(token, 0, length); // ensure initialized memory is blank sprintf(token, "%.*s",(int)length,p); // store the token from a substring of Input Buffer p+=length; // move pointer to next ',' parseToken(token, n); // extract information from the token be it latitude, longitude etc memset(token, 0, length); // clear the token free(token); // free up the token's spot in memory token = NULL; // set token pointer to null n++; } } }while(*((++p)+1) != '*'); // The expected string ends with a checksum character '*' after the last ',' } ``` I've re-examined the function and made a lot of changes now I can successfully step through the entire function without issue, the program then returns to my main loop, and I let it run for a while but then I suddenly run back into the same memset issue, even without receiving any bytes over USART here is the code for my main loop and the subsequent function calls it makes: ```c while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if (byteFlag){ byteRecieved(); byteFlag = 0; } if(msgFlag){ msgRecieved(); msgFlag = 0; } if(secFlag){ setOutputBuffer(); HAL_UART_Transmit(&huart1, (uint8_t *)bufferOut, 91, 1000); secFlag = 0; } } ``` byteReceived: ```c if((char) byteIn == '$'){ clearInputBuffer(); } else if((char) byteIn == '\n'){ msgFlag = 1; } else{ storeChar(); } ``` msgReceived: ```c if(isValid()){ if (checksum()) { tokenize(bufferIn); clearInputBuffer(); } } ``` isValid: ```c char substr[5]; strncpy(substr, (bufferIn+1), 5); if(!strcmp(substr, "GPGGA")){ return 1; } return 0; ``` checksum: ```c int checksum(){ int calc_checksum = 0; int in_checksum; int i = 0; char checkstr[2]; uint8_t hasCheckSum = 0; for(int j = 0; j<91; j++){ if (bufferIn[j] == '*') { hasCheckSum = 1; i = 1; } } if (hasCheckSum) { while (bufferIn[i] != '*'){ calc_checksum ^= bufferIn[i]; i++; } checkstr[0] = bufferIn[i+1]; checkstr[1] = bufferIn[i+2]; } else {return 0;} in_checksum = parseStr_HexToInt(checkstr); if (calc_checksum == in_checksum){ return 1; } else { return 0; } } ``` clearInputBuffer: ```c void clearInputBuffer(){ int i = 0; for(i = 0; i < 100; i++){ bufferIn[i] = ' '; } bufferIn[0] = '$'; } ```
(此问题已得到解决)
本质上,我的问题的根源是滥用sprintf
和用空字符覆盖程序代码
我在填充板子内存的 bss 段时遇到了断点陷阱
在为 4 位模式 LCD(即 PA12、PA11、PB12、PB11、PB2、PB1、PB15)和 DMA 模式下的两通道 ADC(PA1、PA0)添加两个 GPIO 端口后:
程序收到信号 SIGTRAP,跟踪/断点陷阱。LoopFillZerobss () at ..\startup/startup_stm32f334x8.s:103 103 cmp r2, r3 在尝试实现 LCD 和 ADC 功能时,我在启动的 LoopFillZerobss 函数期间收到断点陷阱错误,这被证明是致命的,特别是通过阻止我的 USART 报告完全没有(但是它仍然可以接收字节作为中断和处理令牌等,只是拒绝传输),在读入 bss 段后,我尝试通过将尽可能多的全局变量初始化为非零值来解决问题,但这不起作用,在添加 STM32CubeMx 设置后观察到问题对于 ADC 和 LCD 中使用的 7 个 GPIO 引脚,但据我所知,这些都没有使用单元化变量,除非 CubeMX 生成的预定义代码超出了内存 bss 段的范围并且 bss 段的大小也太大了现在对于董事会的内存很大(我怀疑这不太可能,但不能排除)。
本质上,这个项目的想法是通过 USART、ADC 和后来的 I2C 接收各种数据,并在当前通过 USART 和 LCD 显示数据的各个方面,如果我丢弃 ADC 和 LCD 错误,我的 USART 代码作为 memset() 错误的功能是非致命的,但我怀疑把它留在那里只会导致我以后的问题,但我也不确定在哪里修复我的标记化代码,假设它是我问题的根源。