McuStudioMcuStudio
指南
开发者
组件
API
  • 版本发布
指南
开发者
组件
API
  • 版本发布
  • 概述
  • 快速开始
  • 添加厂商的芯片到平台
  • 芯片模板教程

    • 芯片模板开发教程
    • 创建引脚封装
    • 配置时钟树
    • 配置 GPIO 外设
    • 配置 ADC 外设
    • 配置通信外设
    • 配置 TIM 外设
  • 开发参考

    • 框架与规则
    • 芯片包结构
    • 芯片描述
    • 芯片包配置
    • 引脚配置详解
    • 外设配置详解
    • 外设元素参考
    • GPIO 开发参考
    • ADC 开发参考
    • TIM 开发参考
    • 固件库开发指南
    • 版本管理机制
    • Define 映射指南
    • 多语言(i18n)

固件库开发指南

本文档介绍芯片模板中 HAL(硬件抽象层)和 LL(底层)固件库的开发方法,以及通用模板的使用方式。

HAL vs LL 库对比

特性HALLLSTD
抽象层级高低中
代码量较大较小中等
性能较低较高中等
易用性最易较难中等
可移植性最好一般一般
适用场景快速开发性能敏感传统项目

通用模板目录

芯片模板中的通用模板位于 common/ 目录下,提供跨外设共享的代码片段:

common/
├── gpio/
│   ├── gpio_enable_hal.ejs       # HAL 使能 GPIO
│   ├── gpio_enable_ll.ejs        # LL 使能 GPIO
│   ├── gpio_disable_hal.ejs      # HAL 禁用 GPIO
│   └── peripheral_gpio_init.ejs  # 外设 GPIO 初始化
├── dma/
│   ├── dma_hal.ejs               # DMA HAL 初始化结构
│   ├── dma_struct.ejs            # DMA 通道配置
│   └── dma_unit.ejs              # 单个 DMA 单元
├── nvic/
│   ├── nvic_enable_hal.ejs       # NVIC 使能中断
│   └── nvic_disable_hal.ejs      # NVIC 禁用中断
├── hal_conf.ejs                  # HAL 库配置文件
├── hal_msp.ejs                   # HAL MSP 初始化
├── main.c.ejs                    # 主函数模板
├── main.h.ejs                    # 主头文件模板
└── define.cjs                    # 通用宏定义

GPIO 通用模板

gpio_enable_hal.ejs

用于生成外设 GPIO 的 HAL 库使能代码:

// 模板输出示例
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) {
  // 使能 GPIO 时钟
  __HAL_RCC_GPIOx_CLK_ENABLE();
  // 配置引脚
  // ...
}

gpio_enable_ll.ejs

用于生成外设 GPIO 的 LL 库使能代码:

// 模板输出示例
void LL_GPIO_Init(GPIO_TypeDef *GPIOx, LL_GPIO_InitTypeDef *GPIO_Init) {
  // LL 库更加精简
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOx);
  // 直接寄存器操作
  // ...
}

gpio_disable_hal.ejs

用于生成外设 GPIO 的 HAL 库禁用代码:

void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin) {
  // 复位引脚配置
  // 可选:禁用 GPIO 时钟
}

peripheral_gpio_init.ejs

通用的外设 GPIO 初始化代码,被各外设模板引用:

// 用于生成外设特定引脚的 GPIO 初始化
void Peripheral_GPIO_Init(void) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  // USART1 TX: PA9
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  // USART1 RX: PA10
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

DMA 通用模板

dma_hal.ejs

DMA HAL 初始化结构模板:

DMA_HandleTypeDef hdma_usart1_tx;
hdma_usart1_tx.Instance = DMA1_Channel4;
hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_tx.Init.Mode = DMA_NORMAL;
hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
HAL_DMA_Init(&hdma_usart1_tx);

dma_struct.ejs

DMA 通道配置数据结构:

// 模板处理的变量结构
{
  channel: 'DMA1_Channel4',
  direction: 'MEMORY_TO_PERIPH',
  peripheral: 'USART1',
  stream: 'TX',
  priority: 'LOW',
  mode: 'NORMAL'
}

dma_unit.ejs

单个 DMA 传输单元模板,处理基本的 DMA 传输参数。

NVIC 通用模板

nvic_enable_hal.ejs

// NVIC 中断使能配置
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);

nvic_disable_hal.ejs

// NVIC 中断禁用
HAL_NVIC_DisableIRQ(USART1_IRQn);

EJS 模板语法参考

芯片模板使用 EJS(Embedded JavaScript)作为模板引擎。以下是常用语法:

变量输出

<!-- 输出变量值 -->
<%= variableName %>

<!-- 输出并转义 HTML -->
<%- htmlContent %>

条件判断

<% if (condition) { %>
  条件成立的内容
<% } else { %>
  条件不成立的内容
<% } %>

循环

<% items.forEach(function(item) { %>
  <%- item.name %>
<% }) %>

模板之间的交互流程

用户配置界面
    ↓
pre.cjs (数据预处理)
    ↓ 处理后的数据
EJS 模板 (代码渲染)
    ↓ 生成的代码
最终工程文件 (.c/.h)

pre.cjs 示例

// GPIO pre.cjs
module.exports = ({ ip, ide, locals }) => {
  const global = locals.global

  // 获取 GPIO 数据
  let ip_pins = global.GPIO.get_ip_gpios(
    [ip.$name, 'EVENTOUT', 'IR', 'MCO']
  )

  // 固件参数映射
  global.GPIO.set_gpio_define_map(
    locals.defineMap,
    ip.firmware.value,
    ip_pins.pins
  )

  // 合并数据
  Object.assign(ip, ip_pins)

  // 生成中断处理
  set_nvic_handlers(global, ip)
}

最佳实践

  1. 模板复用:通用功能(GPIO初始化、DMA配置、NVIC配置)应抽取到 common/ 目录
  2. 固件分离:HAL 和 LL 模板分开维护,通过 firmware 参数选择
  3. 版本管理:模板的每次修改应递增版本号,确保已有芯片配置不受影响
  4. 注释清晰:生成的代码应包含有意义的注释,说明配置意图
  5. 命名规范:模板文件名应清晰表达其用途(如 gpio_enable_hal.ejs)
Prev
TIM 开发参考
Next
版本管理机制