一、内存管理不当
1、栈溢出
初学者经常容易忽视嵌入式系统有限的栈空间,函数层级调用过深或者在函数内部定义过大的局部变量,容易导致栈溢出。//错误示例void process_data() { uint8_t large_buffer[4096]; // 在只有2KB栈空间的MCU上 // ... 使用large_buffer}
//改进方法void process_data() { static uint8_t large_buffer[4096]; // 改为静态存储 // 或者使用动态分配(如果支持) // uint8_t* large_buffer = malloc(4096); // ... 使用large_buffer // free(large_buffer);}2、内存泄漏
在支持动态内存分配的嵌入式软件系统中,使用malloc分配内存之后,忘记调用free释放内存,导致内存泄漏。//错误示例void create_packet() { Packet* pkt = (Packet*)malloc(sizeof(Packet)); // ... 使用pkt // 忘记free(pkt);}
//改进方法void create_packet() { Packet* pkt = (Packet*)malloc(sizeof(Packet)); if(pkt == NULL) { // 错误处理 return; } // ... 使用pkt free(pkt); // 确保释放}二、未考虑并发和中断问题
1、共享资源未进行保护
在中断服务程序和主程序之间共享全局变量的时候未进行变量保护,导致两者可能对全局变量同时进行修改和引用。//错误示例volatile uint32_t counter; // 主程序和ISR都会修改void ISR() { counter++; // 中断中修改}void main() { while(1) { if(counter > 100) { // 主程序读取 // ... } }}
//改进方法volatile uint32_t counter;void ISR() { counter++; // 简单变量在大多数架构上是原子操作}void main() { while(1) { uint32_t local_counter = counter; // 先读取到局部变量 if(local_counter > 100) { // ... } }}2、中断函数执行耗时操作
在中断服务函数里面执行非常耗时的操作,影响了嵌入式系统的实时性。//错误示例void UART_ISR() { uint8_t data = UART->DR; process_data(data); // 复杂的数据处理 send_response(); // 可能阻塞的操作}
//改进方法#define BUF_SIZE 64volatile uint8_t uart_buffer[BUF_SIZE];volatile uint8_t uart_idx = 0;
void UART_ISR() { if(uart_idx < BUF_SIZE) { uart_buffer[uart_idx++] = UART->DR; // 仅快速存储数据 }}
void main() { while(1) { if(uart_idx > 0) { uint8_t data = uart_buffer[--uart_idx]; process_data(data); // 在主循环中处理 } }}
|