杰理 SDK 文档中心
首页
首页
  • 概述与入门

    • 项目概览
    • 快速开始与开发环境
  • 应用与运行时

    • 应用入口与主循环
    • 按键驱动与用户消息处理
    • 消息系统
  • 固件升级

    • 双备份升级机制与状态机
    • UART 升级传输
    • 升级校验、启动信息与复位流程
  • 芯片与硬件支持

    • AC63 系列芯片 BSP 结构
    • 外设接口与驱动
    • 低功耗、RTC 与时基唤醒
  • 构建与工具

    • 构建系统与工作区
    • 烧写与量产工具
  • 参考资源

    • 数据手册与原理图
    • 双备份升级文档

外设接口与驱动

本文档介绍 AC632N(AC63 系列 MCU)BSP 层提供的外设接口与驱动体系,涵盖 GPIO、引脚复用(CrossBar)、ADC、硬件/软件 IIC、MCPWM、脉冲计数、按键、唤醒、充电检测等驱动的接口约定、寄存器操作模型与典型使用流程。

Purpose and Scope

本页面向 sdk/bsp/AC632N/ 目录下的外设驱动层,说明:

  • GPIO 驱动:引脚编号体系、方向/上下拉/数字模拟功能控制、输出驱动能力配置。
  • CrossBar 引脚复用:通过 JL_IMAP / JL_OMAP 寄存器把外设信号(UART、SPI、IIC、定时器捕获、PWM 故障引脚等)路由到任意 IO。
  • ADC 驱动:通道定义、异步中断采样与同步轮询采样两种模式、AD 值到电压的换算。
  • IIC 驱动:硬件 IIC(寄存器级主从模式)与软件模拟 IIC 两套实现。
  • 其他外设:MCPWM、脉冲计数(PL-CNT)、按键驱动、端口唤醒、充电检测、调试串口等 BSP 模块的定位与归属。

不涉及的内容:时钟/电源管理(见时钟与电源相关页面)、Flash 存储、蓝牙协议栈、音频编解码等由 sdk/apps 与其他 BSP 模块承载的能力。本文聚焦"如何把芯片引脚与片内外设用起来"这一层。

Overview

AC632N 是杰理科技 AC63 系列低功耗 MCU,其 BSP(Board Support Package)位于 sdk/bsp/AC632N/,其中:

  • include/asm/ 存放驱动头文件(gpio.h、adc_api.h、iic_hw.h、iic_soft.h、charge.h、hwi.h、io_imap.h、io_omap.h 等);
  • src/ 存放驱动实现(gpio.c、adc.c、iic_hw.c、iic_soft.c、mcpwm.c、plcnt.c、key_driver.c、port_wkup.c、charge.c、debug_uart.c 等)。

外设驱动的设计遵循"寄存器封装 + 句柄式 API"的经典 BSP 模式:

  1. 引脚抽象:所有外设共用同一套 IO_PORTx_xx 编号,例如 IO_PORTA_00 表示 A 组第 0 脚,编号本身即端口基址的偏移,gpio2reg() 可将其换算成 struct gpio_reg * 寄存器视图。
  2. 功能复用:IO 既是普通 GPIO,也是外设信号的载体,通过 CrossBar 的输入功能表(enum PFI_TABLE)与输出映射寄存器(io_omap.h 中的 FO_* 索引)实现任意 IO 到任意外设的灵活路由。
  3. 同步/异步双模式:如 ADC 同时提供 adc_get_value()(死等)与 adc_get_value_by_isr()(中断回调)两种采样方式,兼顾简单性与实时性。
  4. 主从模式统一:硬件 IIC 通过 struct hw_iic_config 配置端口/波特率/角色,主机与从机行为由 CON0 寄存器位控制宏区分。

关键概念:

  • struct gpio_reg:一组端口的 9 个控制寄存器(out/in/dir/die/pu/pd/hd0/hd/dieh)。
  • enum PFI_TABLE:CrossBar 可输入外设信号索引(如 PFI_UART0_RX、PFI_IIC_SCL)。
  • AD_CH_* / ADC_PMU_CH_*:ADC 模拟输入通道与 PMU 内部通道(VBAT、LDO5V、温度等)。
  • hw_iic_dev:硬件 IIC 句柄(const int),配合 hw_iic_cfg[] 平台配置表使用。

Architecture

flowchart TD
    subgraph sg_App["应用层 sdk/apps"]
        Main["main.c / board_demo.c"]
    end

    subgraph sg_BSP_API["BSP 外设 API 层 include/asm"]
        GPIO_H["gpio.h<br/>GPIO + CrossBar"]
        ADC_H["adc_api.h"]
        IIC_HW_H["iic_hw.h"]
        IIC_SOFT_H["iic_soft.h"]
        MISC_H["charge.h / hwi.h / clock.h ..."]
    end

    subgraph sg_BSP_SRC["BSP 驱动实现层 src"]
        GPIO_C["gpio.c"]
        ADC_C["adc.c"]
        IIC_HW_C["iic_hw.c"]
        IIC_SOFT_C["iic_soft.c"]
        OTHER_C["mcpwm.c / plcnt.c / key_driver.c<br/>port_wkup.c / charge.c / debug_uart.c"]
    end

    subgraph sg_HW["硬件层"]
        REGS["寄存器视图<br/>struct gpio_reg / JL_IMAP / JL_OMAP / JL_IIC / JL_ADC"]
        PINS["芯片引脚 A/B/D/P + USB + P33"]
    end

    Main --> GPIO_H
    Main --> ADC_H
    Main --> IIC_HW_H
    Main --> IIC_SOFT_H

    GPIO_H --> GPIO_C
    ADC_H --> ADC_C
    IIC_HW_H --> IIC_HW_C
    IIC_SOFT_H --> IIC_SOFT_C
    MISC_H --> OTHER_C

    GPIO_C --> REGS
    ADC_C --> REGS
    IIC_HW_C --> REGS
    OTHER_C --> REGS
    REGS --> PINS

各层职责:

  • 应用层(sdk/apps/main.c、board_demo.c)通过头文件暴露的 API 使用外设,不直接触碰寄存器。
  • API 层以头文件形式定义接口契约:引脚宏、枚举、结构体与函数原型,是驱动唯一的"公共表面"。
  • 实现层把 API 翻译成对 struct gpio_reg、JL_IMAP、JL_OMAP、JL_IIC、JL_ADC 等寄存器结构的读写,完成位操作。
  • 硬件层由 AC632N.h / csfr.h 定义寄存器布局,最终作用到芯片引脚(A/B/D/P 四组普通 IO + USB 复用 IO + P33 电源检测 IO)。

该分层让应用代码与具体寄存器解耦:更换引脚只需改宏/配置表,无需改动业务逻辑。

主要外设驱动详解

GPIO 驱动

引脚编号体系

gpio.h 以 IO_GROUP_NUM 16 为每组端口容量,用线性编号统一表达所有引脚:

#define IO_GROUP_NUM 		16
#define IO_PORTA_00 			(IO_GROUP_NUM * 0 + 0)
#define IO_PORTA_09 			(IO_GROUP_NUM * 0 + 9)
#define IO_PORTB_00 			(IO_GROUP_NUM * 1 + 0)
#define IO_PORTB_09 			(IO_GROUP_NUM * 1 + 9)
#define IO_PORTD_00 			(IO_GROUP_NUM * 2 + 0)
#define IO_PORTP_00 			(IO_GROUP_NUM * 3 + 0)
#define IO_MAX_NUM 			(IO_PORTP_00 + 1)

Source: gpio.h

编号设计意图:IO_PORTx_yy = 组号*16 + 组内序号,因此"引脚序号"与"端口基址偏移"天然对应,gpio2reg() 只需按编号定位到 GPIOA/GPIOB/GPIOD/GPIOP 之一,即可返回 struct gpio_reg *。普通 IO 之外,USB 与电源检测引脚被编码在 IO_MAX_NUM 之后的扩展区:

#define IO_PORT_DP                  (IO_MAX_NUM + 0)
#define IO_PORT_DM                  (IO_MAX_NUM + 1)
#define IO_PORT_DP1                 (IO_MAX_NUM + 2)
#define IO_PORT_DM1                 (IO_MAX_NUM + 3)
#define IO_CHGFL_DET                (IO_MAX_NUM + 4)
#define IO_VBGOK_DET                (IO_MAX_NUM + 5)
#define IO_VBTCH_DET                (IO_MAX_NUM + 6)
#define IO_LDOIN_DET                (IO_MAX_NUM + 7)
#define IO_PORT_MAX			(IO_LDOIN_DET + 1)

Source: gpio.h

寄存器视图

每个端口组对应一个 struct gpio_reg,它直接映射硬件寄存器布局:

struct gpio_reg {
    volatile unsigned int out;
    volatile unsigned int in;
    volatile unsigned int dir;
    volatile unsigned int die;
    volatile unsigned int pu;
    volatile unsigned int pd;
    volatile unsigned int hd0;
    volatile unsigned int hd;
    volatile unsigned int dieh;
};

Source: gpio.h

  • out:输出电平寄存器;in:输入电平寄存器。
  • dir:方向(0 输出 / 1 输入,见 enum gpio_direction)。
  • die/dieh:数字功能使能。作为 ADC 等模拟输入时必须把 die 置 0(数字缓冲关闭)。
  • pu/pd:上拉/下拉(10K,输入模式有效)。
  • hd0/hd:输出内阻与电流增强控制(输出模式有效),用于驱动能力调整。

核心 API 一览

函数作用关键约定
struct gpio_reg *gpio2reg(u32 gpio)引脚序号 → 端口寄存器返回 JL_PORTA 等基址
int gpio_set_direction(u32 gpio, u32 value)设置方向1 输入 / 0 输出;非 0 返回失败
int gpio_direction_input(u32 gpio)直接设为输入便捷封装
int gpio_direction_output(u32 gpio, u32 value)设为输出并同时置电平避免先配方向再写电平的毛刺
int gpio_read(u32 gpio) / gpio_read_input_value()读输入电平输入模式下有效
int gpio_write(u32 gpio, u32 value) / gpio_set_output_value()写输出电平输出模式下有效
int gpio_set_pull_up(u32 gpio, u32 value)上拉 10K输入模式有效
int gpio_set_pull_down(u32 gpio, u32 value)下拉 10K输入模式有效
int gpio_set_hd0(u32 gpio, u32 value)关闭内阻增强输出输出模式有效
int gpio_set_hd(u32 gpio, u32 value)增大输出电流输出模式有效
int gpio_set_die(u32 gpio, u32 value)数字/模拟功能切换ADC 输入需 die=0
int gpio_set_dieh(u32 gpio, u32 value)另一组数字/模拟切换与 die 模拟通路不同
u32 get_gpio(const char *p)解析 "PA00" 字符串"PB01" → 17
void usb_iomode(u32 enable) / usb1_iomode()USB 引脚复用为普通 IO使能后 DP/DM 变 GPIO

设计意图:gpio_direction_output(gpio, value) 把"方向+初值"合成一个原子操作,避免按键/指示灯等场景下输出瞬间出现错误电平;get_gpio() 支持用字符串配置引脚,便于板级配置表(如 board_demo.c)以文本形式描述管脚用途。

CrossBar 引脚复用(BR30 Crossbar API)

CrossBar 是 AC632N 外设路由的核心:IO 既是 GPIO,又能承载 UART/SPI/IIC/定时器捕获/PWM 等片内外设信号,路由关系通过 JL_IMAP(输入映射)与 JL_OMAP(输出映射)寄存器配置。

输入侧信号索引定义在 enum PFI_TABLE 中,覆盖了绝大多数外设输入:

enum PFI_TABLE {
    PFI_GP_ICH0 = ((u32)(&(JL_IMAP->FI_GP_ICH0))),
    PFI_TMR0_CIN = ((u32)(&(JL_IMAP->FI_TMR0_CIN))),
    PFI_TMR0_CAP = ((u32)(&(JL_IMAP->FI_TMR0_CAP))),
    PFI_SPI0_CLK = ((u32)(&(JL_IMAP->FI_SPI0_CLK))),
    PFI_SPI1_DA3 = ((u32)(&(JL_IMAP->FI_SPI1_DA3))),
    PFI_MCPWM_TMR0_CLKI = ((u32)(&(JL_IMAP->FI_MCPWM_TMR0_CLKI))),
    PFI_MCPWM_FPIN_A = ((u32)(&(JL_IMAP->FI_MCPWM_FPIN_A))),
    PFI_IIC_SCL = ((u32)(&(JL_IMAP->FI_IIC_SCL))),
    PFI_IIC_SDA = ((u32)(&(JL_IMAP->FI_IIC_SDA))),
    PFI_UART0_RX = ((u32)(&(JL_IMAP->FI_UART0_RX))),
    PFI_UART1_RX = ((u32)(&(JL_IMAP->FI_UART1_RX))),
    PFI_UART1_CTS = ((u32)(&(JL_IMAP->FI_UART1_CTS))),
    PFI_UART2_RX = ((u32)(&(JL_IMAP->FI_UART2_RX))),
    PFI_RDEC0_DAT0 = ((u32)(&(JL_IMAP->FI_RDEC0_DAT0))),
    PFI_CHAIN_IN0 = ((u32)(&(JL_IMAP->FI_CHAIN_IN0))),
    PFI_TOTAL = ((u32)(&(JL_IMAP->FI_TOTAL))),
};

Source: gpio.h

枚举值直接取 JL_IMAP 寄存器地址,因此 gpio_set_fun_input_port(gpio, pfun) 内部只需把对应寄存器写成目标 IO 序号。输出侧由 gpio_set_fun_output_port() 完成,功能索引(如 FO_UART0_TX)定义在 io_omap.h。四个关键 API:

函数作用
int gpio_set_fun_output_port(u32 gpio, u32 fun_index, u8 dir_ctl, u8 data_ctl)把外设输出信号(fun_index)路由到指定 IO;dir_ctl/data_ctl 常设为 1,表示方向与电平由外设接管
int gpio_disable_fun_output_port(u32 gpio)释放 IO 的外设输出控制,恢复普通 IO
int gpio_set_fun_input_port(u32 gpio, enum PFI_TABLE pfun)把外设输入信号(如 PFI_UART0_RX)接到指定 IO
int gpio_disable_fun_input_port(enum PFI_TABLE pfun)释放某外设输入的 IO 占用

头文件给出了标准使用顺序(UART0 TX 输出到 IO_PORTA_05):

// gpio_direction_output(IO_PORTA_05, 1); //设置IO为输出状态
// gpio_set_fun_output_port(IO_PORTA_05, FO_UART0_TX, 1, 1); //将UART0的Tx信号输出到IO_PORTA_05口

Source: gpio.h

输入方向(UART0 RX 从 IO_PORTA_05 输入)的约定是:先 gpio_set_die(pin, 1) 使能数字输入,再 gpio_set_pull_up(pin, 1) 上拉,然后 gpio_direction_input(),最后 gpio_set_fun_input_port(IO_PORTA_05, PFI_UART0_RX)。这个顺序保证在信号接驳前引脚已经是稳定的数字输入态,避免误触发。

ADC 驱动

adc_api.h 定义了完整的 ADC 通道体系:14 个模拟输入通道(PA1/PA3/PA5/PA7/PA8/PA9、PB1/PB4/PB6、DP/DM/DP1/DM1、PMU)加上 PMU 内部通道(VBG 基准、SYSVDD、VBAT 1/4 分压、LDO5V 1/4 分压、DIE 温度等):

#define AD_CH_PA1    (0x0)
#define AD_CH_PA8    (0x4)
#define AD_CH_PB1    (0x7)
#define AD_CH_PMU    (0xd)

#define ADC_PMU_CH_VBG       (0x0<<16)  //MVBG
#define ADC_PMU_CH_VBAT      (0x5<<16)     //1/4vbat
#define ADC_PMU_CH_LDO5V     (0x6<<16)     //1/4 LDO5V
#define ADC_PMU_CH_DTEMP     (0x3<<16)

#define AD_CH_PMU_VBG   (AD_CH_PMU | ADC_PMU_CH_VBG)
#define AD_CH_VBAT      (AD_CH_PMU | ADC_PMU_CH_VBAT)
#define AD_CH_LDO5V     (AD_CH_PMU | ADC_PMU_CH_LDO5V)
#define AD_CH_LDOREF    AD_CH_PMU_VBG

Source: adc_api.h

通道号编码技巧:低 16 位放物理通道,高 16 位放 PMU 子通道,通过 AD_CH_PMU | ADC_PMU_CH_xxx 组合出内部通道。AD_CH_LDOREF 即内部 VBG 基准,是电压换算的参考值来源。

核心 API:

函数模式说明
void adc_init(void)—ADC 模块初始化
u32 adc_get_value(u32 ch)同步死等转换结束返回 AD 值,简单但阻塞
void adc_get_value_by_isr(u32 ch, void (*cbfun)(u8, u16))异步使能采样后立即返回,转换完成中断里执行回调
u32 adc_value_to_voltage(u32 adc_vbg, u32 adc_ch_val)—用 VBG 基准 AD 值换算通道电压(mV)
u32 adc_get_voltage(u32 ch)同步一步获取通道电压(mV),内部完成基准采样+换算
void adc_test(void)—SDK 参考示例

设计意图:同步模式适合初始化自检、低频轮询;异步中断模式适合电源监测等需要"采完就走、不阻塞主循环"的场景,回调签名 void(*)(u8, u16) 携带通道号与 16 位 AD 值。电压换算不依赖固定满量程,而是实时采样 AD_CH_LDOREF 基准再按比例计算,从而抵消 VDD 波动对采样精度的干扰。

IIC 驱动

AC632N 同时提供两套 IIC 实现:硬件 IIC(iic_hw.h / iic_hw.c,占用片内 IIC 外设)与软件模拟 IIC(iic_soft.h / iic_soft.c,GPIO 位翻转模拟时序)。

硬件 IIC

iic_hw.h 是典型的寄存器宏封装头:全部时序控制以宏方式映射到 CON0/BAUD/BUF/ADR/CNT 寄存器位,分为公共、主机、从机三组:

#define iic_enable(reg)             (reg->CON0 |= BIT(0))
#define iic_kick_start(reg)         (reg->CON0 |= BIT(1))
#define iic_isel_filter(reg)        (reg->CON0 |= BIT(3))
#define iic_dir_in(reg)             (reg->CON0 |= BIT(4))
#define iic_int_enable(reg)         (reg->CON0 |= BIT(8))
#define iic_is_pnding(reg)          ((reg->CON0 & BIT(31)))
#define iic_force_nack(reg)         (reg->CON0 |= BIT(11))
#define iic_restart(reg)            (reg->CON0 |= BIT(13)) //没有stop, 发start

#define iic_host_mode(reg)          (reg->CON0 &= ~BIT(2))
#define iic_host_send_stop(reg)     (reg->CON0 |= BIT(5))
#define iic_host_is_stop_pending(reg)   ((reg->CON0 & BIT(29)))
#define iic_host_send_is_ack(reg)       ((reg->CON0 & BIT(30)))
#define iic_host_dma_send_enable(reg)   (reg->CON0 |= BIT(17))

#define iic_slave_mode(reg)         (reg->CON0 |= BIT(2))
#define iic_slave_dma_enable(reg)   (reg->CON0 |= BIT(15))
#define iic_slave_dma_buf(reg)      (reg->ADR)
#define iic_slave_dma_buf_depth(reg)(reg->CNT)
#define iic_slave_scl_pull_down_enble(reg) (reg->CON0 |= BIT(12))
#define iic_slave_is_required_send(reg)    (reg->CON0 & BIT(28))
#define iic_slave_send_is_end(reg)         (reg->CON0 & BIT(27))

Source: iic_hw.h

位定义的设计要点:方向位(BIT4)、中断位(BIT8)、主从模式位(BIT2)共用同一个 CON0 寄存器,因此宏按位操作而非常量赋值——避免并发配置时互相覆盖;iic_kick_start/iic_host_read_kick_start 是"启动"位,写 1 即触发一次总线动作,完成状态通过 iic_is_pnding/iic_host_is_stop_pending/iic_host_send_is_ack 查询。

句柄与配置表:hw_iic_dev 是 const int 句柄,索引平台配置表 hw_iic_cfg[],每个条目描述端口、波特率与角色:

typedef const int hw_iic_dev;
enum {IIC_MASTER, IIC_SLAVE};

struct hw_iic_config {
    u8 port[2];
    u32 baudrate;
    u8 hdrive;
    u8 io_filter;
    u8 io_pu;
    u8 role;
};
extern const struct hw_iic_config hw_iic_cfg[];

Source: iic_hw.h

API 分为生命周期(hw_iic_init / hw_iic_uninit / hw_iic_suspend / hw_iic_resume)、总线控制(hw_iic_start / hw_iic_stop)、单字节收发(hw_iic_tx_byte / hw_iic_rx_byte)与批量收发(hw_iic_read_buf / hw_iic_write_buf)以及 hw_iic_set_baud。约定:tx_byte 返回 1 表示收到 ACK;批量接口返回实际长度,< 0 表示失败。suspend/resume 与 uninit/init 的区别在于:前者保留配置、仅停用外设(低功耗挂起场景),后者彻底释放资源。

软件模拟 IIC

iic_soft.h / iic_soft.c 提供不依赖片内外设的 GPIO 位操作 IIC,适用于引脚数量紧张或硬件 IIC 已被占用的场景。其接口形态与硬件版对等(初始化、起始/停止、读写字节/缓冲),实现上通过 gpio_set_direction / gpio_write / gpio_read 在 SCL/SDA 上逐位翻转时序。选择建议:总线速率要求高、或需要 DMA/多从机仲裁时用硬件 IIC;只是低速挂接 EEPROM/传感器时,软件 IIC 可节省片内外设资源(BSP 中 iic_eeprom_test.c 即典型应用场景)。

其他 BSP 外设模块

src/ 下还有若干面向产品功能的外设驱动,均遵循"头文件声明 + 配置表 + 回调"的同一风格:

模块源文件职责
MCPWMmcpwm.c多通道 PWM,支持 4 组定时器时钟输入与 A/B/C/D 故障引脚(见 PFI_MCPWM_*),用于电机/背光等驱动
脉冲计数plcnt.c脉冲计数/编码器计数,输入可来自 PFI_GP_ICHx 或 PFI_RDECx_DATx
按键驱动key_driver.c矩阵/AD 按键扫描、去抖与事件上报
端口唤醒port_wkup.c低功耗模式下 IO 电平变化唤醒,复用 gpio_set_pull_up 等配置
充电检测charge.c充电状态监测,依赖扩展 IO IO_CHGFL_DET / IO_VBGOK_DET / IO_VBTCH_DET / IO_LDOIN_DET
调试串口debug_uart.c早期打印与调试通道,通常独占一路 UART(PFI_UARTx_RX 输入侧)
硬件中断hwi.c中断控制器封装,供驱动注册 ISR(ADC 异步回调即挂在此机制上)

注:以上模块的接口细节未在本次文档采集中逐一定位,具体函数签名请以对应头文件为准;本文档侧重共享的引脚/寄存器/复用机制。

Core Flow

CrossBar 外设复用配置流程

flowchart TD
    Start([配置外设复用]) --> Die["gpio_set_die(pin, 1)<br/>使能数字功能"]
    Die --> Dir{"输入 or 输出?"}
    Dir -->|"输入 (如 UART RX)"| Pull["gpio_set_pull_up(pin, 1)<br/>上拉稳定电平"]
    Pull --> In["gpio_direction_input(pin)"]
    In --> MapIn["gpio_set_fun_input_port(pin, PFI_UART0_RX)"]
    Dir -->|"输出 (如 UART TX)"| Out["gpio_direction_output(pin, 1)<br/>设为输出"]
    Out --> MapOut["gpio_set_fun_output_port(pin, FO_UART0_TX, 1, 1)"]
    MapIn --> Done([外设信号生效])
    MapOut --> Done

ADC 异步采样时序

sequenceDiagram
    participant App as 应用
    participant ADC as ADC 驱动 (adc.c)
    participant HWI as 中断控制器 (hwi.c)
    participant REG as ADC 寄存器

    App->>ADC: adc_init()
    ADC->>REG: 初始化时钟/通道选择
    App->>ADC: adc_get_value_by_isr(ch, cbfun)
    ADC->>REG: 使能通道并启动转换
    ADC-->>App: 立即返回(不死等)
    REG->>HWI: 转换完成触发中断
    HWI->>ADC: 进入 ISR
    ADC->>App: cbfun(ch, adc_val) 回调
    App->>ADC: adc_value_to_voltage(adc_vbg, adc_val)
    App->>App: 得到 mV 电压值

流程要点:异步模式下调用方在 adc_get_value_by_isr 返回后即可继续主循环,转换结果经中断回调送达,适合周期性电源监测;同步模式 adc_get_value 则是同一驱动的简化路径——使能、轮询 pending 位、返回 AD 值,用阻塞换代码简洁。

Usage Examples

GPIO:LED 输出 + 按键输入(典型板级用法)

// 设置 PA1 为输出并输出高电平(点亮 LED)
gpio_direction_output(IO_PORTA_01, 1);
// 设置 PA3 为输入并开启上拉(按键按下拉低)
gpio_direction_input(IO_PORTA_03);
gpio_set_pull_up(IO_PORTA_03, 1);
// 读取按键电平
int key_level = gpio_read(IO_PORTA_03);

Source: gpio.h(API 行为定义)

ADC:同步采电压

u32 vbat_mv = adc_get_voltage(AD_CH_VBAT);  // 电池电压(mV,内部已做 1/4 分压补偿前的换算)
u32 temp_mv = adc_get_voltage(AD_CH_DTEMP); // 芯片温度对应电压

Source: adc_api.h(adc_get_voltage 契约)

IIC:硬件 IIC 向 EEPROM 写读一字节

hw_iic_dev iic = 0;                       // 句柄,索引 hw_iic_cfg[0]
hw_iic_init(iic);                         // 按配置表初始化
hw_iic_start(iic);                        // 产生起始条件
hw_iic_tx_byte(iic, (dev_addr << 1) | 0); // 发送设备地址+写位,返回 1 表示 ACK
hw_iic_tx_byte(iic, reg_addr);            // 发送寄存器地址
hw_iic_tx_byte(iic, data);                // 写数据
hw_iic_stop(iic);                         // 产生停止条件
u8 ack = hw_iic_tx_byte(iic, byte);       // 单字节发送可获取应答状态
u8 rx  = hw_iic_rx_byte(iic, 1);          // 读 1 字节并回 ACK

Source: iic_hw.h(收发接口契约)

Configuration Options

配置项类型默认/取值范围说明
IO_GROUP_NUM宏16每组端口引脚容量,决定 IO_PORTx_yy 线性编号步长
enum gpio_direction枚举GPIO_OUT=0 / GPIO_IN=1方向语义,与 gpio_set_direction 的 value 对应
enum gpio_op_mode枚举GPIO_SET/AND/OR/XOR多引脚批量位操作模式(GPIO_SET=1 起)
hw_iic_cfg[].port[2]u8[2]平台配置表定义硬件 IIC 的 SCL/SDA 引脚编号
hw_iic_cfg[].baudrateu32配置表定义IIC 总线波特率
hw_iic_cfg[].roleu8IIC_MASTER / IIC_SLAVE主/从角色,决定 CON0 BIT2 置位方式
hw_iic_cfg[].hdrive / .io_filter / .io_puu80/1驱动能力、输入滤波(iic_isel_filter)、上拉开关
AD_CH_*宏0x0~0xdADC 物理通道编号(低 16 位)
ADC_PMU_CH_*宏0x0<<16~0xe<<16PMU 内部通道(高 16 位),与 AD_CH_PMU 组合使用
hw_iic_devconst int0(IIC_HW_NUM=1)IIC 句柄,本芯片仅 1 路硬件 IIC

配置哲学:BSP 不把外设参数散落在业务代码里,而是收敛到 hw_iic_cfg[] 这类平台配置表(定义于 src/ 实现中),应用层只传句柄。改板卡只需改配置表,不动调用代码。

API Reference

GPIO

int gpio_set_direction(u32 gpio, u32 value)

  • 参数:gpio 引脚宏(如 IO_PORTA_00);value 1=输入,0=输出。
  • 返回:0 成功,非 0 失败(越界引脚)。
  • 别名封装:gpio_direction_input(gpio)、gpio_direction_output(gpio, value)。

int gpio_read(u32 gpio) / int gpio_read_input_value(u32 gpio)

  • 参数:gpio 引脚宏。
  • 返回:输入电平值;仅在输入模式下有效。

int gpio_write(u32 gpio, u32 value) / int gpio_set_output_value(u32 gpio, u32 value)

  • 参数:gpio 引脚宏;value 1 输出高,0 输出低。
  • 返回:0 成功,非 0 失败;仅在输出模式下有效。

int gpio_set_pull_up(u32 gpio, u32 value) / gpio_set_pull_down(u32 gpio, u32 value)

  • 参数:gpio;value 1 使能 10K 上/下拉。
  • 返回:0 成功,非 0 失败;输入模式下才有效。

int gpio_set_die(u32 gpio, u32 value)

  • 参数:gpio;value 1=数字功能,0=模拟功能(ADC 输入场景)。
  • 返回:0 成功,非 0 失败。

u32 get_gpio(const char *p)

  • 参数:引脚字符串,如 "PA00"、"PB01"。
  • 返回:引脚线性序号("PB01" → 17)。

int gpio_set_fun_output_port(u32 gpio, u32 fun_index, u8 dir_ctl, u8 data_ctl)

  • 参数:gpio 目标 IO;fun_index 输出功能索引(见 io_omap.h 的 FO_*);dir_ctl/data_ctl 置 1 表示方向/电平由外设接管。
  • 返回:0 正确;-EINVAL 传参出错。
  • 前置:IO 需先配置为输出(gpio_direction_output)。

int gpio_set_fun_input_port(u32 gpio, enum PFI_TABLE pfun)

  • 参数:gpio 目标 IO;pfun 输入功能索引(见 enum PFI_TABLE,如 PFI_UART0_RX)。
  • 返回:0 正确;-EINVAL 传参出错。
  • 前置:IO 需先配置为数字输入(gpio_set_die(pin,1) + gpio_direction_input)。

ADC

u32 adc_get_value(u32 ch)

  • 参数:ch 通道宏(AD_CH_PA1、AD_CH_VBAT 等)。
  • 返回:当前通道 AD 值;同步死等模式,转换完成才返回。

void adc_get_value_by_isr(u32 ch, void (*cbfun)(u8, u16))

  • 参数:ch 通道号;cbfun 中断回调,形参为 (通道号, 16 位 AD 值)。
  • 返回:无;使能采样后立即返回,转换结束在中断上下文执行回调。

u32 adc_value_to_voltage(u32 adc_vbg, u32 adc_ch_val)

  • 参数:adc_vbg 基准通道(AD_CH_LDOREF)AD 值;adc_ch_val 目标通道 AD 值。
  • 返回:目标通道电压,单位 mV。

u32 adc_get_voltage(u32 ch)

  • 参数:ch 通道宏。
  • 返回:通道电压(mV),内部自动完成基准采样与换算。

硬件 IIC

int hw_iic_init(hw_iic_dev iic)

  • 参数:iic 句柄(索引 hw_iic_cfg[])。
  • 返回:0 成功,< 0 失败。

u8 hw_iic_tx_byte(hw_iic_dev iic, u8 byte)

  • 参数:iic 句柄;byte 待发字节。
  • 返回:1 收到 ACK,0 未收到 ACK。

u8 hw_iic_rx_byte(hw_iic_dev iic, u8 ack)

  • 参数:iic 句柄;ack 1=收后回 ACK,0=不回 ACK。
  • 返回:接收到的字节。

int hw_iic_read_buf(hw_iic_dev iic, void *buf, int len) / hw_iic_write_buf(hw_iic_dev iic, const void *buf, int len)

  • 参数:iic 句柄;buf 缓冲区;len 期望长度。
  • 返回:实际收发长度;< 0 表示失败。

int hw_iic_set_baud(hw_iic_dev iic, u32 baud)

  • 参数:iic 句柄;baud 目标波特率。
  • 返回:0 成功,< 0 失败。

Failure Modes, Edge Cases & Concurrency

  • 引脚参数越界:GPIO 系列函数对 gpio >= IO_PORT_MAX 或非法端口组返回非 0 失败;gpio_set_fun_output_port/gpio_set_fun_input_port 以 -EINVAL 区分传参错误。应用应先 get_gpio() 或宏常量校验,避免把 USB/P33 扩展 IO 直接当作普通 IO 配置。
  • 数字/模拟功能误配:ADC 输入通道若未 gpio_set_die(pin, 0),数字缓冲仍使能,模拟采样会被数字通路干扰甚至损坏信号完整性——这是外设复用时最常见的"能采到值但不准"问题。
  • IIC 无应答:hw_iic_tx_byte 返回 0 表示从机未 ACK(地址错误、器件不在线、总线被拉死)。上拉电阻(io_pu)与波特率(baudrate)配置不当会导致 NACK 或数据错位。
  • IIC 主从模式互斥:IIC_HW_NUM = 1 表明芯片仅一路硬件 IIC,主机与从机角色互斥;同时需要两路 IIC 总线时必须启用软件 IIC 作为第二路。
  • 中断回调上下文:adc_get_value_by_isr 的回调在中断上下文执行,回调内禁止阻塞等待(如死等另一路 ADC、打印长日志),应只做标记/置标志/搬数据。
  • 并发访问:寄存器宏均为位操作(|=/&=),对同一 CON0 的不同位并发配置不会互相覆盖;但应用层对同一外设的两次事务(如两次 hw_iic_write_buf)需自行保证串行化,BSP 不提供互斥锁。
  • CrossBar 占用冲突:同一外设信号只能路由到一个 IO(输入侧),同一 IO 也只能承载一个输出功能;重复 gpio_set_fun_input_port 会覆盖旧映射,释放时须配对调用 gpio_disable_fun_*_port。

Performance & Operational Considerations

  • 同步 ADC 采样阻塞时长:adc_get_value 死等转换,高频调用会拖慢主循环;周期性电源监测建议改用 adc_get_value_by_isr + 中断回调。
  • IIC 批量收发:优先用 hw_iic_read_buf/hw_iic_write_buf 代替逐字节 tx_byte 循环,减少总线起停开销;主机批量读时可配合 iic_host_receive_continue_byte 连续收字节。
  • GPIO 驱动能力:长走线/大负载场景用 gpio_set_hd(gpio, 1) 增大输出电流、gpio_set_hd0(gpio, 1) 关闭内阻增强输出,降低压降与边沿劣化。
  • 低功耗挂起:进入低功耗前对 IIC 等外设调用 suspend 而非 uninit,恢复时 resume 可保留配置,减少重初始化开销;USB 引脚复用为普通 IO 需先 usb_iomode(1)。
  • 调试串口独占:debug_uart.c 通常独占一路 UART,量产固件可关闭以释放 PFI_UARTx_RX/FO_UARTx_TX 给业务使用。

Extension Points

  • 新增外设实例:扩展 hw_iic_cfg[] 配置表条目即可增加硬件 IIC 实例(受 IIC_HW_NUM 限制);软件 IIC 无数量硬限制,只需分配 SCL/SDA 引脚。
  • 自定义引脚字符串解析:get_gpio() 支持 "PAxx" 文本解析,板级配置(如 board_demo.c)可把管脚表写成字符串数组,便于按板卡切换。
  • ADC 回调链:adc_get_value_by_isr 的回调机制与 hwi.c 中断框架解耦,业务可注册自己的通道回调而不侵入驱动。
  • CrossBar 功能扩展:io_imap.h/io_omap.h 定义了完整的输入/输出功能表,新外设信号(如 RDEC、CHAIN)可直接通过 PFI_*/FO_* 枚举路由,无需改动 GPIO 驱动本体。

Tests

BSP 层以参考示例形式提供自测入口:adc_test()(ADC 各通道采样打印)、iic_eeprom_test.c(硬件/软件 IIC 读写 EEPROM 验证)以及 board_demo.c/test.c 中的板级外设演示。这些示例同时充当 API 的"活文档":新板卡 bring-up 时可先跑通 ADC 电压换算与 IIC 读写,再接入业务逻辑。驱动本身的寄存器级行为验证依赖上述示例在目标板上的人工/自动化比对。

Related Links

  • GPIO 头文件 — 引脚宏、寄存器结构、CrossBar API 完整定义
  • ADC 接口头文件 — 通道定义与采样 API
  • 硬件 IIC 头文件 — 寄存器宏与主从模式 API
  • BSP 驱动实现目录 — gpio.c / adc.c / iic_hw.c / iic_soft.c / mcpwm.c / plcnt.c / key_driver.c / port_wkup.c / charge.c / debug_uart.c
  • IO 输入映射头文件 — CrossBar 输入信号表(PFI_*)
  • IO 输出映射头文件 — CrossBar 输出信号表(FO_*)
  • 相关目录页:时钟与电源管理、系统启动与中断(hwi.h/boot.h)、板级配置(board_demo.c)
Prev
AC63 系列芯片 BSP 结构
Next
低功耗、RTC 与时基唤醒