板级配置
本文档介绍 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),其设计意图非常明确:
- 把硬件差异收口到一处:时钟频率、引脚分配、存储规格、按键档位、电源档位等全部以
TCFG_*/CONFIG_*宏形式集中定义,驱动代码只读这些宏,不直接写硬件数值; - 配置与实现分离:头文件(
*_cfg.h/*_demo.h)只声明"配置什么",board.c负责把配置实例化为驱动可消费的platform_data结构体并注册; - 多板支持:通过
#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 维护引脚状态
流程要点:
- 编译期:
board_config.h汇总chip_cfg.h+board_demo.h的宏,board.c据此生成常量结构体,全部配置在编译时定型,运行期零解析开销; - 启动期:设备表把
uart0/uart1与平台数据绑定;驱动初始化时通过get_adkey_platform_data()等 getter 拉取按键配置,通过power_pdata拉取电源配置; - 运行期:应用层只依赖设备名与平台数据 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 | 整数 | 2 | HSB_CLK = SYS_CLK / HSB_CLK_DIV |
TCFG_SFCTZ_CLK | 整数(Hz) | 48000000 | SFC 时钟,影响代码加载速度 |
TCFG_SDRAM_CLK | 整数(Hz) | 200000000 | SDRAM/DDR 时钟 |
Flash / SDRAM
| 宏 | 类型 | 默认值 | 说明 |
|---|---|---|---|
__FLASH_SIZE__ | 整数(Byte) | 1MB | 外挂 Flash 容量 |
__SDRAM_SIZE__ | 整数(Byte) | 2MB | 外挂 SDRAM/DDR 容量 |
TCFG_SPITZ_WIDTH_CLKDIV_MODE_PORT | 拼接宏 | 4_3_0_0 | SPI 线宽_分频_模式_端口 |
TCFG_FLASH_QE_POS | 整数 | 0 | QE 位位置:0 常规(SR2-BIT1),1 特殊(SR1-BIT6) |
TCFG_FLASH_SPEC_QE_ID | 字符串 | C220XX_9D70XX_1C7019 | QE 在 SR1-BIT6 的 FlashID 列表,X 通配 |
TCFG_SDRAM_MODE | 整数 | 1 | 0-SDRAM,1-DDR1 |
TCFG_FREE_DCACHE_WAY | 整数 | 0 | 释放的 D-Cache way 数 |
UART
| 宏 | 类型 | 默认值 | 说明 |
|---|---|---|---|
TCFG_DEBUG_PORT / TCFG_UBOOT_DEBUG_PORT | IO 枚举/字符串 | IO_PORTD_01 / PD01 | 调试口,uboot 与运行态须一致 |
TCFG_UART0_ENABLE | 整数 | 1 | UART0 使能(默认打印口) |
TCFG_UART0_BAUDRATE | 整数 | 1000000 | UART0 波特率 |
TCFG_UART0_TX_IO / TCFG_UART0_RX_IO | IO 枚举 | PD01 / -1 | UART0 引脚(-1 表示未用) |
TCFG_UART1_ENABLE | 整数 | 1 | UART1 使能 |
TCFG_UART1_TX_IO / TCFG_UART1_RX_IO | IO 枚举 | USB_DPA / USB_DMA | UART1 复用 USB 引脚 |
TCFG_UART1_FLOW_CTL_ENABLE / TCFG_UART1_RTS_HW_ENABLE | 整数 | 0 / 0 | 流控开关 |
TCFG_UART1_RTS_RX_THRESH | 整数 | 80 | RTS 拉低触发阈值 |
TCFG_UART1_MAX_CONTINUE_RECV_CNT | 整数 | 1024 | 连续接收上限 |
TCFG_UART1_PARITY | 枚举 | UART_PARITY_DISABLE | 校验位 |
AD 按键 / 电源
| 宏 | 类型 | 默认值 | 说明 |
|---|---|---|---|
TCFG_ADKEY_ENABLE | 整数 | 1 | AD 按键使能 |
TCFG_ADKEY_INPUT_IO / TCFG_ADKEY_INPUT_CHANNEL | IO 枚举 | 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 转串口芯片时可能不稳定,量产验证建议使用板级宏统一调整。
扩展点:如何新增一块板子
- 在
board/wl83/同级新建board/<新板名>/目录,复制board_config.h、board_demo.h、chip_cfg.h、board.c为模板; - 在
board_demo.h中把#ifdef CONFIG_BOARD_DEMO改为#ifdef CONFIG_BOARD_<新板名>,并修改各TCFG_*宏匹配新板硬件(引脚、时钟、Flash 容量、按键电阻、电源档位); - 在
board_config.h中定义CONFIG_BOARD_<新板名>并#include "board_<新板名>.h"(源码注释明确建议"在这里同理添加"); - 在
board.c中确认设备表与平台数据 getter 覆盖新板启用的外设,并同步 Makefile/工程文件中源文件列表; - 同一 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 驱动(各驱动内部实现细节请参见对应驱动页面)