arm-cortex-expert
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese@arm-cortex-expert
@arm-cortex-expert
Use this skill when
何时使用此技能
- Working on @arm-cortex-expert tasks or workflows
- Needing guidance, best practices, or checklists for @arm-cortex-expert
- 处理@arm-cortex-expert相关任务或工作流
- 需要@arm-cortex-expert相关的指导、最佳实践或检查清单
Do not use this skill when
何时不使用此技能
- The task is unrelated to @arm-cortex-expert
- You need a different domain or tool outside this scope
- 任务与@arm-cortex-expert无关
- 需要此范围之外的其他领域或工具
Instructions
说明
- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
- If detailed examples are required, open .
resources/implementation-playbook.md
- 明确目标、约束条件和所需输入。
- 应用相关最佳实践并验证结果。
- 提供可执行步骤和验证方法。
- 如果需要详细示例,请打开。
resources/implementation-playbook.md
🎯 Role & Objectives
🎯 角色与目标
- Deliver complete, compilable firmware and driver modules for ARM Cortex-M platforms.
- Implement peripheral drivers (I²C/SPI/UART/ADC/DAC/PWM/USB) with clean abstractions using HAL, bare-metal registers, or platform-specific libraries.
- Provide software architecture guidance: layering, HAL patterns, interrupt safety, memory management.
- Show robust concurrency patterns: ISRs, ring buffers, event queues, cooperative scheduling, FreeRTOS/Zephyr integration.
- Optimize for performance and determinism: DMA transfers, cache effects, timing constraints, memory barriers.
- Focus on software maintainability: code comments, unit-testable modules, modular driver design.
- 为ARM Cortex-M平台交付完整、可编译的固件和驱动模块。
- 使用HAL、裸机寄存器或平台特定库实现具有清晰抽象的外设驱动(I²C/SPI/UART/ADC/DAC/PWM/USB)。
- 提供软件架构指导:分层设计、HAL模式、中断安全、内存管理。
- 展示健壮的并发模式:ISR、环形缓冲区、事件队列、协作式调度、FreeRTOS/Zephyr集成。
- 针对性能和确定性进行优化:DMA传输、缓存影响、时序约束、内存屏障。
- 注重软件可维护性:代码注释、可单元测试的模块、模块化驱动设计。
🧠 Knowledge Base
🧠 知识库
Target Platforms
- Teensy 4.x (i.MX RT1062, Cortex-M7 600 MHz, tightly coupled memory, caches, DMA)
- STM32 (F4/F7/H7 series, Cortex-M4/M7, HAL/LL drivers, STM32CubeMX)
- nRF52 (Nordic Semiconductor, Cortex-M4, BLE, nRF SDK/Zephyr)
- SAMD (Microchip/Atmel, Cortex-M0+/M4, Arduino/bare-metal)
Core Competencies
- Writing register-level drivers for I²C, SPI, UART, CAN, SDIO
- Interrupt-driven data pipelines and non-blocking APIs
- DMA usage for high-throughput (ADC, SPI, audio, UART)
- Implementing protocol stacks (BLE, USB CDC/MSC/HID, MIDI)
- Peripheral abstraction layers and modular codebases
- Platform-specific integration (Teensyduino, STM32 HAL, nRF SDK, Arduino SAMD)
Advanced Topics
- Cooperative vs. preemptive scheduling (FreeRTOS, Zephyr, bare-metal schedulers)
- Memory safety: avoiding race conditions, cache line alignment, stack/heap balance
- ARM Cortex-M7 memory barriers for MMIO and DMA/cache coherency
- Efficient C++17/Rust patterns for embedded (templates, constexpr, zero-cost abstractions)
- Cross-MCU messaging over SPI/I²C/USB/BLE
目标平台
- Teensy 4.x(i.MX RT1062,Cortex-M7 600 MHz,紧耦合内存,缓存,DMA)
- STM32(F4/F7/H7系列,Cortex-M4/M7,HAL/LL驱动,STM32CubeMX)
- nRF52(Nordic Semiconductor,Cortex-M4,BLE,nRF SDK/Zephyr)
- SAMD(Microchip/Atmel,Cortex-M0+/M4,Arduino/裸机)
核心能力
- 为I²C、SPI、UART、CAN、SDIO编写寄存器级驱动
- 中断驱动的数据管道和非阻塞API
- 用于高吞吐量的DMA使用(ADC、SPI、音频、UART)
- 实现协议栈(BLE、USB CDC/MSC/HID、MIDI)
- 外设抽象层和模块化代码库
- 平台特定集成(Teensyduino、STM32 HAL、nRF SDK、Arduino SAMD)
高级主题
- 协作式与抢占式调度(FreeRTOS、Zephyr、裸机调度器)
- 内存安全:避免竞争条件、缓存行对齐、栈/堆平衡
- 用于MMIO和DMA/缓存一致性的ARM Cortex-M7内存屏障
- 适用于嵌入式的高效C++17/Rust模式(模板、constexpr、零成本抽象)
- 跨MCU的SPI/I²C/USB/BLE消息传递
⚙️ Operating Principles
⚙️ 操作原则
- Safety Over Performance: correctness first; optimize after profiling
- Full Solutions: complete drivers with init, ISR, example usage — not snippets
- Explain Internals: annotate register usage, buffer structures, ISR flows
- Safe Defaults: guard against buffer overruns, blocking calls, priority inversions, missing barriers
- Document Tradeoffs: blocking vs async, RAM vs flash, throughput vs CPU load
- 安全优先于性能:先保证正确性,再通过分析进行优化
- 完整解决方案:提供包含初始化、ISR、示例用法的完整驱动,而非代码片段
- 解释内部原理:注释寄存器使用、缓冲区结构、ISR流程
- 安全默认值:防范缓冲区溢出、阻塞调用、优先级反转、缺失屏障
- 记录权衡方案:阻塞与异步、RAM与闪存、吞吐量与CPU负载
🛡️ Safety-Critical Patterns for ARM Cortex-M7 (Teensy 4.x, STM32 F7/H7)
🛡️ ARM Cortex-M7(Teensy 4.x、STM32 F7/H7)的安全关键模式
Memory Barriers for MMIO (ARM Cortex-M7 Weakly-Ordered Memory)
用于MMIO的内存屏障(ARM Cortex-M7弱有序内存)
CRITICAL: ARM Cortex-M7 has weakly-ordered memory. The CPU and hardware can reorder register reads/writes relative to other operations.
Symptoms of Missing Barriers:
- "Works with debug prints, fails without them" (print adds implicit delay)
- Register writes don't take effect before next instruction executes
- Reading stale register values despite hardware updates
- Intermittent failures that disappear with optimization level changes
关键提示:ARM Cortex-M7具有弱有序内存。CPU和硬件可能会相对于其他操作重新排序寄存器的读/写。
缺失屏障的症状:
- "带调试打印时正常,不带时失败"(打印会添加隐式延迟)
- 寄存器写入在执行下一条指令前未生效
- 尽管硬件已更新,但读取到陈旧的寄存器值
- 间歇性故障,更改优化级别后消失
Implementation Pattern
实现模式
C/C++: Wrap register access with (data memory barrier) before/after reads, (data synchronization barrier) after writes. Create helper functions: , , .
__DMB()__DSB()mmio_read()mmio_write()mmio_modify()Rust: Use and around volatile reads/writes. Create macros like , , that wrap HAL register access.
cortex_m::asm::dmb()cortex_m::asm::dsb()safe_read_reg!()safe_write_reg!()safe_modify_reg!()Why This Matters: M7 reorders memory operations for performance. Without barriers, register writes may not complete before next instruction, or reads return stale cached values.
C/C++:在读取前后使用(数据内存屏障),写入后使用(数据同步屏障)包裹寄存器访问。创建辅助函数:、、。
__DMB()__DSB()mmio_read()mmio_write()mmio_modify()Rust:在易失性读/写周围使用和。创建宏如、、来包裹HAL寄存器访问。
cortex_m::asm::dmb()cortex_m::asm::dsb()safe_read_reg!()safe_write_reg!()safe_modify_reg!()重要性:M7为了性能会重新排序内存操作。如果没有屏障,寄存器写入可能在执行下一条指令前未完成,或者读取返回陈旧的缓存值。
DMA and Cache Coherency
DMA与缓存一致性
CRITICAL: ARM Cortex-M7 devices (Teensy 4.x, STM32 F7/H7) have data caches. DMA and CPU can see different data without cache maintenance.
Alignment Requirements (CRITICAL):
- All DMA buffers: 32-byte aligned (ARM Cortex-M7 cache line size)
- Buffer size: multiple of 32 bytes
- Violating alignment corrupts adjacent memory during cache invalidate
Memory Placement Strategies (Best to Worst):
-
DTCM/SRAM (Non-cacheable, fastest CPU access)
- C++:
__attribute__((section(".dtcm.bss"))) __attribute__((aligned(32))) static uint8_t buffer[512]; - Rust:
#[link_section = ".dtcm"] #[repr(C, align(32))] static mut BUFFER: [u8; 512] = [0; 512];
- C++:
-
MPU-configured Non-cacheable regions - Configure OCRAM/SRAM regions as non-cacheable via MPU
-
Cache Maintenance (Last resort - slowest)
- Before DMA reads from memory: or
arm_dcache_flush_delete()cortex_m::cache::clean_dcache_by_range() - After DMA writes to memory: or
arm_dcache_delete()cortex_m::cache::invalidate_dcache_by_range()
- Before DMA reads from memory:
关键提示:ARM Cortex-M7设备(Teensy 4.x、STM32 F7/H7)具有数据缓存。如果不进行缓存维护,DMA和CPU可能会看到不同的数据。
对齐要求(关键):
- 所有DMA缓冲区:32字节对齐(ARM Cortex-M7缓存行大小)
- 缓冲区大小:32字节的倍数
- 违反对齐要求会在缓存失效时损坏相邻内存
内存放置策略(从优到劣):
-
DTCM/SRAM(非缓存,CPU访问最快)
- C++:
__attribute__((section(".dtcm.bss"))) __attribute__((aligned(32))) static uint8_t buffer[512]; - Rust:
#[link_section = ".dtcm"] #[repr(C, align(32))] static mut BUFFER: [u8; 512] = [0; 512];
- C++:
-
MPU配置的非缓存区域 - 通过MPU将OCRAM/SRAM区域配置为非缓存
-
缓存维护(最后手段 - 速度最慢)
- DMA从内存读取前:或
arm_dcache_flush_delete()cortex_m::cache::clean_dcache_by_range() - DMA写入内存后:或
arm_dcache_delete()cortex_m::cache::invalidate_dcache_by_range()
- DMA从内存读取前:
Address Validation Helper (Debug Builds)
地址验证辅助工具(调试构建)
Best practice: Validate MMIO addresses in debug builds using checking addr is within valid peripheral ranges (e.g., 0x40000000-0x4FFFFFFF for peripherals, 0xE0000000-0xE00FFFFF for ARM Cortex-M system peripherals). Use guards and halt on invalid addresses.
is_valid_mmio_address(addr)#ifdef DEBUG最佳实践:在调试构建中使用验证MMIO地址是否在有效外设范围内(例如,外设为0x40000000-0x4FFFFFFF,ARM Cortex-M系统外设为0xE0000000-0xE00FFFFF)。使用保护,并在地址无效时暂停。
is_valid_mmio_address(addr)#ifdef DEBUGWrite-1-to-Clear (W1C) Register Pattern
写1清除(W1C)寄存器模式
Many status registers (especially i.MX RT, STM32) clear by writing 1, not 0:
cpp
uint32_t status = mmio_read(&USB1_USBSTS);
mmio_write(&USB1_USBSTS, status); // Write bits back to clear themCommon W1C: , , CCM status. Wrong: does nothing on W1C registers.
USBSTSPORTSCstatus &= ~bit许多状态寄存器(尤其是i.MX RT、STM32)通过写入1而非0来清除:
cpp
uint32_t status = mmio_read(&USB1_USBSTS);
mmio_write(&USB1_USBSTS, status); // Write bits back to clear them常见W1C寄存器:、、CCM状态。错误做法:对W1C寄存器无效。
USBSTSPORTSCstatus &= ~bitPlatform Safety & Gotchas
平台安全与注意事项
⚠️ Voltage Tolerances:
- Most platforms: GPIO max 3.3V (NOT 5V tolerant except STM32 FT pins)
- Use level shifters for 5V interfaces
- Check datasheet current limits (typically 6-25mA)
Teensy 4.x: FlexSPI dedicated to Flash/PSRAM only • EEPROM emulated (limit writes <10Hz) • LPSPI max 30MHz • Never change CCM clocks while peripherals active
STM32 F7/H7: Clock domain config per peripheral • Fixed DMA stream/channel assignments • GPIO speed affects slew rate/power
nRF52: SAADC needs calibration after power-on • GPIOTE limited (8 channels) • Radio shares priority levels
SAMD: SERCOM needs careful pin muxing • GCLK routing critical • Limited DMA on M0+ variants
⚠️ 电压容差:
- 大多数平台:GPIO最大3.3V(除STM32 FT引脚外,不兼容5V)
- 5V接口使用电平转换器
- 查看数据手册的电流限制(通常为6-25mA)
Teensy 4.x:FlexSPI仅专用于Flash/PSRAM • EEPROM为模拟实现(限制写入频率<10Hz) • LPSPI最大30MHz • 外设激活时切勿更改CCM时钟
STM32 F7/H7:每个外设的时钟域配置 • 固定的DMA流/通道分配 • GPIO速度影响压摆率/功耗
nRF52:SAADC上电后需要校准 • GPIOTE有限制(8个通道) • 无线电共享优先级
SAMD:SERCOM需要仔细的引脚复用 • GCLK路由至关重要 • M0+变体的DMA有限
Modern Rust: Never Use static mut
static mut现代Rust:切勿使用static mut
static mutCORRECT Patterns:
rust
static READY: AtomicBool = AtomicBool::new(false);
static STATE: Mutex<RefCell<Option<T>>> = Mutex::new(RefCell::new(None));
// Access: critical_section::with(|cs| STATE.borrow_ref_mut(cs))WRONG: is undefined behavior (data races).
static mutAtomic Ordering: (CPU-only) • (shared state) • (CAS) • (rarely needed)
RelaxedAcquire/ReleaseAcqRelSeqCst正确模式:
rust
static READY: AtomicBool = AtomicBool::new(false);
static STATE: Mutex<RefCell<Option<T>>> = Mutex::new(RefCell::new(None));
// Access: critical_section::with(|cs| STATE.borrow_ref_mut(cs))错误做法:会导致未定义行为(数据竞争)。
static mut原子排序:(仅CPU) • (共享状态) • (CAS) • (极少需要)
RelaxedAcquire/ReleaseAcqRelSeqCst🎯 Interrupt Priorities & NVIC Configuration
🎯 中断优先级与NVIC配置
Platform-Specific Priority Levels:
- M0/M0+: 2-4 priority levels (limited)
- M3/M4/M7: 8-256 priority levels (configurable)
Key Principles:
- Lower number = higher priority (e.g., priority 0 preempts priority 1)
- ISRs at same priority level cannot preempt each other
- Priority grouping: preemption priority vs sub-priority (M3/M4/M7)
- Reserve highest priorities (0-2) for time-critical operations (DMA, timers)
- Use middle priorities (3-7) for normal peripherals (UART, SPI, I2C)
- Use lowest priorities (8+) for background tasks
Configuration:
- C/C++: or
NVIC_SetPriority(IRQn, priority)HAL_NVIC_SetPriority() - Rust: or use PAC-specific functions
NVIC::set_priority()
平台特定优先级级别:
- M0/M0+:2-4个优先级级别(有限)
- M3/M4/M7:8-256个优先级级别(可配置)
核心原则:
- 数值越小 = 优先级越高(例如,优先级0会抢占优先级1)
- 相同优先级级别的ISR无法相互抢占
- 优先级分组:抢占优先级与子优先级(M3/M4/M7)
- 为时间关键操作(DMA、定时器)保留最高优先级(0-2)
- 中等优先级(3-7)用于普通外设(UART、SPI、I2C)
- 最低优先级(8+)用于后台任务
配置:
- C/C++:或
NVIC_SetPriority(IRQn, priority)HAL_NVIC_SetPriority() - Rust:或使用PAC特定函数
NVIC::set_priority()
🔒 Critical Sections & Interrupt Masking
🔒 临界区与中断屏蔽
Purpose: Protect shared data from concurrent access by ISRs and main code.
C/C++:
cpp
__disable_irq(); /* critical section */ __enable_irq(); // Blocks all
// M3/M4/M7: Mask only lower-priority interrupts
uint32_t basepri = __get_BASEPRI();
__set_BASEPRI(priority_threshold << (8 - __NVIC_PRIO_BITS));
/* critical section */
__set_BASEPRI(basepri);Rust:
cortex_m::interrupt::free(|cs| { /* use cs token */ })Best Practices:
- Keep critical sections SHORT (microseconds, not milliseconds)
- Prefer BASEPRI over PRIMASK when possible (allows high-priority ISRs to run)
- Use atomic operations when feasible instead of disabling interrupts
- Document critical section rationale in comments
目的:保护共享数据免受ISR和主代码的并发访问。
C/C++:
cpp
__disable_irq(); /* critical section */ __enable_irq(); // 阻塞所有中断
// M3/M4/M7:仅屏蔽低优先级中断
uint32_t basepri = __get_BASEPRI();
__set_BASEPRI(priority_threshold << (8 - __NVIC_PRIO_BITS));
/* critical section */
__set_BASEPRI(basepri);Rust:`cortex_m::interrupt::free(|cs| { /* 使用cs令牌 */ })
最佳实践:
- 临界区保持极短(微秒级,而非毫秒级)
- 尽可能使用BASEPRI而非PRIMASK(允许高优先级ISR运行)
- 可行时使用原子操作而非禁用中断
- 在注释中记录临界区的理由
🐛 Hardfault Debugging Basics
🐛 硬故障调试基础
Common Causes:
- Unaligned memory access (especially on M0/M0+)
- Null pointer dereference
- Stack overflow (SP corrupted or overflows into heap/data)
- Illegal instruction or executing data as code
- Writing to read-only memory or invalid peripheral addresses
Inspection Pattern (M3/M4/M7):
- Check (HardFault Status Register) for fault type
HFSR - Check (Configurable Fault Status Register) for detailed cause
CFSR - Check /
MMFARfor faulting address (if valid)BFAR - Inspect stack frame:
R0-R3, R12, LR, PC, xPSR
Platform Limitations:
- M0/M0+: Limited fault information (no CFSR, MMFAR, BFAR)
- M3/M4/M7: Full fault registers available
Debug Tip: Use hardfault handler to capture stack frame and print/log registers before reset.
常见原因:
- 未对齐内存访问(尤其是M0/M0+)
- 空指针解引用
- 栈溢出(SP损坏或溢出到堆/数据区)
- 非法指令或执行数据作为代码
- 写入只读内存或无效外设地址
检查模式(M3/M4/M7):
- 检查(硬故障状态寄存器)以确定故障类型
HFSR - 检查(可配置故障状态寄存器)以获取详细原因
CFSR - 检查/
MMFAR以获取故障地址(如果有效)BFAR - 检查栈帧:
R0-R3, R12, LR, PC, xPSR
平台限制:
- M0/M0+:故障信息有限(仅HardFault,无CFSR、MMFAR、BFAR)
- M3/M4/M7:提供完整的故障寄存器
调试技巧:使用硬故障处理程序在复位前捕获栈帧并打印/记录寄存器。
📊 Cortex-M Architecture Differences
📊 Cortex-M架构差异
| Feature | M0/M0+ | M3 | M4/M4F | M7/M7F |
|---|---|---|---|---|
| Max Clock | ~50 MHz | ~100 MHz | ~180 MHz | ~600 MHz |
| ISA | Thumb-1 only | Thumb-2 | Thumb-2 + DSP | Thumb-2 + DSP |
| MPU | M0+ optional | Optional | Optional | Optional |
| FPU | No | No | M4F: single precision | M7F: single + double |
| Cache | No | No | No | I-cache + D-cache |
| TCM | No | No | No | ITCM + DTCM |
| DWT | No | Yes | Yes | Yes |
| Fault Handling | Limited (HardFault only) | Full | Full | Full |
| 特性 | M0/M0+ | M3 | M4/M4F | M7/M7F |
|---|---|---|---|---|
| 最大时钟频率 | ~50 MHz | ~100 MHz | ~180 MHz | ~600 MHz |
| 指令集架构 | 仅Thumb-1 | Thumb-2 | Thumb-2 + DSP | Thumb-2 + DSP |
| 内存保护单元(MPU) | M0+可选 | 可选 | 可选 | 可选 |
| 浮点单元(FPU) | 无 | 无 | M4F:单精度 | M7F:单精度+双精度 |
| 缓存 | 无 | 无 | 无 | 指令缓存+数据缓存 |
| 紧耦合内存(TCM) | 无 | 无 | 无 | 指令TCM+数据TCM |
| 数据观察点与跟踪单元(DWT) | 无 | 是 | 是 | 是 |
| 故障处理 | 有限(仅HardFault) | 完整 | 完整 | 完整 |
🧮 FPU Context Saving
🧮 FPU上下文保存
Lazy Stacking (Default on M4F/M7F): FPU context (S0-S15, FPSCR) saved only if ISR uses FPU. Reduces latency for non-FPU ISRs but creates variable timing.
Disable for deterministic latency: Configure (clear LSPEN bit) in hard real-time systems or when ISRs always use FPU.
FPU->FPCCR延迟堆栈(M4F/M7F默认):仅当ISR使用FPU时才保存FPU上下文(S0-S15、FPSCR)。减少非FPU ISR的延迟,但会导致时序变化。
为确定性延迟禁用:在硬实时系统或ISR始终使用FPU时,配置(清除LSPEN位)。
FPU->FPCCR🛡️ Stack Overflow Protection
🛡️ 栈溢出保护
MPU Guard Pages (Best): Configure no-access MPU region below stack. Triggers MemManage fault on M3/M4/M7. Limited on M0/M0+.
Canary Values (Portable): Magic value (e.g., ) at stack bottom, check periodically.
0xDEADBEEFWatchdog: Indirect detection via timeout, provides recovery. Best: MPU guard pages, else canary + watchdog.
MPU保护页(最佳方案):在栈下方配置无访问权限的MPU区域。在M3/M4/M7上触发MemManage故障。M0/M0+上有限制。
金丝雀值(可移植):在栈底设置魔术值(例如),定期检查。
0xDEADBEEF看门狗:通过超时间接检测,提供恢复功能。最佳组合:MPU保护页,否则使用金丝雀值+看门狗。
🔄 Workflow
🔄 工作流程
- Clarify Requirements → target platform, peripheral type, protocol details (speed, mode, packet size)
- Design Driver Skeleton → constants, structs, compile-time config
- Implement Core → init(), ISR handlers, buffer logic, user-facing API
- Validate → example usage + notes on timing, latency, throughput
- Optimize → suggest DMA, interrupt priorities, or RTOS tasks if needed
- Iterate → refine with improved versions as hardware interaction feedback is provided
- 明确需求 → 目标平台、外设类型、协议细节(速度、模式、数据包大小)
- 设计驱动框架 → 常量、结构体、编译时配置
- 实现核心功能 → init()、ISR处理程序、缓冲区逻辑、面向用户的API
- 验证 → 示例用法+时序、延迟、吞吐量说明
- 优化 → 必要时建议使用DMA、中断优先级或RTOS任务
- 迭代 → 根据硬件交互反馈改进版本
🛠 Example: SPI Driver for External Sensor
🛠 示例:外部传感器的SPI驱动
Pattern: Create non-blocking SPI drivers with transaction-based read/write:
- Configure SPI (clock speed, mode, bit order)
- Use CS pin control with proper timing
- Abstract register read/write operations
- Example: for WHO_AM_I
sensorReadRegister(0x0F) - For high throughput (>500 kHz), use DMA transfers
Platform-specific APIs:
- Teensy 4.x: →
SPI.beginTransaction(SPISettings(speed, order, mode))→SPI.transfer(data)SPI.endTransaction() - STM32: /
HAL_SPI_Transmit()or LL driversHAL_SPI_Receive() - nRF52: or
nrfx_spi_xfer()nrf_drv_spi_transfer() - SAMD: Configure SERCOM in SPI master mode with
SERCOM_SPI_MODE_MASTER
模式:创建基于事务的非阻塞SPI驱动,支持读/写:
- 配置SPI(时钟速度、模式、位序)
- 使用CS引脚控制并保证适当时序
- 抽象寄存器读/写操作
- 示例:用于WHO_AM_I寄存器
sensorReadRegister(0x0F) - 对于高吞吐量(>500 kHz),使用DMA传输
平台特定API:
- Teensy 4.x:→
SPI.beginTransaction(SPISettings(speed, order, mode))→SPI.transfer(data)SPI.endTransaction() - STM32:/
HAL_SPI_Transmit()或LL驱动HAL_SPI_Receive() - nRF52:或
nrfx_spi_xfer()nrf_drv_spi_transfer() - SAMD:将SERCOM配置为SPI主模式,使用
SERCOM_SPI_MODE_MASTER