W1:达拉斯 1-Wire 总线

作者:

David Fries

内核内部的 W1 API

include/linux/w1.h

W1 内核 API 函数。

struct w1_reg_num

分解的从设备 ID

定义:

struct w1_reg_num {
#if defined(__LITTLE_ENDIAN_BITFIELD);
    __u64 family:8,id:48, crc:8;
#elif defined(__BIG_ENDIAN_BITFIELD);
    __u64 crc:8,id:48, family:8;
#else;
#error "Please fix <asm/byteorder.h>";
#endif;
};

成员

family

标识设备类型

id

与 family 一起是唯一的设备 ID

crc

其他字节的校验和

crc

其他字节的校验和

id

与 family 一起是唯一的设备 ID

family

标识设备类型

struct w1_slave

保存总线上单个从设备

定义:

struct w1_slave {
    struct module           *owner;
    unsigned char           name[W1_MAXNAMELEN];
    struct list_head        w1_slave_entry;
    struct w1_reg_num       reg_num;
    atomic_t refcnt;
    int ttl;
    unsigned long           flags;
    struct w1_master        *master;
    struct w1_family        *family;
    void *family_data;
    struct device           dev;
    struct device           *hwmon;
};

成员

owner

指向单线“wire”内核模块。

name

设备 ID 是 ASCII 码。

w1_slave_entry

链表的数据

reg_num

二进制的从设备 ID

refcnt

引用计数,当为 0 时删除

ttl

每次搜索未找到此从设备时递减,为 0 时分离

flags

W1_SLAVE_ACTIVE W1_SLAVE_DETACH 的位标志

master

此从设备所在的总线

family

设备系列类型的模块

family_data

供系列模块使用的指针

dev

内核设备标识符

hwmon

指向 hwmon 设备的指针

struct w1_bus_master

总线主设备上可用的操作

定义:

struct w1_bus_master {
    void *data;
    u8 (*read_bit)(void *);
    void (*write_bit)(void *, u8);
    u8 (*touch_bit)(void *, u8);
    u8 (*read_byte)(void *);
    void (*write_byte)(void *, u8);
    u8 (*read_block)(void *, u8 *, int);
    void (*write_block)(void *, const u8 *, int);
    u8 (*triplet)(void *, u8);
    u8 (*reset_bus)(void *);
    u8 (*set_pullup)(void *, int);
    void (*search)(void *, struct w1_master *, u8, w1_slave_found_callback);
    char *dev_id;
};

成员

data

下面所有函数中的第一个参数

read_bit

采样线路电平 返回 读取的电平(0 或 1)

write_bit

设置线路电平

touch_bit

对于真正支持 1-Wire 协议的设备来说,这是最低级别的函数。touch_bit(0) = 写 0 周期 touch_bit(1) = 写 1/读周期 返回 读取的位(0 或 1)

read_byte

读取一个字节。与 8 次 touch_bit(1) 调用相同。返回 读取的字节

write_byte

写入一个字节。与 8 次 touch_bit(x) 调用相同。

read_block

与一系列 read_byte() 调用相同 返回 读取的字节数

write_block

与一系列 write_byte() 调用相同

triplet

组合两个读取和一个用于 ROM 搜索的智能写入 返回 bit0=Id bit1=comp_id bit2=dir_taken

reset_bus

长写入 0 并读取以进行存在脉冲检测 返回 -1=错误,0=存在设备,1=不存在设备

set_pullup

发出指定持续时间的强上拉脉冲。 返回 -1=错误,0=完成

search

非常好的硬件可以处理不同类型的 ROM 搜索,w1_master* 被传递给找到的从设备回调。u8 是 search_type,W1_SEARCH 或 W1_ALARM_SEARCH

dev_id

可选的设备 ID 字符串,w1 从设备可以使用该字符串创建名称,然后建立与 w1 主设备的连接

注意

read_bit 和 write_bit 是非常低级别的函数,只应与不支持 1-Wire 操作的硬件(如并行/串行端口)一起使用。要么定义 read_bit 和 write_bit,要么至少定义 touch_bit 和 reset_bus。

enum w1_master_flags

w1_master.flags 中使用的位域

常量

W1_ABORT_SEARCH

在关闭时提前中止搜索

W1_WARN_MAX_COUNT

限制达到最大计数时的警告

struct w1_master

每个总线主设备一个

定义:

struct w1_master {
    struct list_head        w1_master_entry;
    struct module           *owner;
    unsigned char           name[W1_MAXNAMELEN];
    struct mutex            list_mutex;
    struct list_head        slist;
    struct list_head        async_list;
    int max_slave_count, slave_count;
    unsigned long           attempts;
    int slave_ttl;
    int initialized;
    u32 id;
    int search_count;
    u64 search_id;
    atomic_t refcnt;
    void *priv;
    int enable_pullup;
    int pullup_duration;
    long flags;
    struct task_struct      *thread;
    struct mutex            mutex;
    struct mutex            bus_mutex;
    struct device_driver    *driver;
    struct device           dev;
    struct w1_bus_master    *bus_master;
    u32 seq;
};

成员

w1_master_entry

主设备链表

owner

模块所有者

name

动态分配总线名称

list_mutex

保护 slist 和 async_list

slist

从设备链表

async_list

要执行的 netlink 命令链表

max_slave_count

一次搜索的最大从设备数量

slave_count

当前已知的从设备数量

attempts

运行的搜索次数

slave_ttl

从设备超时前的搜索次数

initialized

防止初始化/删除竞争条件

id

w1 总线编号

search_count

要运行的自动搜索次数,-1 为无限制

search_id

允许继续搜索

refcnt

引用计数

priv

私有数据存储

enable_pullup

允许强上拉

pullup_duration

下一次强上拉的时间

flags

w1_master_flags 之一

thread

用于总线搜索和 netlink 命令的线程

mutex

保护大多数 w1_master

bus_mutex

保护并发的总线访问

driver

sysfs 驱动程序

dev

sysfs 设备

bus_master

可用的 I/O 操作

seq

用于 netlink 广播的序列号

struct w1_family_ops

系列类型的操作

定义:

struct w1_family_ops {
    int (*add_slave)(struct w1_slave *sl);
    void (*remove_slave)(struct w1_slave *sl);
    const struct attribute_group **groups;
    const struct hwmon_chip_info *chip_info;
};

成员

add_slave

add_slave

remove_slave

remove_slave

groups

sysfs 组

chip_info

指向 struct hwmon_chip_info 的指针

struct w1_family

引用计数的系列结构。

定义:

struct w1_family {
    struct list_head        family_entry;
    u8 fid;
    const struct w1_family_ops *fops;
    const struct of_device_id *of_match_table;
    atomic_t refcnt;
};

成员

family_entry

系列链表

fid

8 位系列标识符

fops

此系列的操作

of_match_table

开放固件匹配表

refcnt

引用计数器

module_w1_family

module_w1_family (__w1_family)

用于注册 1-Wire 系列的辅助宏

参数

__w1_family

w1_family 结构

描述

对于在模块初始化/退出时不做任何特殊操作的 1-Wire 系列的辅助宏。这消除了大量样板代码。每个模块只能使用此宏一次,并且调用它会替换 module_init()module_exit()

drivers/w1/w1.c

W1 核心函数。

执行 ROM 搜索并注册找到的任何设备。

参数

struct w1_master *dev

要搜索的主设备

u8 search_type

W1_SEARCH 搜索所有设备,或 W1_ALARM_SEARCH 仅返回处于报警状态的设备

w1_slave_found_callback cb

找到设备时调用的函数

描述

1-Wire 搜索是一个简单的二叉树搜索。对于地址的每一位,我们读取两位并写入一位。写入的位将使所有不匹配该位的设备进入休眠状态。当两次读取不同时,方向选择是显而易见的。当两位均为 0 时,我们必须选择要采取的路径。当我们可以在不选择路径的情况下扫描所有 64 位时,我们就完成了。

请参阅 www.maxim-ic.com 上的“应用说明 187 1-Wire 搜索算法”

int w1_process_callbacks(struct w1_master *dev)

执行每个 dev->async_list 回调条目

参数

struct w1_master *dev

w1 主设备

描述

必须持有 w1 主列表互斥锁。

返回值

如果存在要执行的命令则返回 1,否则返回 0

drivers/w1/w1_family.c

允许注册设备族操作。

int w1_register_family(struct w1_family *newf)

注册设备族驱动程序

参数

struct w1_family *newf

要注册的族

void w1_unregister_family(struct w1_family *fent)

注销设备族驱动程序

参数

struct w1_family *fent

要注销的族

drivers/w1/w1_internal.h

W1 主设备的内部初始化。

struct w1_async_cmd

从 w1_process kthread 执行回调

定义:

struct w1_async_cmd {
    struct list_head        async_entry;
    void (*cb)(struct w1_master *dev, struct w1_async_cmd *async_cmd);
};

成员

async_entry

链接条目

cb

回调函数,必须在返回之前 list_del 并销毁此列表

描述

当插入到 w1_master async_list 中时,w1_process 将执行回调。将此嵌入到具有命令详细信息的结构中。

drivers/w1/w1_int.c

W1 主设备的内部初始化。

int w1_add_master_device(struct w1_bus_master *master)

注册新的主设备

参数

struct w1_bus_master *master

要注册的主总线设备

void w1_remove_master_device(struct w1_bus_master *bm)

注销主设备

参数

struct w1_bus_master *bm

要移除的主总线设备

drivers/w1/w1_io.c

W1 输入/输出。

u8 w1_touch_bit(struct w1_master *dev, int bit)

生成一个写-0 或写-1 周期并采样电平。

参数

struct w1_master *dev

主设备

int bit

0 - 写入 0,1 - 写入 0 读取电平

void w1_write_8(struct w1_master *dev, u8 byte)

写入 8 位。

参数

struct w1_master *dev

主设备

u8 byte

要写入的字节

u8 w1_triplet(struct w1_master *dev, int bdir)
  • 执行三元组 - 用于搜索 ROM 地址。

参数

struct w1_master *dev

主设备

int bdir

如果 id_bit 和 comp_bit 均为 0,则要写入的位

描述

返回值

位 0 = id_bit 位 1 = comp_bit 位 2 = dir_taken

如果同时设置了位 0 和 1,则应重新启动搜索。

返回值

位字段 - 请参见上文

u8 w1_read_8(struct w1_master *dev)

读取 8 位。

参数

struct w1_master *dev

主设备

返回值

读取的字节

void w1_write_block(struct w1_master *dev, const u8 *buf, int len)

写入一系列字节。

参数

struct w1_master *dev

主设备

const u8 *buf

指向要写入的数据的指针

int len

要写入的字节数

void w1_touch_block(struct w1_master *dev, u8 *buf, int len)

触摸一系列字节。

参数

struct w1_master *dev

主设备

u8 *buf

指向要写入的数据的指针

int len

要写入的字节数

u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)

读取一系列字节。

参数

struct w1_master *dev

主设备

u8 *buf

指向要填充的缓冲区的指针

int len

要读取的字节数

返回值

已读取的字节数

int w1_reset_bus(struct w1_master *dev)

发出总线复位序列。

参数

struct w1_master *dev

主设备

返回值

0=设备存在,1=设备不存在或错误

int w1_reset_select_slave(struct w1_slave *sl)

复位并选择从设备

参数

struct w1_slave *sl

要选择的从设备

描述

复位总线,然后通过发送跳过 ROM 或匹配 ROM 来选择从设备。如果总线上只注册了一个设备,则发出跳过 ROM。必须持有 w1 主锁。

返回值

0=成功,任何其他值=错误

int w1_reset_resume_command(struct w1_master *dev)

恢复而不是另一个匹配 ROM

参数

struct w1_master *dev

主设备

描述

当多个从设备的工作流程需要在每个命令之间进行复位时,此函数类似于为上次匹配的 ROM 进行复位然后匹配 ROM。优点是跳过了匹配 ROM 步骤,而是执行恢复命令。当然,从设备必须支持该命令。

如果总线上只有一个从设备,传统上会跳过匹配 ROM,并为了效率执行“跳过 ROM”。当然,在多从设备总线上,这是行不通的,但恢复命令是次优选择。

必须持有 w1 主锁。

void w1_next_pullup(struct w1_master *dev, int delay)

注册一个强上拉

参数

struct w1_master *dev

主设备

int delay

以毫秒为单位的时间

描述

在下一次写入操作后,发出指定持续时间的强上拉。并非所有硬件都支持强上拉。不支持强上拉的硬件将在写入操作后休眠指定的时间,而不进行强上拉。这是对下一次写入操作的一次性请求,指定零将清除之前的请求。必须持有 w1 主锁。

返回值

0=成功,任何其他值=错误

void w1_write_bit(struct w1_master *dev, int bit)

生成写-0 或写-1 周期。

参数

struct w1_master *dev

主设备

int bit

要写入的位

描述

仅当 dev->bus_master->touch_bit 为 NULL 时调用

void w1_pre_write(struct w1_master *dev)

预写操作

参数

struct w1_master *dev

主设备

描述

预写操作,目前仅支持强上拉。如果已请求强上拉且硬件支持,则对硬件进行编程以进行强上拉。

void w1_post_write(struct w1_master *dev)

后写选项

参数

struct w1_master *dev

主设备

描述

后写操作,目前仅支持强上拉。如果请求了强上拉,如果硬件支持则清除它,否则执行延迟,无论哪种情况都清除请求。

u8 w1_read_bit(struct w1_master *dev)

生成写-1 周期并采样电平。

参数

struct w1_master *dev

主设备

描述

仅当 dev->bus_master->touch_bit 为 NULL 时调用