Purple Pi OH2 开发板 I2C 驱动入门教程(基于 HYM8563 RTC)

电子说

1.4w人已加入

描述

本文基于触觉智能Purple Pi OH2 开发板讲解和调试,聚焦I2C驱动开发核心知识点,以HYM8563 RTC芯片为例,从协议原理到驱动源码全维度解析。

一、I2C 基本概念

1.1 什么是 I2C?

I2C(Inter-Integrated Circuit)是一种两线串行总线协议,由 Philips(现 NXP)在 1980 年代发明,广泛用于连接低速外设:

SDA(Serial Data):数据线,双向传输,开漏输出

SCL(Serial Clock):时钟线,由主设备产生,开漏输出

•外部需接上拉电阻(典型 4.7kΩ)将总线拉高

1.2 I2C 总线特点

特性 说明
线数 2 根(SDA + SCL),节省 PCB 空间
设备数量 最多 127 个(7 位地址)或 1023 个(10 位地址)
速率 标准模式 100 kHz,快速模式 400 kHz,高速模式 3.4 MHz
通信方式 主从架构,主设备(Master)发起通信并产生时钟
数据传输 MSB 优先,每个字节后跟一个 ACK/NACK 位

1.3 I2C 与 SPI 的简要对比

特性 I2C SPI
引脚数 2(SDA + SCL) 3+N(SCK + MOSI + MISO + N×CS)
速率 ~100 kHz–3.4 MHz ~MHz–几十 MHz
寻址 软件寻址(7/10 位地址) 硬件片选(每个设备一根 CS)
多主支持 支持(冲突检测) 不支持
功耗 较低(开漏+上拉) 较高(推挽输出)
适合场景 低复杂度、节省引脚的外设 高速、大批量数据传输

1.4 RK3576 I2C 资源

RK3576 提供 10 路 I2C 控制器(I2C0 ~ I2C9),每个控制器可通过 pinctrl 选择多个引脚复用(mux)选项:

 

i2c0 = &i2c0;   // 通常用于 PMIC (RK806)i2c1 = &i2c1;   // 通用i2c2 = &i2c2;   // 本教程使用:RTC (hym8563)i2c3 = &i2c3;   // Audio Codec...i2c9 = &i2c9;

 

二、I2C 通信协议

2.1 I2C 协议交互流程

I2C 总线上一次完整的数据传输遵循以下流程:

 

起始条件(S) → 7位从机地址 → R/W位 → ACK → 8位数据 → ACK → 停止条件(P)

 

以下是主设备与从设备之间的完整协议交互序列图(含起始条件、地址发送、数据读写、应答和停止条件):

开发板

协议时序参数表

阶段 时钟周期数 说明
S (起始条件) 0 SCL=High,SDA 下降沿
7位地址 7 个 SCL MSB (A6) 先发,LSB (A0) 最后
R/W 位 1 个 SCL 0 = 写操作,1 = 读操作
ACK 1 个 SCL(第9个) 从机拉低 SDA 应答
数据字节 8 个 SCL 数据位 D7~D0,MSB 先发
P (停止条件) 0 SCL=High,SDA 上升沿

数据帧结构 — I2C 总线上一个完整数据帧的比特布局(共 19 个 SCL 时钟周期):

 

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐│ S │A6 │A5 │A4 │A3 │A2 │A1 │A0 │R/W│ACK│D7 │D6 │D5 │D4 │D3 │D2 │D1 │D0 │ P ││ ↓ │◄──────── 从机地址7bit ────────►│   │◄──────── 数据8bit────────────►│ ↑ │└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘  S     ▲──── SCL 时钟采样 SDA ────▲                                     P起始          每个时钟1位数据          停止条件                                   条件

 

2.2 起始条件与停止条件

这是 I2C 总线最核心的时序特征 — SDA 在 SCL 高电平时跳变,此信号在数据传输阶段被严格禁止。以下是两个关键边沿的序列图:

开发板

规则:在数据传输阶段(S 和 P 之间),SDA 只能在 SCL 低电平时变化,SCL 高电平时 SDA 必须保持稳定 — 这是 I2C 协议的根本规则。

2.3 数据有效性规则

以下是 SCL 与 SDA 配合关系的序列图:

开发板

2.4 应答机制(ACK/NACK)

每个字节传输完成后,接收方必须在第 9 个 SCL 时钟周期驱动 SDA 发送应答位。以下是应答机制的序列图:

开发板

应答 SDA 电平 发送方 含义
ACK Low 接收方驱动 接收成功,继续发送下一字节
NACK High 上拉电阻拉高 接收失败或传输结束

2.5 I2C 设备地址

I2C 7 位地址由芯片厂商分配(高位)和硬件引脚电平(低位)共同决定,在总线上地址左移 1 位后附加 R/W 位发送:

 

7'h51 (HYM8563) → 左移1位 → 0xA2 (写) / 0xA3 (读)   bit:  6   5   4   3   2   1   0   R/W        1   0   1   0   0   0   1   0/1        └──────── 0xA2 (写) / 0xA3 (读)

 

设备 7位地址 写地址(<<1) 典型用途
HYM8563 RTC 0x51 0xA2 本教程 RTC 芯片
PCF8563 RTC 0x51 0xA2 NXP 兼容 RTC
EEPROM (AT24Cxx) 0x50 0xA0 存储
ES8316 Audio Codec 0x18 0x30 音频编解码
RK806 PMIC 0x23 0x46 电源管理

三、HYM8563 RTC 硬件原理

3.1 HYM8563 芯片简介

HYM8563 是 Haoyu Microelectronics 生产的低功耗 RTC(实时时钟)芯片,与 NXP PCF8563 兼容,通过 I2C 接口与主控通信。

关键特性

•I2C 总线接口(最大 400 kHz)

•计时精度依赖外部 32768 Hz 晶振

•内置秒、分、时、日、星期、月、年计数(BCD 格式)

•具有闹钟(Alarm)和定时器(Timer)功能

•可编程 CLKOUT 引脚输出时钟(32768 / 1024 / 32 / 1 Hz)

•低功耗:典型 0.25 μA(VDD=3.0V,定时器关闭)

•宽电压:1.0V ~ 5.5V

3.2 引脚定义与典型电路

应用电路:

开发板

3.3 寄存器映射表(核心)

HYM8563 内部寄存器共 16 个(0x00 ~ 0x0f),其中时间寄存器从 0x02 开始,全部采用 BCD 编码

地址 名称 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 取值范围
0x00 CTL1 TEST STOP TESTC
0x01 CTL2 TI/TP AF TF AIE TIE
0x02 SEC VL 秒(BCD 十位)       秒(BCD 个位)   00–59  
0x03 MIN 分(BCD 十位)       分(BCD 个位)   00–59  
0x04 HOUR 时(BCD 十位)     时(BCD 个位)   00–23  
0x05 DAY 日(BCD 十位)     日(BCD 个位)   01–31  
0x06 WEEKDAY 星期   00–06  
0x07 MONTH C 月(BCD 十位)     月(BCD 个位) 01–12  
0x08 YEAR 年(BCD 千位+百位)     年(BCD 十位)     年(BCD 个位) 00–99  
0x09 ALM_MIN AE 闹钟分(BCD)         00–59  
0x0A ALM_HOUR AE 闹钟时(BCD)       00–23  
0x0B ALM_DAY AE 闹钟日(BCD)       01–31  
0x0C ALM_WEEK AE 闹钟星期     00–06  
0x0D CLKOUT OE FD1 FD0
0x0E TMR_CTL TE TD1 TD0
0x0F TMR_CNT 定时器倒计数值             0–255  

关键位说明

所在寄存器 功能
STOP (Bit 5) CTL1 (0x00) 1 = RTC 停止计数,0 = 正常运行
VL (Bit 7) SEC (0x02) 0 = 时间有效,1 = 时间无效(掉电或晶振停振)
C (Bit 7) MONTH (0x07) 世纪位— 但驱动实测不可靠,内核限制为 2000–2099
AE (Bit 7) ALM_* (0x09~0x0C) 1 = 该闹钟字段不参与匹配(即忽略此项)
OE (Bit 7) CLKOUT (0x0D) 1 = 使能 CLKOUT 输出
FD[1:0] CLKOUT (0x0D) 00=32768Hz, 01=1024Hz, 10=32Hz, 11=1Hz
TE (Bit 7) TMR_CTL (0x0E) 1 = 使能定时器
TD[1:0] TMR_CTL (0x0E) 定时器时钟源选择

3.4 BCD 编码说明

时间寄存器使用 BCD(Binary-Coded Decimal)编码,即每个十进制数字用 4 位二进制表示,驱动中使用bcd2bin() / bin2bcd() 完成转换:

 

BCD 编码示例:时间 1256  秒(0x56) = 0101 0110 → 高4位(5) + 低4位(6) = 56 秒  分(0x34) = 0011 0100 → 高4位(3) + 低4位(4) = 34 分  时(0x12) = 0001 0010 → 高4位(1) + 低4位(2) = 12 时驱动中的 BCD 转换函数(定义在 linux/bcd.h):  bcd2bin(0x56) = 5*10 + 6 = 56          // BCD → 整数  bin2bcd(34)   = (3<<4) | 4 = 0x34       // 整数 → BCD

 

四、I2C 设备树配置

4.1 使能 I2C 控制器并添加 RTC 设备

在设备树文件(如ido-evb7609-v1a.dtsi)中配置 I2C2 控制器及 HYM8563 子设备:

 

/* I2C2 - 挂载 HYM8563 RTC */&i2c2 {    status = "okay";    pinctrl-names = "default";    pinctrl-0 = <&i2c2m0_xfer>;    hym8563: hym8563@51 {        compatible = "haoyu,hym8563";       // 驱动匹配的关键字符串        reg = <0x51>;                       // I2C 7 位从机地址 (7'h51)        #clock-cells = <0>;                 // 可作为时钟提供者        clock-frequency = <32768>;          // CLKOUT 输出频率        clock-output-names = "hym8563";     // 时钟输出名称        interrupt-parent = <&gpio0>;        // 中断控制器        interrupts = ;  // 中断引脚与触发方式        wakeup-source;                      // 支持系统唤醒    };};

 

各属性详解

属性 作用 说明
compatible 驱动匹配 内核据此查找of_device_id 表中匹配的驱动
reg I2C 地址 7 位地址左对齐写入,0x51 即器件地址
#clock-cells 时钟接口 0 表示直接输出固定频率时钟
clock-frequency 输出频率 仅描述信息,实际由 CLKOUT 寄存器控制
interrupts 中断配置 指定 INT 引脚对应的 GPIO 和触发类型
wakeup-source 唤醒标记 系统 Suspend 时 RTC 闹钟可唤醒 SoC

4.2 pinctrl 引脚复用配置

I2C2 的 SDA/SCL 引脚可以复用到不同的 GPIO 组,需要根据实际硬件原理图选择对应的 mux:

 

&pinctrl {    i2c2 {        /* I2C2 M0 组:SCL = GPIO1_B4, SDA = GPIO1_B3 */        i2c2m0_xfer: i2c2m0-xfer {            rockchip,pins =                <1 RK_PB4 9 &pcfg_pull_none>,   /* i2c2_scl_m0 */                <1 RK_PB3 9 &pcfg_pull_none>;   /* i2c2_sda_m0 */        };        /* I2C2 M1 组:备用引脚(如需要) */        i2c2m1_xfer: i2c2m1-xfer {            rockchip,pins =                <1 RK_PB4 10 &pcfg_pull_none>,  /* i2c2_scl_m1 */                <1 RK_PB3 10 &pcfg_pull_none>;  /* i2c2_sda_m1 */        };    };};

 

pinctrl 字段说明

•<1 RK_PB4 9 &pcfg_pull_none> = 

•每个 SoC 的 function 编号不同,需参考 RK3576 TRM(Technical Reference Manual) 的 GPIO 复用表格

4.3 查看当前引脚复用状态

 

# 查看 GPIO1_B3 (I2C2_SDA) 当前功能cat /sys/kernel/debug/pinctrl/pinctrl-handles | grep i2c2# 或者检查 pinctrl 设置cat /sys/kernel/debug/gpio | grep i2c

 

五、hym8563 驱动源码分析

5.1 驱动文件概览

源文件:kernel-6.1/drivers/rtc/rtc-hym8563.c(643 行)

编译配置

 

// Kconfigconfig RTC_DRV_HYM8563    tristate "Haoyu Microelectronics HYM8563"    depends on OF    help      Say Y to enable support for the HYM8563 I2C RTC chip.// Makefileobj-$(CONFIG_RTC_DRV_HYM8563)   += rtc-hym8563.o

 

5.2 数据结构与寄存器定义

 

struct hym8563 {    struct i2c_client   *client;         // I2C 客户端(关联设备和适配器)    struct rtc_device   *rtc;            // RTC 核心框架设备#ifdef CONFIG_COMMON_CLK    struct clk_hw       clkout_hw;       // CLKOUT 时钟提供者#endif    int alarm_or_timer_irq;             // 0=闹钟模式, 1=定时器模式    int alarm_tm_sec;                    // 闹钟秒数(定时器模式用)};

 

寄存器宏定义(驱动中命名对应数据手册):

对应寄存器
HYM8563_CTL1 0x00 控制寄存器 1
HYM8563_CTL2 0x01 控制寄存器 2
HYM8563_SEC 0x02 秒寄存器(含 VL 位)
HYM8563_MIN 0x03 分钟寄存器
HYM8563_HOUR 0x04 小时寄存器
HYM8563_DAY 0x05 日寄存器
HYM8563_WEEKDAY 0x06 星期寄存器
HYM8563_MONTH 0x07 月寄存器(含 C 世纪位)
HYM8563_YEAR 0x08 年寄存器
HYM8563_ALM_MIN 0x09 闹钟分钟
HYM8563_CLKOUT 0x0D 时钟输出控制
HYM8563_TMR_CTL 0x0E 定时器控制
HYM8563_TMR_CNT 0x0F 定时器计数值

5.3 核心函数分析:读取时间

 

static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm){    struct i2c_client *client = to_i2c_client(dev);    u8 buf[7];    int ret;    // ---- I2C 通信:一次读取 7 个时间寄存器 (SEC ~ YEAR) ----    // SMBus 协议:发送寄存器地址 0x02 → 连续读取 7 个字节    ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);    if (ret < 0)        return ret;    // ---- BCD 解码:将 BCD 格式转为内核 tm 结构体 ----    tm->tm_sec   = bcd2bin(buf[0] & HYM8563_SEC_MASK);    // buf[0]=SEC    tm->tm_min   = bcd2bin(buf[1] & HYM8563_MIN_MASK);    // buf[1]=MIN    tm->tm_hour  = bcd2bin(buf[2] & HYM8563_HOUR_MASK);   // buf[2]=HOUR    tm->tm_mday  = bcd2bin(buf[3] & HYM8563_DAY_MASK);    // buf[3]=DAY    tm->tm_wday  = bcd2bin(buf[4] & HYM8563_WEEKDAY_MASK); // buf[4]=WEEKDAY, 0=周日    tm->tm_mon   = bcd2bin(buf[5] & HYM8563_MONTH_MASK) - 1; // buf[5]=MONTH, -1=0基    tm->tm_year  = bcd2bin(buf[6]) + 100;                   // buf[6]=YEAR, +100=2000基    return 0;}

 

I2C 读写复合时序(i2c_smbus_read_i2c_block_data 的实际总线波形):

开发板

数据结构转换关系

开发板

5.4 核心函数分析:写入时间

 

static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm){    struct i2c_client *client = to_i2c_client(dev);    u8 buf[7];    int ret;    // ---- 年份范围检查 ----    // 硬件世纪位不可靠,驱动限制:2000–2099    if (tm->tm_year < 100 || tm->tm_year >= 200)        return -EINVAL;    // ---- BCD 编码:将 tm 结构体转为 BCD 格式 ----    buf[0] = bin2bcd(tm->tm_sec);    buf[1] = bin2bcd(tm->tm_min);    buf[2] = bin2bcd(tm->tm_hour);    buf[3] = bin2bcd(tm->tm_mday);    buf[4] = bin2bcd(tm->tm_wday);    buf[5] = bin2bcd(tm->tm_mon + 1);   // +1: 0基→1基    buf[6] = bin2bcd(tm->tm_year - 100); // -100: 2000基→0基    // ---- 写入时序:STOP → 写时间 → 清除STOP ----    // ① 先设置 STOP 位,暂停 RTC 计数(防止写入过程中时间变化)    ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1,                                     HYM8563_CTL1_STOP);    if (ret < 0)        return ret;    // ② 一次性写入 7 个时间寄存器    ret = i2c_smbus_write_i2c_block_data(client, HYM8563_SEC, 7, buf);    if (ret < 0)        return ret;    // ③ 清除 STOP 位,RTC 恢复计数(从新设定的时间开始)    ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0);    if (ret < 0)        return ret;    return 0;}

 

写入时序要点 — 为什么需要先暂停 RTC?

开发板

5.5 Probe 函数分析

 

static int hym8563_probe(struct i2c_client *client){    struct hym8563 *hym8563;    int ret;    struct rtc_time tm_read, tm = {        .tm_wday = 0,        .tm_year = 121,      // 2021年        .tm_mon  = 0,        // 1月        .tm_mday = 1,        .tm_hour = 12,        .tm_min  = 0,        .tm_sec  = 0,    };    // ① 分配私有数据结构    hym8563 = devm_kzalloc(&client->dev, sizeof(*hym8563), GFP_KERNEL);    if (!hym8563)        return -ENOMEM;    // ② 分配 RTC 核心设备    hym8563->rtc = devm_rtc_allocate_device(&client->dev);    if (IS_ERR(hym8563->rtc))        return PTR_ERR(hym8563->rtc);    hym8563->client = client;    i2c_set_clientdata(client, hym8563);    // ③ 初始化硬件:清除STOP/中断/标志位    ret = hym8563_init_device(client);    if (ret) {        dev_err(&client->dev, "could not init device, %dn", ret);        return ret;    }    // ④ 注册中断(仅当 DT 中配置了 interrupt 时才执行)    if (client->irq > 0) {        ret = devm_request_threaded_irq(&client->dev, client->irq,                        NULL, hym8563_irq,                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,                        client->name, hym8563);        // ... 错误处理 ...    }    // ⑤ 检查 VL 位 — 判断 RTC 时间是否有效    ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);    dev_info(&client->dev, "rtc information is %sn",        (ret & HYM8563_SEC_VL) ? "invalid" : "valid");    // ⑥ 如果时间无效或超出范围,重置为默认时间 (2021-01-01 1200)    hym8563_rtc_read_time(&client->dev, &tm_read);    if ((ret & HYM8563_SEC_VL) || (tm_read.tm_year < 70) ||        (tm_read.tm_year > 200) || (rtc_valid_tm(&tm_read) != 0))        hym8563_rtc_set_time(&client->dev, &tm);    // ⑦ 注册 RTC 设备到 Linux RTC 核心框架    hym8563->rtc->ops = &hym8563_rtc_ops;    clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, hym8563->rtc->features);    return devm_rtc_register_device(hym8563->rtc);}

 

Probe 完整流程图

开发板

5.6 初始化设备分析

 

static int hym8563_init_device(struct i2c_client *client){    int ret;    ret = i2c_smbus_read_byte_data(client, HYM8563_CTL1);    // ... error check ...    // 清除 STOP 位(如果 RTC 之前被停止过)    ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0);    if (ret < 0) return ret;    ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);    if (ret < 0) return ret;    // 禁用闹钟中断 (AIE) 和定时器中断 (TIE)    ret &= ~HYM8563_CTL2_AIE;    ret &= ~HYM8563_CTL2_TIE;    // 清除任何待处理的闹钟/定时器标志    if (ret & HYM8563_CTL2_AF) ret &= ~HYM8563_CTL2_AF;    if (ret & HYM8563_CTL2_TF) ret &= ~HYM8563_CTL2_TF;    // 复位定时器(写回配置)    i2c_smbus_write_byte_data(client, HYM8563_TMR_CNT, 0);    i2c_smbus_write_byte_data(client, HYM8563_TMR_CTL, HYM8563_TMR_CFG);    // HYM8563_TMR_CFG = TE(使能) | 01(时钟源=64Hz)    //                      ↑每 1/64 秒减1    return i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret);}

 

5.7 中断处理分析

 

static irqreturn_t hym8563_irq(int irq, void *dev_id){    struct hym8563 *hym8563 = (struct hym8563 *)dev_id;    struct i2c_client *client = hym8563->client;    int data, ret;    rtc_lock(hym8563->rtc);    // 读取 CTL2,获取中断状态    data = i2c_smbus_read_byte_data(client, HYM8563_CTL2);    // 清除闹钟标志 (AF) 和定时器标志 (TF)    data &= ~HYM8563_CTL2_AF;    data &= ~HYM8563_CTL2_TF;    // 复位定时器计数器    i2c_smbus_write_byte_data(client, HYM8563_TMR_CNT, 0);    // 写回清除后的 CTL2    ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, data);out:    rtc_unlock(hym8563->rtc);    return IRQ_HANDLED;}// 中断注册参数:// IRQF_TRIGGER_LOW  — INT 引脚为低电平触发// IRQF_ONESHOT      — 线程化中断,中断线在handler运行期间保持屏蔽

 

5.8 闹钟与定时器双模式

这是一个巧妙的设计:HYM8563 硬件同时支持闹钟(Alarm)和定时器(Timer),驱动根据唤醒间隔自动选择:

 

static int hym8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm){    // ...    interval = alarm - now;  // 计算到闹钟的秒数    if (interval < HYM8563_TMR_MAXCNT) {  // < 255 秒        // ---- 定时器模式(1秒精度) ----        // 使用硬件定时器做短间隔唤醒        // 精度高,但最长只能 255 秒        hym8563->alarm_or_timer_irq = 1;        i2c_smbus_write_byte_data(client, HYM8563_TMR_CNT, (u8)interval);    } else {        // ---- 闹钟模式(分钟精度) ----        // 使用硬件闹钟做长间隔唤醒        // 没有秒级精度(tm_sec 被强制设为 0)        // 但可以设置任意未来的时间        hym8563->alarm_or_timer_irq = 0;        alm_tm->tm_sec = 0;  // 秒强制归零    }    // ...}

 

双模式选择流程图

开发板

5.9 CLKOUT 时钟提供者

HYM8563 的 CLKOUT 引脚可以输出 32768/1024/32/1 Hz 的方波,驱动通过 Common Clock Framework 注册为时钟提供者:

 

#ifdef CONFIG_COMMON_CLKstatic int clkout_rates[] = {    32768,      // FD[1:0] = 00    1024,       // FD[1:0] = 01    32,         // FD[1:0] = 10    1,          // FD[1:0] = 11};static int hym8563_clkout_control(struct clk_hw *hw, bool enable){    // 读 CLKOUT 寄存器 → 设置/清除 OE 位 → 写回    int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT);    if (enable)        ret |= HYM8563_CLKOUT_ENABLE;    else        ret &= ~HYM8563_CLKOUT_ENABLE;    return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret);}// 驱动标记为 CLK_IS_CRITICAL — 防止系统关闭 CLKOUT// 某些 SoC 依赖此时钟源,关闭会导致系统问题init.flags = CLK_IS_CRITICAL;#endif

 

5.10 I2C 驱动注册

 

// 设备树匹配表 — 与 dts 中的 compatible 关联static const struct of_device_id hym8563_dt_idtable[] = {    { .compatible = "haoyu,hym8563" },    {},};MODULE_DEVICE_TABLE(of, hym8563_dt_idtable);// I2C 设备 ID 表(用于非设备树平台)static const struct i2c_device_id hym8563_id[] = {    { "hym8563", 0 },    {},};MODULE_DEVICE_TABLE(i2c, hym8563_id);// I2C 驱动结构体static struct i2c_driver hym8563_driver = {    .driver = {        .name = "hym8563",        .of_match_table = hym8563_dt_idtable,    },    .probe = hym8563_probe,    .id_table = hym8563_id,};module_i2c_driver(hym8563_driver);MODULE_DESCRIPTION("Haoyu HYM8563 RTC driver");MODULE_LICENSE("GPL");MODULE_AUTHOR("Haoyu Microelectronics");

 

本文完整覆盖了I2C协议原理、HYM8563硬件设计、设备树配置及驱动源码核心逻辑,是嵌入式开发者学习I2C驱动开发的实用参考。基于Purple Pi OH2开发板的实战场景,所有代码和配置均可直接落地调试。

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分