杰理 SDK 文档中心
首页
首页
  • 概述与快速开始

    • SDK 总览与芯片能力
    • 环境搭建与编译构建
    • 烧录与固件升级
    • 文档与版本资源
  • 应用与示例方案

    • demo 示例工程
    • WiFi 摄像头方案 (wifi_camera)
    • WiFi 音箱方案 (wifi_soundbox)
    • WiFi 婴儿监护方案 (wifi_bbm)
    • 公共应用模块库
    • 示例代码库 (example)
  • 系统架构与平台

    • 总体架构与工程分层
    • 系统启动与运行框架
    • 芯片驱动与板级适配
    • 设备管理与文件系统
    • 系统工具库与算法
  • 音频子系统

    • 音频框架与处理节点
    • 音频编解码与音效
    • 播放器与录音器
    • 语音交互与 AI 唤醒
    • LE Audio 与蓝牙音频
    • 音频调试与歌词
  • 视频与显示子系统

    • 摄像头驱动与 ISP
    • 视频编码与图像处理
    • 显示与 GPU 加速
    • 屏幕镜像 (screen_mirror)
  • 无线连接与网络

    • 蓝牙协议栈 (双模蓝牙)
    • WiFi 协议栈与配网
    • 网络协议栈
    • 云平台与 IoT 协议
  • UI 子系统

    • LVGL 集成与应用
    • UI 工程与工具链
  • 配置系统

    • 功能配置
    • 板级配置
    • 网络与蓝牙配置
    • 音频配置与提示音
  • 工具与测试

    • 产测与射频测试工具
    • 固件升级与更新机制
    • 调试与日志工具
  • 硬件参考设计

    • 原理图参考设计
    • 芯片数据手册

板级配置

本文档介绍 AC792N SDK 中板级配置(Board-level Configuration)的完整机制:从 board_config.h 的板型选择入口,到 chip_cfg.h 的芯片存储配置、board_demo.h 的外设与时钟宏定义,再到 board.c 中将这些宏实例化为驱动平台数据并注册到系统设备表的过程。

Purpose and Scope

板级配置是 SDK 中连接"芯片能力"与"具体硬件电路"的一层:同一颗 AC792N 芯片可以搭载不同规格的 Flash、SDRAM、按键、串口与电源电路,板级配置目录负责把这些差异集中到少数几个文件中,使上层应用与驱动代码无需关心具体板子。

本页覆盖:

  • 板级配置文件的目录结构与分层 include 关系(board_config.h / chip_cfg.h / board_demo.h / board.c);
  • 板型选择宏(CONFIG_BOARD_DEMO)与新增板子的扩展方式;
  • 时钟、Flash、SDRAM、UART、AD 按键、电源低功耗等各模块的配置宏及其含义;
  • board.c 中平台数据结构(uart0_data、uart1_data、adkey_data、power_param)、设备表注册与低功耗回调。

本页以 sdk/apps/demo/demo_ble/board/wl83 目录为具体示例展开。与板级配置相关的驱动内部实现(如 UART 驱动如何消费 uart_dev_ops、AD 按键驱动如何轮询电压阈值、电源管理模块如何进入低功耗)属于各自驱动页面的范畴,本页只说明板级层如何向它们提供配置;应用层的模块裁剪(如 CONFIG_BT_ENABLE 对应的蓝牙协议栈)也仅在本页说明其在板级的开关入口。

概述

在 Jieli 的 AC792N 嵌入式 SDK 中,每个 demo 工程都带有一个 board/<board_name>/ 目录,例如 sdk/apps/demo/demo_ble/board/wl83/。该目录是"这块板子长什么样"的唯一事实来源(single source of truth),其设计意图非常明确:

  1. 把硬件差异收口到一处:时钟频率、引脚分配、存储规格、按键档位、电源档位等全部以 TCFG_* / CONFIG_* 宏形式集中定义,驱动代码只读这些宏,不直接写硬件数值;
  2. 配置与实现分离:头文件(*_cfg.h / *_demo.h)只声明"配置什么",board.c 负责把配置实例化为驱动可消费的 platform_data 结构体并注册;
  3. 多板支持:通过 #ifdef CONFIG_BOARD_XXX 选择板型,新增板子只需新增一个 board_xxx.h 并在 board_config.h 中引入,无需改动驱动。

典型使用场景:量产时更换不同容量的 Flash、调整系统主频、把调试串口改到其他引脚、为不同按键电阻分压网络配置 AD 按键阈值、调整低功耗唤醒引脚等——这些改动都发生在板级配置文件中,而不是业务代码里。

架构

板级配置的整体结构如下图所示(以 demo_ble/wl83 为例):

flowchart TD
    subgraph sg_BoardDir["board/wl83 板级配置目录"]
        BoardConfig["board_config.h<br/>板型选择入口"]
        ChipCfg["chip_cfg.h<br/>Flash/SDRAM 容量"]
        BoardDemo["board_demo.h<br/>时钟/外设/电源宏"]
        BoardC["board.c<br/>平台数据实例化"]
    end

    subgraph sg_Driver["驱动与框架层"]
        UartDrv["uart_dev_ops 驱动"]
        AdkeyDrv["adkey 驱动"]
        PowerDrv["电源/低功耗管理"]
        DevTable["REGISTER_DEVICES 设备表"]
    end

    subgraph sg_App["应用层"]
        AppConfig["app_config.h"]
        AppTask["应用任务"]
    end

    BoardConfig -->|"#include"| ChipCfg
    BoardConfig -->|"#include"| BoardDemo
    BoardConfig -->|"CONFIG_BOARD_DEMO 开关"| BoardDemo
    BoardDemo -->|"TCFG_* 宏"| BoardC
    ChipCfg -->|"__FLASH_SIZE__ / __SDRAM_SIZE__"| BoardC
    BoardC -->|"uart0_data / uart1_data"| UartDrv
    BoardC -->|"adkey_data + get_adkey_platform_data()"| AdkeyDrv
    BoardC -->|"power_param / power_pdata"| PowerDrv
    BoardC -->|"设备表条目"| DevTable
    DevTable --> AppConfig
    AppConfig --> AppTask

各层职责说明:

  • board_config.h:板级目录的"总入口",先包含芯片存储配置,再根据板型宏选择对应的外设配置文件,并统一处理 SDRAM 使能逻辑;
  • chip_cfg.h:定义芯片外挂存储的容量宏(__FLASH_SIZE__、__SDRAM_SIZE__),uboot/链接脚本与内存布局会引用这些值;
  • board_demo.h:以功能模块分块注释(时钟、flash、sdram、UART、AD 按键、电源)组织的 TCFG_* 宏集合,是绝大多数板级调整发生的地方;
  • board.c:把上述宏组装成 UART0_PLATFORM_DATA_BEGIN(...) 等平台数据结构、AD 按键电压阈值表、电源参数表,并通过 REGISTER_DEVICES(device_table) 把设备注册进系统框架,供驱动按名查找(如 "uart0")。

这种"宏定义 → 结构体实例 → 设备表注册"的三段式设计,使硬件配置变更的编译期可见、运行期零开销:所有配置在编译时即已确定,运行时驱动只需读取常量结构体。

板级配置的分层机制

1. 总入口:board_config.h

board_config.h 是整个板级配置的枢纽,代码非常简短但结构清晰:

//板子型号
#define CONFIG_BOARD_DEMO

//芯片型号sdram和flash配置文件
#include "chip_cfg.h"

//不同板子外设配置文件,如有新的板子,在这里同理添加
#include "board_demo.h"

#ifdef CONFIG_NO_SDRAM_ENABLE
#undef  __SDRAM_SIZE__
#define __SDRAM_SIZE__    0
#else
#if (__SDRAM_SIZE__ == 0)
#ifndef CONFIG_NO_SDRAM_ENABLE
#define CONFIG_NO_SDRAM_ENABLE
#endif
#endif
#endif

Source: board_config.h

设计要点:

  • 板型开关:CONFIG_BOARD_DEMO 宏用于选中"demo 板"的外设配置。SDK 注释明确说明"如有新的板子,在这里同理添加"——即新增板子时在 board_config.h 中新增对应宏并 #include 新的 board_xxx.h;
  • 容量宏归一化:末尾的 #ifdef 逻辑保证"无 SDRAM 板子"(CONFIG_NO_SDRAM_ENABLE)与"__SDRAM_SIZE__ == 0"两种写法等价:要么在 board_demo.h 中显式关闭 SDRAM,要么由容量宏为 0 自动推导出关闭,避免两个配置源互相矛盾。

2. 芯片存储规格:chip_cfg.h

#define __FLASH_SIZE__    (1 * 1024 * 1024)
#define __SDRAM_SIZE__    (2 * 1024 * 1024)

Source: chip_cfg.h

这两个宏定义了板上 Flash(1MB)与 SDRAM/DDR(2MB)的容量,会被链接脚本、uboot 初始化及 board_config.h 的 SDRAM 开关逻辑共同引用。更换 Flash/SDRAM 颗粒规格时,优先改这里。

3. 外设与时钟配置:board_demo.h

board_demo.h 是所有 TCFG_* 宏的集中地,被 #ifdef CONFIG_BOARD_DEMO 包住,与板型开关一一对应。文件内部按功能模块分块:

//*********************************************************************************//
//                                功能模块配置                                     //
//*********************************************************************************//
#define CONFIG_SFC_ENABLE
#define CONFIG_BT_ENABLE
#define CONFIG_NO_SDRAM_ENABLE                                //关闭sdram

//*********************************************************************************//
//                                   时钟配置                                      //
//*********************************************************************************//
#define TCFG_OSC_FREQUENCY                  24000000
#define TCFG_SYS_CLK                        192000000         //240M,192M,160M,120M,96M,80M,64M,60M,48M,40M,32M,24M,其他值时启用SYS_PLL
#define TCFG_LSB_CLK                        48000000          //96M,80M,60M,48M,40M,24M,20M,12M
#define TCFG_HSB_CLK_DIV                    2                 //HSB_CLK = SYS_CLK / HSB_CLK_DIV
#define TCFG_SFCTZ_CLK                      48000000          //SFC时钟,和加载代码的速度有关
#define TCFG_SDRAM_CLK                      200000000         //SDRAM/DDR时钟

Source: board_demo.h

模块开关宏(CONFIG_SFC_ENABLE、CONFIG_BT_ENABLE、CONFIG_NO_SDRAM_ENABLE)决定了编译进固件的功能集;时钟宏则决定了芯片的电源域/总线频率。注意 TCFG_SYS_CLK 的注释列出了合法的整分频频率列表(240M/192M/160M/120M/96M/80M/64M/60M/48M/40M/32M/24M),只有列表之外的值才会走 SYS_PLL 路径——这体现了"优先使用片上分频、尽量避免 PLL 开销"的功耗设计取向。

4. Flash 与 SDRAM 时序参数

/*
#data_width[1 2 3 4] 3的时候uboot自动识别2或者4线
#clkdiv [1-255] SPITZ_CLK=SYS_CLK/HSB_CLK_DIV/clkdiv
#mode:
#	  0 RD_OUTPUT,		 1 cmd 		 1 addr
#	  1 RD_I/O,   		 1 cmd 		  x addr
#	  2 RD_I/O_CONTINUE] no_send_cmd x add
#port:固定0
*/
#define TCFG_SPITZ_WIDTH_CLKDIV_MODE_PORT   4_3_0_0

/*
#FLASH_QE_POS和FLASH_SPEC_QE_ID为'或'关系, 有一项条件符合,开机会按特殊QE位flash配置
#TCFG_FLASH_QE_POS     —— QE位置, 0-常规(SR2-BIT1), 1-特殊(SR1-BIT6)
#TCFG_FLASH_SPEC_QE_ID —— QE在SR1_BIT6的FlashID列表(最长128个字符, 'X'为通配符)
*/
#define TCFG_FLASH_QE_POS                   0
#define TCFG_FLASH_SPEC_QE_ID               C220XX_9D70XX_1C7019

#define TCFG_FREE_DCACHE_WAY                0
#define TCFG_SDRAM_MODE                     1              //0-sdram    1-ddr1

Source: board_demo.h

  • TCFG_SPITZ_WIDTH_CLKDIV_MODE_PORT 用下划线拼接四个参数:数据线宽度(1~4 线)、时钟分频、读取模式、端口。宽度为 3 时 uboot 自动识别 2/4 线,这是为了兼容不同封装/走线质量的板子;
  • QE(Quad Enable)位是 Flash 四线模式的前提:不同厂商 Flash 的 QE 位位置不同(常规在 SR2-BIT1,特殊在 SR1-BIT6)。TCFG_FLASH_QE_POS 与 TCFG_FLASH_SPEC_QE_ID 是"或"关系,任一命中即按特殊 QE 位配置,X 为通配符,可覆盖一整个 Flash ID 系列;
  • SDRAM 侧 TCFG_SDRAM_MODE 选择 SDRAM 还是 DDR1,TCFG_FREE_DCACHE_WAY 释放部分 D-Cache way 以换取更多可寻址内存。

5. UART 调试与数据口

#define TCFG_DEBUG_PORT                     IO_PORTD_01
#define TCFG_UBOOT_DEBUG_PORT               PD01

#define TCFG_UART0_ENABLE                   1              //UART0默认用来打印口
#define TCFG_UART0_TX_IO                    TCFG_DEBUG_PORT
#define TCFG_UART0_RX_IO                    -1
#define TCFG_UART0_BAUDRATE                 1000000
#define TCFG_UART0_PARITY                   UART_PARITY_DISABLE

#define TCFG_UART1_ENABLE                   1
#define TCFG_UART1_TX_IO                    IO_PORT_USB_DPA
#define TCFG_UART1_RX_IO                    IO_PORT_USB_DMA
#define TCFG_UART1_BAUDRATE                 1000000
#define TCFG_UART1_FLOW_CTL_ENABLE          0
#define TCFG_UART1_RTS_HW_ENABLE            0
#define TCFG_UART1_RTS_RX_THRESH            80
#define TCFG_UART1_MAX_CONTINUE_RECV_CNT    1024
#define TCFG_UART1_RTS_IO                   -1
#define TCFG_UART1_CTS_IO                   -1
#define TCFG_UART1_RTS_IDLE_LEVEL           0
#define TCFG_UART1_CTS_IDLE_LEVEL           0
#define TCFG_UART1_PARITY                   UART_PARITY_DISABLE

Source: board_demo.h

UART0 固定作为调试打印口(TCFG_DEBUG_PORT 同时被 uboot 使用,注意 uboot 阶段用字符串形式的 PD01,运行阶段用枚举 IO_PORTD_01,两者必须保持一致)。UART1 复用 USB 的 D+/D- 引脚(IO_PORT_USB_DPA/IO_PORT_USB_DMA),这是 AC792 系列常见的"串口复用 USB 引脚"做法,省去额外引脚;-1 表示未使用的引脚(如单 TX 的 UART0 RX、未启用的 RTS/CTS)。硬件流控相关宏(TCFG_UART1_RTS_RX_THRESH、TCFG_UART1_MAX_CONTINUE_RECV_CNT 等)只在 FLOW_CTL_ENABLE 打开时生效,为 MCU 侧拉低 RTS 的阈值提供了板级可调参数。

6. AD 按键分压网络

#define TCFG_ADKEY_ENABLE                   1              //AD按键
#define TCFG_ADKEY_INPUT_IO                 IO_PORTD_00
#define TCFG_ADKEY_INPUT_CHANNEL            ADC_IO_CH_PD00

#define ADKEY_UPLOAD_R                      22             //上拉电阻值
#define TCFG_ADC_LEVEL_09                   0x3FF
...
#define TCFG_ADC_LEVEL_04                   (ADC_VDDIO * 100 / (100 + ADKEY_UPLOAD_R))
#define TCFG_ADC_LEVEL_03                   (ADC_VDDIO * 33  / (33  + ADKEY_UPLOAD_R))
#define TCFG_ADC_LEVEL_02                   (ADC_VDDIO * 15  / (15  + ADKEY_UPLOAD_R))
#define TCFG_ADC_LEVEL_01                   (ADC_VDDIO * 51  / (51  + ADKEY_UPLOAD_R * 10))
#define TCFG_ADC_LEVEL_00                   (0)

#define TCFG_ADKEY_VALUE_0                  0
#define TCFG_ADKEY_VALUE_1                  1
#define TCFG_ADKEY_VALUE_2                  2
#define TCFG_ADKEY_VALUE_3                  3
#define TCFG_ADKEY_VALUE_4                  NO_KEY
...

Source: board_demo.h

AD 按键利用"按键串不同电阻 → ADC 采到不同分压"的原理,用一根 ADC 引脚识别多颗按键。TCFG_ADC_LEVEL_xx 定义各档位的分压阈值,TCFG_ADKEY_VALUE_xx 定义该档位映射的按键值(NO_KEY 表示无按键)。可以看到阈值直接按 ADC_VDDIO * R / (R + ADKEY_UPLOAD_R) 电阻分压公式写成宏——换按键电阻网络时只需改 ADKEY_UPLOAD_R 和各档位电阻值,无需动驱动。阈值的"中间值"计算(相邻档位取平均)发生在 board.c 中。

7. 电源与低功耗

#define TCFG_POWER_MODE                     PWR_DCDC15
#define TCFG_POWER_AVDD18_ENABLE            1
#define TCFG_POWER_AVDD28_ENABLE            1

#define TCFG_LOWPOWER_VDDIOM_LEVEL          VDDIOM_VOL_330V//强VDDIO电压档位
#define TCFG_LOWPOWER_VDDIOW_LEVEL          VDDIOW_VOL_200V //弱VDDIO电压档位
#define TCFG_LOWPOWER_VDC14_LEVEL           DCVDD_VOL_140V
#define TCFG_LOWPOWER_FUNCTION              LOWPOWER_CLOSE
#define TCFG_LOWPOWER_OSC_TYPE              OSC_TYPE_LRC

#define TCFG_LOWPOWER_WAKEUP_PORT0_ENABLE   0
#define TCFG_LOWPOWER_WAKEUP_PORT0_IO       IO_PORTA_01
#define TCFG_LOWPOWER_WAKEUP_PORT0_EDGE     FALLING_EDGE
#define TCFG_LOWPOWER_WAKEUP_PORT0_FILTER   PORT_FLT_DISABLE

Source: board_demo.h

电源配置体现了两级设计:运行态由 TCFG_POWER_MODE(DCDC 输出 1.5V 内核供电)与 AVDD18/AVDD28 使能决定;低功耗态由 TCFG_LOWPOWER_* 决定——进入低功耗后 VDDIO 从强档 3.3V 降到弱档 2.0V、内核电压降到 1.4V,振荡器切到 LRC(低频 RC 振荡器)。唤醒引脚(TCFG_LOWPOWER_WAKEUP_PORT0_*)支持边沿触发与滤波配置,board.c 中会为它注册 IRQ 上下文中的回调。

从宏到结构体:board.c 的平台数据实例化

board.c 是配置宏"落地"的地方:它把 board_demo.h 中的宏组装成驱动可以直接读取的 platform_data 结构体。以下按模块拆解其实现。

UART 平台数据

#if TCFG_UART0_ENABLE
UART0_PLATFORM_DATA_BEGIN(uart0_data)
#ifdef CONFIG_DEBUG_ENABLE
    .disable_tx_irq         = 1,
#endif
    .baudrate               = TCFG_UART0_BAUDRATE,
    .tx_pin                 = TCFG_UART0_TX_IO,
    .rx_pin                 = TCFG_UART0_RX_IO,
    .max_continue_recv_cnt  = 1024,
    .idle_sys_clk_cnt       = 500000,
    .flags                  = UART_DEBUG,
    .parity                 = TCFG_UART0_PARITY,
UART0_PLATFORM_DATA_END();
#endif

#if TCFG_UART1_ENABLE
UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .flow_ctl_enable        = TCFG_UART1_FLOW_CTL_ENABLE,
    .rts_hw_enable          = TCFG_UART1_RTS_HW_ENABLE,
    .baudrate               = TCFG_UART1_BAUDRATE,
    .tx_pin                 = TCFG_UART1_TX_IO,
    .rx_pin                 = TCFG_UART1_RX_IO,
    .rts_pin                = TCFG_UART1_RTS_IO,
    .cts_pin                = TCFG_UART1_CTS_IO,
    .rts_idle_level         = TCFG_UART1_RTS_IDLE_LEVEL,
    .cts_idle_level         = TCFG_UART1_CTS_IDLE_LEVEL,
    .rx_thresh              = TCFG_UART1_RTS_RX_THRESH,
    .max_continue_recv_cnt  = TCFG_UART1_MAX_CONTINUE_RECV_CNT,
    .idle_sys_clk_cnt       = 500000,
    .parity                 = TCFG_UART1_PARITY,
UART1_PLATFORM_DATA_END();
#endif

Source: board.c

UART0_PLATFORM_DATA_BEGIN/END 宏生成带有指定段属性(section attribute)的结构体实例,使链接器可以把平台数据放到特定内存区域。注意 CONFIG_DEBUG_ENABLE 时 UART0 会关闭 TX 中断(disable_tx_irq = 1)并打上 UART_DEBUG 标志——调试串口使用轮询发送以保证在中断被关闭的临界区(如低功耗切换)也能输出。

AD 按键阈值表

#if TCFG_ADKEY_ENABLE
#define ADC_VDDIO   (0x3FF)

#define ADKEY_V_9   ((TCFG_ADC_LEVEL_09 + ADC_VDDIO) / 2)
#define ADKEY_V_8   ((TCFG_ADC_LEVEL_08 + TCFG_ADC_LEVEL_09) / 2)
...
#define ADKEY_V_1   ((TCFG_ADC_LEVEL_01 + TCFG_ADC_LEVEL_02) / 2)
#define ADKEY_V_0   ((TCFG_ADC_LEVEL_00 + TCFG_ADC_LEVEL_01) / 2)

static const struct adkey_platform_data adkey_data = {
    .adkey_pin              = TCFG_ADKEY_INPUT_IO,
    .extern_up_en           = 1,
    .ad_channel             = TCFG_ADKEY_INPUT_CHANNEL,
    .ad_value               = { ADKEY_V_0, ..., ADKEY_V_9 },
    .key_value              = { TCFG_ADKEY_VALUE_0, ..., TCFG_ADKEY_VALUE_9 },
};

const struct adkey_platform_data *get_adkey_platform_data(void)
{
    return &adkey_data;
}
#endif

Source: board.c

关键设计:TCFG_ADC_LEVEL_xx 是"档位标称电压",而驱动需要的判定阈值取相邻档位的平均值(如 ADKEY_V_4 = (LEVEL_04 + LEVEL_05) / 2),从而把 ADC 采样值与按键档位做成"就近归类",对电阻精度和电源纹波有更好的容差。extern_up_en = 1 表示使用外部上拉电阻(与 ADKEY_UPLOAD_R 对应)。get_adkey_platform_data() 这种"getter 函数"是 SDK 平台数据注入的标准模式:驱动在初始化时调用它拿到只读配置。

设备表注册与电源参数

REGISTER_DEVICES(device_table) = {
#if TCFG_UART0_ENABLE
    { "uart0", &uart_dev_ops, (void *) &uart0_data },
#endif
#if TCFG_UART1_ENABLE
    { "uart1", &uart_dev_ops, (void *) &uart1_data },
#endif
};

static const power_param_t power_param = {
    .config                 = TCFG_LOWPOWER_FUNCTION,
    .btosc_hz               = 24000000,
    .vddiom_lev             = TCFG_LOWPOWER_VDDIOM_LEVEL,
    .vddiow_lev             = TCFG_LOWPOWER_VDDIOW_LEVEL,
    .vdc14_lev              = TCFG_LOWPOWER_VDC14_LEVEL,
    .osc_type               = TCFG_LOWPOWER_OSC_TYPE,
    .osc_delay_us           = 8000,
#if TCFG_POWER_AVDD18_ENABLE
    .avdd18_enable          = 1,
#endif
#if TCFG_POWER_AVDD28_ENABLE
    .avdd28_enable          = 1,
#endif
};

static const power_pdata_t power_pdata = {
    .power_param            = &power_param,
};

Source: board.c

REGISTER_DEVICES(device_table) 把 "uart0"/"uart1" 两个设备名、设备操作集 uart_dev_ops 与平台数据绑定在一起,应用层通过设备名(如 dev_open("uart0", ...))即可打开串口——设备表的存在让上层代码与具体引脚完全解耦。电源参数同样由宏驱动:osc_delay_us = 8000 是低功耗切振荡器时的稳定等待时间,属于芯片级经验值。

低功耗进入/退出回调

static u32 fusb_io_con = 0;
static u32 husb_io_con = 0;

// 进入、退出低功耗函数回调状态,函数单核操作、关中断,请勿做耗时操作
void sleep_enter_callback(u8 step)
{
    /* 此函数禁止添加打印 */
    putchar('<');

    //USB IO打印引脚特殊处理
#if (defined CONFIG_DEBUG_ENABLE) && ((TCFG_DEBUG_UART_TX_PIN == IO_PORT_USB_DPA) || (TCFG_DEBUG_UART_TX_PIN == IO_PORT_USB_DMA))
    fusb_io_con = JL_PORTFUSB->DIR;
    gpio_close(PORTFUSB, 0xffff);
#endif
...
}

void sleep_exit_callback(u32 usec)
{
#if (defined CONFIG_DEBUG_ENABLE) && ((TCFG_DEBUG_UART_TX_PIN == IO_PORT_USB_DPA) || (TCFG_DEBUG_UART_TX_PIN == IO_PORT_USB_DMA))
    JL_PORTFUSB->DIR = fusb_io_con;
#endif
...
}

Source: board.c

若调试串口复用了 USB D+/D- 引脚,则进入低功耗前必须保存并关闭对应端口(gpio_close),退出时恢复方向寄存器——否则 USB 引脚在低功耗下可能漏电或影响唤醒。注释明确要求回调内"禁止添加打印、单核操作、关中断",这是低功耗时序对板级代码的硬约束。

配置到运行的数据流

sequenceDiagram
    participant BoardC as board.c
    participant Driver as 外设驱动
    participant DevTable as 设备表
    participant App as 应用层

    BoardC->>BoardC: 读取 TCFG_* 宏,构造 platform_data 结构体
    BoardC->>DevTable: REGISTER_DEVICES(device_table) 注册 uart0/uart1
    BoardC->>Driver: get_adkey_platform_data() / power_pdata
    Driver->>Driver: 初始化时解析 platform_data 配置硬件寄存器
    App->>DevTable: dev_open("uart0")
    DevTable-->>App: 返回设备句柄(绑定 uart0_data)
    App->>Driver: 读写操作(收发、按键扫描、低功耗切换)
    Driver->>Driver: sleep_enter_callback / sleep_exit_callback 维护引脚状态

流程要点:

  1. 编译期:board_config.h 汇总 chip_cfg.h + board_demo.h 的宏,board.c 据此生成常量结构体,全部配置在编译时定型,运行期零解析开销;
  2. 启动期:设备表把 uart0/uart1 与平台数据绑定;驱动初始化时通过 get_adkey_platform_data() 等 getter 拉取按键配置,通过 power_pdata 拉取电源配置;
  3. 运行期:应用层只依赖设备名与平台数据 getter,换板子/换引脚不需要改应用代码,只需改板级配置宏后重新编译。

配置选项速查表

以下为 wl83 demo 板默认值,均定义于 board_demo.h 与 chip_cfg.h。

时钟

宏类型默认值说明
TCFG_OSC_FREQUENCY整数(Hz)24000000外部晶振频率
TCFG_SYS_CLK整数(Hz)192000000系统主频,支持 240M/192M/160M/…/24M,其他值启用 SYS_PLL
TCFG_LSB_CLK整数(Hz)48000000低速总线时钟
TCFG_HSB_CLK_DIV整数2HSB_CLK = SYS_CLK / HSB_CLK_DIV
TCFG_SFCTZ_CLK整数(Hz)48000000SFC 时钟,影响代码加载速度
TCFG_SDRAM_CLK整数(Hz)200000000SDRAM/DDR 时钟

Flash / SDRAM

宏类型默认值说明
__FLASH_SIZE__整数(Byte)1MB外挂 Flash 容量
__SDRAM_SIZE__整数(Byte)2MB外挂 SDRAM/DDR 容量
TCFG_SPITZ_WIDTH_CLKDIV_MODE_PORT拼接宏4_3_0_0SPI 线宽_分频_模式_端口
TCFG_FLASH_QE_POS整数0QE 位位置:0 常规(SR2-BIT1),1 特殊(SR1-BIT6)
TCFG_FLASH_SPEC_QE_ID字符串C220XX_9D70XX_1C7019QE 在 SR1-BIT6 的 FlashID 列表,X 通配
TCFG_SDRAM_MODE整数10-SDRAM,1-DDR1
TCFG_FREE_DCACHE_WAY整数0释放的 D-Cache way 数

UART

宏类型默认值说明
TCFG_DEBUG_PORT / TCFG_UBOOT_DEBUG_PORTIO 枚举/字符串IO_PORTD_01 / PD01调试口,uboot 与运行态须一致
TCFG_UART0_ENABLE整数1UART0 使能(默认打印口)
TCFG_UART0_BAUDRATE整数1000000UART0 波特率
TCFG_UART0_TX_IO / TCFG_UART0_RX_IOIO 枚举PD01 / -1UART0 引脚(-1 表示未用)
TCFG_UART1_ENABLE整数1UART1 使能
TCFG_UART1_TX_IO / TCFG_UART1_RX_IOIO 枚举USB_DPA / USB_DMAUART1 复用 USB 引脚
TCFG_UART1_FLOW_CTL_ENABLE / TCFG_UART1_RTS_HW_ENABLE整数0 / 0流控开关
TCFG_UART1_RTS_RX_THRESH整数80RTS 拉低触发阈值
TCFG_UART1_MAX_CONTINUE_RECV_CNT整数1024连续接收上限
TCFG_UART1_PARITY枚举UART_PARITY_DISABLE校验位

AD 按键 / 电源

宏类型默认值说明
TCFG_ADKEY_ENABLE整数1AD 按键使能
TCFG_ADKEY_INPUT_IO / TCFG_ADKEY_INPUT_CHANNELIO 枚举PD00 / ADC_IO_CH_PD00采样引脚与 ADC 通道
ADKEY_UPLOAD_R整数(kΩ)22上拉电阻值
TCFG_ADC_LEVEL_00~09表达式见源码各档位分压阈值
TCFG_ADKEY_VALUE_0~9整数/枚举0~3, NO_KEY…档位映射的按键值
TCFG_POWER_MODE枚举PWR_DCDC15内核供电方式
TCFG_LOWPOWER_VDDIOM/W_LEVEL枚举330V / 200V强/弱 VDDIO 电压档
TCFG_LOWPOWER_FUNCTION枚举LOWPOWER_CLOSE低功耗开关
TCFG_LOWPOWER_OSC_TYPE枚举OSC_TYPE_LRC低功耗振荡器
TCFG_LOWPOWER_WAKEUP_PORT0_*组合关闭唤醒引脚/边沿/滤波

API 参考(板级层对外接口)

REGISTER_DEVICES(device_table)

板级设备注册宏,将平台数据与设备操作集绑定进系统设备表。

  • 作用:注册 "uart0" / "uart1" 设备,应用层经 dev_open("uart0", ...) 使用;
  • 实现位置:board.c 第 129-136 行。

const struct adkey_platform_data *get_adkey_platform_data(void)

返回 AD 按键平台数据指针,由 AD 按键驱动在初始化时调用。

  • 返回:静态 adkey_data 的地址(含 adkey_pin、ad_channel、10 档 ad_value 阈值与 key_value 映射);
  • 实现位置:board.c 第 88-91 行。

void sleep_enter_callback(u8 step) / void sleep_exit_callback(u32 usec)

低功耗进出回调,由电源管理框架在关中断的 IRQ 上下文调用。

  • 约束:禁止打印(仅允许 putchar)、单核操作、禁止耗时操作;
  • 职责:保存/恢复 USB 复用调试口的 GPIO 方向寄存器,防止低功耗下漏电;
  • 实现位置:board.c 第 178-200 行。

平台数据 getter 约定

SDK 中每个可配置外设都有对应的 get_xxx_platform_data() 模式(如 get_adkey_platform_data),板级层提供常量数据,驱动层只读消费,二者通过弱符号/头文件声明解耦——这是新增板级配置项时应当遵循的扩展模式。

失败模式、边界情况与并发注意

  • SDRAM 配置自相矛盾:board_config.h 末尾的逻辑保证 __SDRAM_SIZE__ == 0 时自动推导 CONFIG_NO_SDRAM_ENABLE。若两者不一致(例如头文件中写死 0 却未定义关闭宏),配置会被强制归一化——修改容量时两个地方需同步确认;
  • uboot 与运行态调试口不一致:TCFG_DEBUG_PORT(IO 枚举)与 TCFG_UBOOT_DEBUG_PORT(字符串)必须指向同一引脚,否则会出现"uboot 有打印、进系统后无打印"的经典问题;
  • UART 引脚冲突:UART1 复用 USB D+/D- 时,若同时使能 USB 设备,引脚方向会被抢占;板级配置应保证同一引脚只被一个外设占用;
  • AD 按键档位重叠:若电阻分压网络设计不当,ADKEY_V_x 相邻阈值可能重叠,导致按键误判。调整 TCFG_ADC_LEVEL_xx 时需保证各档位电压间隔大于 ADC 噪声(建议 ≥ 50mV);
  • 低功耗回调时序:sleep_enter_callback 在关中断上下文执行,任何耗时操作(如 I²C 访问、打印)都会拉长低功耗切换窗口,甚至导致唤醒失败;USB 复用引脚未在退出时恢复方向寄存器会引发漏电;
  • 调试口关闭 TX 中断:CONFIG_DEBUG_ENABLE 时 UART0 走轮询发送,高波特率(1Mbps)下长时间打印会占用 CPU——量产固件通常关闭该宏。

性能与运维提示

  • TCFG_SFCTZ_CLK 直接决定 SFC 读 Flash 的速度,进而影响上电代码搬运耗时;提高它可加快启动,但需确认 Flash 时序余量;
  • TCFG_SYS_CLK 越高,CPU 越省电(同负载下更快进入空闲),但动态功耗上升;TCFG_HSB_CLK_DIV 控制高速总线分频,外设(如 SFC、DMA)频率上限受其约束;
  • 所有板级配置均为编译期常量,不占用运行期解析成本;改动板级配置后需全量重编(宏参与链接脚本与启动代码生成);
  • 调试串口波特率(1Mbps)在换用不同 USB 转串口芯片时可能不稳定,量产验证建议使用板级宏统一调整。

扩展点:如何新增一块板子

  1. 在 board/wl83/ 同级新建 board/<新板名>/ 目录,复制 board_config.h、board_demo.h、chip_cfg.h、board.c 为模板;
  2. 在 board_demo.h 中把 #ifdef CONFIG_BOARD_DEMO 改为 #ifdef CONFIG_BOARD_<新板名>,并修改各 TCFG_* 宏匹配新板硬件(引脚、时钟、Flash 容量、按键电阻、电源档位);
  3. 在 board_config.h 中定义 CONFIG_BOARD_<新板名> 并 #include "board_<新板名>.h"(源码注释明确建议"在这里同理添加");
  4. 在 board.c 中确认设备表与平台数据 getter 覆盖新板启用的外设,并同步 Makefile/工程文件中源文件列表;
  5. 同一 SDK 内多板并存时,各板配置互不影响——这正是 board_config.h → board_demo.h 两级 include 设计的价值所在。

Related Links

  • 板级配置总入口 board_config.h
  • wl83 外设配置 board_demo.h
  • 芯片存储配置 chip_cfg.h
  • 平台数据实例化 board.c
  • 相关能力页面:时钟/电源管理、UART 驱动、AD 按键驱动、Flash/SFC 驱动(各驱动内部实现细节请参见对应驱动页面)
Prev
功能配置
Next
网络与蓝牙配置