第 5 章 - USBX OTG

当在硬件设计中采用兼容 OTG 的 USB 控制器时,USBX 支持使用 USB 的 OTG 功能。

USBX 支持核心 USB 堆栈中的 OTG。 但要使 OTG 正常工作,它需要一个特定的 USB 控制器。 USBX OTG 控制器函数可在 usbx_otg 目录中找到。 当前 USBX 版本仅支持具有完全 OTG 功能的 NXP LPC3131。

常规的控制器驱动程序函数(主机或设备)仍然可以在标准 USBX usbx_device_controllers 和 usbx_host_controllers 中找到,但是 usbx_otg 目录包含与 USB 控制器关联的特定 OTG 函数。

除了常见的主机/设备函数外,OTG 控制器还有四类函数。

  • VBUS 特定函数
  • 控制器的启动和停止
  • USB 角色管理器
  • 中断处理程序

VBUS 函数

每个控制器都需要配备一个 VBUS 管理器,以根据电源管理要求更改 VBUS 的状态。 通常,此函数仅用于打开或关闭 VBUS。

启动和停止控制器

与常规的 USB 实现不同,OTG 要求在角色发生更改时激活和停用主机和/或设备堆栈。

USB 角色管理器

USB 角色管理器可接收用于更改 USB 状态的命令。 需要在多个状态之间进行转换:

状态 描述
UX_OTG_IDLE 0 设备处于空闲状态。 未连接到任何对象
UX_OTG_IDLE_TO_HOST 1 设备已连接 A 类型连接器
UX_OTG_IDLE_TO_SLAVE 2 设备已连接 B 类型连接器
UX_OTG_HOST_TO_IDLE 3 主机设备已断开连接
UX_OTG_HOST_TO_SLAVE 4 将角色从主机调换为从属设备
UX_OTG_SLAVE_TO_IDLE 5 从属设备已断开连接
UX_OTG_SLAVE_TO_HOST 6 将角色从从属设备调换为主机

中断处理程序

OTG 的主机驱动程序和设备控制器驱动程序都需要不同的中断处理程序来监视传统 USB 中断以外的信号,尤其是 SRP 和 VBUS 引起的信号。

如何初始化 USB OTG 控制器。 此处以 NXP LPC3131 为例。

/* Initialize the LPC3131 OTG controller. */
status = ux_otg_lpc3131_initialize(0x19000000, lpc3131_vbus_function,
    tx_demo_change_mode_callback);

在此示例中,我们通过传递 VBUS 函数和模式更改回调(从主机到从属设备,或者相反的方向),在 OTG 模式下初始化 LPC3131。

回调函数应直接记录新模式并唤醒待处理的线程以处理新状态。

void tx_demo_change_mode_callback(ULONG mode) {
    /* Simply save the otg mode. */
    otg_mode = mode;

    /* Wake up the thread that is waiting. */
    ux_utility_semaphore_put(&mode_change_semaphore);
}

传递的模式值可以有以下值。

  • UX_OTG_MODE_IDLE
  • UX_OTG_MODE_SLAVE
  • UX_OTG_MODE_HOST

应用程序始终可以通过查看变量来确定是哪个设备:

_ux_system_otg -> ux_system_otg_device_type

它的值可以是下列任一值。

  • UX_OTG_DEVICE_A
  • UX_OTG_DEVICE_B
  • UX_OTG_DEVICE_IDLE

USB OTG 主机设备始终可以通过发出以下命令来请求角色交换。

/* Ask the stack to perform a HNP swap with the device. We relinquish the host role to A device. */
ux_host_stack_role_swap(storage -> ux_host_class_storage_device);

对于从属设备,没有要发出的命令,但从属设备可以设置状态以更改角色,主机在发出 GET_STATUS 时将选取该角色,然后发起交换。

/* We are a B device, ask for role swap.
   The next GET_STATUS from the host will get the status change and do the HNP. */
_ux_system_otg -> ux_system_otg_slave_role_swap_flag =
    UX_OTG_HOST_REQUEST_FLAG;