返回首页

微控制器 C 问题

本文包含微控制器 C 编程、构建系统、中断和 RTOS 的关键问题。该选集基于中高级专家的真实面试。附代码示例和术语解释。

微控制器 C:60+ 关键问题
Advertisement 728x90

嵌入式C精要:单片机编程核心问题

单片机开发者必须熟练掌握C语言在资源受限环境下的特殊用法。下面精选了一系列实用问题,聚焦编译、内存管理和优化。这些话题常出现在嵌入式公司面试中。

核心关键字及其用法

Static 将变量作用域限制在当前文件或函数内,本地静态变量可在多次调用间保持值。Volatile 防止编译器优化外部修改的变量(如寄存器、内存、中断)。

问题代码示例:

Google AdInline article slot
int square(volatile int *ptr) {
    return *ptr * *ptr;
}

这里,volatile仅作用于首次解引用,第二次可能被优化掉。修复:(ptr) (*ptr)

Const volatile 适用于只读外部数据如状态寄存器。Register 建议将变量存入CPU寄存器(C11已弃用)。Restrict 告知编译器指针无别名,可启用向量化优化。

内存管理和结构体

全局const变量置于Flash内存。对于32 KB全0xFF常量数组,使用链接脚本节并指定fill(0xFF)

Google AdInline article slot

位操作:检查位用n & (1 << k),清零用n & ~(1 << k)。浮点比较:fabs(a - b) < EPSILON

结构体大小受对齐影响。例如:

struct Foo {
    int iiii;
    char c;
};

大小为8字节(4字节填充)。GCC打包:__attribute__((packed))

Google AdInline article slot

字符串声明示例:

char str5[]={'s','t','r','i','n','g'};  // 大小:7 长度:6
char *str1="string";                    // 大小:4 长度:6 (指针)
char str3[]="string";                   // 大小:7 长度:6
char str4[10]="string";                 // 大小:10 长度:6

构建系统与工具链

构建系统自动化编译、链接和依赖管理。Make处理文件变更,而Ninja凭借并行性和简洁更快。

GNU Make中的VPATH 在指定目录搜索源文件。

代码流水线:.c → .i (预处理器) → .s (汇编) → .o → .elf → .bin/.hex

禁用GCC警告:#pragma GCC diagnostic ignored "-Wrestrict"

缩小固件:-ffunction-sections -fdata-sectionsld --gc-sections,以及-Os优化。

构建产物

  • .o — 目标文件
  • .elf — 带符号的可执行文件
  • .hex/.bin — 用于烧录(hex包含地址)

Binutils:objdump(反汇编)、objcopy(转换)、readelf(ELF分析)。

验证构建:make V=1-n(干跑)。

数据结构与算法

循环缓冲区 — 环形数组用头/尾索引,与移位元素的FIFO不同。

链表删除:设置prev->next = node->next(需prev)或node->next->prev = node->prev(双向链表)。

C语言多态:结构体中函数指针(类似vtable)。

无if/switch任务:

void print_num(int n) {
    const char *nums[] = {"","One","Two"};
    printf("%s", nums[n]);
}

do-while(0) 用于宏 — 单次迭代支持多语句。

中断与RTOS

中断 — 硬件机制,在事件发生时跳转至ISR。向量表存储ISR地址。Cortex-M4进入需12–16周期(上下文保存)。

流程:硬件保存PC/LR,加载向量,跳转ISR,返回用POP。

Reentrant 函数 — 可并发调用安全(无静态/局部变量或加同步)。

RTOS中:

  • Thread — 带独立栈的执行单元
  • Mutex — 互斥锁
  • Semaphore — 事件计数器
  • Spinlock — 忙等锁

代码问题:锁顺序死锁(TaskA: ma→mb,TaskB: mb→mc→ma)。

Priority inversion:高优先级任务等待低优先级。解决:优先级继承。

原子操作

示例:__atomic_exchange_n(&x, &y, __ATOMIC_SEQ_CST)

位带 — 无掩码直接位访问(Cortex-M3/4)。

工具链与调试

ABI — 二进制接口(调用约定)。

段:.text(Flash代码)、.data(RAM初始化)、.bss(RAM零初始化)、.rodata(Flash常量)。

展开预处理器:gcc -E file.c > expanded.i

关键文档:数据手册、参考手册、编程手册、原理图。

核心要点

  • Volatile对外设寄存器至关重要
  • Packed结构体省RAM但访问慢
  • RTOS需线程安全代码和临界区保护
  • 构建优化:分节 + gc-sections
  • 中断使用当前线程栈

结构体0xFF填充:链接脚本fill或__attribute__((packed)) + 手动填充。

— Editorial Team

Advertisement 728x90

继续阅读