Просмотр исходного кода

feat(core/otg): add otg framework

Signed-off-by: sakumisu <1203593632@qq.com>
sakumisu 1 год назад
Родитель
Сommit
99e2e6bfd4
3 измененных файлов с 212 добавлено и 0 удалено
  1. 41 0
      common/usb_otg.h
  2. 137 0
      core/usbotg_core.c
  3. 34 0
      core/usbotg_core.h

+ 41 - 0
common/usb_otg.h

@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2025, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_OTG_H
+#define USB_OTG_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief usb otg controller hardware or gpio id simulator init.
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usb_otg_init(uint8_t busid);
+/**
+ * @brief usb otg controller hardware or gpio id simulator deinit.
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usb_otg_deinit(uint8_t busid);
+/**
+ * @brief get current role mode.
+ *
+ * @return return USBOTG_MODE_HOST or USBOTG_MODE_DEVICE.
+ */
+uint8_t usbotg_get_current_mode(uint8_t busid);
+
+/* called by user */
+void USBOTG_IRQHandler(uint8_t busid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USB_OTG_H */

+ 137 - 0
core/usbotg_core.c

@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2025, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbotg_core.h"
+
+struct usbotg_core_priv {
+    uint8_t busid;
+    uint32_t reg_base;
+    usb_osal_sem_t change_sem;
+    usb_osal_thread_t change_thread;
+    bool usbh_initialized;
+    bool usbd_initialized;
+    int (*usbh_initialize)(uint8_t busid, uint32_t reg_base);
+    int (*usbd_initialize)(uint8_t busid, uint32_t reg_base);
+} g_usbotg_core[CONFIG_USBHOST_MAX_BUS];
+
+static void usbotg_host_initialize(uint8_t busid)
+{
+    if (g_usbotg_core[busid].usbd_initialized) {
+        g_usbotg_core[busid].usbd_initialized = false;
+        usbd_deinitialize(busid);
+    }
+    if (g_usbotg_core[busid].usbh_initialize && !g_usbotg_core[busid].usbh_initialized) {
+        g_usbotg_core[busid].usbh_initialized = true;
+        g_usbotg_core[busid].usbh_initialize(g_usbotg_core[busid].busid, g_usbotg_core[busid].reg_base);
+    }
+}
+
+static void usbotg_device_initialize(uint8_t busid)
+{
+    if (g_usbotg_core[busid].usbh_initialized) {
+        g_usbotg_core[busid].usbh_initialized = false;
+        usbh_deinitialize(busid);
+    }
+    if (g_usbotg_core[busid].usbd_initialize && !g_usbotg_core[busid].usbd_initialize) {
+        g_usbotg_core[busid].usbd_initialized = true;
+        g_usbotg_core[busid].usbd_initialize(g_usbotg_core[busid].busid, g_usbotg_core[busid].reg_base);
+    }
+}
+
+static void usbotg_rolechange_thread(void *argument)
+{
+    uint8_t busid = (uint8_t)(uintptr_t)argument;
+
+    usb_otg_init(busid);
+
+    while (1) {
+        if (usb_osal_sem_take(g_usbotg_core[busid].change_sem, USB_OSAL_WAITING_FOREVER) == 0) {
+            if (usbotg_get_current_mode(busid) == USBOTG_MODE_HOST) {
+                usbotg_host_initialize(busid);
+            } else if (usbotg_get_current_mode(busid) == USBOTG_MODE_DEVICE) {
+                usbotg_device_initialize(busid);
+            }
+        }
+    }
+}
+
+int usbotg_initialize(uint8_t otg_mode, uint8_t busid, uint32_t reg_base,
+                      int (*usbh_initialize)(uint8_t busid, uint32_t reg_base),
+                      int (*usbd_initialize)(uint8_t busid, uint32_t reg_base))
+{
+    char thread_name[32] = { 0 };
+
+    if (busid >= CONFIG_USBHOST_MAX_BUS) {
+        USB_LOG_ERR("bus overflow\r\n");
+        while (1) {
+        }
+    }
+
+    g_usbotg_core[busid].busid = busid;
+    g_usbotg_core[busid].reg_base = reg_base;
+    g_usbotg_core[busid].usbh_initialize = usbh_initialize;
+    g_usbotg_core[busid].usbd_initialize = usbd_initialize;
+
+    if (otg_mode == USBOTG_MODE_OTG) {
+        g_usbotg_core[busid].change_sem = usb_osal_sem_create(0);
+        if (g_usbotg_core[busid].change_sem == NULL) {
+            USB_LOG_ERR("Failed to create change_sem\r\n");
+            return -1;
+        }
+
+        snprintf(thread_name, 32, "usbotg%u", busid);
+        g_usbotg_core[busid].change_thread = usb_osal_thread_create(thread_name, CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbotg_rolechange_thread, (void *)(uintptr_t)busid);
+        if (g_usbotg_core[busid].change_thread == NULL) {
+            USB_LOG_ERR("Failed to create usbotg thread\r\n");
+            return -1;
+        }
+    } else {
+        if (otg_mode == USBOTG_MODE_HOST) {
+            usbotg_host_initialize(busid);
+        } else if (otg_mode == USBOTG_MODE_DEVICE) {
+            usbotg_device_initialize(busid);
+        }
+    }
+
+    return 0;
+}
+
+int usbotg_deinitialize(uint8_t busid, uint32_t reg_base)
+{
+    if (g_usbotg_core[busid].usbd_initialized) {
+        g_usbotg_core[busid].usbd_initialized = false;
+        usbd_deinitialize(busid);
+    }
+
+    if (g_usbotg_core[busid].usbh_initialized) {
+        g_usbotg_core[busid].usbh_initialized = false;
+        usbh_deinitialize(busid);
+    }
+
+    if (g_usbotg_core[busid].change_sem) {
+        usb_otg_deinit(busid);
+        usb_osal_sem_delete(g_usbotg_core[busid].change_sem);
+    }
+
+    if (g_usbotg_core[busid].change_thread) {
+        usb_osal_thread_delete(g_usbotg_core[busid].change_thread);
+    }
+
+    return 0;
+}
+
+void usbotg_trigger_role_change(uint8_t busid)
+{
+    usb_osal_sem_give(g_usbotg_core[busid].change_sem);
+}
+
+void USBOTG_IRQHandler(uint8_t busid)
+{
+    if (usbotg_get_current_mode(busid) == USBOTG_MODE_HOST) {
+        USBH_IRQHandler(busid);
+    } else if (usbotg_get_current_mode(busid) == USBOTG_MODE_DEVICE) {
+        USBD_IRQHandler(busid);
+    }
+}

+ 34 - 0
core/usbotg_core.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2025, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBOTG_CORE_H
+#define USBOTG_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define USBOTG_MODE_UNKNOWN 0
+#define USBOTG_MODE_OTG     1
+#define USBOTG_MODE_HOST    2
+#define USBOTG_MODE_DEVICE  3
+
+#include "usbd_core.h"
+#include "usbh_core.h"
+#include "usb_otg.h"
+
+int usbotg_initialize(uint8_t otg_mode, uint8_t busid, uint32_t reg_base,
+                      int (*usbh_initialize)(uint8_t busid, uint32_t reg_base),
+                      int (*usbd_initialize)(uint8_t busid, uint32_t reg_base));
+int usbotg_deinitialize(uint8_t busid, uint32_t reg_base);
+
+/* called by user */
+void usbotg_trigger_role_change(uint8_t busid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBOTG_CORE_H */