目前的位置: 首页 学术信息 正文

ZDS 2023技术报告分享第40篇:USB Type-C and You:将产品概念转化为实施的必需品


前言

2023年Zephyr开发者大会(ZDS)于6月27日至30日在捷克布拉格隆重举行。与以往两次不同,本次ZDS由Zephyr项目规划和管理,并作为首届嵌入式开源峰会(EOSS)的一部分进行。在这个令人期待已久的盛会中,全球Zephyr开发者们共同探讨了Zephyr实时操作系统(RTOS)的最新技术与发展趋势。作为一款开源、灵活和可扩展的嵌入式实时操作系统,Zephyr项目在2014年由英特尔发起,2016年作为Linux基金会项目正式面向公众启动,得到了全球范围内的广泛关注和采用。


ZDS 2023共70余个技术报告,涵盖了使用指导与展示、新功能与技术、架构修改与操作系统、多核异构与虚拟化、模拟器、测试、工业流程与代码管理、安全性、应用案例、工具与调试等丰富多样的内容。湖大嵌入式实验室的小伙伴们将对本次大会的所有技术报告进行逐一收集、整理与分享,尽最大努力为Zephyr开发者提供ZDS 2023技术报告的开发经验、实践成果以及解决方案的参考。


今天分享第40篇技术报告,由毕方琦整理,题目为:

USB Type-C and You:将产品概念转化为实施的必需品



作者简介

Sam Hurst, Google,Github ID: sambhurst


Diana Zigterman, Google, Github ID: DianaZig



端口作用回顾


电源角色

数据角色

附加电源输出线角色(Vconn)

来源:供电

下行端口(DFP):

1.充当USB主机或集线器下游端口

2.控制备用模式进入

来源:

1.为电子标记电缆提供Vconn

2.与电子标记电缆通信

受电方(Sink):消耗功率

上行端口(UFP):充当USB设备

关闭:可能无法与电缆通信


更多详情,请参阅去年的USB-C Power Delivery Overview



规格要求

Accessing the Specifications

1. USB Type-C规格

  • https://usb.org/document-library/usb-type-cr-cable-and-connector-specification-release-22

  • 查看规格书,了解有效电压范围、连接和断开时序以及TBT交替模式的具体说明


2. USB送电规格

  • https://usb.org/document-library/usb-power-delivery

  • 查看规格,了解最低PD要求和需要探索的功能


3. USB合规性规范也可从usb.org上获取


哪些USB Type-C状态适用?

1. 您想连接什么?

  • 想一想您的客户可能认为他们可以插入的所有东西


2. 附件模式?

  • 调试附件:一般只有在您的产品有特定调试附件时才有用

  • 音频配件:在工业中很少使用


3. 尝试状态(Try states)?

  • 主要在您或您的合作伙伴不支持Power Delivery时有用


我是否属于“双重角色数据”?

1. 如果您的端口既能作为主机又能作为设备,则肯定是“是”。


2. 如果你还需要使用PD DR_Swap消息

  • 因为您想使用非默认角色组合(sink/DFP)

  • 或者因为您具有双重角色能力,首选数据角色


3. DR交换的注意事项:对方可能会回复 "拒绝"。


我是否必须提供Vconn电压?

1. 电源端口可参考USB Type-C规范

  • 如果设备电源<=3A,且不支持USB 3,则不需要

  • 所需的Vconn功率级别从100mW到1.5W不等



2. 如果需要探测电缆,汇接端口主要需要Vconn信号源



3. 可以关闭Vconn吗?

是的,如果:

  • 电缆电子标记报告不需要Vconn

  • 未检测到Ra

  • 电缆电子标记不回复“Discover Identity”VDMs

注意:即使关闭了Vconn,您的端口在Vconn交换时,您的端口仍被视为“Vconn源”。


我需要Power Delivery支持吗?

1. 如果您对默认的USB Type-C角色满意,并且不需要超过15W的供电或吸电能力,那么可能不需要。


2. 但是,如果您需要以下功能,则需要Power Delivery支持:

  • 更多的功率

  • 非默认的角色组合

  • 备用模式

  • 电源按钮传输


必须支持哪些PD信息?

参考PD规范中的“信息适用性”部分



USB Type-C下游设备应用

创建USB Type-C设备的三个步骤

  • 创建一个Devicetree usb-c-connector节点

  • 创建一个特定应用的数据结构

  • 定义一些策略回调函数



USB Type-C设备树节点

Zephyr的USB Type-C端口视角


设备树USB Type-C下游端口描述



Type-C端口控制器(TCPC)驱动程序


VBUS驱动



应用程序特定的数据结构

检查是否支持电源角色

#define PORT1_NODE DT_NODELABEL(port1)

#define PORT1_POWER_ROLE DT_ENUM_IDX(DT_NODELABEL(port1), power_role)

#if (PORT1_POWER_ROLE != TC_ROLE_SINK)

#error "Unsupported board: Only Sink device supported"

#endif
port1: usbc-port@1 {

compatible = "usb-c-connector";

reg = <1>;

tcpc = <&amp;ucpd1>;

vbus = <&amp;vbus1>;

power-role = "sink";

sink-pdos = <PDO_FIXED(5000, 100, 0)>;

};


应用程序数据结构(提取下游PDO)

static struct port1_data_t { 

    uint32_t snk_caps[DT_PROP_LEN(DT_NODELABEL(port1), sink_pdos)]; 
    
    int snk_cap_cnt;
    
} port1_data = { 

    .snk_caps = {DT_FOREACH_PROP_ELEM(DT_NODELABEL(port1), sink_pdos, SINK_PDO)}, 
    
    .snk_cap_cnt = DT_PROP_LEN(DT_NODELABEL(port1), sink_pdos),
    
};
port1: usbc-port@1 {

compatible = "usb-c-connector";

reg = <1>;

tcpc = <&amp;ucpd1>;

vbus = <&amp;vbus1>;

power-role = "sink";

sink-pdos = <PDO_FIXED(5000, 100, 0)>;

};


应用程序数据结构(附加成员)

static struct port1_data_t { 

    ... 
    
    uint32_t src_caps[PDO_MAX_DATA_OBJECTS]; 
    
    int src_cap_cnt; 
    
    atomic_t ps_ready;
    
} port1_data = {

     ... 
     
     .src_caps = {0}, 
     
     .src_cap_cnt = 0, 
     
     .ps_ready = 0
     
};



策略回调函数

最小下游策略回调函数

int (*policy_cb_get_snk_cap_t)(const struct device *dev, uint32_t **pdos, int *num_pdos);

void (*policy_cb_set_src_cap_t)(const struct device *dev, const uint32_t *pdos, const int num_pdos); 

uint32_t (*policy_cb_get_rdo_t)(const struct device *dev); 

bool (*policy_cb_check_t)(const struct device *dev, const enum usbc_policy_check_t policy_check); 

void (*policy_cb_notify_t)(const struct device *dev, const enum usbc_policy_notify_t policy_notify);

电源传输协商(第一步)

policy_cb_set_src_cap_t

Zephyr USB Type-C PD Subsystem使用此回调函数将收到的Source capabilities发送给应用程序。对于这个应用程序,以下内容将被设置:


port1_data.src_caps

port1_data.src_cap_cnt


static struct port1_data_t { 

    ... 
    
    uint32_t src_caps[PDO_MAX_DATA_OBJECTS]; 
    
    int src_cap_cnt; 
    
    atomic_t ps_ready;
    
} port1_data = {

     ... 
     
     .src_caps = {0}, 
     
     .src_cap_cnt = 0, 
     
     .ps_ready = 0
     
}


示例的源能力(Sample Source Capabilities)可能包括:


PDO1: 5V(ALWAYS 5V)

PDO2: 12

PDO3: 20



电源传输协商(第二步)

policy_cb_get_rdo_t

在存储了源PDO之后,应用程序必须选择其中一个并构建一个RDO(Requested Data Object)返回给协议栈。Zephyr使用此回调函数来获取该RDO。

union pd_rdo rdo; 

/* Maximum operating current 100mA */ 

rdo.fixed.min_or_max_operating_current = PD_CONVERT_MA_TO_FIXED_PDO_CURRENT(100); 

/* Operating current 100mA */ 

rdo.fixed.operating_current = PD_CONVERT_MA_TO_FIXED_PDO_CURRENT(100); 

/* Object position 1 (5V PDO) */ 

rdo.fixed.object_pos = 1; 

return rdo.raw_value;


电源传输协商(第三步)


policy_cb_notify_t

随着Zephyr USB Type-C子系统的执行,它会通知应用程序某些变化的发生。这就是此回调函数的用途。在接下来的情况下,应用程序会被通知已接收到一个Accept消息。

case MSG_ACCEPT_RECEIVED:

LOG_INF("Source accepted the request");

break;

case TRANSITION_PS:

atomic_set_bit(&amp;dpm_data->ps_ready, 0);

break;

case NOT_PD_CONNECTED:

break;

case POWER_CHANGE_0A0:

LOG_INF("PWR 0A");

break;

case POWER_CHANGE_DEF:

LOG_INF("PWR DEF");

break;


电源传输协商(第四步)

policy_cb_notify_t

随着Zephyr USB Type-C子系统的执行,它会通知应用程序某些变化的发生。这就是此回调函数的用途。在接下来的情况下,应用程序会被通知已接收到一个PS_RDY消息。

case MSG_ACCEPT_RECEIVED:

LOG_INF("Source accepted the request");

break;

case TRANSITION_PS:

atomic_set_bit(&amp;dpm_data->ps_ready, 0);

break;

case NOT_PD_CONNECTED:

break;

case POWER_CHANGE_0A0:LOG_INF("PWR 0A");

break;

case POWER_CHANGE_DEF:

LOG_INF("PWR DEF");

break;


获取下游能力

policy_cb_get_snk_cap_t

Zephyr USB Type-C PD堆栈使用此回调函数来获取下游PDO以及它们的数量。对于这个应用程序,将返回以下内容:


port1_data.snk_caps

port1_data.snk_cap_cnt


static struct port1_data_t {

    uint32_t snk_caps[DT_PROP_LEN(DT_NODELABEL(port1), sink_pdos)];
 
    int snk_cap_cnt;
  
} port1_data = { 

    .snk_caps = {DT_FOREACH_PROP_ELEM(DT_NODELABEL(port1), sink_pdos, SINK_PDO)}, 
    
    .snk_cap_cnt = DT_PROP_LEN(DT_NODELABEL(port1), sink_pdos),
    
};


电源角色切换为源

policy_cb_check_t

随着Zephyr USB Type-C堆栈的执行,它需要在执行某些操作之前与应用程序进行确认。这就是此回调函数的用途。

switch (policy_check) {

case CHECK_POWER_ROLE_SWAP:

/* Reject power role swaps */

return false;

case CHECK_DATA_ROLE_SWAP_TO_DFP:

/* Reject data role swap to DFP */

return false;

case CHECK_DATA_ROLE_SWAP_TO_UFP:

/* Accept data role swap to UFP */

return true;

case CHECK_SNK_AT_DEFAULT_LEVEL:

/* The device is at the default power level */

return true;

default:

/* Reject all other policy checks */

return false;

}


注册以下API的回调函数

usbc_set_policy_cb_set_src_cap 

usbc_set_policy_cb_get_rdo 

usbc_set_policy_cb_get_snk_cap 

usbc_set_policy_cb_notify 

usbc_set_policy_cb_check


注册应用程序的数据结构

usbc_set_dpm_data

注册后,应用程序的数据结构可以通过以下内容:

usbc_get_dpm_data


启动Zephyr USB Type-C堆栈

 usbc_start


Zephyr USB Type-C示例

Sample Sink: zephyr/samples/subsys/sink 

Sample Source: zephyr/samples/subsys/source


Zephyr USB Type-C开发板


上一条:开放申请:欢迎加入湖南大学openEuler技术小组 下一条:ZDS 2023技术报告分享第39篇:East--构建NCS/Zephyr应用的辅助工具

关闭

嵌入式与网络计算湖南省重点实验室
版权所有 © 2023 湖南大学