summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxiao xie <[email protected]>2022-11-15 12:51:35 +0800
committerGitHub <[email protected]>2022-11-14 23:51:35 -0500
commit5338b1d5f2f532096ad734020312e46e6f688280 (patch)
tree52cdad78bb9b5ada299e051835e5bd334bc94c86
parent15eeb25ba05d8218fb55240308d8342b1a9296b1 (diff)
[imxrt1176]Fix usb (#6589)
修复USB驱动,实现imxrt1176平台usb host,支持usb3.0读写
-rw-r--r--bsp/imxrt/imxrt1170-nxp-evk/m7/board/Kconfig35
-rw-r--r--bsp/imxrt/imxrt1170-nxp-evk/m7/board/board.c18
-rw-r--r--bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction.h812
-rw-r--r--bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_config.h36
-rw-r--r--bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_rtthread.c917
-rw-r--r--bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_rtthread.h130
-rw-r--r--bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/generic_list.c475
-rw-r--r--bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/generic_list.h203
-rw-r--r--bsp/imxrt/libraries/MIMXRT1170/SConscript4
-rw-r--r--bsp/imxrt/libraries/drivers/drv_usbh.c25
-rw-r--r--bsp/imxrt/libraries/drivers/usb/host/usb_host.h5
-rw-r--r--bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.c1327
-rw-r--r--bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.c192
-rw-r--r--bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.h9
-rw-r--r--bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.c16
-rw-r--r--bsp/imxrt/libraries/drivers/usb/include/usb.h16
-rw-r--r--bsp/imxrt/libraries/drivers/usb/include/usb_host_config.h26
-rw-r--r--bsp/imxrt/libraries/drivers/usb/phy/usb_phy.c268
-rw-r--r--bsp/imxrt/libraries/drivers/usb/phy/usb_phy.h18
19 files changed, 4497 insertions, 35 deletions
diff --git a/bsp/imxrt/imxrt1170-nxp-evk/m7/board/Kconfig b/bsp/imxrt/imxrt1170-nxp-evk/m7/board/Kconfig
index 9da703c118..7092b19828 100644
--- a/bsp/imxrt/imxrt1170-nxp-evk/m7/board/Kconfig
+++ b/bsp/imxrt/imxrt1170-nxp-evk/m7/board/Kconfig
@@ -27,7 +27,22 @@ menu "On-chip Peripheral Drivers"
bool "Enable RTC"
select RT_USING_RTC
default n
+
+ config BSP_USING_USB
+ bool "Enable USB"
+ select RT_USING_USB_HOST
+ default n
+
+ if BSP_USING_USB
+ config BSP_USB0_HOST
+ bool "Enable USB0"
+ default n
+ config BSP_USB1_HOST
+ bool "Enable USB1"
+ default n
+ endif
+
config BSP_USING_SDIO
bool "Enable SDIO"
select RT_USING_SDIO
@@ -52,17 +67,17 @@ menu "On-chip Peripheral Drivers"
bool "Enable LPUART1"
default y
- config BSP_LPUART1_RX_USING_DMA
- bool "Enable LPUART1 RX DMA"
- depends on BSP_USING_LPUART1
- select BSP_USING_DMA
- select RT_SERIAL_USING_DMA
- default n
+ config BSP_LPUART1_RX_USING_DMA
+ bool "Enable LPUART1 RX DMA"
+ depends on BSP_USING_LPUART1
+ select BSP_USING_DMA
+ select RT_SERIAL_USING_DMA
+ default n
- config BSP_LPUART1_RX_DMA_CHANNEL
- depends on BSP_LPUART1_RX_USING_DMA
- int "Set LPUART1 RX DMA channel (0-32)"
- default 0
+ config BSP_LPUART1_RX_DMA_CHANNEL
+ depends on BSP_LPUART1_RX_USING_DMA
+ int "Set LPUART1 RX DMA channel (0-32)"
+ default 0
config BSP_LPUART1_TX_USING_DMA
bool "Enable LPUART1 TX DMA"
diff --git a/bsp/imxrt/imxrt1170-nxp-evk/m7/board/board.c b/bsp/imxrt/imxrt1170-nxp-evk/m7/board/board.c
index a9dc521eb4..e9f0b90ad2 100644
--- a/bsp/imxrt/imxrt1170-nxp-evk/m7/board/board.c
+++ b/bsp/imxrt/imxrt1170-nxp-evk/m7/board/board.c
@@ -126,7 +126,7 @@ static void BOARD_ConfigMPU(void)
/* Region 0 setting: Instruction access disabled, No data access permission. */
MPU->RBAR = ARM_MPU_RBAR(0, 0x00000000U);
- MPU->RASR = ARM_MPU_RASR(1, ARM_MPU_AP_NONE, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_4GB);
+ MPU->RASR = ARM_MPU_RASR(1, ARM_MPU_AP_NONE, 0, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_4GB);
/* Region 1 setting: Memory with Device type, not shareable, non-cacheable. */
MPU->RBAR = ARM_MPU_RBAR(1, 0x80000000U);
@@ -148,6 +148,15 @@ static void BOARD_ConfigMPU(void)
MPU->RBAR = ARM_MPU_RBAR(5, 0x20000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB);
+#if defined(CACHE_MODE_WRITE_THROUGH) && CACHE_MODE_WRITE_THROUGH
+ /* Region 6 setting: Memory with Normal type, not shareable, write through */
+ MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_1MB);
+
+ /* Region 7 setting: Memory with Normal type, not shareable, write trough */
+ MPU->RBAR = ARM_MPU_RBAR(7, 0x20300000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_512KB);
+#else
/* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_1MB);
@@ -155,6 +164,7 @@ static void BOARD_ConfigMPU(void)
/* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(7, 0x20300000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_512KB);
+#endif
#if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)
/* Region 8 setting: Memory with Normal type, not shareable, outer/inner write back. */
@@ -163,10 +173,16 @@ static void BOARD_ConfigMPU(void)
#endif
#ifdef USE_SDRAM
+#if defined(CACHE_MODE_WRITE_THROUGH) && CACHE_MODE_WRITE_THROUGH
+ /* Region 9 setting: Memory with Normal type, not shareable, write trough */
+ MPU->RBAR = ARM_MPU_RBAR(9, 0x80000000U);
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_64MB);
+#else
/* Region 9 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(9, 0x80000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB);
#endif
+#endif
while ((size >> i) > 0x1U)
{
diff --git a/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction.h b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction.h
new file mode 100644
index 0000000000..379bde9c2c
--- /dev/null
+++ b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction.h
@@ -0,0 +1,812 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016-2020 NXP
+ *
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_OS_ABSTRACTION_H_
+#define _FSL_OS_ABSTRACTION_H_
+
+#include "fsl_common.h"
+#include "fsl_os_abstraction_config.h"
+#include "generic_list.h"
+
+/*!
+ * @addtogroup osa_adapter
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief Type for the Task Priority*/
+typedef uint16_t osa_task_priority_t;
+/*! @brief Type for a task handler */
+typedef void *osa_task_handle_t;
+/*! @brief Type for the parameter to be passed to the task at its creation */
+typedef void *osa_task_param_t;
+/*! @brief Type for task pointer. Task prototype declaration */
+typedef void (*osa_task_ptr_t)(osa_task_param_t task_param);
+/*! @brief Type for the semaphore handler */
+typedef void *osa_semaphore_handle_t;
+/*! @brief Type for the mutex handler */
+typedef void *osa_mutex_handle_t;
+/*! @brief Type for the event handler */
+typedef void *osa_event_handle_t;
+/*! @brief Type for an event flags group, bit 32 is reserved. */
+typedef uint32_t osa_event_flags_t;
+/*! @brief Message definition. */
+typedef void *osa_msg_handle_t;
+/*! @brief Type for the message queue handler */
+typedef void *osa_msgq_handle_t;
+/*! @brief Type for the Timer handler */
+typedef void *osa_timer_handle_t;
+/*! @brief Type for the Timer callback function pointer. */
+typedef void (*osa_timer_fct_ptr_t)(void const *argument);
+/*! @brief Thread Definition structure contains startup information of a thread.*/
+typedef struct osa_task_def_tag
+{
+ osa_task_ptr_t pthread; /*!< start address of thread function*/
+ uint32_t tpriority; /*!< initial thread priority*/
+ uint32_t instances; /*!< maximum number of instances of that thread function*/
+ uint32_t stacksize; /*!< stack size requirements in bytes; 0 is default stack size*/
+ uint32_t *tstack; /*!< stack pointer*/
+ void *tlink; /*!< link pointer*/
+ uint8_t *tname; /*!< name pointer*/
+ uint8_t useFloat; /*!< is use float*/
+} osa_task_def_t;
+/*! @brief Thread Link Definition structure .*/
+typedef struct osa_thread_link_tag
+{
+ uint8_t link[12]; /*!< link*/
+ osa_task_handle_t osThreadId; /*!< thread id*/
+ osa_task_def_t *osThreadDefHandle; /*!< pointer of thread define handle*/
+ uint32_t *osThreadStackHandle; /*!< pointer of thread stack handle*/
+} osa_thread_link_t, *osa_thread_link_handle_t;
+
+/*! @brief Definition structure contains timer parameters.*/
+typedef struct osa_time_def_tag
+{
+ osa_timer_fct_ptr_t pfCallback; /* < start address of a timer function */
+ void *argument; /* < argument of a timer function */
+} osa_time_def_t;
+
+/*! @brief Type for the timer definition*/
+typedef enum _osa_timer
+{
+ KOSA_TimerOnce = 0, /*!< one-shot timer*/
+ KOSA_TimerPeriodic = 1 /*!< repeating timer*/
+} osa_timer_t;
+
+/*! @brief Defines the return status of OSA's functions */
+typedef enum _osa_status
+{
+ KOSA_StatusSuccess = kStatus_Success, /*!< Success */
+ KOSA_StatusError = MAKE_STATUS(kStatusGroup_OSA, 1), /*!< Failed */
+ KOSA_StatusTimeout = MAKE_STATUS(kStatusGroup_OSA, 2), /*!< Timeout occurs while waiting */
+ KOSA_StatusIdle = MAKE_STATUS(kStatusGroup_OSA, 3), /*!< Used for bare metal only, the wait object is not ready
+ and timeout still not occur */
+} osa_status_t;
+
+#ifdef USE_RTOS
+#undef USE_RTOS
+#endif
+
+#define USE_RTOS (1)
+#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
+#define OSA_TASK_HANDLE_SIZE (12U)
+#else
+#define OSA_TASK_HANDLE_SIZE (16U)
+#endif
+#define OSA_EVENT_HANDLE_SIZE (8U)
+#define OSA_SEM_HANDLE_SIZE (4U)
+#define OSA_MUTEX_HANDLE_SIZE (4U)
+#define OSA_MSGQ_HANDLE_SIZE (4U)
+#define OSA_MSG_HANDLE_SIZE (0U)
+
+/*! @brief Priority setting for OSA. */
+#ifndef OSA_PRIORITY_IDLE
+#define OSA_PRIORITY_IDLE (6)
+#endif
+
+#ifndef OSA_PRIORITY_LOW
+#define OSA_PRIORITY_LOW (5)
+#endif
+
+#ifndef OSA_PRIORITY_BELOW_NORMAL
+#define OSA_PRIORITY_BELOW_NORMAL (4)
+#endif
+
+#ifndef OSA_PRIORITY_NORMAL
+#define OSA_PRIORITY_NORMAL (3)
+#endif
+
+#ifndef OSA_PRIORITY_ABOVE_NORMAL
+#define OSA_PRIORITY_ABOVE_NORMAL (2)
+#endif
+
+#ifndef OSA_PRIORITY_HIGH
+#define OSA_PRIORITY_HIGH (1)
+#endif
+
+#ifndef OSA_PRIORITY_REAL_TIME
+#define OSA_PRIORITY_REAL_TIME (0)
+#endif
+
+#ifndef OSA_TASK_PRIORITY_MAX
+#define OSA_TASK_PRIORITY_MAX (0)
+#endif
+
+#ifndef OSA_TASK_PRIORITY_MIN
+#define OSA_TASK_PRIORITY_MIN (15)
+#endif
+
+#define SIZE_IN_UINT32_UNITS(size) (((size) + sizeof(uint32_t) - 1) / sizeof(uint32_t))
+
+/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
+#define osaWaitForever_c ((uint32_t)(-1))
+#define osaEventFlagsAll_c ((osa_event_flags_t)(0x00FFFFFF))
+#define osThreadStackArray(name) osThread_##name##_stack
+#define osThreadStackDef(name, stacksize, instances) \
+ uint32_t osThreadStackArray(name)[SIZE_IN_UINT32_UNITS(stacksize) * (instances)];
+
+/* ==== Thread Management ==== */
+
+/* Create a Thread Definition with function, priority, and stack requirements.
+ * \param name name of the thread function.
+ * \param priority initial priority of the thread function.
+ * \param instances number of possible thread instances.
+ * \param stackSz stack size (in bytes) requirements for the thread function.
+ * \param useFloat
+ */
+#if defined(FSL_RTOS_MQX)
+#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
+ osa_thread_link_t osThreadLink_##name[instances] = {0}; \
+ osThreadStackDef(name, stackSz, instances) osa_task_def_t os_thread_def_##name = { \
+ (name), (priority), (instances), (stackSz), osThreadStackArray(name), osThreadLink_##name, \
+ (uint8_t *)#name, (useFloat)}
+#elif defined(FSL_RTOS_UCOSII)
+#if gTaskMultipleInstancesManagement_c
+#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
+ osa_thread_link_t osThreadLink_##name[instances] = {0}; \
+ osThreadStackDef(name, stackSz, instances) osa_task_def_t os_thread_def_##name = { \
+ (name), (priority), (instances), (stackSz), osThreadStackArray(name), osThreadLink_##name, \
+ (uint8_t *)#name, (useFloat)}
+#else
+#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
+ osThreadStackDef(name, stackSz, instances) osa_task_def_t os_thread_def_##name = { \
+ (name), (priority), (instances), (stackSz), osThreadStackArray(name), NULL, (uint8_t *)#name, (useFloat)}
+#endif
+#else
+#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
+ osa_task_def_t os_thread_def_##name = {(name), (priority), (instances), (stackSz), \
+ NULL, NULL, (uint8_t *)#name, (useFloat)}
+#endif
+/* Access a Thread defintion.
+ * \param name name of the thread definition object.
+ */
+#define OSA_TASK(name) &os_thread_def_##name
+
+#define OSA_TASK_PROTO(name) externosa_task_def_t os_thread_def_##name
+/* ==== Timer Management ====
+ * Define a Timer object.
+ * \param name name of the timer object.
+ * \param function name of the timer call back function.
+ */
+
+#define OSA_TIMER_DEF(name, function) osa_time_def_t os_timer_def_##name = {(function), NULL}
+
+/* Access a Timer definition.
+ * \param name name of the timer object.
+ */
+#define OSA_TIMER(name) &os_timer_def_##name
+
+/* ==== Buffer Definition ==== */
+
+/*!
+ * @brief Defines the semaphore handle
+ *
+ * This macro is used to define a 4 byte aligned semaphore handle.
+ * Then use "(osa_semaphore_handle_t)name" to get the semaphore handle.
+ *
+ * The macro should be global and could be optional. You could also define semaphore handle by yourself.
+ *
+ * This is an example,
+ * @code
+ * OSA_SEMAPHORE_HANDLE_DEFINE(semaphoreHandle);
+ * @endcode
+ *
+ * @param name The name string of the semaphore handle.
+ */
+#define OSA_SEMAPHORE_HANDLE_DEFINE(name) \
+ uint32_t name[(OSA_SEM_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)]
+
+/*!
+ * @brief Defines the mutex handle
+ *
+ * This macro is used to define a 4 byte aligned mutex handle.
+ * Then use "(osa_mutex_handle_t)name" to get the mutex handle.
+ *
+ * The macro should be global and could be optional. You could also define mutex handle by yourself.
+ *
+ * This is an example,
+ * @code
+ * OSA_MUTEX_HANDLE_DEFINE(mutexHandle);
+ * @endcode
+ *
+ * @param name The name string of the mutex handle.
+ */
+#define OSA_MUTEX_HANDLE_DEFINE(name) uint32_t name[(OSA_MUTEX_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)]
+
+/*!
+ * @brief Defines the event handle
+ *
+ * This macro is used to define a 4 byte aligned event handle.
+ * Then use "(osa_event_handle_t)name" to get the event handle.
+ *
+ * The macro should be global and could be optional. You could also define event handle by yourself.
+ *
+ * This is an example,
+ * @code
+ * OSA_EVENT_HANDLE_DEFINE(eventHandle);
+ * @endcode
+ *
+ * @param name The name string of the event handle.
+ */
+#define OSA_EVENT_HANDLE_DEFINE(name) uint32_t name[(OSA_EVENT_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)]
+
+/*!
+ * @brief Defines the message queue handle
+ *
+ * This macro is used to define a 4 byte aligned message queue handle.
+ * Then use "(osa_msgq_handle_t)name" to get the message queue handle.
+ *
+ * The macro should be global and could be optional. You could also define message queue handle by yourself.
+ *
+ * This is an example,
+ * @code
+ * OSA_MSGQ_HANDLE_DEFINE(msgqHandle, 3, sizeof(msgStruct));
+ * @endcode
+ *
+ * @param name The name string of the message queue handle.
+ * @param numberOfMsgs Number of messages.
+ * @param msgSize Message size.
+ *
+ */
+
+/*< Macro For FREE_RTOS*/
+#define OSA_MSGQ_HANDLE_DEFINE(name, numberOfMsgs, msgSize) \
+ uint32_t name[(OSA_MSGQ_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)]
+
+/*!
+ * @brief Defines the TASK handle
+ *
+ * This macro is used to define a 4 byte aligned TASK handle.
+ * Then use "(osa_task_handle_t)name" to get the TASK handle.
+ *
+ * The macro should be global and could be optional. You could also define TASK handle by yourself.
+ *
+ * This is an example,
+ * @code
+ * OSA_TASK_HANDLE_DEFINE(taskHandle);
+ * @endcode
+ *
+ * @param name The name string of the TASK handle.
+ */
+#define OSA_TASK_HANDLE_DEFINE(name) uint32_t name[(OSA_TASK_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)]
+
+#include "fsl_os_abstraction_rtthread.h"
+
+extern const uint8_t gUseRtos_c;
+
+/*
+ * alloc the temporary memory to store the status
+ */
+#define OSA_SR_ALLOC() uint32_t osaCurrentSr;
+/*
+ * Enter critical mode
+ */
+#define OSA_ENTER_CRITICAL() OSA_EnterCritical(&osaCurrentSr)
+/*
+ * Exit critical mode and retore the previous mode
+ */
+#define OSA_EXIT_CRITICAL() OSA_ExitCritical(osaCurrentSr)
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @brief Reserves the requested amount of memory in bytes.
+ *
+ * The function is used to reserve the requested amount of memory in bytes and initializes it to 0.
+ *
+ * @param length Amount of bytes to reserve.
+ *
+ * @return Pointer to the reserved memory. NULL if memory can't be allocated.
+ */
+void *OSA_MemoryAllocate(uint32_t length);
+
+/*!
+ * @brief Frees the memory previously reserved.
+ *
+ * The function is used to free the memory block previously reserved.
+ *
+ * @param p Pointer to the start of the memory block previously reserved.
+ *
+ */
+void OSA_MemoryFree(void *p);
+
+/*!
+ * @brief Enter critical with nesting mode.
+ *
+ * @param sr Store current status and return to caller.
+ */
+void OSA_EnterCritical(uint32_t *sr);
+
+/*!
+ * @brief Exit critical with nesting mode.
+ *
+ * @param sr Previous status to restore.
+ */
+void OSA_ExitCritical(uint32_t sr);
+
+/*!
+ * @name Task management
+ * @{
+ */
+
+/*!
+ * @brief Creates a task.
+ *
+ * This function is used to create task based on the resources defined
+ * by the macro OSA_TASK_DEFINE.
+ *
+ * Example below shows how to use this API to create the task handle.
+ * @code
+ * OSA_TASK_HANDLE_DEFINE(taskHandle);
+ * OSA_TASK_DEFINE( Job1, OSA_PRIORITY_HIGH, 1, 800, 0);
+ * OSA_TaskCreate((osa_task_handle_t)taskHandle, OSA_TASK(Job1), (osa_task_param_t)NULL);
+ * @endcode
+ *
+ * @param taskHandle Pointer to a memory space of size OSA_TASK_HANDLE_SIZE allocated by the caller, task handle.
+ * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices.
+ * You can define the handle in the following two ways:
+ * #OSA_TASK_HANDLE_DEFINE(taskHandle);
+ * or
+ * uint32_t taskHandle[((OSA_TASK_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
+ * @param thread_def pointer to theosa_task_def_t structure which defines the task.
+ * @param task_param Pointer to be passed to the task when it is created.
+ * @retval KOSA_StatusSuccess The task is successfully created.
+ * @retval KOSA_StatusError The task can not be created.
+ */
+#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_status_t OSA_TaskCreate(osa_task_handle_t taskHandle, osa_task_def_t *thread_def, osa_task_param_t task_param);
+#endif /* FSL_OSA_TASK_ENABLE */
+
+/*!
+ * @brief Gets the handler of active task.
+ *
+ * @return Handler to current active task.
+ */
+#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_task_handle_t OSA_TaskGetCurrentHandle(void);
+#endif /* FSL_OSA_TASK_ENABLE */
+
+/*!
+ * @brief Puts the active task to the end of scheduler's queue.
+ *
+ * When a task calls this function, it gives up the CPU and puts itself to the
+ * end of a task ready list.
+ *
+ * @retval KOSA_StatusSuccess The function is called successfully.
+ * @retval KOSA_StatusError Error occurs with this function.
+ */
+#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_status_t OSA_TaskYield(void);
+#endif /* FSL_OSA_TASK_ENABLE */
+
+/*!
+ * @brief Gets the priority of a task.
+ *
+ * @param taskHandle The handler of the task whose priority is received.
+ *
+ * @return Task's priority.
+ */
+#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_task_priority_t OSA_TaskGetPriority(osa_task_handle_t taskHandle);
+#endif /* FSL_OSA_TASK_ENABLE */
+
+/*!
+ * @brief Sets the priority of a task.
+ *
+ * @param taskHandle The handler of the task whose priority is set.
+ * @param taskPriority The priority to set.
+ *
+ * @retval KOSA_StatusSuccess Task's priority is set successfully.
+ * @retval KOSA_StatusError Task's priority can not be set.
+ */
+#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_status_t OSA_TaskSetPriority(osa_task_handle_t taskHandle, osa_task_priority_t taskPriority);
+#endif /* FSL_OSA_TASK_ENABLE */
+
+/*!
+ * @brief Destroys a previously created task.
+ *
+ * @param taskHandle The handler of the task to destroy.
+ *
+ * @retval KOSA_StatusSuccess The task was successfully destroyed.
+ * @retval KOSA_StatusError Task destruction failed or invalid parameter.
+ */
+#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_status_t OSA_TaskDestroy(osa_task_handle_t taskHandle);
+#endif /* FSL_OSA_TASK_ENABLE */
+
+/*!
+ * @brief Creates a semaphore with a given value.
+ *
+ * This function creates a semaphore and sets the value to the parameter
+ * initValue.
+ *
+ * Example below shows how to use this API to create the semaphore handle.
+ * @code
+ * OSA_SEMAPHORE_HANDLE_DEFINE(semaphoreHandle);
+ * OSA_SemaphoreCreate((osa_semaphore_handle_t)semaphoreHandle, 0xff);
+ * @endcode
+ *
+ * @param semaphoreHandle Pointer to a memory space of size OSA_SEM_HANDLE_SIZE allocated by the caller.
+ * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices.
+ * You can define the handle in the following two ways:
+ * #OSA_SEMAPHORE_HANDLE_DEFINE(semaphoreHandle);
+ * or
+ * uint32_t semaphoreHandle[((OSA_SEM_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
+ * @param initValue Initial value the semaphore will be set to.
+ *
+ * @retval KOSA_StatusSuccess the new semaphore if the semaphore is created successfully.
+ * @retval KOSA_StatusError if the semaphore can not be created.
+ */
+osa_status_t OSA_SemaphoreCreate(osa_semaphore_handle_t semaphoreHandle, uint32_t initValue);
+
+/*!
+ * @brief Destroys a previously created semaphore.
+ *
+ * @param semaphoreHandle The semaphore handle.
+ * The macro SEMAPHORE_HANDLE_BUFFER_GET is used to get the semaphore buffer pointer,
+ * and should not be used before the macro SEMAPHORE_HANDLE_BUFFER_DEFINE is used.
+ *
+ * @retval KOSA_StatusSuccess The semaphore is successfully destroyed.
+ * @retval KOSA_StatusError The semaphore can not be destroyed.
+ */
+osa_status_t OSA_SemaphoreDestroy(osa_semaphore_handle_t semaphoreHandle);
+
+/*!
+ * @brief Pending a semaphore with timeout.
+ *
+ * This function checks the semaphore's counting value. If it is positive,
+ * decreases it and returns KOSA_StatusSuccess. Otherwise, a timeout is used
+ * to wait.
+ *
+ * @param semaphoreHandle The semaphore handle.
+ * @param millisec The maximum number of milliseconds to wait if semaphore is not
+ * positive. Pass osaWaitForever_c to wait indefinitely, pass 0
+ * will return KOSA_StatusTimeout immediately.
+ *
+ * @retval KOSA_StatusSuccess The semaphore is received.
+ * @retval KOSA_StatusTimeout The semaphore is not received within the specified 'timeout'.
+ * @retval KOSA_StatusError An incorrect parameter was passed.
+ */
+osa_status_t OSA_SemaphoreWait(osa_semaphore_handle_t semaphoreHandle, uint32_t millisec);
+
+/*!
+ * @brief Signals for someone waiting on the semaphore to wake up.
+ *
+ * Wakes up one task that is waiting on the semaphore. If no task is waiting, increases
+ * the semaphore's counting value.
+ *
+ * @param semaphoreHandle The semaphore handle to signal.
+ *
+ * @retval KOSA_StatusSuccess The semaphore is successfully signaled.
+ * @retval KOSA_StatusError The object can not be signaled or invalid parameter.
+ *
+ */
+osa_status_t OSA_SemaphorePost(osa_semaphore_handle_t semaphoreHandle);
+
+/*!
+ * @brief Create an unlocked mutex.
+ *
+ * This function creates a non-recursive mutex and sets it to unlocked status.
+ *
+ * Example below shows how to use this API to create the mutex handle.
+ * @code
+ * OSA_MUTEX_HANDLE_DEFINE(mutexHandle);
+ * OSA_MutexCreate((osa_mutex_handle_t)mutexHandle);
+ * @endcode
+ *
+ * @param mutexHandle Pointer to a memory space of size OSA_MUTEX_HANDLE_SIZE allocated by the caller.
+ * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices.
+ * You can define the handle in the following two ways:
+ * #OSA_MUTEX_HANDLE_DEFINE(mutexHandle);
+ * or
+ * uint32_t mutexHandle[((OSA_MUTEX_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
+ * @retval KOSA_StatusSuccess the new mutex if the mutex is created successfully.
+ * @retval KOSA_StatusError if the mutex can not be created.
+ */
+osa_status_t OSA_MutexCreate(osa_mutex_handle_t mutexHandle);
+
+/*!
+ * @brief Waits for a mutex and locks it.
+ *
+ * This function checks the mutex's status. If it is unlocked, locks it and returns the
+ * KOSA_StatusSuccess. Otherwise, waits for a timeout in milliseconds to lock.
+ *
+ * @param mutexHandle The mutex handle.
+ * @param millisec The maximum number of milliseconds to wait for the mutex.
+ * If the mutex is locked, Pass the value osaWaitForever_c will
+ * wait indefinitely, pass 0 will return KOSA_StatusTimeout
+ * immediately.
+ *
+ * @retval KOSA_StatusSuccess The mutex is locked successfully.
+ * @retval KOSA_StatusTimeout Timeout occurred.
+ * @retval KOSA_StatusError Incorrect parameter was passed.
+ *
+ * @note This is non-recursive mutex, a task can not try to lock the mutex it has locked.
+ */
+osa_status_t OSA_MutexLock(osa_mutex_handle_t mutexHandle, uint32_t millisec);
+
+/*!
+ * @brief Unlocks a previously locked mutex.
+ *
+ * @param mutexHandle The mutex handle.
+ *
+ * @retval KOSA_StatusSuccess The mutex is successfully unlocked.
+ * @retval KOSA_StatusError The mutex can not be unlocked or invalid parameter.
+ */
+osa_status_t OSA_MutexUnlock(osa_mutex_handle_t mutexHandle);
+
+/*!
+ * @brief Destroys a previously created mutex.
+ *
+ * @param mutexHandle The mutex handle.
+ *
+ * @retval KOSA_StatusSuccess The mutex is successfully destroyed.
+ * @retval KOSA_StatusError The mutex can not be destroyed.
+ *
+ */
+osa_status_t OSA_MutexDestroy(osa_mutex_handle_t mutexHandle);
+
+/*!
+ * @brief Initializes an event object with all flags cleared.
+ *
+ * This function creates an event object and set its clear mode. If autoClear
+ * is 1, when a task gets the event flags, these flags will be
+ * cleared automatically. Otherwise these flags must
+ * be cleared manually.
+ *
+ * Example below shows how to use this API to create the event handle.
+ * @code
+ * OSA_EVENT_HANDLE_DEFINE(eventHandle);
+ * OSA_EventCreate((osa_event_handle_t)eventHandle, 0);
+ * @endcode
+ *
+ * @param eventHandle Pointer to a memory space of size OSA_EVENT_HANDLE_SIZE allocated by the caller.
+ * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices.
+ * You can define the handle in the following two ways:
+ * #OSA_EVENT_HANDLE_DEFINE(eventHandle);
+ * or
+ * uint32_t eventHandle[((OSA_EVENT_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
+ * @param autoClear 1 The event is auto-clear.
+ * 0 The event manual-clear
+ * @retval KOSA_StatusSuccess the new event if the event is created successfully.
+ * @retval KOSA_StatusError if the event can not be created.
+ */
+osa_status_t OSA_EventCreate(osa_event_handle_t eventHandle, uint8_t autoClear);
+
+/*!
+ * @brief Sets one or more event flags.
+ *
+ * Sets specified flags of an event object.
+ *
+ * @param eventHandle The event handle.
+ * @param flagsToSet Flags to be set.
+ *
+ * @retval KOSA_StatusSuccess The flags were successfully set.
+ * @retval KOSA_StatusError An incorrect parameter was passed.
+ */
+osa_status_t OSA_EventSet(osa_event_handle_t eventHandle, osa_event_flags_t flagsToSet);
+
+/*!
+ * @brief Clears one or more flags.
+ *
+ * Clears specified flags of an event object.
+ *
+ * @param eventHandle The event handle.
+ * @param flagsToClear Flags to be clear.
+ *
+ * @retval KOSA_StatusSuccess The flags were successfully cleared.
+ * @retval KOSA_StatusError An incorrect parameter was passed.
+ */
+osa_status_t OSA_EventClear(osa_event_handle_t eventHandle, osa_event_flags_t flagsToClear);
+
+/*!
+ * @brief Get event's flags.
+ *
+ * Get specified flags of an event object.
+ *
+ * @param eventHandle The event handle.
+ * The macro EVENT_HANDLE_BUFFER_GET is used to get the event buffer pointer,
+ * and should not be used before the macro EVENT_HANDLE_BUFFER_DEFINE is used.
+ * @param flagsMask The flags user want to get are specified by this parameter.
+ * @param pFlagsOfEvent The event flags are obtained by this parameter.
+ *
+ * @retval KOSA_StatusSuccess The event flags were successfully got.
+ * @retval KOSA_StatusError An incorrect parameter was passed.
+ */
+osa_status_t OSA_EventGet(osa_event_handle_t eventHandle,
+ osa_event_flags_t flagsMask,
+ osa_event_flags_t *pFlagsOfEvent);
+
+/*!
+ * @brief Waits for specified event flags to be set.
+ *
+ * This function waits for a combination of flags to be set in an event object.
+ * Applications can wait for any/all bits to be set. Also this function could
+ * obtain the flags who wakeup the waiting task.
+ *
+ * @param eventHandle The event handle.
+ * @param flagsToWait Flags that to wait.
+ * @param waitAll Wait all flags or any flag to be set.
+ * @param millisec The maximum number of milliseconds to wait for the event.
+ * If the wait condition is not met, pass osaWaitForever_c will
+ * wait indefinitely, pass 0 will return KOSA_StatusTimeout
+ * immediately.
+ * @param pSetFlags Flags that wakeup the waiting task are obtained by this parameter.
+ *
+ * @retval KOSA_StatusSuccess The wait condition met and function returns successfully.
+ * @retval KOSA_StatusTimeout Has not met wait condition within timeout.
+ * @retval KOSA_StatusError An incorrect parameter was passed.
+ *
+ * @note Please pay attention to the flags bit width, FreeRTOS uses the most
+ * significant 8 bis as control bits, so do not wait these bits while using
+ * FreeRTOS.
+ *
+ */
+osa_status_t OSA_EventWait(osa_event_handle_t eventHandle,
+ osa_event_flags_t flagsToWait,
+ uint8_t waitAll,
+ uint32_t millisec,
+ osa_event_flags_t *pSetFlags);
+
+/*!
+ * @brief Destroys a previously created event object.
+ *
+ * @param eventHandle The event handle.
+ *
+ * @retval KOSA_StatusSuccess The event is successfully destroyed.
+ * @retval KOSA_StatusError Event destruction failed.
+ */
+osa_status_t OSA_EventDestroy(osa_event_handle_t eventHandle);
+
+/*!
+ * @brief Initializes a message queue.
+ *
+ * This function allocates memory for and initializes a message queue. Message queue elements are hardcoded as void*.
+ *
+ * Example below shows how to use this API to create the massage queue handle.
+ * @code
+ * OSA_MSGQ_HANDLE_DEFINE(msgqHandle);
+ * OSA_MsgQCreate((osa_msgq_handle_t)msgqHandle, 5U, sizeof(msg));
+ * @endcode
+ *
+ * @param msgqHandle Pointer to a memory space of size #(OSA_MSGQ_HANDLE_SIZE + msgNo*msgSize) on bare-matel
+ * and #(OSA_MSGQ_HANDLE_SIZE) on FreeRTOS allocated by the caller, message queue handle.
+ * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices.
+ * You can define the handle in the following two ways:
+ * #OSA_MSGQ_HANDLE_DEFINE(msgqHandle);
+ * or
+ * For bm: uint32_t msgqHandle[((OSA_MSGQ_HANDLE_SIZE + msgNo*msgSize + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
+ * For freertos: uint32_t msgqHandle[((OSA_MSGQ_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
+ * @param msgNo :number of messages the message queue should accommodate.
+ * @param msgSize :size of a single message structure.
+ *
+ * @retval KOSA_StatusSuccess Message queue successfully Create.
+ * @retval KOSA_StatusError Message queue create failure.
+ */
+osa_status_t OSA_MsgQCreate(osa_msgq_handle_t msgqHandle, uint32_t msgNo, uint32_t msgSize);
+
+/*!
+ * @brief Puts a message at the end of the queue.
+ *
+ * This function puts a message to the end of the message queue. If the queue
+ * is full, this function returns the KOSA_StatusError;
+ *
+ * @param msgqHandle Message Queue handler.
+ * @param pMessage Pointer to the message to be put into the queue.
+ *
+ * @retval KOSA_StatusSuccess Message successfully put into the queue.
+ * @retval KOSA_StatusError The queue was full or an invalid parameter was passed.
+ */
+osa_status_t OSA_MsgQPut(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage);
+
+/*!
+ * @brief Reads and remove a message at the head of the queue.
+ *
+ * This function gets a message from the head of the message queue. If the
+ * queue is empty, timeout is used to wait.
+ *
+ * @param msgqHandle Message Queue handler.
+ * @param pMessage Pointer to a memory to save the message.
+ * @param millisec The number of milliseconds to wait for a message. If the
+ * queue is empty, pass osaWaitForever_c will wait indefinitely,
+ * pass 0 will return KOSA_StatusTimeout immediately.
+ *
+ * @retval KOSA_StatusSuccess Message successfully obtained from the queue.
+ * @retval KOSA_StatusTimeout The queue remains empty after timeout.
+ * @retval KOSA_StatusError Invalid parameter.
+ */
+osa_status_t OSA_MsgQGet(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage, uint32_t millisec);
+
+/*!
+ * @brief Destroys a previously created queue.
+ *
+ * @param msgqHandle Message Queue handler.
+ *
+ * @retval KOSA_StatusSuccess The queue was successfully destroyed.
+ * @retval KOSA_StatusError Message queue destruction failed.
+ */
+osa_status_t OSA_MsgQDestroy(osa_msgq_handle_t msgqHandle);
+
+/*!
+ * @brief Enable all interrupts.
+ */
+void OSA_InterruptEnable(void);
+
+/*!
+ * @brief Disable all interrupts.
+ */
+void OSA_InterruptDisable(void);
+
+/*!
+ * @brief Enable all interrupts using PRIMASK.
+ */
+void OSA_EnableIRQGlobal(void);
+
+/*!
+ * @brief Disable all interrupts using PRIMASK.
+ */
+void OSA_DisableIRQGlobal(void);
+
+/*!
+ * @brief Delays execution for a number of milliseconds.
+ *
+ * @param millisec The time in milliseconds to wait.
+ */
+void OSA_TimeDelay(uint32_t millisec);
+
+/*!
+ * @brief This function gets current time in milliseconds.
+ *
+ * @retval current time in milliseconds
+ */
+uint32_t OSA_TimeGetMsec(void);
+
+/*!
+ * @brief Installs the interrupt handler.
+ *
+ * @param IRQNumber IRQ number of the interrupt.
+ * @param handler The interrupt handler to install.
+ */
+void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void));
+
+/*! @}*/
+#ifdef __cplusplus
+}
+#endif
+/*! @}*/
+#endif
diff --git a/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_config.h b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_config.h
new file mode 100644
index 0000000000..234cf972bc
--- /dev/null
+++ b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_config.h
@@ -0,0 +1,36 @@
+/*!
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016-2018 NXP
+ *
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_OS_ABSTRACTION_CONFIG_H_
+#define _FSL_OS_ABSTRACTION_CONFIG_H_
+
+#ifndef gMainThreadStackSize_c
+#define gMainThreadStackSize_c 1024
+#endif
+
+#ifndef gMainThreadPriority_c
+#define gMainThreadPriority_c 1
+#endif
+
+#ifndef gTaskMultipleInstancesManagement_c
+#define gTaskMultipleInstancesManagement_c 0
+#endif
+
+/*! @brief Definition to determine whether enable OSA's TASK module. */
+#ifndef OSA_USED
+#ifndef FSL_OSA_TASK_ENABLE
+#define FSL_OSA_TASK_ENABLE 0U
+#endif
+#else
+#if defined(FSL_OSA_TASK_ENABLE)
+#undef FSL_OSA_TASK_ENABLE
+#endif
+#define FSL_OSA_TASK_ENABLE 1U
+#endif /* OSA_USED */
+
+#endif /* _FSL_OS_ABSTRACTION_CONFIG_H_ */
diff --git a/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_rtthread.c b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_rtthread.c
new file mode 100644
index 0000000000..524744c251
--- /dev/null
+++ b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_rtthread.c
@@ -0,0 +1,917 @@
+/*! *********************************************************************************
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * Copyright 2016-2017, 2019 NXP
+ * All rights reserved.
+ *
+ *
+ * This is the source file for the OS Abstraction layer for freertos.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ ********************************************************************************** */
+
+/*! *********************************************************************************
+*************************************************************************************
+* Include
+*************************************************************************************
+********************************************************************************** */
+#include "fsl_common.h"
+#include "fsl_os_abstraction.h"
+#include "fsl_os_abstraction_rtthread.h"
+#include <string.h>
+#include "generic_list.h"
+
+/*! *********************************************************************************
+*************************************************************************************
+* Private macros
+*************************************************************************************
+********************************************************************************** */
+
+/* Weak function. */
+#if defined(__GNUC__)
+#define __WEAK_FUNC __attribute__((weak))
+#elif defined(__ICCARM__)
+#define __WEAK_FUNC __weak
+#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
+#define __WEAK_FUNC __attribute__((weak))
+#endif
+
+#define millisecToTicks(millisec) (((millisec)*configTICK_RATE_HZ + 999U) / 1000U)
+
+#ifdef DEBUG_ASSERT
+#define OS_ASSERT(condition) \
+ if (!(condition)) \
+ while (1) \
+ ;
+#else
+#define OS_ASSERT(condition) (void)(condition);
+#endif
+
+/*! @brief Converts milliseconds to ticks*/
+#define MSEC_TO_TICK(msec) \
+ (((uint32_t)(msec) + 500uL / (uint32_t)configTICK_RATE_HZ) * (uint32_t)configTICK_RATE_HZ / 1000uL)
+#define TICKS_TO_MSEC(tick) ((uint32_t)((uint64_t)(tick)*1000uL / (uint64_t)configTICK_RATE_HZ))
+/************************************************************************************
+*************************************************************************************
+* Private type definitions
+*************************************************************************************
+************************************************************************************/
+typedef struct osa_freertos_task
+{
+ list_element_t link;
+ rt_thread_t taskHandle;
+} osa_freertos_task_t;
+
+typedef struct _osa_event_struct
+{
+ rt_event_t handle; /* The event handle */
+ uint8_t autoClear; /*!< Auto clear or manual clear */
+} osa_event_struct_t;
+
+/*! @brief State structure for bm osa manager. */
+typedef struct _osa_state
+{
+#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
+ list_label_t taskList;
+ OSA_TASK_HANDLE_DEFINE(mainTaskHandle);
+#endif
+ uint32_t basePriority;
+ int32_t basePriorityNesting;
+ uint32_t interruptDisableCount;
+} osa_state_t;
+
+/*! *********************************************************************************
+*************************************************************************************
+* Private prototypes
+*************************************************************************************
+********************************************************************************** */
+__WEAK_FUNC void main_task(void const *argument);
+__WEAK_FUNC void main_task(void const *argument)
+{
+}
+
+void startup_task(void *argument);
+
+/*! *********************************************************************************
+*************************************************************************************
+* Public memory declarations
+*************************************************************************************
+********************************************************************************** */
+const uint8_t gUseRtos_c = USE_RTOS; // USE_RTOS = 0 for BareMetal and 1 for OS
+
+static osa_state_t s_osaState = {0};
+/*! *********************************************************************************
+*************************************************************************************
+* Private memory declarations
+*************************************************************************************
+********************************************************************************** */
+
+/*! *********************************************************************************
+*************************************************************************************
+* Public functions
+*************************************************************************************
+********************************************************************************** */
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MemoryAllocate
+ * Description : Reserves the requested amount of memory in bytes.
+ *
+ *END**************************************************************************/
+void *OSA_MemoryAllocate(uint32_t length)
+{
+ void *p = rt_malloc(length);
+
+ if (RT_NULL != p)
+ {
+ rt_memset(p, 0, length);
+ }
+
+ return p;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MemoryFree
+ * Description : Frees the memory previously reserved.
+ *
+ *END**************************************************************************/
+void OSA_MemoryFree(void *p)
+{
+ rt_free(p);
+}
+
+void OSA_EnterCritical(uint32_t *sr)
+{
+ if (rt_thread_self() != RT_NULL)
+ rt_enter_critical();
+}
+
+void OSA_ExitCritical(uint32_t sr)
+{
+ if (rt_thread_self() != RT_NULL)
+ rt_exit_critical();
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : startup_task
+ * Description : Wrapper over main_task..
+ *
+ *END**************************************************************************/
+void startup_task(void *argument)
+{
+ main_task(argument);
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_TaskGetCurrentHandle
+ * Description : This function is used to get current active task's handler.
+ *
+ *END**************************************************************************/
+#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_task_handle_t OSA_TaskGetCurrentHandle(void)
+{
+ list_element_handle_t list_element;
+ osa_freertos_task_t *ptask;
+
+ list_element = LIST_GetHead(&s_osaState.taskList);
+ while (NULL != list_element)
+ {
+ ptask = (osa_freertos_task_t *)(void *)list_element;
+ if (ptask->taskHandle == xTaskGetCurrentTaskHandle())
+ {
+ return (osa_task_handle_t)ptask;
+ }
+ list_element = LIST_GetNext(list_element);
+ }
+ return NULL;
+}
+#endif
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_TaskYield
+ * Description : When a task calls this function, it will give up CPU and put
+ * itself to the tail of ready list.
+ *
+ *END**************************************************************************/
+#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_status_t OSA_TaskYield(void)
+{
+ taskYIELD();
+ return KOSA_StatusSuccess;
+}
+#endif
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_TaskGetPriority
+ * Description : This function returns task's priority by task handler.
+ *
+ *END**************************************************************************/
+#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_task_priority_t OSA_TaskGetPriority(osa_task_handle_t taskHandle)
+{
+ assert(taskHandle);
+ osa_freertos_task_t *ptask = (osa_freertos_task_t *)taskHandle;
+ return (osa_task_priority_t)(PRIORITY_RTOS_TO_OSA(uxTaskPriorityGet(ptask->taskHandle)));
+}
+#endif
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_TaskSetPriority
+ * Description : This function sets task's priority by task handler.
+ *
+ *END**************************************************************************/
+#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_status_t OSA_TaskSetPriority(osa_task_handle_t taskHandle, osa_task_priority_t taskPriority)
+{
+ assert(taskHandle);
+ osa_freertos_task_t *ptask = (osa_freertos_task_t *)taskHandle;
+ vTaskPrioritySet((task_handler_t)ptask->taskHandle, PRIORITY_OSA_TO_RTOS(taskPriority));
+ return KOSA_StatusSuccess;
+}
+#endif
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_TaskCreate
+ * Description : This function is used to create a task and make it ready.
+ * Param[in] : threadDef - Definition of the thread.
+ * task_param - Parameter to pass to the new thread.
+ * Return Thread handle of the new thread, or NULL if failed.
+ *
+ *END**************************************************************************/
+#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_status_t OSA_TaskCreate(osa_task_handle_t taskHandle, osa_task_def_t *thread_def, osa_task_param_t task_param)
+{
+ assert(sizeof(osa_freertos_task_t) == OSA_TASK_HANDLE_SIZE);
+ assert(taskHandle);
+ TaskHandle_t pxCreatedTask;
+ osa_freertos_task_t *ptask = (osa_freertos_task_t *)taskHandle;
+
+ if (xTaskCreate((TaskFunction_t)thread_def->pthread, /* pointer to the task */
+ (char const *)thread_def->tname, /* task name for kernel awareness debugging */
+ (configSTACK_DEPTH_TYPE)thread_def->stacksize / sizeof(portSTACK_TYPE), /* task stack size */
+ (task_param_t)task_param, /* optional task startup argument */
+ PRIORITY_OSA_TO_RTOS(thread_def->tpriority), /* initial priority */
+ &pxCreatedTask /* optional task handle to create */
+ ) == pdPASS)
+ {
+ ptask->taskHandle = pxCreatedTask;
+ OSA_InterruptDisable();
+ (void)LIST_AddTail(&s_osaState.taskList, (list_element_handle_t) & (ptask->link));
+ OSA_InterruptEnable();
+ return KOSA_StatusSuccess;
+ }
+ return KOSA_StatusError;
+}
+#endif
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_TaskDestroy
+ * Description : This function destroy a task.
+ * Param[in] :taskHandle - Thread handle.
+ * Return KOSA_StatusSuccess if the task is destroied, otherwise return KOSA_StatusError.
+ *
+ *END**************************************************************************/
+#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
+osa_status_t OSA_TaskDestroy(osa_task_handle_t taskHandle)
+{
+ assert(taskHandle);
+ osa_freertos_task_t *ptask = (osa_freertos_task_t *)taskHandle;
+ osa_status_t status;
+ uint16_t oldPriority;
+ /*Change priority to avoid context switches*/
+ oldPriority = OSA_TaskGetPriority(OSA_TaskGetCurrentHandle());
+ (void)OSA_TaskSetPriority(OSA_TaskGetCurrentHandle(), OSA_PRIORITY_REAL_TIME);
+#if INCLUDE_vTaskDelete /* vTaskDelete() enabled */
+ vTaskDelete((task_handler_t)ptask->taskHandle);
+ status = KOSA_StatusSuccess;
+#else
+ status = KOSA_StatusError; /* vTaskDelete() not available */
+#endif
+ (void)OSA_TaskSetPriority(OSA_TaskGetCurrentHandle(), oldPriority);
+ OSA_InterruptDisable();
+ (void)LIST_RemoveElement(taskHandle);
+ OSA_InterruptEnable();
+ return status;
+}
+#endif
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_TimeDelay
+ * Description : This function is used to suspend the active thread for the given number of milliseconds.
+ *
+ *END**************************************************************************/
+void OSA_TimeDelay(uint32_t millisec)
+{
+ rt_thread_mdelay(millisec);
+}
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_TimeGetMsec
+ * Description : This function gets current time in milliseconds.
+ *
+ *END**************************************************************************/
+uint32_t OSA_TimeGetMsec(void)
+{
+ return rt_tick_get_millisecond();
+}
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_SemaphoreCreate
+ * Description : This function is used to create a semaphore.
+ * Return : Semaphore handle of the new semaphore, or NULL if failed.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_SemaphoreCreate(osa_semaphore_handle_t semaphoreHandle, uint32_t initValue)
+{
+ assert(sizeof(osa_semaphore_handle_t) == OSA_SEM_HANDLE_SIZE);
+ assert(semaphoreHandle);
+
+ union
+ {
+ rt_sem_t sem;
+ uint32_t semhandle;
+ } xSemaHandle;
+
+ xSemaHandle.sem = rt_sem_create("osa_sem", initValue, RT_IPC_FLAG_PRIO);
+ if (NULL != xSemaHandle.sem)
+ {
+ *(uint32_t *)semaphoreHandle = xSemaHandle.semhandle;
+ return KOSA_StatusSuccess;
+ }
+ return KOSA_StatusError;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_SemaphoreDestroy
+ * Description : This function is used to destroy a semaphore.
+ * Return : KOSA_StatusSuccess if the semaphore is destroyed successfully, otherwise return KOSA_StatusError.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_SemaphoreDestroy(osa_semaphore_handle_t semaphoreHandle)
+{
+ assert(semaphoreHandle);
+ rt_sem_t sem = (rt_sem_t)(void *)(uint32_t *)(*(uint32_t *)semaphoreHandle);
+
+ rt_sem_delete(sem);
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_SemaphoreWait
+ * Description : This function checks the semaphore's counting value, if it is
+ * positive, decreases it and returns KOSA_StatusSuccess, otherwise, timeout
+ * will be used for wait. The parameter timeout indicates how long should wait
+ * in milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will
+ * return KOSA_StatusTimeout immediately if semaphore is not positive.
+ * This function returns KOSA_StatusSuccess if the semaphore is received, returns
+ * KOSA_StatusTimeout if the semaphore is not received within the specified
+ * 'timeout', returns KOSA_StatusError if any errors occur during waiting.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_SemaphoreWait(osa_semaphore_handle_t semaphoreHandle, uint32_t millisec)
+{
+ int32_t timeoutTicks;
+ assert(semaphoreHandle);
+ rt_sem_t sem = (rt_sem_t)(void *)(uint32_t *)(*(uint32_t *)semaphoreHandle);
+
+ /* Convert timeout from millisecond to tick. */
+ if (millisec == osaWaitForever_c)
+ {
+ timeoutTicks = RT_WAITING_FOREVER;
+ }
+ else
+ {
+ timeoutTicks = rt_tick_from_millisecond(millisec);
+ }
+
+ if (RT_EOK != rt_sem_take(sem, timeoutTicks))
+ {
+ return KOSA_StatusTimeout; /* timeout */
+ }
+ else
+ {
+ return KOSA_StatusSuccess; /* semaphore taken */
+ }
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_SemaphorePost
+ * Description : This function is used to wake up one task that wating on the
+ * semaphore. If no task is waiting, increase the semaphore. The function returns
+ * KOSA_StatusSuccess if the semaphre is post successfully, otherwise returns
+ * KOSA_StatusError.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_SemaphorePost(osa_semaphore_handle_t semaphoreHandle)
+{
+ assert(semaphoreHandle);
+ rt_sem_t sem = (rt_sem_t)(void *)(uint32_t *)(*(uint32_t *)semaphoreHandle);
+ rt_sem_release(sem);
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MutexCreate
+ * Description : This function is used to create a mutex.
+ * Return : Mutex handle of the new mutex, or NULL if failed.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_MutexCreate(osa_mutex_handle_t mutexHandle)
+{
+ assert(sizeof(osa_mutex_handle_t) == OSA_MUTEX_HANDLE_SIZE);
+ assert(mutexHandle);
+
+ union
+ {
+ rt_mutex_t mutex;
+ uint32_t pmutexHandle;
+ } xMutexHandle;
+
+ xMutexHandle.mutex = rt_mutex_create("osa_mutex", RT_IPC_FLAG_PRIO);
+ if (RT_NULL != xMutexHandle.mutex)
+ {
+ *(uint32_t *)mutexHandle = xMutexHandle.pmutexHandle;
+ return KOSA_StatusSuccess;
+ }
+ return KOSA_StatusError;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MutexLock
+ * Description : This function checks the mutex's status, if it is unlocked,
+ * lock it and returns KOSA_StatusSuccess, otherwise, wait for the mutex.
+ * This function returns KOSA_StatusSuccess if the mutex is obtained, returns
+ * KOSA_StatusError if any errors occur during waiting. If the mutex has been
+ * locked, pass 0 as timeout will return KOSA_StatusTimeout immediately.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_MutexLock(osa_mutex_handle_t mutexHandle, uint32_t millisec)
+{
+ assert(mutexHandle);
+ int32_t timeoutTicks;
+ rt_mutex_t mutex = (rt_mutex_t)(void *)(uint32_t *)(*(uint32_t *)mutexHandle);
+
+ /* Convert timeout from millisecond to tick. */
+ if (millisec == osaWaitForever_c)
+ {
+ timeoutTicks = RT_WAITING_FOREVER;
+ }
+ else
+ {
+ timeoutTicks = rt_tick_from_millisecond(millisec);
+ }
+
+ if (RT_EOK != rt_mutex_take(mutex, timeoutTicks))
+ {
+ return KOSA_StatusTimeout; /* timeout */
+ }
+ else
+ {
+ return KOSA_StatusSuccess; /* semaphore taken */
+ }
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MutexUnlock
+ * Description : This function is used to unlock a mutex.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_MutexUnlock(osa_mutex_handle_t mutexHandle)
+{
+ assert(mutexHandle);
+ rt_mutex_t mutex = (rt_mutex_t)(void *)(uint32_t *)(*(uint32_t *)mutexHandle);
+ rt_mutex_release(mutex);
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MutexDestroy
+ * Description : This function is used to destroy a mutex.
+ * Return : KOSA_StatusSuccess if the lock object is destroyed successfully, otherwise return KOSA_StatusError.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_MutexDestroy(osa_mutex_handle_t mutexHandle)
+{
+ assert(mutexHandle);
+ rt_mutex_t mutex = (rt_mutex_t)(void *)(uint32_t *)(*(uint32_t *)mutexHandle);
+
+ rt_mutex_delete(mutex);
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_EventCreate
+ * Description : This function is used to create a event object.
+ * Return : Event handle of the new event, or NULL if failed.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_EventCreate(osa_event_handle_t eventHandle, uint8_t autoClear)
+{
+ assert(eventHandle);
+ osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
+
+ pEventStruct->handle = rt_event_create("osa_event", RT_IPC_FLAG_PRIO);
+ if (RT_NULL != pEventStruct->handle)
+ {
+ pEventStruct->autoClear = autoClear;
+ }
+ else
+ {
+ return KOSA_StatusError;
+ }
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_EventSet
+ * Description : Set one or more event flags of an event object.
+ * Return : KOSA_StatusSuccess if set successfully, KOSA_StatusError if failed.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_EventSet(osa_event_handle_t eventHandle, osa_event_flags_t flagsToSet)
+{
+ rt_err_t result;
+ assert(eventHandle);
+ osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
+
+ if (RT_NULL == pEventStruct->handle)
+ {
+ return KOSA_StatusError;
+ }
+
+ rt_event_send(pEventStruct->handle, (rt_uint32_t)flagsToSet);
+
+ (void)result;
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_EventClear
+ * Description : Clear one or more event flags of an event object.
+ * Return :KOSA_StatusSuccess if clear successfully, KOSA_StatusError if failed.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_EventClear(osa_event_handle_t eventHandle, osa_event_flags_t flagsToClear)
+{
+ assert(eventHandle);
+ osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
+
+ if (RT_NULL == pEventStruct->handle)
+ {
+ return KOSA_StatusError;
+ }
+
+ rt_uint32_t recved;
+ rt_event_recv(pEventStruct->handle, (rt_uint32_t)flagsToClear, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0, &recved);
+
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_EventGet
+ * Description : This function is used to get event's flags that specified by prameter
+ * flagsMask, and the flags (user specified) are obatianed by parameter pFlagsOfEvent. So
+ * you should pass the parameter 0xffffffff to specify you want to check all.
+ * Return :KOSA_StatusSuccess if event flags were successfully got, KOSA_StatusError if failed.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_EventGet(osa_event_handle_t eventHandle, osa_event_flags_t flagsMask, osa_event_flags_t *pFlagsOfEvent)
+{
+ assert(eventHandle);
+ osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
+ rt_uint32_t eventFlags;
+
+ if (RT_NULL == pEventStruct->handle)
+ {
+ return KOSA_StatusError;
+ }
+
+ if (RT_NULL == pFlagsOfEvent)
+ {
+ return KOSA_StatusError;
+ }
+
+ if (RT_EOK != rt_event_recv(pEventStruct->handle, (rt_uint32_t)flagsMask, RT_EVENT_FLAG_OR, 0, &eventFlags))
+ {
+ eventFlags = 0;
+ }
+
+ *pFlagsOfEvent = (osa_event_flags_t)eventFlags & flagsMask;
+
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_EventWait
+ * Description : This function checks the event's status, if it meets the wait
+ * condition, return KOSA_StatusSuccess, otherwise, timeout will be used for
+ * wait. The parameter timeout indicates how long should wait in milliseconds.
+ * Pass osaWaitForever_c to wait indefinitely, pass 0 will return the value
+ * KOSA_StatusTimeout immediately if wait condition is not met. The event flags
+ * will be cleared if the event is auto clear mode. Flags that wakeup waiting
+ * task could be obtained from the parameter setFlags.
+ * This function returns KOSA_StatusSuccess if wait condition is met, returns
+ * KOSA_StatusTimeout if wait condition is not met within the specified
+ * 'timeout', returns KOSA_StatusError if any errors occur during waiting.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_EventWait(osa_event_handle_t eventHandle,
+ osa_event_flags_t flagsToWait,
+ uint8_t waitAll,
+ uint32_t millisec,
+ osa_event_flags_t *pSetFlags)
+{
+ assert(eventHandle);
+ rt_uint8_t option = 0;
+ rt_int32_t timeoutTicks;
+ rt_uint32_t flagsSave;
+ osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
+
+ /* Clean FreeRTOS cotrol flags */
+ flagsToWait = flagsToWait & 0x00FFFFFFU;
+ if (RT_NULL == pEventStruct->handle)
+ {
+ return KOSA_StatusError;
+ }
+
+ /* Convert timeout from millisecond to tick. */
+ if (millisec == osaWaitForever_c)
+ {
+ timeoutTicks = RT_WAITING_FOREVER;
+ }
+ else
+ {
+ timeoutTicks = rt_tick_from_millisecond(millisec);
+ }
+
+ if (pEventStruct->autoClear != 0U)
+ {
+ option |= RT_EVENT_FLAG_CLEAR;
+ }
+ option |= waitAll ? RT_EVENT_FLAG_AND : RT_EVENT_FLAG_OR;
+
+ rt_err_t status = rt_event_recv(pEventStruct->handle, (rt_uint32_t)flagsToWait, option, timeoutTicks, &flagsSave);
+
+ flagsSave &= (rt_uint32_t)flagsToWait;
+ if (RT_NULL != pSetFlags)
+ {
+ *pSetFlags = (osa_event_flags_t)flagsSave;
+ }
+
+ if (RT_EOK != status)
+ {
+ return KOSA_StatusTimeout;
+ }
+ else
+ {
+ return KOSA_StatusSuccess;
+ }
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_EventDestroy
+ * Description : This function is used to destroy a event object. Return
+ * KOSA_StatusSuccess if the event object is destroyed successfully, otherwise
+ * return KOSA_StatusError.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_EventDestroy(osa_event_handle_t eventHandle)
+{
+ assert(eventHandle);
+ osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
+
+ if (RT_NULL == pEventStruct->handle)
+ {
+ return KOSA_StatusError;
+ }
+ rt_event_delete(pEventStruct->handle);
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MsgQCreate
+ * Description : This function is used to create a message queue.
+ * Return : the handle to the message queue if create successfully, otherwise
+ * return NULL.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_MsgQCreate(osa_msgq_handle_t msgqHandle, uint32_t msgNo, uint32_t msgSize)
+{
+ assert(sizeof(osa_msgq_handle_t) == OSA_MSGQ_HANDLE_SIZE);
+ assert(msgqHandle);
+
+ union
+ {
+ rt_mq_t msgq;
+ uint32_t pmsgqHandle;
+ } xMsgqHandle;
+
+ /* Create the message queue where the number and size is specified by msgNo and msgSize */
+ xMsgqHandle.msgq = rt_mq_create("osa_mq", msgSize, msgNo, RT_IPC_FLAG_PRIO);
+ if (RT_NULL != xMsgqHandle.msgq)
+ {
+ *(uint32_t *)msgqHandle = xMsgqHandle.pmsgqHandle;
+ return KOSA_StatusSuccess;
+ }
+ return KOSA_StatusError;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MsgQPut
+ * Description : This function is used to put a message to a message queue.
+ * Return : KOSA_StatusSuccess if the message is put successfully, otherwise return KOSA_StatusError.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_MsgQPut(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage)
+{
+ assert(msgqHandle);
+ rt_mq_t handler = (rt_mq_t)(void *)(uint32_t *)(*(uint32_t *)msgqHandle);
+
+ if (RT_EOK == rt_mq_send(handler, pMessage, handler->msg_size))
+ {
+ return KOSA_StatusSuccess;
+ }
+ else
+ {
+ return KOSA_StatusError;
+ }
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MsgQGet
+ * Description : This function checks the queue's status, if it is not empty,
+ * get message from it and return KOSA_StatusSuccess, otherwise, timeout will
+ * be used for wait. The parameter timeout indicates how long should wait in
+ * milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will return
+ * KOSA_StatusTimeout immediately if queue is empty.
+ * This function returns KOSA_StatusSuccess if message is got successfully,
+ * returns KOSA_StatusTimeout if message queue is empty within the specified
+ * 'timeout', returns KOSA_StatusError if any errors occur during waiting.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_MsgQGet(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage, uint32_t millisec)
+{
+ osa_status_t osaStatus;
+ assert(msgqHandle);
+ rt_mq_t handler = (rt_mq_t)(void *)(uint32_t *)(*(uint32_t *)msgqHandle);
+
+ int32_t timeoutTicks;
+
+ if (millisec == osaWaitForever_c)
+ {
+ timeoutTicks = RT_WAITING_FOREVER;
+ }
+ else
+ {
+ timeoutTicks = rt_tick_from_millisecond(millisec);
+ }
+ if (RT_EOK != rt_mq_recv(handler, pMessage, handler->msg_size, timeoutTicks))
+ {
+ osaStatus = KOSA_StatusTimeout; /* not able to send it to the queue? */
+ }
+ else
+ {
+ osaStatus = KOSA_StatusSuccess;
+ }
+ return osaStatus;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_MsgQDestroy
+ * Description : This function is used to destroy the message queue.
+ * Return : KOSA_StatusSuccess if the message queue is destroyed successfully, otherwise return KOSA_StatusError.
+ *
+ *END**************************************************************************/
+osa_status_t OSA_MsgQDestroy(osa_msgq_handle_t msgqHandle)
+{
+ assert(msgqHandle);
+ rt_mq_t handler = (rt_mq_t)(void *)(uint32_t *)(*(uint32_t *)msgqHandle);
+
+ rt_mq_delete(handler);
+ return KOSA_StatusSuccess;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_InterruptEnable
+ * Description : self explanatory.
+ *
+ *END**************************************************************************/
+void OSA_InterruptEnable(void)
+{
+ rt_exit_critical();
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_InterruptDisable
+ * Description : self explanatory.
+ *
+ *END**************************************************************************/
+void OSA_InterruptDisable(void)
+{
+ rt_enter_critical();
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_EnableIRQGlobal
+ * Description : enable interrupts using PRIMASK register.
+ *
+ *END**************************************************************************/
+void OSA_EnableIRQGlobal(void)
+{
+ if (s_osaState.interruptDisableCount > 0U)
+ {
+ s_osaState.interruptDisableCount--;
+
+ if (0U == s_osaState.interruptDisableCount)
+ {
+ __enable_irq();
+ }
+ /* call core API to enable the global interrupt*/
+ }
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_DisableIRQGlobal
+ * Description : disable interrupts using PRIMASK register.
+ *
+ *END**************************************************************************/
+void OSA_DisableIRQGlobal(void)
+{
+ /* call core API to disable the global interrupt*/
+ __disable_irq();
+
+ /* update counter*/
+ s_osaState.interruptDisableCount++;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : OSA_InstallIntHandler
+ * Description : This function is used to install interrupt handler.
+ *
+ *END**************************************************************************/
+void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void))
+{
+#if defined(__IAR_SYSTEMS_ICC__)
+ _Pragma("diag_suppress = Pm138")
+#endif
+#if defined(ENABLE_RAM_VECTOR_TABLE)
+ (void) InstallIRQHandler((IRQn_Type)IRQNumber, (uint32_t) * (uint32_t *)&handler);
+#endif /* ENABLE_RAM_VECTOR_TABLE. */
+#if defined(__IAR_SYSTEMS_ICC__)
+ _Pragma("diag_remark = PM138")
+#endif
+}
+
+/*!*********************************************************************************
+*************************************************************************************
+* Private functions
+*************************************************************************************
+********************************************************************************** */
+#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
+
+static OSA_TASK_DEFINE(startup_task, gMainThreadPriority_c, 1, gMainThreadStackSize_c, 0);
+
+int main(void)
+{
+ extern void BOARD_InitHardware(void);
+ /* Initialize MCU clock */
+ BOARD_InitHardware();
+ LIST_Init((&s_osaState.taskList), 0);
+
+ s_osaState.basePriorityNesting = 0;
+ s_osaState.interruptDisableCount = 0;
+ (void)OSA_TaskCreate((osa_task_handle_t)s_osaState.mainTaskHandle, OSA_TASK(startup_task), NULL);
+
+ vTaskStartScheduler();
+ return 0;
+}
+#endif /* FSL_OSA_TASK_ENABLE */
diff --git a/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_rtthread.h b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_rtthread.h
new file mode 100644
index 0000000000..40bd24271a
--- /dev/null
+++ b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_os_abstraction_rtthread.h
@@ -0,0 +1,130 @@
+/*! *********************************************************************************
+ * Copyright (c) 2013-2014, Freescale Semiconductor, Inc.
+ * Copyright 2016-2017 NXP
+ * All rights reserved.
+ *
+ * ile
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ ********************************************************************************** */
+#if !defined(__FSL_OS_ABSTRACTION_RTTHREAD_H__)
+#define __FSL_OS_ABSTRACTION_RTTHREAD_H__
+
+#if defined(__IAR_SYSTEMS_ICC__)
+/**
+ * Workaround to disable MISRA C message suppress warnings for IAR compiler.
+ */
+// http://supp.iar.com/Support/?note=24725
+
+#define MISRAC_DISABLE \
+ _Pragma( \
+ "diag_suppress= \
+ Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
+ Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
+ Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
+ Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
+ Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
+ Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
+ Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
+ Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
+ Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
+ Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
+ Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
+ Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
+ Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
+ Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
+ Pm155")
+
+#define MISRAC_ENABLE \
+ _Pragma( \
+ "diag_default= \
+ Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
+ Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
+ Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
+ Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
+ Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
+ Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
+ Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
+ Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
+ Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
+ Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
+ Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
+ Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
+ Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
+ Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
+ Pm155")
+#else
+/* Empty MISRA C macros for other toolchains. */
+#define MISRAC_DISABLE
+#define MISRAC_ENABLE
+#endif
+
+MISRAC_DISABLE
+#include <rtthread.h>
+MISRAC_ENABLE
+
+/*!
+ * @addtogroup os_abstraction_free_rtos
+ * @{
+ */
+
+/*******************************************************************************
+ * Declarations
+ ******************************************************************************/
+/*! @brief Type for a task handler, returned by the OSA_TaskCreate function. */
+typedef rt_thread_t task_handler_t;
+
+/*! @brief Type for a task stack.*/
+typedef rt_uint32_t task_stack_t;
+
+/*! @brief Type for task parameter */
+typedef void *task_param_t;
+
+/*! @brief Type for an event flags object.*/
+typedef rt_uint32_t event_flags_t;
+
+/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
+#define OSA_WAIT_FOREVER 0xFFFFFFFFU
+
+/*! @brief OSA's time range in millisecond, OSA time wraps if exceeds this value. */
+#define FSL_OSA_TIME_RANGE 0xFFFFFFFFU
+
+/*! @brief The default interrupt handler installed in vector table. */
+#define OSA_DEFAULT_INT_HANDLER ((osa_int_handler_t)(&DefaultISR))
+
+extern void DefaultISR(void);
+
+/*!
+ * @name Thread management
+ * @{
+ */
+
+/*!
+ * @brief To provide unified task piority for upper layer, OSA layer makes conversion.
+ */
+#define PRIORITY_OSA_TO_RTOS(osa_prio) ((UBaseType_t)configMAX_PRIORITIES - (osa_prio)-2U)
+#define PRIORITY_RTOS_TO_OSA(rtos_prio) ((UBaseType_t)configMAX_PRIORITIES - (rtos_prio)-2U)
+
+/* @}*/
+
+/*!
+ * @name Message queues
+ * @{
+ */
+
+/*!
+ * @brief This macro statically reserves the memory required for the queue.
+ *
+ * @param name Identifier for the memory region.
+ * @param number Number of elements in the queue.
+ * @param size Size of every elements in words.
+ */
+#define MSG_QUEUE_DECLARE(name, number, size) msg_queue_t *name = NULL
+
+/* @}*/
+
+/*! @}*/
+/*! @}*/
+/*! @}*/
+
+#endif // __FSL_OS_ABSTRACTION_RTTHREAD_H__
diff --git a/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/generic_list.c b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/generic_list.c
new file mode 100644
index 0000000000..80dd21425d
--- /dev/null
+++ b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/generic_list.c
@@ -0,0 +1,475 @@
+/*
+ * Copyright 2018-2019 NXP
+ * All rights reserved.
+ *
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*! *********************************************************************************
+*************************************************************************************
+* Include
+*************************************************************************************
+********************************************************************************** */
+#include "generic_list.h"
+
+static list_status_t LIST_Error_Check(list_handle_t list, list_element_handle_t newElement)
+{
+ list_status_t listStatus = kLIST_Ok;
+ list_element_handle_t element = list->head;
+
+ if ((list->max != 0U) && (list->max == list->size))
+ {
+ listStatus = kLIST_Full; /*List is full*/
+ }
+ else
+ {
+ while (element != NULL) /*Scan list*/
+ {
+ /* Determine if element is duplicated */
+ if (element == newElement)
+ {
+ listStatus = kLIST_DuplicateError;
+ break;
+ }
+ element = element->next;
+ }
+ }
+
+ return listStatus;
+}
+
+/*! *********************************************************************************
+*************************************************************************************
+* Public functions
+*************************************************************************************
+********************************************************************************** */
+/*! *********************************************************************************
+ * \brief Initialises the list descriptor.
+ *
+ * \param[in] list - LIST_ handle to init.
+ * max - Maximum number of elements in list. 0 for unlimited.
+ *
+ * \return void.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+void LIST_Init(list_handle_t list, uint32_t max)
+{
+ list->head = NULL;
+ list->tail = NULL;
+ list->max = (uint16_t)max;
+ list->size = 0;
+}
+
+/*! *********************************************************************************
+ * \brief Gets the list that contains the given element.
+ *
+ * \param[in] element - Handle of the element.
+ *
+ * \return NULL if element is orphan.
+ * Handle of the list the element is inserted into.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+list_handle_t LIST_GetList(list_element_handle_t element)
+{
+ return element->list;
+}
+
+/*! *********************************************************************************
+ * \brief Links element to the tail of the list.
+ *
+ * \param[in] list - ID of list to insert into.
+ * element - element to add
+ *
+ * \return kLIST_Full if list is full.
+ * kLIST_Ok if insertion was successful.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+list_status_t LIST_AddTail(list_handle_t list, list_element_handle_t element)
+{
+ uint32_t regPrimask = DisableGlobalIRQ();
+ list_status_t listStatus = kLIST_Ok;
+
+ listStatus = LIST_Error_Check(list, element);
+ if (listStatus == kLIST_Ok) /* Avoiding list status error */
+ {
+ if (list->size == 0U)
+ {
+ list->head = element;
+ }
+ else
+ {
+ list->tail->next = element;
+ }
+#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
+#else
+ element->prev = list->tail;
+#endif
+ element->list = list;
+ element->next = NULL;
+ list->tail = element;
+ list->size++;
+ }
+
+ EnableGlobalIRQ(regPrimask);
+ return listStatus;
+}
+
+/*! *********************************************************************************
+ * \brief Links element to the head of the list.
+ *
+ * \param[in] list - ID of list to insert into.
+ * element - element to add
+ *
+ * \return kLIST_Full if list is full.
+ * kLIST_Ok if insertion was successful.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+list_status_t LIST_AddHead(list_handle_t list, list_element_handle_t element)
+{
+ uint32_t regPrimask = DisableGlobalIRQ();
+ list_status_t listStatus = kLIST_Ok;
+
+ listStatus = LIST_Error_Check(list, element);
+ if (listStatus == kLIST_Ok) /* Avoiding list status error */
+ {
+ /* Links element to the head of the list */
+ if (list->size == 0U)
+ {
+ list->tail = element;
+ }
+#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
+#else
+ else
+ {
+ list->head->prev = element;
+ }
+ element->prev = NULL;
+#endif
+ element->list = list;
+ element->next = list->head;
+ list->head = element;
+ list->size++;
+ }
+
+ EnableGlobalIRQ(regPrimask);
+ return listStatus;
+}
+
+/*! *********************************************************************************
+ * \brief Unlinks element from the head of the list.
+ *
+ * \param[in] list - ID of list to remove from.
+ *
+ * \return NULL if list is empty.
+ * ID of removed element(pointer) if removal was successful.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+list_element_handle_t LIST_RemoveHead(list_handle_t list)
+{
+ list_element_handle_t element;
+
+ uint32_t regPrimask = DisableGlobalIRQ();
+
+ if ((NULL == list) || (list->size == 0U))
+ {
+ element = NULL; /*LIST_ is empty*/
+ }
+ else
+ {
+ element = list->head;
+ list->size--;
+ if (list->size == 0U)
+ {
+ list->tail = NULL;
+ }
+#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
+#else
+ else
+ {
+ element->next->prev = NULL;
+ }
+#endif
+ element->list = NULL;
+ list->head = element->next; /*Is NULL if element is head*/
+ }
+
+ EnableGlobalIRQ(regPrimask);
+ return element;
+}
+
+/*! *********************************************************************************
+ * \brief Gets head element ID.
+ *
+ * \param[in] list - ID of list.
+ *
+ * \return NULL if list is empty.
+ * ID of head element if list is not empty.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+list_element_handle_t LIST_GetHead(list_handle_t list)
+{
+ return list->head;
+}
+
+/*! *********************************************************************************
+ * \brief Gets next element ID.
+ *
+ * \param[in] element - ID of the element.
+ *
+ * \return NULL if element is tail.
+ * ID of next element if exists.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+list_element_handle_t LIST_GetNext(list_element_handle_t element)
+{
+ return element->next;
+}
+
+/*! *********************************************************************************
+ * \brief Gets previous element ID.
+ *
+ * \param[in] element - ID of the element.
+ *
+ * \return NULL if element is head.
+ * ID of previous element if exists.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+list_element_handle_t LIST_GetPrev(list_element_handle_t element)
+{
+#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
+ return NULL;
+#else
+ return element->prev;
+#endif
+}
+
+/*! *********************************************************************************
+ * \brief Unlinks an element from its list.
+ *
+ * \param[in] element - ID of the element to remove.
+ *
+ * \return kLIST_OrphanElement if element is not part of any list.
+ * kLIST_Ok if removal was successful.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+list_status_t LIST_RemoveElement(list_element_handle_t element)
+{
+ list_status_t listStatus = kLIST_Ok;
+ uint32_t regPrimask = DisableGlobalIRQ();
+
+ if (element->list == NULL)
+ {
+ listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/
+ }
+ else
+ {
+#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
+ list_element_handle_t element_list = element->list->head;
+ while (element_list)
+ {
+ if (element->list->head == element)
+ {
+ element->list->head = element_list->next;
+ break;
+ }
+ if (element_list->next == element)
+ {
+ element_list->next = element->next;
+ break;
+ }
+ element_list = element_list->next;
+ }
+#else
+ if (element->prev == NULL) /*Element is head or solo*/
+ {
+ element->list->head = element->next; /*is null if solo*/
+ }
+ if (element->next == NULL) /*Element is tail or solo*/
+ {
+ element->list->tail = element->prev; /*is null if solo*/
+ }
+ if (element->prev != NULL) /*Element is not head*/
+ {
+ element->prev->next = element->next;
+ }
+ if (element->next != NULL) /*Element is not tail*/
+ {
+ element->next->prev = element->prev;
+ }
+#endif
+ element->list->size--;
+ element->list = NULL;
+ }
+
+ EnableGlobalIRQ(regPrimask);
+ return listStatus;
+}
+
+/*! *********************************************************************************
+ * \brief Links an element in the previous position relative to a given member
+ * of a list.
+ *
+ * \param[in] element - ID of a member of a list.
+ * newElement - new element to insert before the given member.
+ *
+ * \return kLIST_OrphanElement if element is not part of any list.
+ * kLIST_Full if list is full.
+ * kLIST_Ok if insertion was successful.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+list_status_t LIST_AddPrevElement(list_element_handle_t element, list_element_handle_t newElement)
+{
+ list_status_t listStatus = kLIST_Ok;
+ uint32_t regPrimask = DisableGlobalIRQ();
+
+ if (element->list == NULL)
+ {
+ listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/
+ }
+ else
+ {
+ listStatus = LIST_Error_Check(element->list, newElement);
+ if (listStatus == kLIST_Ok)
+ {
+#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
+ list_element_handle_t element_list = element->list->head;
+ while (element_list)
+ {
+ if ((element_list->next == element) || (element_list == element))
+ {
+ if (element_list == element)
+ {
+ element->list->head = newElement;
+ }
+ else
+ {
+ element_list->next = newElement;
+ }
+ newElement->list = element->list;
+ newElement->next = element;
+ element->list->size++;
+ break;
+ }
+ element_list = element_list->next;
+ }
+
+#else
+ if (element->prev == NULL) /*Element is list head*/
+ {
+ element->list->head = newElement;
+ }
+ else
+ {
+ element->prev->next = newElement;
+ }
+ newElement->list = element->list;
+ element->list->size++;
+ newElement->next = element;
+ newElement->prev = element->prev;
+ element->prev = newElement;
+#endif
+ }
+ }
+
+ EnableGlobalIRQ(regPrimask);
+ return listStatus;
+}
+
+/*! *********************************************************************************
+ * \brief Gets the current size of a list.
+ *
+ * \param[in] list - ID of the list.
+ *
+ * \return Current size of the list.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+uint32_t LIST_GetSize(list_handle_t list)
+{
+ return list->size;
+}
+
+/*! *********************************************************************************
+ * \brief Gets the number of free places in the list.
+ *
+ * \param[in] list - ID of the list.
+ *
+ * \return Available size of the list.
+ *
+ * \pre
+ *
+ * \post
+ *
+ * \remarks
+ *
+ ********************************************************************************** */
+uint32_t LIST_GetAvailableSize(list_handle_t list)
+{
+ return ((uint32_t)list->max - (uint32_t)list->size); /*Gets the number of free places in the list*/
+}
diff --git a/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/generic_list.h b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/generic_list.h
new file mode 100644
index 0000000000..def00efe8e
--- /dev/null
+++ b/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/generic_list.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2018-2020 NXP
+ * All rights reserved.
+ *
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _GENERIC_LIST_H_
+#define _GENERIC_LIST_H_
+
+#include "fsl_common.h"
+/*!
+ * @addtogroup GenericList
+ * @{
+ */
+
+/*!*********************************************************************************
+*************************************************************************************
+* Include
+*************************************************************************************
+********************************************************************************** */
+
+/*! *********************************************************************************
+*************************************************************************************
+* Public macro definitions
+*************************************************************************************
+********************************************************************************** */
+#ifndef GENERIC_LIST_LIGHT
+#define GENERIC_LIST_LIGHT (0)
+#endif
+/*! *********************************************************************************
+*************************************************************************************
+* Public type definitions
+*************************************************************************************
+********************************************************************************** */
+/*! @brief The list status */
+typedef enum _list_status
+{
+ kLIST_Ok = kStatus_Success, /*!< Success */
+ kLIST_DuplicateError = MAKE_STATUS(kStatusGroup_LIST, 1), /*!< Duplicate Error */
+ kLIST_Full = MAKE_STATUS(kStatusGroup_LIST, 2), /*!< FULL */
+ kLIST_Empty = MAKE_STATUS(kStatusGroup_LIST, 3), /*!< Empty */
+ kLIST_OrphanElement = MAKE_STATUS(kStatusGroup_LIST, 4), /*!< Orphan Element */
+ kLIST_NotSupport = MAKE_STATUS(kStatusGroup_LIST, 5), /*!< Not Support */
+} list_status_t;
+
+/*! @brief The list structure*/
+typedef struct list_label
+{
+ struct list_element_tag *head; /*!< list head */
+ struct list_element_tag *tail; /*!< list tail */
+ uint16_t size; /*!< list size */
+ uint16_t max; /*!< list max number of elements */
+} list_label_t, *list_handle_t;
+#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
+/*! @brief The list element*/
+typedef struct list_element_tag
+{
+ struct list_element_tag *next; /*!< next list element */
+ struct list_label *list; /*!< pointer to the list */
+} list_element_t, *list_element_handle_t;
+#else
+/*! @brief The list element*/
+typedef struct list_element_tag
+{
+ struct list_element_tag *next; /*!< next list element */
+ struct list_element_tag *prev; /*!< previous list element */
+ struct list_label *list; /*!< pointer to the list */
+} list_element_t, *list_element_handle_t;
+#endif
+/*! *********************************************************************************
+*************************************************************************************
+* Public prototypes
+*************************************************************************************
+********************************************************************************** */
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* _cplusplus */
+/*!
+ * @brief Initialize the list.
+ *
+ * This function initialize the list.
+ *
+ * @param list - List handle to initialize.
+ * @param max - Maximum number of elements in list. 0 for unlimited.
+ */
+void LIST_Init(list_handle_t list, uint32_t max);
+
+/*!
+ * @brief Gets the list that contains the given element.
+ *
+ *
+ * @param element - Handle of the element.
+ * @retval NULL if element is orphan, Handle of the list the element is inserted into.
+ */
+list_handle_t LIST_GetList(list_element_handle_t element);
+
+/*!
+ * @brief Links element to the head of the list.
+ *
+ * @param list - Handle of the list.
+ * @param element - Handle of the element.
+ * @retval kLIST_Full if list is full, kLIST_Ok if insertion was successful.
+ */
+list_status_t LIST_AddHead(list_handle_t list, list_element_handle_t element);
+
+/*!
+ * @brief Links element to the tail of the list.
+ *
+ * @param list - Handle of the list.
+ * @param element - Handle of the element.
+ * @retval kLIST_Full if list is full, kLIST_Ok if insertion was successful.
+ */
+list_status_t LIST_AddTail(list_handle_t list, list_element_handle_t element);
+
+/*!
+ * @brief Unlinks element from the head of the list.
+ *
+ * @param list - Handle of the list.
+ *
+ * @retval NULL if list is empty, handle of removed element(pointer) if removal was successful.
+ */
+list_element_handle_t LIST_RemoveHead(list_handle_t list);
+
+/*!
+ * @brief Gets head element handle.
+ *
+ * @param list - Handle of the list.
+ *
+ * @retval NULL if list is empty, handle of removed element(pointer) if removal was successful.
+ */
+list_element_handle_t LIST_GetHead(list_handle_t list);
+
+/*!
+ * @brief Gets next element handle for given element handle.
+ *
+ * @param element - Handle of the element.
+ *
+ * @retval NULL if list is empty, handle of removed element(pointer) if removal was successful.
+ */
+list_element_handle_t LIST_GetNext(list_element_handle_t element);
+
+/*!
+ * @brief Gets previous element handle for given element handle.
+ *
+ * @param element - Handle of the element.
+ *
+ * @retval NULL if list is empty, handle of removed element(pointer) if removal was successful.
+ */
+list_element_handle_t LIST_GetPrev(list_element_handle_t element);
+
+/*!
+ * @brief Unlinks an element from its list.
+ *
+ * @param element - Handle of the element.
+ *
+ * @retval kLIST_OrphanElement if element is not part of any list.
+ * @retval kLIST_Ok if removal was successful.
+ */
+list_status_t LIST_RemoveElement(list_element_handle_t element);
+
+/*!
+ * @brief Links an element in the previous position relative to a given member of a list.
+ *
+ * @param list - Handle of the list.
+ * @param element - Handle of the element.
+ * @param newElement - New element to insert before the given member.
+ *
+ * @retval kLIST_OrphanElement if element is not part of any list.
+ * @retval kLIST_Ok if removal was successful.
+ */
+list_status_t LIST_AddPrevElement(list_element_handle_t element, list_element_handle_t newElement);
+
+/*!
+ * @brief Gets the current size of a list.
+ *
+ * @param list - Handle of the list.
+ *
+ * @retval Current size of the list.
+ */
+uint32_t LIST_GetSize(list_handle_t list);
+
+/*!
+ * @brief Gets the number of free places in the list.
+ *
+ * @param list - Handle of the list.
+ *
+ * @retval Available size of the list.
+ */
+uint32_t LIST_GetAvailableSize(list_handle_t list);
+
+/* @} */
+
+#if defined(__cplusplus)
+}
+#endif
+/*! @}*/
+#endif /*_GENERIC_LIST_H_*/
diff --git a/bsp/imxrt/libraries/MIMXRT1170/SConscript b/bsp/imxrt/libraries/MIMXRT1170/SConscript
index 967053fce5..dabc973a4e 100644
--- a/bsp/imxrt/libraries/MIMXRT1170/SConscript
+++ b/bsp/imxrt/libraries/MIMXRT1170/SConscript
@@ -51,6 +51,10 @@ if GetDepend(['RT_USING_CAN']):
if GetDepend(['BSP_USING_FLEXSPI']):
src += ['MIMXRT1176/drivers/fsl_flexspi.c']
+
+#fsl os abstract files
+src += ['MIMXRT1176/drivers/fsl_os_abstraction_rtthread.c']
+src += ['MIMXRT1176/drivers/generic_list.c']
if rtconfig.PLATFORM in ['gcc']:
group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, ASFLAGS = '$ASFLAGS -D __STARTUP_CLEAR_BSS')
diff --git a/bsp/imxrt/libraries/drivers/drv_usbh.c b/bsp/imxrt/libraries/drivers/drv_usbh.c
index 69f076c18f..73e16ae9ae 100644
--- a/bsp/imxrt/libraries/drivers/drv_usbh.c
+++ b/bsp/imxrt/libraries/drivers/drv_usbh.c
@@ -24,8 +24,12 @@
/* USB PHY configuration */
#ifndef BOARD_USB_PHY_D_CAL
+#ifdef SOC_IMXRT1170_SERIES
+#define BOARD_USB_PHY_D_CAL (0x07U)
+#else
#define BOARD_USB_PHY_D_CAL (0x0CU)
#endif
+#endif
#ifndef BOARD_USB_PHY_TXCAL45DP
#define BOARD_USB_PHY_TXCAL45DP (0x06U)
#endif
@@ -33,7 +37,12 @@
#define BOARD_USB_PHY_TXCAL45DM (0x06U)
#endif
-#define USB_HOST_INTERRUPT_PRIORITY 3
+#define USB_HOST_INTERRUPT_PRIORITY 6
+
+/* Allocate the memory for the heap. */
+#if defined(configAPPLICATION_ALLOCATED_HEAP) && (configAPPLICATION_ALLOCATED_HEAP)
+USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t ucHeap[configTOTAL_HEAP_SIZE];
+#endif
enum
{
@@ -91,20 +100,22 @@ static void _imxrt_usb_host_send_callback(void *param, usb_host_transfer_t *tran
*/
static void USB_HostClockInit(usb_controller_index_t controller_id)
{
+ uint32_t usbClockFreq;
usb_phy_config_struct_t phyConfig = {
BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
};
- uint32_t notUsed = 0;
+
+ usbClockFreq = 24000000;
if (controller_id == kUSB_ControllerEhci0)
{
- CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
- CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
+ CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, usbClockFreq);
+ CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, usbClockFreq);
}
else
{
- CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
- CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
+ CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, usbClockFreq);
+ CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, usbClockFreq);
}
USB_EhciPhyInit(controller_id, 24000000U, &phyConfig);
@@ -151,7 +162,7 @@ static uint8_t _ehci0_pipe_idx;
static int _ehci0_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
{
- int timeout = timeouts;
+// int timeout = timeouts;
if (!imxrt_usb_host_obj[USBH0_INDEX].connect_status)
{
diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host.h b/bsp/imxrt/libraries/drivers/usb/host/usb_host.h
index 6d9167ceac..8f83396ad1 100644
--- a/bsp/imxrt/libraries/drivers/usb/host/usb_host.h
+++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host.h
@@ -105,8 +105,13 @@ typedef struct _usb_host_process_descriptor_param
uint8_t descriptorIndex; /*!< The descriptor index is used to select a specific descriptor (only for configuration
and string descriptors) when several descriptors of the same type are implemented in a
device */
+#ifdef SOC_IMXRT1170_SERIES
+ uint16_t languageId; /*!< It specifies the language ID for string descriptors or is reset to zero for other
+ descriptors */
+#else
uint8_t languageId; /*!< It specifies the language ID for string descriptors or is reset to zero for other
descriptors */
+#endif
uint8_t *descriptorBuffer; /*!< Buffer pointer */
uint16_t descriptorLength; /*!< Buffer data length */
} usb_host_process_descriptor_param_t;
diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.c b/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.c
index 2bbc89233a..2798434f6e 100644
--- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.c
+++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.c
@@ -182,7 +182,1333 @@ static const usb_host_enum_process_entry_t s_EnumEntries[] = {
/*******************************************************************************
* Code
******************************************************************************/
+#ifdef SOC_IMXRT1170_SERIES
+static void USB_HostEnumerationTransferCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ /* 0 - retry current transfer, 1 - transfer success process,
+ * 2 - retry whole process, 3 - fail process
+ */
+ uint8_t nextStep = 0U;
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)param;
+ usb_status_t failReason = kStatus_USB_Success;
+ uint32_t dataLength;
+
+ dataLength = transfer->transferSofar;
+ (void)USB_HostFreeTransfer(deviceInstance->hostHandle, transfer); /* free transfer */
+
+ if (status == kStatus_USB_Success)
+ {
+ nextStep = 1U;
+ }
+ else if (status == kStatus_USB_TransferStall)
+ {
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+ (void)usb_echo("no response from device\r\n");
+#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */
+ if (deviceInstance->stallRetries > 0U) /* retry same transfer when stall */
+ {
+ nextStep = 0U;
+ deviceInstance->stallRetries--;
+ }
+ else
+ {
+ failReason = kStatus_USB_TransferFailed;
+ nextStep = 2U;
+ }
+ }
+ else if (status == kStatus_USB_TransferCancel)
+ {
+ failReason = kStatus_USB_TransferCancel;
+ nextStep = 3U;
+ }
+ else
+ {
+ failReason = kStatus_USB_TransferFailed;
+ nextStep = 2U;
+ }
+
+ if (nextStep == 1U)
+ {
+ deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+ if (s_EnumEntries[deviceInstance->state - 1U].process == NULL)
+ {
+ deviceInstance->state = (uint8_t)s_EnumEntries[deviceInstance->state - 1U].successState; /* next state */
+ }
+ else
+ {
+ status = s_EnumEntries[deviceInstance->state - 1U].process(
+ deviceInstance, dataLength); /* process the previous state result */
+ if (status == kStatus_USB_Success) /* process success */
+ {
+ deviceInstance->state = (uint8_t)s_EnumEntries[deviceInstance->state - 1U].successState;
+ }
+ else if (status == kStatus_USB_Retry) /* need retry */
+ {
+ deviceInstance->state = (uint8_t)s_EnumEntries[deviceInstance->state - 1U].retryState;
+ }
+ else if (status == kStatus_USB_NotSupported) /* device don't suport by the application */
+ {
+ return; /* unrecoverable fail */
+ }
+ else /* process error, next retry */
+ {
+ /* kStatus_USB_Error or kStatus_USB_AllocFail */
+ failReason = status;
+ nextStep = 2U;
+ }
+ }
+ }
+
+ if (nextStep == 2U)
+ {
+ if (deviceInstance->enumRetries > 0U) /* next whole retry */
+ {
+ deviceInstance->enumRetries--;
+ deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+ deviceInstance->configurationValue = 0U;
+ deviceInstance->state = (uint8_t)kStatus_DEV_GetDes8;
+ }
+ else
+ {
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+ usb_echo("Device No Response\r\n");
+#endif
+ nextStep = 3U;
+ }
+ }
+
+ /* process the state */
+ if (nextStep != 3U)
+ {
+ if (USB_HostProcessState(deviceInstance) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("enumation setup error\r\n");
+#endif
+ failReason = kStatus_USB_Error;
+ nextStep = 3U;
+ }
+ }
+
+ if (nextStep == 3U)
+ {
+ (void)USB_HostNotifyDevice(deviceInstance->hostHandle, deviceInstance, (uint32_t)kUSB_HostEventEnumerationFail,
+ (uint32_t)failReason);
+ }
+}
+
+static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInstance)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_process_descriptor_param_t getDescriptorParam;
+ usb_host_transfer_t *transfer;
+ usb_host_device_enumeration_status_t state;
+
+ /* malloc transfer */
+ state = (usb_host_device_enumeration_status_t)deviceInstance->state;
+ if (state != kStatus_DEV_EnumDone)
+ {
+ if (USB_HostMallocTransfer(deviceInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ transfer->callbackFn = USB_HostEnumerationTransferCallback;
+ transfer->callbackParam = deviceInstance;
+
+ /* reset transfer fields */
+ transfer->setupPacket->bmRequestType = 0x00U;
+ transfer->setupPacket->wIndex = 0U;
+ transfer->setupPacket->wLength = 0U;
+ transfer->setupPacket->wValue = 0U;
+ }
+
+ switch (state)
+ {
+ case kStatus_DEV_GetDes8:
+ case kStatus_DEV_GetDes: /* get descriptor state */
+ getDescriptorParam.descriptorLength = (uint16_t)sizeof(usb_descriptor_device_t);
+ if (deviceInstance->state == (uint8_t)kStatus_DEV_GetDes8)
+ {
+ getDescriptorParam.descriptorLength = 8U;
+ }
+ getDescriptorParam.descriptorBuffer = (uint8_t *)deviceInstance->deviceDescriptor;
+ getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE;
+ getDescriptorParam.descriptorIndex = 0U;
+ getDescriptorParam.languageId = 0U;
+
+ transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+ status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+ break;
+ case kStatus_DEV_SetAddress: /* set address state */
+ transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_ADDRESS;
+ status = USB_HostStandardSetAddress(deviceInstance, transfer, &deviceInstance->allocatedAddress);
+ break;
+
+ case kStatus_DEV_GetCfg9: /* get 9 bytes configuration state */
+ getDescriptorParam.descriptorBuffer = deviceInstance->enumBuffer;
+ getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE;
+ getDescriptorParam.descriptorIndex = deviceInstance->configurationValue;
+ getDescriptorParam.descriptorLength = 9;
+ getDescriptorParam.languageId = 0;
+
+ transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+ status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+ break;
+
+ case kStatus_DEV_GetCfg: /* get configuration state */
+ getDescriptorParam.descriptorBuffer = deviceInstance->configurationDesc;
+ getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE;
+ getDescriptorParam.descriptorIndex = deviceInstance->configurationValue;
+ getDescriptorParam.descriptorLength = deviceInstance->configurationLen;
+ getDescriptorParam.languageId = 0;
+
+ transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+ status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+ break;
+
+ case kStatus_DEV_SetCfg: /* set configuration state */
+ transfer->setupPacket->wValue =
+ USB_SHORT_TO_LITTLE_ENDIAN(deviceInstance->configuration.configurationDesc->bConfigurationValue);
+ transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_CONFIGURATION;
+ status = USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0);
+ break;
+
+ case kStatus_DEV_EnumDone: /* enumeration done state */
+ /* notify device enumeration done */
+ status = USB_HostNotifyDevice(deviceInstance->hostHandle, deviceInstance,
+ (uint32_t)kUSB_HostEventEnumerationDone, (uint32_t)kStatus_USB_Success);
+ if (status == kStatus_USB_Success)
+ {
+ deviceInstance->state = (uint8_t)kStatus_DEV_AppUsed;
+ }
+ break;
+
+ default:
+ /*no action*/
+ break;
+ }
+
+ return status;
+}
+
+static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceInstance, uint32_t dataLength)
+{
+ usb_host_pipe_t *pipe = (usb_host_pipe_t *)deviceInstance->controlPipe;
+ usb_status_t status = kStatus_USB_Success;
+ usb_descriptor_configuration_t *configureDesc;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+ void *temp;
+ usb_host_device_enumeration_status_t state;
+#if (defined(USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+#if (defined(USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ usb_host_hub_instance_t *hubInstance4Device = NULL;
+#endif
+#endif
+
+ state = (usb_host_device_enumeration_status_t)deviceInstance->state;
+ switch (state)
+ {
+ case kStatus_DEV_GetDes8: /* process get 8 bytes descriptor result */
+ if (dataLength != 8u)
+ {
+ return kStatus_USB_Error;
+ }
+ pipe->maxPacketSize = deviceInstance->deviceDescriptor->bMaxPacketSize0;
+ /* the callbackFn is initialized in USB_HostGetControllerInterface */
+ (void)hostInstance->controllerTable->controllerIoctl(
+ hostInstance->controllerHandle, kUSB_HostUpdateControlPacketSize, deviceInstance->controlPipe);
+ break;
+
+ case kStatus_DEV_SetAddress: /* process set address result */
+ deviceInstance->setAddress = deviceInstance->allocatedAddress;
+ /* the callbackFn is initialized in USB_HostGetControllerInterface */
+ (void)hostInstance->controllerTable->controllerIoctl(
+ hostInstance->controllerHandle, kUSB_HostUpdateControlEndpointAddress, deviceInstance->controlPipe);
+ break;
+
+ case kStatus_DEV_GetDes: /* process get full device descriptor result */
+ if (dataLength != sizeof(usb_descriptor_device_t))
+ {
+ return kStatus_USB_Error;
+ }
+ break;
+
+ case kStatus_DEV_GetCfg9: /* process get 9 bytes configuration result */
+ if (dataLength != 9u)
+ {
+ return kStatus_USB_Error;
+ }
+ temp = (void *)&deviceInstance->enumBuffer[0];
+ configureDesc = (usb_descriptor_configuration_t *)temp;
+
+ deviceInstance->configurationLen = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(configureDesc->wTotalLength);
+ if (deviceInstance->configurationDesc != NULL)
+ {
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+ SDK_Free(deviceInstance->configurationDesc);
+#else
+ OSA_MemoryFree(deviceInstance->configurationDesc);
+#endif
+ deviceInstance->configurationDesc = NULL;
+ }
+
+ /* the only configuration descriptor is at least 9 bytes length */
+ if (deviceInstance->configurationLen < 9U)
+ {
+ return kStatus_USB_Error;
+ }
+ /* fix misra 4.14 */
+ if (deviceInstance->configurationLen > USB_HOST_CONFIG_MAX_CONFIGURATION_DESCRIPTOR_LENGTH)
+ {
+ return kStatus_USB_Error;
+ }
+ /* for KHCI, the start address and the length should be 4 byte align */
+ if ((deviceInstance->configurationLen & 0x03U) != 0U)
+ {
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+ deviceInstance->configurationDesc =
+ (uint8_t *)SDK_Malloc((deviceInstance->configurationLen & 0xFFFCu) + 4, USB_CACHE_LINESIZE);
+#else
+ deviceInstance->configurationDesc =
+ (uint8_t *)OSA_MemoryAllocate((((uint32_t)deviceInstance->configurationLen) & 0xFFFCU) + 4UL);
+#endif
+ }
+ else
+ {
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+ deviceInstance->configurationDesc =
+ (uint8_t *)SDK_Malloc(deviceInstance->configurationLen, USB_CACHE_LINESIZE);
+#else
+ deviceInstance->configurationDesc = (uint8_t *)OSA_MemoryAllocate(deviceInstance->configurationLen);
+#endif
+ }
+ if (deviceInstance->configurationDesc == NULL)
+ {
+ return kStatus_USB_AllocFail;
+ }
+ break;
+
+ case kStatus_DEV_GetCfg: /* process get configuration result */
+ if (dataLength != deviceInstance->configurationLen)
+ {
+#if (defined(USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+ usb_echo("Host can only provide a maximum of 500mA current\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+
+#if (defined(USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+#if (defined(USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ hubInstance4Device = USB_HostHubGetHubDeviceHandle(hostInstance, deviceInstance->hubNumber);
+ if ((!(((usb_descriptor_configuration_t *)deviceInstance->configurationDesc)->bmAttributes &
+ USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_MASK)) &&
+ (((usb_descriptor_configuration_t *)deviceInstance->configurationDesc)->bMaxPower > 50) &&
+ (hubInstance4Device != NULL) &&
+ (!(((usb_descriptor_configuration_t *)((usb_host_device_instance_t *)hubInstance4Device->deviceHandle)
+ ->configurationDesc)
+ ->bmAttributes &
+ USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_SELF_POWERED_MASK)))
+ {
+ usb_echo("The device power exceeded\r\n");
+ return kStatus_USB_Error;
+ }
+#endif
+#endif
+ temp = (void *)deviceInstance->configurationDesc;
+ if (((usb_descriptor_configuration_t *)temp)->bMaxPower > USB_HOST_CONFIG_MAX_POWER)
+ {
+ return kStatus_USB_Error;
+ }
+ deviceInstance->configurationValue++;
+ if (USB_HostParseDeviceConfigurationDescriptor(deviceInstance) !=
+ kStatus_USB_Success) /* parse configuration descriptor */
+ {
+ return kStatus_USB_Error;
+ }
+
+ status = USB_HostNotifyDevice(deviceInstance->hostHandle, deviceInstance, (uint32_t)kUSB_HostEventAttach,
+ (uint32_t)kStatus_USB_Success);
+
+ if (status != kStatus_USB_Success)
+ {
+ /* next configuration */
+ if (deviceInstance->configurationValue < deviceInstance->deviceDescriptor->bNumConfigurations)
+ {
+ return kStatus_USB_Retry;
+ }
+ else
+ {
+ /* notify application device is not supported */
+ (void)USB_HostNotifyDevice(deviceInstance->hostHandle, deviceInstance,
+ (uint32_t)kUSB_HostEventNotSupported, (uint32_t)kStatus_USB_Success);
+ return kStatus_USB_NotSupported;
+ }
+ }
+ break;
+
+ case kStatus_DEV_SetCfg:
+ /* NULL */
+ break;
+
+ default:
+ /*no action*/
+ break;
+ }
+
+ return status;
+}
+
+static usb_status_t USB_HostNotifyDevice(usb_host_handle hostHandle,
+ usb_host_device_instance_t *deviceInstance,
+ uint32_t eventCode,
+ uint32_t eventParameter)
+{
+ usb_host_instance_t *hostInstance;
+ usb_status_t status1 = kStatus_USB_Error;
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ usb_status_t status2 = kStatus_USB_Error;
+ uint8_t haveHub;
+ uint8_t haveNoHub;
+ uint8_t interfaceIndex;
+#endif /* USB_HOST_CONFIG_HUB */
+
+ eventCode = (((uint32_t)eventParameter << 16U) | (uint32_t)eventCode);
+ hostInstance = (usb_host_instance_t *)hostHandle;
+ if (deviceInstance == NULL)
+ {
+ (void)hostInstance->deviceCallback(NULL, NULL, eventCode);
+ return kStatus_USB_InvalidHandle;
+ }
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ haveHub = 0U;
+ haveNoHub = 0U;
+ for (interfaceIndex = 0U; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+ {
+ if (((usb_descriptor_interface_t *)deviceInstance->configuration.interfaceList[interfaceIndex].interfaceDesc)
+ ->bInterfaceClass == USB_HOST_HUB_CLASS_CODE)
+ {
+ haveHub = 1U;
+ }
+ else
+ {
+ haveNoHub = 1U;
+ }
+ }
+
+ if ((hostInstance->deviceCallback != NULL) &&
+ ((haveNoHub == 1U) || (deviceInstance->configuration.interfaceCount == 0U)))
+ {
+ /* call host callback function, function is initialized in USB_HostInit */
+ status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration, eventCode);
+ }
+ if (0U != haveHub)
+ {
+ status2 = USB_HostHubDeviceEvent(hostInstance, deviceInstance, &deviceInstance->configuration,
+ eventCode); /* notify hub event */
+ }
+
+ if ((status1 == kStatus_USB_Success) || (status2 == kStatus_USB_Success)) /* the device is supported */
+ {
+ return kStatus_USB_Success;
+ }
+ else if (eventCode == (uint32_t)kUSB_HostEventAttach) /* attach event */
+ {
+ status1 = kStatus_USB_NotSupported;
+ }
+ else
+ {
+ status1 = kStatus_USB_Error;
+ }
+#else
+ if (hostInstance->deviceCallback != NULL)
+ {
+ /* call host callback function, function is initialized in USB_HostInit */
+ status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration, eventCode);
+ }
+#endif
+ return status1;
+}
+
+static uint8_t USB_HostAllocateDeviceAddress(usb_host_instance_t *hostInstance)
+{
+ uint8_t address = 0U;
+ uint8_t addressIndex;
+ uint8_t addressBitIndex;
+ for (addressIndex = 0U; addressIndex < 8U; ++addressIndex) /* find the idle address position byte */
+ {
+ if (hostInstance->addressBitMap[addressIndex] != 0xFFU)
+ {
+ break;
+ }
+ }
+ if (addressIndex < 8U)
+ {
+ for (addressBitIndex = 0U; addressBitIndex < 8U; ++addressBitIndex) /* find the idle address position bit */
+ {
+ if (0U == (hostInstance->addressBitMap[addressIndex] & (0x01U << addressBitIndex)))
+ {
+ hostInstance->addressBitMap[addressIndex] |= (0x01U << addressBitIndex); /* set the allocated bit */
+ address = addressIndex * 8U + addressBitIndex + 1U; /* the address minimum is 1 */
+ break;
+ }
+ }
+ }
+ return address;
+}
+
+static void USB_HostReleaseDeviceAddress(usb_host_instance_t *hostInstance, uint8_t address)
+{
+ (void)USB_HostLock();
+ hostInstance->addressBitMap[((uint32_t)address - 1U) >> 3U] &=
+ (~(0x01U << (((uint32_t)address - 1U) & 0x07U))); /* reset the allocated bit */
+ (void)USB_HostUnlock();
+}
+
+static usb_status_t USB_HostRemoveDeviceInstance(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ usb_host_device_instance_t *currentInstance;
+ usb_host_device_instance_t *prevInstance;
+ if ((hostHandle == NULL) || (deviceHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* search and remove device instance */
+ prevInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+ if (prevInstance == deviceHandle)
+ {
+ hostInstance->deviceList = prevInstance->next;
+ return kStatus_USB_Success;
+ }
+ else
+ {
+ currentInstance = prevInstance->next;
+ }
+
+ while (currentInstance != NULL)
+ {
+ if (currentInstance == deviceHandle)
+ {
+ prevInstance->next = currentInstance->next;
+ return kStatus_USB_Success;
+ }
+ prevInstance = currentInstance;
+ currentInstance = currentInstance->next;
+ }
+
+ return kStatus_USB_Success;
+}
+
+static void USB_HostReleaseDeviceResource(usb_host_instance_t *hostInstance, usb_host_device_instance_t *deviceInstance)
+{
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ uint8_t level = 0;
+#endif
+
+#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+ if (deviceInstance == hostInstance->suspendedDevice)
+ {
+ hostInstance->suspendedDevice = NULL;
+ }
+#endif
+ /* release device's address */
+ if (deviceInstance->setAddress != 0U)
+ {
+ USB_HostReleaseDeviceAddress(hostInstance, deviceInstance->setAddress);
+ }
+ else
+ {
+ if (deviceInstance->allocatedAddress != 0U)
+ {
+ USB_HostReleaseDeviceAddress(hostInstance, deviceInstance->allocatedAddress);
+ }
+ }
+
+ /* close control pipe */
+ if (deviceInstance->controlPipe != NULL)
+ {
+ (void)USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL);
+ if (USB_HostClosePipe(hostInstance, deviceInstance->controlPipe) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ deviceInstance->controlPipe = NULL;
+ }
+
+ /* free configuration buffer */
+ if (deviceInstance->configurationDesc != NULL)
+ {
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+ SDK_Free(deviceInstance->configurationDesc);
+#else
+ OSA_MemoryFree(deviceInstance->configurationDesc);
+#endif
+ }
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ level = deviceInstance->level;
+#endif
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+ SDK_Free(deviceInstance->deviceDescriptor);
+#else
+ OSA_MemoryFree(deviceInstance->deviceDescriptor);
+#endif
+ /* free device instance buffer */
+ OSA_MemoryFree(deviceInstance);
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ /* enable controller attach if root hub */
+ if (level == 1U)
+ {
+ (void)USB_HostControlBus(hostInstance, (uint8_t)kUSB_HostBusEnableAttach);
+ }
+#else
+ /* enable controller attach */
+ USB_HostControlBus(hostInstance, (uint8_t)kUSB_HostBusEnableAttach);
+#endif
+}
+
+static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle deviceHandle)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ uint32_t endPos;
+ usb_descriptor_union_t *unionDes;
+ usb_host_interface_t *interfaceParse = NULL;
+ usb_host_ep_t *epParse;
+ uint8_t *buffer;
+ void *temp;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ temp = (void *)&deviceInstance->configuration;
+ buffer = (uint8_t *)temp;
+ /* clear the previous parse result, note: end_pos means buffer index here*/
+ for (endPos = 0U; endPos < sizeof(usb_host_configuration_t); endPos++)
+ {
+ buffer[endPos] = 0U;
+ }
+ for (endPos = 0U; endPos < USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE; ++endPos)
+ {
+ deviceInstance->interfaceStatus[endPos] = 0U;
+ }
+
+ /* parse configuration descriptor */
+ temp = (void *)deviceInstance->configurationDesc;
+ unionDes = (usb_descriptor_union_t *)temp;
+ endPos = (uint32_t)(deviceInstance->configurationDesc + deviceInstance->configurationLen);
+
+ if (((((uint32_t)unionDes) + 1U) < endPos) && (unionDes->common.bLength == USB_DESCRIPTOR_LENGTH_CONFIGURE) &&
+ (unionDes->common.bDescriptorType == USB_DESCRIPTOR_TYPE_CONFIGURE))
+ {
+ /* configuration descriptor */
+ temp = (void *)unionDes;
+ deviceInstance->configuration.configurationDesc = (usb_descriptor_configuration_t *)temp;
+ deviceInstance->configuration.configurationExtensionLength = 0;
+ deviceInstance->configuration.configurationExtension = NULL;
+ deviceInstance->configuration.interfaceCount = 0;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ while ((uint32_t)unionDes < endPos)
+ {
+ if (((((uint32_t)unionDes) + 1U) < endPos) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE))
+ {
+ if (deviceInstance->configuration.configurationExtension == NULL)
+ {
+ deviceInstance->configuration.configurationExtension = (uint8_t *)unionDes;
+ }
+ if ((unionDes->common.bDescriptorType == 0x00U) ||
+ (unionDes->common.bLength == 0x00U)) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ deviceInstance->configuration.configurationExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* interface descriptor */
+ deviceInstance->configuration.interfaceCount = 0U;
+ while ((uint32_t)unionDes < endPos)
+ {
+ if (((((uint32_t)unionDes) + 1U) < endPos) &&
+ (unionDes->common.bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE))
+ {
+ /* the interface descriptor length is 9 bytes */
+ if ((((uint32_t)unionDes) + 9U) > endPos)
+ {
+ return kStatus_USB_Error;
+ }
+ if (unionDes->interface.bAlternateSetting == 0x00U)
+ {
+ if (deviceInstance->configuration.interfaceCount >= USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE)
+ {
+#if (((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) || defined(HOST_ECHO))
+ (void)usb_echo(
+ "Unsupported Device attached\r\n too many interfaces in one configuration, please increase "
+ "the USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE value\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ interfaceParse =
+ &deviceInstance->configuration.interfaceList[deviceInstance->configuration.interfaceCount];
+ deviceInstance->configuration.interfaceCount++;
+ interfaceParse->alternateSettingNumber = 0;
+ interfaceParse->epCount = 0;
+ interfaceParse->interfaceDesc = &unionDes->interface;
+ interfaceParse->interfaceExtensionLength = 0;
+ interfaceParse->interfaceExtension = NULL;
+ interfaceParse->interfaceIndex = unionDes->interface.bInterfaceNumber;
+ if (unionDes->common.bLength == 0x00U) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ while ((uint32_t)unionDes < endPos)
+ {
+ if (((((uint32_t)unionDes) + 1U) < endPos) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+ {
+ if (interfaceParse->interfaceExtension == NULL)
+ {
+ interfaceParse->interfaceExtension = (uint8_t *)unionDes;
+ }
+ if ((unionDes->common.bDescriptorType == 0x00U) ||
+ (unionDes->common.bLength == 0x00U)) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* endpoint descriptor */
+ if (interfaceParse->interfaceDesc->bNumEndpoints != 0U)
+ {
+ if (((((uint32_t)unionDes) + 1U) >= endPos) ||
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) ||
+ (interfaceParse->interfaceDesc->bNumEndpoints > USB_HOST_CONFIG_INTERFACE_MAX_EP))
+ {
+#ifdef HOST_ECHO
+ usb_echo("interface descriptor error\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ for (; interfaceParse->epCount < interfaceParse->interfaceDesc->bNumEndpoints;
+ (interfaceParse->epCount)++)
+ {
+ if (((((uint32_t)unionDes) + 1U) >= endPos) ||
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+ {
+#ifdef HOST_ECHO
+ usb_echo("endpoint descriptor error\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ temp = (void *)&interfaceParse->epList[interfaceParse->epCount];
+ epParse = (usb_host_ep_t *)temp;
+ temp = (void *)unionDes;
+ epParse->epDesc = (usb_descriptor_endpoint_t *)temp;
+ epParse->epExtensionLength = 0U;
+ epParse->epExtension = NULL;
+ if (unionDes->common.bLength == 0x00U) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ while ((uint32_t)unionDes < endPos)
+ {
+ if (((((uint32_t)unionDes) + 1U) < endPos) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE))
+ {
+ if (epParse->epExtension == NULL)
+ {
+ epParse->epExtension = (uint8_t *)unionDes;
+ }
+ if ((unionDes->common.bDescriptorType == 0x00U) ||
+ (unionDes->common.bLength == 0x00U)) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ epParse->epExtensionLength += unionDes->common.bLength;
+ unionDes =
+ (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (interfaceParse == NULL)
+ {
+ return kStatus_USB_Error; /* in normal situation this cannot reach */
+ }
+ interfaceParse->alternateSettingNumber++;
+ if (interfaceParse->interfaceExtension == NULL)
+ {
+ interfaceParse->interfaceExtension = (uint8_t *)unionDes;
+ }
+ if (unionDes->common.bLength == 0x00U) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ while ((uint32_t)unionDes < endPos)
+ {
+ if (((((uint32_t)unionDes) + 1U) < endPos) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE))
+ {
+ if ((unionDes->common.bDescriptorType == 0x00U) ||
+ (unionDes->common.bLength == 0x00U)) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ return kStatus_USB_Error;
+ }
+ }
+ }
+ else
+ {
+ return kStatus_USB_Error;
+ }
+
+ for (endPos = 0U; endPos < deviceInstance->configuration.interfaceCount; ++endPos)
+ {
+ deviceInstance->interfaceStatus[endPos] = (uint8_t)kStatus_interface_Attached;
+ }
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostAttachDevice(usb_host_handle hostHandle,
+ uint8_t speed,
+ uint8_t hubNumber,
+ uint8_t portNumber,
+ uint8_t level,
+ usb_device_handle *deviceHandle)
+{
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ usb_host_device_instance_t *newInstance;
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ usb_host_device_instance_t *currentInstance;
+#endif
+ uint8_t address;
+ usb_host_pipe_init_t pipeInit;
+
+ if (hostHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+/* check whether is the device attached? */
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ currentInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+ while (currentInstance != NULL)
+ {
+ if ((currentInstance->hubNumber == hubNumber) && (currentInstance->portNumber == portNumber))
+ {
+ *deviceHandle = NULL;
+#ifdef HOST_ECHO
+ usb_echo("device has attached\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+ else
+ {
+ currentInstance = currentInstance->next;
+ }
+ }
+#else
+ if (hostInstance->deviceList != NULL)
+ {
+ *deviceHandle = NULL;
+ usb_echo("device has attached\r\n");
+ return kStatus_USB_Busy;
+ }
+#endif
+
+ /* Allocate new device instance */
+ newInstance = (usb_host_device_instance_t *)OSA_MemoryAllocate(sizeof(usb_host_device_instance_t));
+ if (newInstance == NULL)
+ {
+#ifdef HOST_ECHO
+ usb_echo("allocate dev instance fail\r\n");
+#endif
+ (void)USB_HostNotifyDevice(hostInstance, NULL, (uint32_t)kUSB_HostEventEnumerationFail,
+ (uint32_t)kStatus_USB_AllocFail);
+ return kStatus_USB_AllocFail;
+ }
+
+ /* new instance fields init */
+ newInstance->hostHandle = hostHandle;
+ newInstance->speed = speed;
+ newInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+ newInstance->enumRetries = USB_HOST_CONFIG_ENUMERATION_MAX_RETRIES;
+ newInstance->setAddress = 0;
+ newInstance->deviceAttachState = (uint8_t)kStatus_device_Attached;
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+ newInstance->deviceDescriptor =
+ (usb_descriptor_device_t *)SDK_Malloc(sizeof(usb_descriptor_device_t) + 9, USB_CACHE_LINESIZE);
+#else
+ newInstance->deviceDescriptor = (usb_descriptor_device_t *)OSA_MemoryAllocate(sizeof(usb_descriptor_device_t) + 9U);
+#endif
+ if (newInstance->deviceDescriptor == NULL)
+ {
+#ifdef HOST_ECHO
+ usb_echo("allocate newInstance->deviceDescriptor fail\r\n");
+#endif
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+ SDK_Free(newInstance->deviceDescriptor);
+#else
+ OSA_MemoryFree(newInstance->deviceDescriptor);
+#endif
+ OSA_MemoryFree(newInstance);
+ (void)USB_HostNotifyDevice(hostInstance, NULL, (uint32_t)kUSB_HostEventEnumerationFail,
+ (uint32_t)kStatus_USB_AllocFail);
+ return kStatus_USB_AllocFail;
+ }
+ newInstance->enumBuffer = (uint8_t *)((uint8_t *)newInstance->deviceDescriptor + sizeof(usb_descriptor_device_t));
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ newInstance->hubNumber = hubNumber;
+ newInstance->portNumber = portNumber;
+ newInstance->level = level;
+
+ if ((speed != USB_SPEED_HIGH) && (level > 1U))
+ {
+ newInstance->hsHubNumber = (uint8_t)USB_HostHubGetHsHubNumber(hostHandle, hubNumber);
+ newInstance->hsHubPort = (uint8_t)USB_HostHubGetHsHubPort(hostHandle, hubNumber, portNumber);
+ }
+ else
+ {
+ newInstance->hsHubNumber = hubNumber;
+ newInstance->hsHubPort = portNumber;
+ }
+#endif /* USB_HOST_CONFIG_HUB */
+
+ (void)USB_HostLock();
+ /* allocate address && insert to the dev list */
+ address = USB_HostAllocateDeviceAddress(hostInstance);
+ if (address == 0U)
+ {
+#ifdef HOST_ECHO
+ usb_echo("allocate address fail\r\n");
+#endif
+ (void)USB_HostUnlock();
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+ SDK_Free(newInstance->deviceDescriptor);
+#else
+ OSA_MemoryFree(newInstance->deviceDescriptor);
+#endif
+ OSA_MemoryFree(newInstance);
+ (void)USB_HostNotifyDevice(hostInstance, NULL, (uint32_t)kUSB_HostEventEnumerationFail,
+ (uint32_t)kStatus_USB_Error);
+ return kStatus_USB_Error;
+ }
+ newInstance->allocatedAddress = address;
+
+ newInstance->next = (usb_host_device_instance_t *)hostInstance->deviceList;
+ hostInstance->deviceList = newInstance;
+ newInstance->state = (uint8_t)kStatus_DEV_Initial;
+ (void)USB_HostUnlock();
+
+ /* open control pipe */
+ pipeInit.devInstance = newInstance;
+ pipeInit.pipeType = USB_ENDPOINT_CONTROL;
+ pipeInit.direction = 0;
+ pipeInit.endpointAddress = 0;
+ pipeInit.interval = 0;
+ pipeInit.maxPacketSize = 8;
+ pipeInit.numberPerUframe = 0;
+ pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
+ if (USB_HostOpenPipe(hostHandle, &newInstance->controlPipe, &pipeInit) != kStatus_USB_Success)
+ {
+ /* don't need release resource, resource is released when detach */
+ *deviceHandle = newInstance;
+#if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
+ SDK_Free(newInstance->deviceDescriptor);
+#else
+ OSA_MemoryFree(newInstance->deviceDescriptor);
+#endif
+ OSA_MemoryFree(newInstance);
+ (void)USB_HostNotifyDevice(hostInstance, NULL, (uint32_t)kUSB_HostEventEnumerationFail,
+ (uint32_t)kStatus_USB_Error);
+ return kStatus_USB_Error;
+ }
+
+ /* start enumeration */
+ newInstance->state = (uint8_t)kStatus_DEV_GetDes8;
+ /* process enumeration state machine */
+ if (USB_HostProcessState(newInstance) != kStatus_USB_Success)
+ {
+ (void)USB_HostNotifyDevice(hostInstance, newInstance, (uint32_t)kUSB_HostEventEnumerationFail,
+ (uint32_t)kStatus_USB_Error);
+ }
+ *deviceHandle = newInstance;
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostDetachDevice(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber)
+{
+ usb_host_device_instance_t *deviceInstance;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if (hostHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ (void)USB_HostLock();
+/* search for device instance handle */
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+ while (deviceInstance != NULL)
+ {
+ if ((deviceInstance->hubNumber == hubNumber) && (deviceInstance->portNumber == portNumber))
+ {
+ break;
+ }
+ deviceInstance = deviceInstance->next;
+ }
+#else
+ deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+#endif
+ (void)USB_HostUnlock();
+ if (deviceInstance != NULL)
+ {
+ return USB_HostDetachDeviceInternal(hostHandle, deviceInstance); /* device instance detach */
+ }
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostDetachDeviceInternal(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ if ((hostHandle == NULL) || (deviceHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ deviceInstance->deviceAttachState = (uint8_t)kStatus_device_Detached; /* mark the device is detached from host */
+
+ if (deviceInstance->state >= (uint8_t)kStatus_DEV_Initial) /* device instance is valid */
+ {
+ /* detach internally */
+ if (deviceInstance->state < (uint8_t)kStatus_DEV_AppUsed) /* enumeration is not done */
+ {
+ if (deviceInstance->controlPipe != NULL)
+ {
+ (void)USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL);
+ }
+
+ /* remove device instance from host */
+ (void)USB_HostRemoveDeviceInstance(hostInstance, deviceInstance);
+ USB_HostReleaseDeviceResource(hostInstance, deviceInstance);
+ }
+ else /* enumeration has be done and notified application */
+ {
+ /* notify application device detach */
+ (void)USB_HostNotifyDevice(hostInstance, deviceInstance, (uint32_t)kUSB_HostEventDetach,
+ (uint32_t)kStatus_USB_Success);
+ }
+ }
+
+ return kStatus_USB_Success;
+}
+
+uint8_t USB_HostGetDeviceAttachState(usb_device_handle deviceHandle)
+{
+ return (NULL != deviceHandle) ? ((usb_host_device_instance_t *)deviceHandle)->deviceAttachState : 0x0U;
+}
+
+usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+ usb_host_device_instance_t *searchDev;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+ /* search for the device */
+ searchDev = (usb_host_device_instance_t *)((usb_host_instance_t *)hostHandle)->deviceList;
+ while ((searchDev != NULL) && ((usb_device_handle)searchDev != deviceHandle))
+ {
+ searchDev = searchDev->next;
+ }
+
+ if (NULL != searchDev)
+ {
+ return kStatus_USB_Success;
+ }
+ return kStatus_USB_Error;
+}
+
+static usb_status_t USB_HostControlBus(usb_host_handle hostHandle, uint8_t controlType)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if (hostHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+ /* the callbackFn is initialized in USB_HostGetControllerInterface */
+ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl,
+ &controlType);
+
+ return status;
+}
+
+usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle, usb_host_interface_handle interfaceHandle)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ usb_host_instance_t *hostInstance = NULL;
+ uint8_t interfaceIndex;
+ uint8_t index = 0;
+
+ if ((deviceHandle == NULL) || (interfaceHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+ (void)USB_HostLock();
+ /* check host_instance valid? */
+ for (; index < (uint8_t)USB_HOST_CONFIG_MAX_HOST; ++index)
+ {
+ if ((g_UsbHostInstance[index].occupied == 1U) &&
+ ((usb_host_instance_t *)(&g_UsbHostInstance[index]) == (hostInstance)))
+ {
+ break;
+ }
+ }
+ if (index >= (uint8_t)USB_HOST_CONFIG_MAX_HOST)
+ {
+ (void)USB_HostUnlock();
+ return kStatus_USB_Error;
+ }
+
+ /* check deviceHandle valid? */
+ if (USB_HostValidateDevice(hostInstance, deviceHandle) != kStatus_USB_Success)
+ {
+ (void)USB_HostUnlock();
+ return kStatus_USB_Error;
+ }
+
+ /* search interface and set the interface as opened */
+ for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+ {
+ if (&deviceInstance->configuration.interfaceList[interfaceIndex] == interfaceHandle)
+ {
+ deviceInstance->interfaceStatus[interfaceIndex] = (uint8_t)kStatus_interface_Opened;
+ break;
+ }
+ }
+ (void)USB_HostUnlock();
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle, usb_host_interface_handle interfaceHandle)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ usb_host_instance_t *hostInstance = NULL;
+ uint8_t interfaceIndex;
+ uint8_t removeLabel = 1;
+ uint8_t index = 0;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+ (void)USB_HostLock();
+ /* check host_instance valid? */
+ for (; index < (uint8_t)USB_HOST_CONFIG_MAX_HOST; ++index)
+ {
+ if ((g_UsbHostInstance[index].occupied == 1U) &&
+ ((usb_host_instance_t *)(&g_UsbHostInstance[index]) == (hostInstance)))
+ {
+ break;
+ }
+ }
+ if (index >= (uint8_t)USB_HOST_CONFIG_MAX_HOST)
+ {
+ (void)USB_HostUnlock();
+ return kStatus_USB_Error;
+ }
+
+ /* check deviceHandle valid? */
+ if (USB_HostValidateDevice(hostInstance, deviceHandle) != kStatus_USB_Success)
+ {
+ (void)USB_HostUnlock();
+ return kStatus_USB_Error;
+ }
+
+ if (interfaceHandle != NULL)
+ {
+ /* search interface and set the interface as detached */
+ for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+ {
+ if (&deviceInstance->configuration.interfaceList[interfaceIndex] == interfaceHandle)
+ {
+ deviceInstance->interfaceStatus[interfaceIndex] = (uint8_t)kStatus_interface_Detached;
+ break;
+ }
+ }
+ }
+
+ if (deviceInstance->deviceAttachState == (uint8_t)kStatus_device_Detached) /* device is removed from host */
+ {
+ removeLabel = 1;
+ /* check all the interfaces of the device are not opened */
+ for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+ {
+ if (deviceInstance->interfaceStatus[interfaceIndex] == (uint8_t)kStatus_interface_Opened)
+ {
+ removeLabel = 0U;
+ break;
+ }
+ }
+ if (removeLabel == 1U)
+ {
+ /* remove device instance from host */
+ (void)USB_HostRemoveDeviceInstance(hostInstance, deviceInstance);
+ }
+ (void)USB_HostUnlock();
+
+ if (removeLabel == 1U)
+ {
+ USB_HostReleaseDeviceResource((usb_host_instance_t *)deviceInstance->hostHandle,
+ deviceInstance); /* release device resource */
+ }
+ }
+ else
+ {
+ (void)USB_HostUnlock();
+ }
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ uint8_t interfaceIndex = 0;
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ uint8_t level = 0;
+ uint8_t devHubNo;
+ uint8_t devPortNo;
+#endif
+
+ if ((hostHandle == NULL) || (deviceHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+ if (deviceInstance->hostHandle != hostHandle)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ if (USB_HostValidateDevice(hostInstance, deviceInstance) == kStatus_USB_Success) /* device is valid */
+ {
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ devHubNo = deviceInstance->hubNumber;
+ devPortNo = deviceInstance->portNumber;
+ level = deviceInstance->level;
+#endif
+
+ deviceInstance->deviceAttachState = (uint8_t)kStatus_device_Detached;
+ if (deviceInstance->state >= (uint8_t)kStatus_DEV_Initial) /* device is valid */
+ {
+ if (deviceInstance->state <
+ (uint8_t)kStatus_DEV_AppUsed) /* enumeration is not done or application don't use */
+ {
+ /* detach internally */
+ (void)USB_HostDetachDeviceInternal(hostHandle, deviceHandle);
+ }
+ else /* application use the device */
+ {
+ for (interfaceIndex = 0U; interfaceIndex < deviceInstance->configuration.interfaceCount;
+ ++interfaceIndex)
+ {
+ if (deviceInstance->interfaceStatus[interfaceIndex] == (uint8_t)kStatus_interface_Opened)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error: there is class instance that is not deinited\r\n");
+#endif
+ break;
+ }
+ }
+ /* remove device instance from host */
+ (void)USB_HostRemoveDeviceInstance(hostInstance, deviceInstance);
+ USB_HostReleaseDeviceResource(hostInstance, deviceInstance); /* release resource */
+ }
+ }
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ if (level == 1U)
+ {
+ (void)USB_HostControlBus(hostHandle, (uint8_t)kUSB_HostBusReset); /* reset controller port */
+ (void)USB_HostControlBus(hostHandle, (uint8_t)kUSB_HostBusRestart); /* restart controller port */
+ }
+ else
+ {
+ (void)USB_HostHubRemovePort(hostHandle, devHubNo, devPortNo); /* reset hub port */
+ }
+#else
+ USB_HostControlBus(hostHandle, kUSB_HostBusReset); /* reset controller port */
+ USB_HostControlBus(hostHandle, kUSB_HostBusRestart); /* restart controller port */
+#endif /* USB_HOST_CONFIG_HUB */
+ }
+
+ return kStatus_USB_Success;
+}
+#else
static void USB_HostEnumerationTransferCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
/* 0 - retry current transfer, 1 - transfer success process,
@@ -1462,3 +2788,4 @@ usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle
return kStatus_USB_Success;
}
+#endif
diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.c b/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.c
index 58059e033d..59105d46ee 100644
--- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.c
+++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.c
@@ -21,6 +21,11 @@
#include "usb_host.h"
#endif
+//#define USB_GINSTANCE_SIZE (sizeof(usb_host_ehci_instance_t))
+//#if defined(__ICCARM__) /* IAR Workbench */
+//#pragma location = "usb_heap_section"
+//static char ginstance_base[USB_GINSTANCE_SIZE];
+//#endif
/*******************************************************************************
* Definitions
******************************************************************************/
@@ -156,6 +161,15 @@ static void USB_HostEhciZeroMem(uint32_t *buffer, uint32_t length);
*/
static void USB_HostEhciDelay(USBHS_Type *ehciIpBase, uint32_t ms);
+#ifdef SOC_IMXRT1170_SERIES
+/*!
+ * @brief host ehci start async schedule.
+ *
+ * @param ehciInstance ehci instance pointer.
+ */
+static void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance);
+#endif
+
/*!
* @brief host ehci stop async schedule.
*
@@ -163,6 +177,15 @@ static void USB_HostEhciDelay(USBHS_Type *ehciIpBase, uint32_t ms);
*/
static void USB_HostEhciStopAsync(usb_host_ehci_instance_t *ehciInstance);
+#ifdef SOC_IMXRT1170_SERIES
+/*!
+ * @brief host ehci start periodic schedule.
+ *
+ * @param ehciInstance ehci instance pointer.
+ */
+static void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance);
+#endif
+
/*!
* @brief host ehci stop periodic schedule.
*
@@ -482,6 +505,19 @@ static usb_status_t USB_HostEhciCancelPipe(usb_host_ehci_instance_t *ehciInstanc
usb_host_ehci_pipe_t *ehciPipePointer,
usb_host_transfer_t *transfer);
+
+#ifdef SOC_IMXRT1170_SERIES
+/*!
+ * @brief control ehci bus.
+ *
+ * @param ehciInstance ehci instance pointer.
+ * @param bus_control control code.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint8_t busControl);
+#endif
+
/*!
* @brief ehci transaction done process function.
*
@@ -489,7 +525,22 @@ static usb_status_t USB_HostEhciCancelPipe(usb_host_ehci_instance_t *ehciInstanc
*/
void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance);
+#ifdef SOC_IMXRT1170_SERIES
+/*!
+ * @brief ehci port change interrupt process function.
+ *
+ * @param ehciInstance ehci instance pointer.
+ */
+static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance);
+/*!
+ * @brief ehci timer0 interrupt process function.
+ * cancel control/bulk transfer that time out.
+ *
+ * @param ehciInstance ehci instance pointer.
+ */
+static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance);
+#endif
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
/*!
@@ -1045,7 +1096,11 @@ static void USB_HostBandwidthHsHostComputeCurrentFsls(usb_host_ehci_instance_t *
{
usb_host_ehci_pipe_t *ehciPipePointer;
uint8_t index;
+#ifdef SOC_IMXRT1170_SERIES
+ uint32_t deviceInfo = 0;
+#else
uint32_t deviceInfo;
+#endif
void *temp;
for (index = 0; index < 8U; ++index)
@@ -1117,7 +1172,11 @@ static void USB_HostBandwidthHsHostComputeCurrentHsAll(usb_host_ehci_instance_t
{
usb_host_ehci_pipe_t *ehciPipePointer;
uint16_t index;
+#ifdef SOC_IMXRT1170_SERIES
+ uint32_t deviceInfo = 0U;
+#else
uint32_t deviceInfo;
+#endif
uint16_t frameInterval;
void *temp;
for (index = 0; index < 8U; ++index)
@@ -1790,7 +1849,11 @@ static void USB_HostEhciDelay(USBHS_Type *ehciIpBase, uint32_t ms)
} while ((distance & EHCI_MAX_UFRAME_VALUE) < (ms * 8U)); /* compute the distance between sofStart and SofEnd */
}
+#ifdef SOC_IMXRT1170_SERIES
+static void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance)
+#else
void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance)
+#endif
{
uint32_t stateSync;
@@ -1828,7 +1891,11 @@ static void USB_HostEhciStopAsync(usb_host_ehci_instance_t *ehciInstance)
}
}
+#ifdef SOC_IMXRT1170_SERIES
+static void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance)
+#else
void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance)
+#endif
{
uint32_t stateSync;
@@ -3060,6 +3127,9 @@ static uint32_t USB_HostEhciItdArrayRelease(usb_host_ehci_instance_t *ehciInstan
/* USB_HostEhciLock(); */
/*set next link pointer to invalid in case hardware access invalid itd structure in special case*/
itdPointer->nextLinkPointer = EHCI_HOST_T_INVALID_VALUE;
+#ifdef SOC_IMXRT1170_SERIES
+ USB_HostEhciZeroMem((uint32_t *)(void *)itdPointer + 1, ((sizeof(usb_host_ehci_itd_t) >> 2) - 4U));
+#endif
itdPointer->nextItdPointer = (usb_host_ehci_itd_t *)ehciInstance->ehciItdList;
ehciInstance->ehciItdList = itdPointer;
ehciInstance->ehciItdNumber++;
@@ -3379,7 +3449,10 @@ static usb_status_t USB_HostEhciStartIP(usb_host_ehci_instance_t *ehciInstance)
#endif
#endif
}
-
+#ifdef SOC_IMXRT1170_SERIES
+ /* no interrupt threshold */
+ ehciInstance->ehciIpBase->USBCMD &= ~USBHS_USBCMD_ITC_MASK;
+#endif
/* start the controller */
ehciInstance->ehciIpBase->USBCMD |= USBHS_USBCMD_RS_MASK;
@@ -3474,8 +3547,11 @@ static usb_status_t USB_HostEhciCancelPipe(usb_host_ehci_instance_t *ehciInstanc
return kStatus_USB_Success;
}
-
+#ifdef SOC_IMXRT1170_SERIES
+static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint8_t busControl)
+#else
usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint8_t busControl)
+#endif
{
usb_status_t status = kStatus_USB_Success;
uint32_t portScRegister;
@@ -3525,7 +3601,9 @@ usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint
ehciInstance->ehciIpBase->PORTSC1 &= ~USBHS_PORTSC1_WKCN_MASK;
ehciInstance->ehciIpBase->PORTSC1 |= USBHS_PORTSC1_WKDS_MASK;
ehciInstance->ehciIpBase->PORTSC1 |= (USBHS_PORTSC1_SUSP_MASK); /* Suspend the device */
-
+#if (defined(FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT) && (FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT > 0U))
+ PMU->WAKEUP_PM2_MASK1 |= PMU_WAKEUP_PM2_MASK1_USB(1);
+#endif
ehciInstance->matchTick = 0U;
ehciInstance->ehciIpBase->USBINTR |= (USBHS_USBINTR_TIE1_MASK);
ehciInstance->busSuspendStatus = kBus_EhciStartSuspend;
@@ -3544,8 +3622,11 @@ usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint
#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
ehciInstance->registerNcBase->USB_OTGn_CTRL &= ~USBNC_USB_OTGn_CTRL_WIE_MASK;
#else
+#if (defined(FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT) && (FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT > 0U))
+#else
ehciInstance->ehciIpBase->USBGENCTRL &= ~USBHS_USBGENCTRL_WU_IE_MASK;
#endif
+#endif
ehciInstance->ehciIpBase->USBCMD |= (USBHS_USBCMD_RS_MASK);
ehciInstance->ehciIpBase->PORTSC1 |= (USBHS_PORTSC1_FPR_MASK); /* Resume the device */
}
@@ -3583,8 +3664,12 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance)
((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)))
usb_host_ehci_iso_t *isoPointer;
uint32_t dataLength;
+#ifdef SOC_IMXRT1170_SERIES
+ uint32_t speed = 0U;
+#else
uint32_t speed;
#endif
+#endif
void *temp;
uint32_t transferResults;
uint32_t transferOverlayResults;
@@ -3693,12 +3778,30 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance)
else
{
/* remove qtd from qh */
+#ifdef SOC_IMXRT1170_SERIES
+ do
+ {
+ if (vltQtdPointer == NULL)
+ {
+ break;
+ }
+ else if (0U != (vltQtdPointer->transferResults[0] & EHCI_HOST_QTD_IOC_MASK))
+ {
+ break;
+ }
+ else
+ {
+ /* no action */
+ }
+ vltQtdPointer = (volatile usb_host_ehci_qtd_t *)vltQtdPointer->nextQtdPointer;
+ } while (true);
+#else
while ((vltQtdPointer != NULL) &&
(0U == (transferResults & EHCI_HOST_QTD_IOC_MASK))) /* find the IOC qtd */
{
vltQtdPointer = (volatile usb_host_ehci_qtd_t *)vltQtdPointer->nextQtdPointer;
}
-
+#endif
vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE;
vltQhPointer->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE;
vltQhPointer->transferOverlayResults[0] &=
@@ -3823,7 +3926,11 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance)
}
}
+#ifdef SOC_IMXRT1170_SERIES
+static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance)
+#else
void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance)
+#endif
{
/* note: only has one port */
uint32_t portScRegister = ehciInstance->ehciIpBase->PORTSC1;
@@ -3915,7 +4022,13 @@ void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance)
ehciInstance->ehciIpBase->USBINTR &= ~(USBHS_USBINTR_TIE1_MASK);
#endif
/* disable ehci phy disconnection */
+#ifdef SOC_IMXRT1170_SERIES
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+ USB_EhcihostPhyDisconnectDetectCmd(ehciInstance->controllerId, 0);
+#endif
+#else
USB_EhcihostPhyDisconnectDetectCmd(ehciInstance->controllerId, 0);
+#endif
/* disable async and periodic */
USB_HostEhciStopAsync(ehciInstance);
USB_HostEhciStopPeriodic(ehciInstance);
@@ -3924,7 +4037,11 @@ void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance)
}
}
+#ifdef SOC_IMXRT1170_SERIES
+static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance)
+#else
void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance)
+#endif
{
volatile usb_host_ehci_qh_t *vltQhPointer;
usb_host_ehci_qtd_t *vltQtdPointer;
@@ -4071,24 +4188,54 @@ static void USB_HostEhciTimer1(usb_host_ehci_instance_t *ehciInstance)
;
#endif
#endif
+#ifdef SOC_IMXRT1170_SERIES
+#if (defined(FSL_FEATURE_USBPHY_28FDSOI) && (FSL_FEATURE_USBPHY_28FDSOI > 0U))
+ ehciInstance->registerPhyBase->USB1_VBUS_DETECT_SET |=
+ USBPHY_USB1_VBUS_DETECT_VBUSVALID_TO_SESSVALID_MASK;
+#endif
+#endif
ehciInstance->ehciIpBase->PORTSC1 |= USBHS_PORTSC1_PHCD_MASK;
+#ifdef SOC_IMXRT1170_SERIES
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
ehciInstance->registerPhyBase->PWD = 0xFFFFFFFFU;
while (0U != (ehciInstance->registerPhyBase->CTRL & (USBPHY_CTRL_UTMI_SUSPENDM_MASK)))
{
__NOP();
}
+#endif
+#else
+ ehciInstance->registerPhyBase->PWD = 0xFFFFFFFFU;
+ while (0U != (ehciInstance->registerPhyBase->CTRL & (USBPHY_CTRL_UTMI_SUSPENDM_MASK)))
+ {
+ __NOP();
+ }
+#endif
+
#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
ehciInstance->registerNcBase->USB_OTGn_CTRL |= USBNC_USB_OTGn_CTRL_WKUP_ID_EN_MASK |
USBNC_USB_OTGn_CTRL_WKUP_VBUS_EN_MASK |
USBNC_USB_OTGn_CTRL_WKUP_DPDM_EN_MASK;
ehciInstance->registerNcBase->USB_OTGn_CTRL |= USBNC_USB_OTGn_CTRL_WIE_MASK;
#else
+#ifdef SOC_IMXRT1170_SERIES
+#if (defined(FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT) && (FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT > 0U))
+#else
+ ehciInstance->ehciIpBase->USBGENCTRL = USBHS_USBGENCTRL_WU_IE_MASK;
+#endif
+#else
ehciInstance->ehciIpBase->USBGENCTRL = USBHS_USBGENCTRL_WU_IE_MASK;
#endif
+#endif
+#ifdef
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+ ehciInstance->registerPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK;
+#endif
+#else
ehciInstance->registerPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK;
+#endif
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
kUSB_HostEventSuspended); /* call host callback function */
ehciInstance->busSuspendStatus = kBus_EhciSuspended;
@@ -4159,8 +4306,14 @@ usb_status_t USB_HostEhciCreate(uint8_t controllerId,
ehciInstance->busSuspendStatus = kBus_EhciIdle;
#if (defined(USB_HOST_CONFIG_LOW_POWER_MODE) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
+#ifdef SOC_IMXRT1170_SERIES
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
ehciInstance->registerPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
-
+#endif
+#else
+ ehciInstance->registerPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+#endif
+
#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
ehciInstance->registerNcBase = (USBNC_Type *)USB_EhciNCGetBase(controllerId);
#endif
@@ -4386,7 +4539,9 @@ usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle,
usb_status_t status;
uint32_t speed = 0;
usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle;
+#if !defined(SOC_IMXRT1170_SERIES)
uint32_t val32;
+#endif
void *temp;
/* get one pipe */
USB_HostEhciLock();
@@ -4444,6 +4599,7 @@ usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle,
(uint8_t)ehciPipePointer->pipeCommon.interval); /* FS/LS interrupt interval should be the power of
2, it is used for ehci bandwidth */
}
+#if !defined(SOC_IMXRT1170_SERIES)
}
if ((speed == USB_SPEED_HIGH) && (ehciPipePointer->pipeCommon.interval < 8U))
@@ -4452,6 +4608,7 @@ usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle,
val32 &= (~USBHS_USBCMD_ITC_MASK);
val32 |= USBHS_USBCMD_ITC((ehciPipePointer->pipeCommon.interval));
ehciInstance->ehciIpBase->USBCMD = val32;
+#endif
}
}
@@ -4825,6 +4982,8 @@ void USB_HostEhciIsrFunction(void *hostHandle)
/*no action*/
}
#else
+#if (defined(FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT) && (FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT > 0U))
+#else
if (0U != (ehciInstance->ehciIpBase->USBGENCTRL & USBHS_USBGENCTRL_WU_IE_MASK))
{
usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle;
@@ -4857,8 +5016,8 @@ void USB_HostEhciIsrFunction(void *hostHandle)
{
/*no action*/
}
+#endif /* FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT */
#endif /* FSL_FEATURE_SOC_USBNC_COUNT */
-
#endif /* USB_HOST_CONFIG_LOW_POWER_MODE */
interruptStatus = ehciInstance->ehciIpBase->USBSTS;
@@ -4905,6 +5064,27 @@ void USB_HostEhciIsrFunction(void *hostHandle)
/*no action */
}
}
+#if (defined(FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT) && (FSL_FEATURE_USB_ATLANTIC_EHCI_SUPPORT > 0U))
+ if ((kBus_EhciSuspended == ehciInstance->busSuspendStatus))
+ {
+ usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle;
+
+ (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
+ kUSB_HostEventDetectResume); /* call host callback function */
+
+ uint32_t delay = 100000;
+ while (delay-- && !(USBOTG->PLL_CONTROL_0 & USBC_PLL_CONTROL_0_PLL_READY_MASK))
+ {
+ }
+ if (0U != (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK))
+ {
+ USB_HostEhciStartAsync(ehciInstance);
+ USB_HostEhciStartPeriodic(ehciInstance);
+ }
+ ehciInstance->ehciIpBase->USBCMD |= (USBHS_USBCMD_RS_MASK);
+ ehciInstance->busSuspendStatus = kBus_EhciStartResume;
+ }
+#endif
#endif
(void)OSA_EventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_PORT_CHANGE);
}
diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.h b/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.h
index 29a0fd2a3f..1af4880c92 100644
--- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.h
+++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.h
@@ -309,7 +309,13 @@ typedef struct _usb_host_ehci_instance
uint32_t taskEventHandleBuffer[(OSA_EVENT_HANDLE_SIZE + 3) / 4]; /*!< EHCI task event handle buffer*/
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
uint64_t matchTick;
+#ifdef SOC_IMXRT1170_SERIES
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
USBPHY_Type *registerPhyBase; /*!< The base address of the PHY register */
+#endif
+#else
+ USBPHY_Type *registerPhyBase; /*!< The base address of the PHY register */
+#endif
#if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U))
USBNC_Type *registerNcBase; /*!< The base address of the USBNC register */
#endif
@@ -473,6 +479,7 @@ extern usb_status_t USB_HostEhciIoctl(usb_host_controller_handle controllerHandl
uint32_t ioctlEvent,
void *ioctlParam);
+#if !defined(SOC_IMXRT1170_SERIES)
/*!
* @brief control ehci bus.
*
@@ -511,7 +518,7 @@ extern void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance);
* @param ehciInstance ehci instance pointer.
*/
extern void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance);
-
+#endif
/*! @}*/
#ifdef __cplusplus
diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.c b/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.c
index 1409868b7b..9ae82ae50c 100644
--- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.c
+++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.c
@@ -171,7 +171,7 @@ static usb_host_instance_t *USB_HostGetInstance(void)
void *temp;
OSA_SR_ALLOC();
OSA_ENTER_CRITICAL();
- for (; i < USB_HOST_CONFIG_MAX_HOST; i++)
+ for (; i < (uint8_t)USB_HOST_CONFIG_MAX_HOST; i++)
{
if (g_UsbHostInstance[i].occupied != 1U)
{
@@ -182,7 +182,7 @@ static usb_host_instance_t *USB_HostGetInstance(void)
}
g_UsbHostInstance[i].occupied = 1;
OSA_EXIT_CRITICAL();
- for (index = 0; index < USB_HOST_CONFIG_MAX_TRANSFERS; ++index)
+ for (index = 0; index < (uint32_t)USB_HOST_CONFIG_MAX_TRANSFERS; ++index)
{
temp = (void *)&(s_Setupbuffer[i][index][0]);
g_UsbHostInstance[i].transferList[index].setupPacket = (usb_setup_struct_t *)temp;
@@ -266,6 +266,7 @@ usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, hos
{
return kStatus_USB_Error;
}
+
/* HOST instance init*/
hostInstance->controllerId = controllerId;
@@ -290,7 +291,7 @@ usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, hos
transferPrev->next = &hostInstance->transferList[i];
transferPrev = transferPrev->next;
}
-
+
/* controller create, the callbackFn is initialized in USB_HostGetControllerInterface */
status =
hostInstance->controllerTable->controllerCreate(controllerId, hostInstance, &(hostInstance->controllerHandle));
@@ -698,14 +699,19 @@ usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle inter
}
/* parse configuration descriptor */
+#ifdef SOC_IMXRT1170_SERIES
+ temp = (void *)((usb_host_interface_t *)interfaceHandle)->interfaceExtension;
+#else
temp = (void *)((usb_host_interface_t *)interfaceHandle)->interfaceDesc;
- ;
+#endif
unionDes = (usb_descriptor_union_t *)temp; /* interface extend descriptor start */
endPosition =
(uint32_t)unionDes +
((usb_host_interface_t *)interfaceHandle)->interfaceExtensionLength; /* interface extend descriptor end */
+#if !defined(SOC_IMXRT1170_SERIES)
unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
-
+#endif
+
/* search for the alternate setting interface descriptor */
while ((uint32_t)unionDes < endPosition)
{
diff --git a/bsp/imxrt/libraries/drivers/usb/include/usb.h b/bsp/imxrt/libraries/drivers/usb/include/usb.h
index a219f10cec..1472c2a0f8 100644
--- a/bsp/imxrt/libraries/drivers/usb/include/usb.h
+++ b/bsp/imxrt/libraries/drivers/usb/include/usb.h
@@ -56,6 +56,12 @@
/*! @brief USB stack version definition */
#define USB_MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
+#ifdef SOC_IMXRT1170_SERIES
+/*! @brief USB stack component version definition, changed with component in yaml together */
+#define USB_STACK_COMPONENT_VERSION \
+ MAKE_VERSION(USB_STACK_VERSION_MAJOR, USB_STACK_VERSION_MINOR, USB_STACK_VERSION_BUGFIX)
+#endif
+
/*! @brief USB error code */
typedef enum _usb_status
{
@@ -80,6 +86,11 @@ typedef enum _usb_status
kStatus_USB_MSDStatusFail, /*!< For MSD, the CSW status means fail */
kStatus_USB_EHCIAttached,
kStatus_USB_EHCIDetached,
+#ifdef SOC_IMXRT1170_SERIES
+ kStatus_USB_DataOverRun, /*!< The amount of data returned by the endpoint exceeded
+ either the size of the maximum data packet allowed
+ from the endpoint or the remaining buffer size. */
+#endif
} usb_status_t;
/*! @brief USB host handle type define */
@@ -120,6 +131,11 @@ typedef enum _usb_controller_index
kUSB_ControllerIp3516Hs1 =
11U, /*!< IP3516HS 1U, Currently, there are no platforms which have two IP3516HS IPs, this is reserved
to be used in the future. */
+#ifdef SOC_IMXRT1170_SERIES
+ kUSB_ControllerDwc30 = 12U, /*!< DWC3 0U */
+ kUSB_ControllerDwc31 = 13U, /*!< DWC3 1U Currently, there are no platforms which have two Dwc IPs, this is reserved
+ to be used in the future.*/
+#endif
} usb_controller_index_t;
/**
diff --git a/bsp/imxrt/libraries/drivers/usb/include/usb_host_config.h b/bsp/imxrt/libraries/drivers/usb/include/usb_host_config.h
index 8990136352..a3c3b7dbfd 100644
--- a/bsp/imxrt/libraries/drivers/usb/include/usb_host_config.h
+++ b/bsp/imxrt/libraries/drivers/usb/include/usb_host_config.h
@@ -22,8 +22,11 @@
* - if 0, host ehci driver is disable.
* - if greater than 0, host ehci driver is enable.
*/
+#ifdef SOC_IMXRT1170_SERIES
+#define USB_HOST_CONFIG_EHCI (1U)
+#else
#define USB_HOST_CONFIG_EHCI (2U)
-
+#endif
/*!
* @brief host ohci instance count, meantime it indicates ohci enable or disable.
* - if 0, host ohci driver is disable.
@@ -100,8 +103,13 @@
#define USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE (0U)
#endif
/*! @brief if 1, enable usb compliance test codes; if 0, disable usb compliance test codes. */
+#ifdef SOC_IMXRT1170_SERIES
+#ifndef USB_HOST_CONFIG_COMPLIANCE_TEST
#define USB_HOST_CONFIG_COMPLIANCE_TEST (0U)
-
+#endif
+#else
+#define USB_HOST_CONFIG_COMPLIANCE_TEST (0U)
+#endif
/*! @brief if 1, class driver clear stall automatically; if 0, class driver don't clear stall. */
#define USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL (0U)
@@ -148,8 +156,18 @@
/* OHCI configuration */
#if ((defined USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI))
+#ifdef SOC_IMXRT1170_SERIES
+/*!
+ * @brief ohci ED max count.
+ */
+#define USB_HOST_CONFIG_OHCI_MAX_ED (16U)
/*!
+ * @brief ohci GTD max count.
+ */
+#define USB_HOST_CONFIG_OHCI_MAX_GTD (16U)
+#else
+/*!
* @brief ohci ED max count.
*/
#define USB_HOST_CONFIG_OHCI_MAX_ED (8U)
@@ -158,7 +176,8 @@
* @brief ohci GTD max count.
*/
#define USB_HOST_CONFIG_OHCI_MAX_GTD (8U)
-
+#endif
+
/*!
* @brief ohci ITD max count.
*/
@@ -243,5 +262,4 @@
* - if greater than 0, host charger detect is enable.
*/
#define USB_HOST_CONFIG_BATTERY_CHARGER (0U)
-
#endif /* _USB_HOST_CONFIG_H_ */
diff --git a/bsp/imxrt/libraries/drivers/usb/phy/usb_phy.c b/bsp/imxrt/libraries/drivers/usb/phy/usb_phy.c
index 70537b97dc..2ed2b7d3cd 100644
--- a/bsp/imxrt/libraries/drivers/usb/phy/usb_phy.c
+++ b/bsp/imxrt/libraries/drivers/usb/phy/usb_phy.c
@@ -33,6 +33,273 @@
#include <usb/phy/usb_phy.h>
+#ifdef SOC_IMXRT1170_SERIES
+void *USB_EhciPhyGetBase(uint8_t controllerId)
+{
+ void *usbPhyBase = NULL;
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+ uint32_t instance;
+ uint32_t newinstance = 0;
+ uint32_t usbphy_base_temp[] = USBPHY_BASE_ADDRS;
+ uint32_t usbphy_base[] = USBPHY_BASE_ADDRS;
+ uint32_t *temp;
+ if (controllerId < (uint8_t)kUSB_ControllerEhci0)
+ {
+ return NULL;
+ }
+
+ if ((controllerId == (uint8_t)kUSB_ControllerEhci0) || (controllerId == (uint8_t)kUSB_ControllerEhci1))
+ {
+ controllerId = controllerId - (uint8_t)kUSB_ControllerEhci0;
+ }
+ else if ((controllerId == (uint8_t)kUSB_ControllerLpcIp3511Hs0) ||
+ (controllerId == (uint8_t)kUSB_ControllerLpcIp3511Hs1))
+ {
+ controllerId = controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0;
+ }
+ else if ((controllerId == (uint8_t)kUSB_ControllerIp3516Hs0) || (controllerId == (uint8_t)kUSB_ControllerIp3516Hs1))
+ {
+ controllerId = controllerId - (uint8_t)kUSB_ControllerIp3516Hs0;
+ }
+ else
+ {
+ /*no action*/
+ }
+
+ for (instance = 0; instance < (sizeof(usbphy_base_temp) / sizeof(usbphy_base_temp[0])); instance++)
+ {
+ if (0U != usbphy_base_temp[instance])
+ {
+ usbphy_base[newinstance++] = usbphy_base_temp[instance];
+ }
+ }
+ if (controllerId > newinstance)
+ {
+ return NULL;
+ }
+ temp = (uint32_t *)usbphy_base[controllerId];
+ usbPhyBase = (void *)temp;
+#endif
+ return usbPhyBase;
+}
+
+/*!
+ * @brief ehci phy initialization.
+ *
+ * This function initialize ehci phy IP.
+ *
+ * @param[in] controllerId ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] freq the external input clock.
+ * for example: if the external input clock is 16M, the parameter freq should be 16000000.
+ *
+ * @retval kStatus_USB_Success cancel successfully.
+ * @retval kStatus_USB_Error the freq value is incorrect.
+ */
+uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+ USBPHY_Type *usbPhyBase;
+
+ usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+ if (NULL == usbPhyBase)
+ {
+ return (uint8_t)kStatus_USB_Error;
+ }
+
+#if ((defined FSL_FEATURE_SOC_ANATOP_COUNT) && (FSL_FEATURE_SOC_ANATOP_COUNT > 0U))
+ ANATOP->HW_ANADIG_REG_3P0.RW =
+ (ANATOP->HW_ANADIG_REG_3P0.RW &
+ (~(ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x1F) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_ILIMIT_MASK))) |
+ ANATOP_HW_ANADIG_REG_3P0_OUTPUT_TRG(0x17) | ANATOP_HW_ANADIG_REG_3P0_ENABLE_LINREG_MASK;
+ ANATOP->HW_ANADIG_USB2_CHRG_DETECT.SET =
+ ANATOP_HW_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B_MASK | ANATOP_HW_ANADIG_USB2_CHRG_DETECT_EN_B_MASK;
+#endif
+
+#if (defined USB_ANALOG)
+ USB_ANALOG->INSTANCE[controllerId - (uint8_t)kUSB_ControllerEhci0].CHRG_DETECT_SET =
+ USB_ANALOG_CHRG_DETECT_CHK_CHRG_B(1) | USB_ANALOG_CHRG_DETECT_EN_B(1);
+#endif
+
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+
+ usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
+#endif
+ usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
+ usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
+ /* PWD register provides overall control of the PHY power state */
+ usbPhyBase->PWD = 0U;
+ if (((uint8_t)kUSB_ControllerIp3516Hs0 == controllerId) || ((uint8_t)kUSB_ControllerIp3516Hs1 == controllerId) ||
+ ((uint8_t)kUSB_ControllerLpcIp3511Hs0 == controllerId) ||
+ ((uint8_t)kUSB_ControllerLpcIp3511Hs1 == controllerId))
+ {
+ usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_CLKGATE_MASK;
+ usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_PHY_PWD_MASK;
+ }
+ if (NULL != phyConfig)
+ {
+ /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
+ usbPhyBase->TX =
+ ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
+ (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
+ USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
+ }
+#endif
+
+ return (uint8_t)kStatus_USB_Success;
+}
+
+/*!
+ * @brief ehci phy initialization for suspend and resume.
+ *
+ * This function initialize ehci phy IP for suspend and resume.
+ *
+ * @param[in] controllerId ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] freq the external input clock.
+ * for example: if the external input clock is 16M, the parameter freq should be 16000000.
+ *
+ * @retval kStatus_USB_Success cancel successfully.
+ * @retval kStatus_USB_Error the freq value is incorrect.
+ */
+uint32_t USB_EhciLowPowerPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+ USBPHY_Type *usbPhyBase;
+
+ usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+ if (NULL == usbPhyBase)
+ {
+ return (uint8_t)kStatus_USB_Error;
+ }
+
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+ usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */
+#endif
+
+#if ((defined USBPHY_CTRL_AUTORESUME_EN_MASK) && (USBPHY_CTRL_AUTORESUME_EN_MASK > 0U))
+ usbPhyBase->CTRL_CLR |= USBPHY_CTRL_AUTORESUME_EN_MASK;
+#else
+ usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTO_PWRON_PLL_MASK;
+#endif
+ usbPhyBase->CTRL |= USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK;
+ usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */
+ usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */
+ /* PWD register provides overall control of the PHY power state */
+ usbPhyBase->PWD = 0U;
+#if (defined USBPHY_ANACTRL_PFD_CLKGATE_MASK)
+ /* now the 480MHz USB clock is up, then configure fractional divider after PLL with PFD
+ * pfd clock = 480MHz*18/N, where N=18~35
+ * Please note that USB1PFDCLK has to be less than 180MHz for RUN or HSRUN mode
+ */
+ usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_FRAC(24); /* N=24 */
+ usbPhyBase->ANACTRL |= USBPHY_ANACTRL_PFD_CLK_SEL(1); /* div by 4 */
+
+ usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_DEV_PULLDOWN_MASK;
+ usbPhyBase->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK;
+ while (0U == (usbPhyBase->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK))
+ {
+ }
+#endif
+ if (NULL != phyConfig)
+ {
+ /* Decode to trim the nominal 17.78mA current source for the High Speed TX drivers on USB_DP and USB_DM. */
+ usbPhyBase->TX =
+ ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
+ (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) |
+ USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM)));
+ }
+#endif
+
+ return (uint8_t)kStatus_USB_Success;
+}
+
+/*!
+ * @brief ehci phy de-initialization.
+ *
+ * This function de-initialize ehci phy IP.
+ *
+ * @param[in] controllerId ehci controller id, please reference to #usb_controller_index_t.
+ */
+void USB_EhciPhyDeinit(uint8_t controllerId)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+ USBPHY_Type *usbPhyBase;
+
+ usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+ if (NULL == usbPhyBase)
+ {
+ return;
+ }
+#if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT)))
+ usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK; /* power down PLL */
+ usbPhyBase->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* disable USB clock output from USB PHY PLL */
+#endif
+ usbPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* set to 1U to gate clocks */
+#endif
+}
+
+/*!
+ * @brief ehci phy disconnect detection enable or disable.
+ *
+ * This function enable/disable host ehci disconnect detection.
+ *
+ * @param[in] controllerId ehci controller id, please reference to #usb_controller_index_t.
+ * @param[in] enable
+ * 1U - enable;
+ * 0U - disable;
+ */
+void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable)
+{
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+ USBPHY_Type *usbPhyBase;
+
+ usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+ if (NULL == usbPhyBase)
+ {
+ return;
+ }
+
+ if (0U != enable)
+ {
+ usbPhyBase->CTRL |= USBPHY_CTRL_ENHOSTDISCONDETECT_MASK;
+ }
+ else
+ {
+ usbPhyBase->CTRL &= (~USBPHY_CTRL_ENHOSTDISCONDETECT_MASK);
+ }
+#endif
+}
+
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+#if ((defined FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE) && (FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE > 0U))
+void USB_PhyDeviceForceEnterFSMode(uint8_t controllerId, uint8_t enable)
+{
+ USBPHY_Type *usbPhyBase;
+
+ usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId);
+ if (NULL == usbPhyBase)
+ {
+ return;
+ }
+
+ if (0U != enable)
+ {
+ uint32_t delay = 1000000;
+ usbPhyBase->DEBUG0_CLR = USBPHY_DEBUG0_CLKGATE_MASK;
+ while ((0U != (usbPhyBase->USB1_VBUS_DET_STAT & USBPHY_USB1_VBUS_DET_STAT_VBUS_VALID_3V_MASK)) && (0U != delay))
+ {
+ delay--;
+ }
+ usbPhyBase->USB1_LOOPBACK_SET = USBPHY_USB1_LOOPBACK_UTMI_TESTSTART_MASK;
+ }
+ else
+ {
+ usbPhyBase->DEBUG0_CLR = USBPHY_DEBUG0_CLKGATE_MASK;
+ usbPhyBase->USB1_LOOPBACK_CLR = USBPHY_USB1_LOOPBACK_UTMI_TESTSTART_MASK;
+ }
+}
+#endif
+#endif
+#else
void *USB_EhciPhyGetBase(uint8_t controllerId)
{
void *usbPhyBase = NULL;
@@ -238,3 +505,4 @@ void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable)
}
#endif
}
+#endif \ No newline at end of file
diff --git a/bsp/imxrt/libraries/drivers/usb/phy/usb_phy.h b/bsp/imxrt/libraries/drivers/usb/phy/usb_phy.h
index 0409f9c8b9..278dc8fe20 100644
--- a/bsp/imxrt/libraries/drivers/usb/phy/usb_phy.h
+++ b/bsp/imxrt/libraries/drivers/usb/phy/usb_phy.h
@@ -105,7 +105,23 @@ extern void USB_EhciPhyDeinit(uint8_t controllerId);
* 0U - disable;
*/
extern void USB_EhcihostPhyDisconnectDetectCmd(uint8_t controllerId, uint8_t enable);
-
+#ifdef SOC_IMXRT1170_SERIES
+#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
+#if ((defined FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE) && (FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE > 0U))
+/*!
+ * @brief Force the PHY enter FS Mode
+ *
+ * on RT500 and RT600, the device doesn't enter FS Mode after vbus is invalide and the controller works as HS.
+ *
+ * @param[in] controllerId EHCI controller ID; See #usb_controller_index_t.
+ * @param[in] enable
+ * 1U - enable;
+ * 0U - disable;
+ */
+extern void USB_PhyDeviceForceEnterFSMode(uint8_t controllerId, uint8_t enable);
+#endif
+#endif
+#endif
#if defined(__cplusplus)
}
#endif