mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-21 10:25:54 +08:00
更新硬件SDK
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
|
||||
* File name: adc.h
|
||||
* Description: EC618 adc driver header file
|
||||
* History:
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _ADC_EC618_H
|
||||
#define _ADC_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup adc_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/** \brief List of ADC clock source divider */
|
||||
typedef enum
|
||||
{
|
||||
ADC_CLOCK_DIV_4 = 0U, /**< ADC clock is divided by 4 from input clock */
|
||||
ADC_CLOCK_DIV_8 = 1U, /**< ADC clock is divided by 8 from input clock */
|
||||
ADC_CLOCK_DIV_16 = 2U, /**< ADC clock is divided by 16 from input clock */
|
||||
} AdcClockDivider_e;
|
||||
|
||||
/** \brief List of ADC channels */
|
||||
typedef enum
|
||||
{
|
||||
ADC_CHANNEL_THERMAL = 0U, /**< ADC Thermal channel */
|
||||
ADC_CHANNEL_VBAT = 1U, /**< ADC VBAT channel */
|
||||
ADC_CHANNEL_AIO4 = 2U, /**< ADC AIO4 channel */
|
||||
ADC_CHANNEL_AIO3 = 3U, /**< ADC AIO3 channel */
|
||||
ADC_CHANNEL_AIO2 = 4U, /**< ADC AIO2 channel */
|
||||
ADC_CHANNEL_AIO1 = 5U, /**< ADC AIO1 channel */
|
||||
} AdcChannel_e;
|
||||
|
||||
/** \brief List of AIO resdiv select options */
|
||||
typedef enum
|
||||
{
|
||||
ADC_AIO_RESDIV_RATIO_1 = 0U, /**< ADC AIO RESDIV select as VIN */
|
||||
ADC_AIO_RESDIV_RATIO_14OVER16 = 1U, /**< ADC AIO RESDIV select as 14/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_12OVER16 = 2U, /**< ADC AIO RESDIV select as 12/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_10OVER16 = 3U, /**< ADC AIO RESDIV select as 10/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_8OVER16 = 4U, /**< ADC AIO RESDIV select as 8/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_7OVER16 = 5U, /**< ADC AIO RESDIV select as 7/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_6OVER16 = 6U, /**< ADC AIO RESDIV select as 6/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_5OVER16 = 7U, /**< ADC AIO RESDIV select as 5/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_4OVER16 = 8U, /**< ADC AIO RESDIV select as 4/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_3OVER16 = 9U, /**< ADC AIO RESDIV select as 3/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_2OVER16 = 10U, /**< ADC AIO RESDIV select as 2/16 VIN */
|
||||
ADC_AIO_RESDIV_RATIO_1OVER16 = 11U, /**< ADC AIO RESDIV select as 1/16 VIN */
|
||||
ADC_AIO_RESDIV_BYPASS = 12U, /**< BYPASS the whole ADC AIO RESDIV network(direct input) */
|
||||
} AdcAioResDiv_e;
|
||||
|
||||
/** \brief List of VBAT resdiv select options */
|
||||
typedef enum
|
||||
{
|
||||
ADC_VBAT_RESDIV_RATIO_8OVER16 = 0U, /**< ADC AIO RESDIV select as 8/16 VBAT */
|
||||
ADC_VBAT_RESDIV_RATIO_7OVER16 = 1U, /**< ADC AIO RESDIV select as 7/16 VBAT */
|
||||
ADC_VBAT_RESDIV_RATIO_6OVER16 = 2U, /**< ADC AIO RESDIV select as 6/16 VBAT */
|
||||
ADC_VBAT_RESDIV_RATIO_5OVER16 = 3U, /**< ADC AIO RESDIV select as 5/16 VBAT */
|
||||
ADC_VBAT_RESDIV_RATIO_4OVER16 = 4U, /**< ADC AIO RESDIV select as 4/16 VBAT */
|
||||
ADC_VBAT_RESDIV_RATIO_3OVER16 = 5U, /**< ADC AIO RESDIV select as 3/16 VBAT */
|
||||
ADC_VBAT_RESDIV_RATIO_2OVER16 = 6U, /**< ADC AIO RESDIV select as 2/16 VBAT */
|
||||
ADC_VBAT_RESDIV_RATIO_1OVER16 = 7U, /**< ADC AIO RESDIV select as 1/16 VBAT */
|
||||
} AdcVbatResdiv_e;
|
||||
|
||||
/** \brief ADC channel configuration */
|
||||
typedef union
|
||||
{
|
||||
AdcAioResDiv_e aioResDiv; /**< resdiv setting, valid only for AIO channel */
|
||||
AdcVbatResdiv_e vbatResDiv; /**< resdiv setting, valid only for VBAT channel */
|
||||
} AdcChannelConfig_t;
|
||||
|
||||
/** \brief ADC configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
AdcClockDivider_e clockDivider; /**< ADC work clock source divider setting */
|
||||
AdcChannelConfig_t channelConfig; /**< ADC channel configuration */
|
||||
} AdcConfig_t;
|
||||
|
||||
/** \brief List of ADC channel users, used to compose logical channel combining with ADC physical channel
|
||||
each channel can be occupied by these users at the same time, conversion request gets serviced one by one in FIFO ordering.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ADC_USER_PHY = 0U, /**< Internal user ID for PHY */
|
||||
ADC_USER_PLAT = 1U, /**< Internal user ID for PLAT */
|
||||
ADC_USER_APP = 2U, /**< user ID for APP */
|
||||
ADC_USER_MAX /**< Total number of users for one channel */
|
||||
} AdcUser_t;
|
||||
|
||||
|
||||
/**
|
||||
\brief Defines callback function prototype.
|
||||
Callback function will be called in ADC interrupt service routine after sample completes
|
||||
\param result ADC sample result
|
||||
*/
|
||||
typedef void (*adcCallback_t)(uint32_t result);
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \name ADC Configuration */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void ADC_getDefaultConfig(AdcConfig_t *config)
|
||||
\brief Gets the ADC default configuartion.
|
||||
This function sets the configuration structure to default values as below:
|
||||
\code
|
||||
config->clockDivider = ADC_CLOCK_DIV_4;
|
||||
config->channalConfig.aioResDiv = ADC_AIO_RESDIV_BYPASS; // Note: channelConfig field is union
|
||||
\endcode
|
||||
|
||||
\param[in] config Pointer to ADC configuration structure
|
||||
*/
|
||||
void ADC_getDefaultConfig(AdcConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn int32_t ADC_channelInit(AdcChannel_e channel, const AdcConfig_t *config, adcCallback_t callback)
|
||||
\brief Initialize ADC specific channel
|
||||
\param[in] channel ADC physical channel to be configured
|
||||
\param[in] userID user ID of specific channel, customer user is assigned with ADC_USER_APP, used to compose logical channel combining with channel parameter
|
||||
\param[in] config Pointer to ADC configuration
|
||||
\param[in] callback Function to be called when ADC conversion completes
|
||||
\return 0 on success, -1 for parameter check error, -2 for AIO1 channel conflict(vref output has been enabled)
|
||||
*/
|
||||
int32_t ADC_channelInit(AdcChannel_e channel, AdcUser_t userID, const AdcConfig_t *config, adcCallback_t callback);
|
||||
|
||||
/**
|
||||
\fn void ADC_channelDeInit(AdcChannel_e channel)
|
||||
\brief Deinitialize ADC channel
|
||||
\param[in] channel physical channel to be de-initialized, configuration of specific logical channel is invalid after this API call.
|
||||
\param[in] userID user ID of specific channel, customer user is assigned with ADC_USER_APP, used to compose logical channel combining with channel parameter
|
||||
*/
|
||||
void ADC_channelDeInit(AdcChannel_e channel, AdcUser_t userID);
|
||||
|
||||
/**
|
||||
\fn void ADC_startConversion(uint32_t channels)
|
||||
\brief Starts ADC conversion. Conversion is performed imediately when ADC is free, otherwise, the start request is put into a request queue and will be serviced later.
|
||||
|
||||
\param[in] channel ADC physical channel to converse
|
||||
\param[in] userID user ID of specific channel, customer user is assigned with ADC_USER_APP, used to compose logical channel combining with channel parameter
|
||||
\return 0 on success, -1 if request queue is full, -2 if channel has not been initialized yet
|
||||
*/
|
||||
int32_t ADC_startConversion(AdcChannel_e channel, AdcUser_t userID);
|
||||
|
||||
/**
|
||||
\fn int32_t ADC_enableVrefOutput(void)
|
||||
\brief Enable vref output through AIO1
|
||||
\return 0 on success, -2 for AIO1 channel conflict(AIO1 input has been enabled)
|
||||
\note this feature and AIO1 input is mutual exclusive
|
||||
*/
|
||||
int32_t ADC_enableVrefOutput(void);
|
||||
|
||||
/**
|
||||
\fn void ADC_disableVrefOutput(void)
|
||||
\brief Disable vref output through AIO1
|
||||
*/
|
||||
void ADC_disableVrefOutput(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ADC_EC618_H */
|
||||
@@ -0,0 +1,117 @@
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
*(C) Copyright 2018 AirM2M International Ltd.
|
||||
|
||||
* All Rights Reserved
|
||||
|
||||
******************************************************************************
|
||||
* Filename: alarm.h
|
||||
*
|
||||
* Description: header of alarm.c, hw config for hal_alarm
|
||||
*
|
||||
* History: 2021.05.12 initiated by Zhao Weiqi
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef CHIP_ALARM_H
|
||||
#define CHIP_ALARM_H
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* INCLUDES *
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* MACROS *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* DATA TYPE DEFINITION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* GLOBAL FUNCTIONS DECLEARATION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief alarmVBatHwInit
|
||||
* @details configure and start vbat alarm
|
||||
*
|
||||
* @param voltThd100: set the threshold
|
||||
* @return null
|
||||
*/
|
||||
void alarmVBatHwInit(uint16_t voltThd100);
|
||||
/**
|
||||
* @brief alarmThmHwInit
|
||||
* @details configure and start themral alarm
|
||||
*
|
||||
* @param thmThd: set the threshold
|
||||
* @param range: set the hysteresis range
|
||||
* @return null
|
||||
*/
|
||||
void alarmThmHwInit(uint8_t thmThd, uint8_t range);
|
||||
/**
|
||||
* @brief alarmVBatHwDeinit
|
||||
* @details stop vbat alarm
|
||||
|
||||
* @return null
|
||||
*/
|
||||
void alarmVBatHwDeinit(void);
|
||||
/**
|
||||
* @brief alarmThmHwDeinit
|
||||
* @details stop thermal alarm
|
||||
|
||||
* @return null
|
||||
*/
|
||||
void alarmThmHwDeinit(void);
|
||||
/**
|
||||
* @brief alarmVBatGetIntIndicate
|
||||
* @details stop thermal alarm
|
||||
|
||||
* @return 1: high 0: low
|
||||
*/
|
||||
uint8_t alarmVBatGetIntIndicate(void);
|
||||
/**
|
||||
* @brief alarmThmGetIntIndicate
|
||||
* @details stop thermal alarm
|
||||
|
||||
* @return 1: high 0: low
|
||||
*/
|
||||
uint8_t alarmThmGetIntIndicate(void);
|
||||
/**
|
||||
* @brief alarmThmDisableInAdc
|
||||
* @details stop thermal alarm, call in auxadc when sample the thm channel
|
||||
|
||||
* @return 1: disable operation down 0: do nothing
|
||||
*/
|
||||
bool alarmThmDisableInAdc(void);
|
||||
/**
|
||||
* @brief alarmThmEnableInAdc
|
||||
* @details restart thermal alarm, call in auxadc when sample the thm channel
|
||||
|
||||
* @return 1: enable operation down 0: do nothing
|
||||
*/
|
||||
bool alarmThmEnableInAdc(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
#ifndef _APMU_PERIPHERAL_
|
||||
#define _APMU_PERIPHERAL_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void apmuPeriUsbEnterStartProc(bool forceCfgPwrDown);
|
||||
|
||||
void apmuPeriUsbEnterAbortProc(bool forceCfgPwrDown);
|
||||
|
||||
void apmuPeriUsbSusp2VbusTblGuardDlyChk(uint32_t cur_tick);
|
||||
|
||||
void apmuPeriUsbSusp2HibGuardDlyChk(uint32_t cur_tick);
|
||||
|
||||
void apmuPeriUsbSleep1LateRecoverFlow(bool sleepSuccess);
|
||||
|
||||
void apmuPeriUsbSleep1PreRecoverFlow(bool sleepSuccess);
|
||||
|
||||
bool apmuPeriLpuartPreSleepProcess(void);
|
||||
|
||||
bool apmuPeriLpuartIsRxActive(void);
|
||||
|
||||
void apmuPeriStartWFITimer(uint32_t ms);
|
||||
|
||||
void apmuPeriDeleteWFITimer(void);
|
||||
|
||||
void apmuPeriDeleteCPTimer(void);
|
||||
|
||||
void apmuPeriClearCPTimerInterrupt(void);
|
||||
|
||||
void apmuPeriStartCPTimer(uint32_t cpStartTime, void* expFunc);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: cache.h
|
||||
* Description: EC618 cache controller driver header file
|
||||
* History: Rev1.0 2018-07-12
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _CACHE_EC618_H
|
||||
#define _CACHE_EC618_H
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup icache_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
\fn void EnableICache(void)
|
||||
\brief Enables Instrution cache
|
||||
\return void
|
||||
*/
|
||||
void EnableICache(void);
|
||||
/**
|
||||
\fn void DisableICache(void)
|
||||
\brief Disables Instrution cache
|
||||
\return void
|
||||
*/
|
||||
void DisableICache(void);
|
||||
/**
|
||||
\fn bool IsICacheEnabled(void)
|
||||
\brief Check whether cache is enabled
|
||||
\return enabled or not
|
||||
*/
|
||||
bool IsICacheEnabled(void);
|
||||
|
||||
/** \}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CACHE_EC618_H */
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
*(C) Copyright 2018 AirM2M International Ltd.
|
||||
|
||||
* All Rights Reserved
|
||||
|
||||
******************************************************************************
|
||||
* Filename: charge.h
|
||||
*
|
||||
* Description: header of charge.c. api for charge status detect
|
||||
*
|
||||
* History: 2021.05.07 initiated by Zhao Weiqi
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef CHARGE_H
|
||||
#define CHARGE_H
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* INCLUDES *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* MACROS *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* DATA TYPE DEFINITION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef enum
|
||||
{
|
||||
CHARGE_STATUS_DISCONNECT = 0,
|
||||
CHARGE_STATUS_CHARGING = 1,
|
||||
CHARGE_STATUS_FINISH = 2,
|
||||
}chargeStatus_e;
|
||||
|
||||
typedef void(* chargeStatusCb)(chargeStatus_e status);
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* GLOBAL FUNCTIONS DECLEARATION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief chargeGetCurStatus
|
||||
* @details Get current charge status
|
||||
*
|
||||
* @return charge status:
|
||||
CHARGE_STATUS_DISCONNECT = 0,
|
||||
CHARGE_STATUS_CHARGING = 1,
|
||||
CHARGE_STATUS_FINISH = 2,
|
||||
*/
|
||||
chargeStatus_e chargeGetCurStatus(void);
|
||||
/**
|
||||
* @brief chargeHwInit
|
||||
* @details init hardware
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void chargeHwInit(void);
|
||||
/**
|
||||
* @brief chargeHwDeinit
|
||||
* @details deinit hardware
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void chargeHwDeinit(void);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,509 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
|
||||
* File name: clock.h
|
||||
* Description: EC618 clock driver header file
|
||||
* History: Rev1.0 2019-02-20
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _CLOCK_EC618_H
|
||||
#define _CLOCK_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
|
||||
/**
|
||||
\addtogroup clock_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
#ifndef __CLOCK_DECLARATION_DEFINED__
|
||||
#define __CLOCK_DECLARATION_DEFINED__
|
||||
|
||||
#include "gpr_common.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* clock ID with clock source select start */
|
||||
CLK_CC = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 0),
|
||||
CLK_APB_MP = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 1),
|
||||
CLK_APB_XP = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 2),
|
||||
CLK_SMP = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 3),
|
||||
CLK_SYSTICK = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 4),
|
||||
|
||||
FCLK_UART0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 0, 5),
|
||||
FCLK_UART1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 1, 6),
|
||||
FCLK_UART2 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 2, 7),
|
||||
FCLK_SPI0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 3, 8),
|
||||
FCLK_SPI1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 4, 9),
|
||||
FCLK_I2S0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 5, 10),
|
||||
FCLK_I2S1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 6, 11),
|
||||
|
||||
FCLK_WDG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 0, 12),
|
||||
FCLK_TIMER0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 1, 13),
|
||||
FCLK_TIMER1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 2, 14),
|
||||
FCLK_TIMER2 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 3, 15),
|
||||
FCLK_TIMER3 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 4, 16),
|
||||
FCLK_TIMER4 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 5, 17),
|
||||
FCLK_TIMER5 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 6, 18),
|
||||
FCLK_I2C0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 7, 19),
|
||||
FCLK_I2C1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 8, 20),
|
||||
FCLK_USIM0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 9, 21),
|
||||
FCLK_USIM1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 10, 22),
|
||||
FCLK_KPC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 11, 23),
|
||||
|
||||
CLK_FLASH = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 9, 24),
|
||||
CLK_PSRAM = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 10, 25),
|
||||
|
||||
CLK_CLKCAL = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 5, 26),
|
||||
|
||||
/* clock ID with clock source select end */
|
||||
|
||||
/* root clock */
|
||||
CLK_MF = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 27),
|
||||
CLK_32K = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 28),
|
||||
CLK_HF408M = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 29),
|
||||
|
||||
CLK_HF204M = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 0, 30),
|
||||
CLK_HF102M = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 1, 31),
|
||||
CLK_HF51M = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 2, 32),
|
||||
CLK_32K_GATED = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 3, 33),
|
||||
CLK_MF_GATED = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 4, 34),
|
||||
CLK_CC_MP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 5, 35),
|
||||
CLK_CC_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 6, 36),
|
||||
CLK_CC_CP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 7, 37),
|
||||
CLK_AON = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 8, 38),
|
||||
|
||||
CLK_SMP_MP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 11, 39),
|
||||
|
||||
MFAB_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 16, 40),
|
||||
AFBBR_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 17, 41),
|
||||
|
||||
MSMB_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 19, 42),
|
||||
FLASH_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 20, 43),
|
||||
PSRAM_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 21, 44),
|
||||
ULOG_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 22, 45),
|
||||
UTFC_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 23, 46),
|
||||
ULDP_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 24, 47),
|
||||
|
||||
USBC_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 26, 48),
|
||||
USBC_PMU_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 27, 49),
|
||||
USBC_REF_CLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 28, 50),
|
||||
USBP_REF_CLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 29, 51),
|
||||
USBC_UTMI_CLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 30, 52),
|
||||
|
||||
|
||||
CLK_DAP_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 0, 53),
|
||||
CLK_TRACE_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 1, 54),
|
||||
CLK_SYSTICK_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 2, 55),
|
||||
CLK_APB_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 3, 56),
|
||||
CLK_SMP_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 4, 57),
|
||||
|
||||
PCLK_SIPC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 1, 58),
|
||||
PCLK_AON = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 2, 59),
|
||||
PCLK_CPMU = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 3, 60),
|
||||
PCLK_PMDIG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 4, 61),
|
||||
PCLK_RFDIG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 5, 62),
|
||||
PCLK_PAD = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 6, 63),
|
||||
PCLK_GPIO = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 7, 64),
|
||||
PCLK_FUSE = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 8, 65),
|
||||
PCLK_TRNG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 9, 66),
|
||||
PCLK_USBP = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 10, 67),
|
||||
PCLK_LPUC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 11, 68),
|
||||
PCLK_UART0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 12, 69),
|
||||
PCLK_UART1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 13, 70),
|
||||
PCLK_UART2 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 14, 71),
|
||||
PCLK_SPI0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 15, 72),
|
||||
PCLK_SPI1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 16, 73),
|
||||
PCLK_I2S0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 17, 74),
|
||||
PCLK_I2S1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 18, 75),
|
||||
|
||||
|
||||
PCLK_WDG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 0, 76),
|
||||
PCLK_TIMER0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 1, 77),
|
||||
PCLK_TIMER1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 2, 78),
|
||||
PCLK_TIMER2 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 3, 79),
|
||||
PCLK_TIMER3 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 4, 80),
|
||||
PCLK_TIMER4 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 5, 81),
|
||||
PCLK_TIMER5 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 6, 82),
|
||||
PCLK_IPC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 7, 83),
|
||||
PCLK_I2C0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 8, 84),
|
||||
PCLK_I2C1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 9, 85),
|
||||
PCLK_USIM0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 10, 86),
|
||||
PCLK_USIM1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 11, 87),
|
||||
PCLK_KPC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 12, 88),
|
||||
PCLK_ONEW = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 13, 89),
|
||||
|
||||
|
||||
TOP_PBRG_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_TOP_CLKEN_REG_INDEX, 0, 90),
|
||||
TOP_PBRG_PCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_TOP_CLKEN_REG_INDEX, 1, 91),
|
||||
TOP_GPR_PCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_TOP_CLKEN_REG_INDEX, 2, 92),
|
||||
|
||||
TRACE_CLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 1, 93),
|
||||
ETM_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 2, 94),
|
||||
ROMTABLE_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 3, 95),
|
||||
TPIU_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 4, 96),
|
||||
CACHE_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 5, 97),
|
||||
FABSUB_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 6, 98),
|
||||
SBU_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 7, 99),
|
||||
PBRG_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 8, 100),
|
||||
SPIS_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 9, 101),
|
||||
XIC_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 10, 102),
|
||||
ULOG_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 11, 103),
|
||||
TMU_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 12, 104),
|
||||
SCT_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 13, 105),
|
||||
|
||||
UTFC_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 16, 106),
|
||||
ULDP_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 17, 107),
|
||||
SCT_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 18, 108),
|
||||
|
||||
INVALID_CLK = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 109)
|
||||
} ClockId_e;
|
||||
|
||||
|
||||
/** \brief List of all configurable module's functional clock sources */
|
||||
typedef enum
|
||||
{
|
||||
// top clk sel
|
||||
|
||||
/** Core clock sourced from 26M */
|
||||
CLK_CC_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_CC), 0, CLK_MF),
|
||||
/** Core clock sourced from 204M */
|
||||
CLK_CC_SEL_204M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_CC), 1, CLK_HF204M),
|
||||
/** Core clock sourced from 102M */
|
||||
CLK_CC_SEL_102M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_CC), 2, CLK_HF102M),
|
||||
/** Core clock sourced from 32K */
|
||||
CLK_CC_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_CC), 3, CLK_32K),
|
||||
|
||||
|
||||
/** APB MP clock sourced from 26M */
|
||||
CLK_APB_MP_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_APB_MP), 0, CLK_MF),
|
||||
/** APB MP clock sourced from 51M */
|
||||
CLK_APB_MP_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_APB_MP), 1U, CLK_HF51M),
|
||||
|
||||
/** APB XP clock sourced from 26M */
|
||||
CLK_APB_XP_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_APB_XP), 0, CLK_MF),
|
||||
/** APB XP sourced from 51M */
|
||||
CLK_APB_XP_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_APB_XP), 1U, CLK_HF51M),
|
||||
|
||||
/** Systick clock sourced from 32K */
|
||||
CLK_SYSTICK_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_SYSTICK), 0, CLK_32K),
|
||||
/** Systick clock sourced from 26M */
|
||||
CLK_SYSTICK_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_SYSTICK), 1U, CLK_MF),
|
||||
|
||||
// apb mp func clk sel
|
||||
|
||||
/** UART0 clock sourced from 26M */
|
||||
FCLK_UART0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART0), 0, CLK_MF_GATED),
|
||||
/** UART0 clock sourced from 51M */
|
||||
FCLK_UART0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART0), 1U, CLK_HF51M),
|
||||
|
||||
/** UART1 clock sourced from 26M */
|
||||
FCLK_UART1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART1), 0, CLK_MF_GATED),
|
||||
/** UART1 clock sourced from 51M */
|
||||
FCLK_UART1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART1), 1U, CLK_HF51M),
|
||||
|
||||
/** UART2 clock sourced from 26M */
|
||||
FCLK_UART2_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART2), 0, CLK_MF_GATED),
|
||||
/** UART2 clock sourced from 51M */
|
||||
FCLK_UART2_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART2), 1U, CLK_HF51M),
|
||||
|
||||
/** SPI0 clock sourced from 26M */
|
||||
FCLK_SPI0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_SPI0), 0, CLK_MF_GATED),
|
||||
/** SPI0 clock sourced from 51M */
|
||||
FCLK_SPI0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_SPI0), 1U, CLK_HF51M),
|
||||
|
||||
/** SPI1 clock sourced from 26M */
|
||||
FCLK_SPI1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_SPI1), 0, CLK_MF_GATED),
|
||||
/** SPI1 clock sourced from 51M */
|
||||
FCLK_SPI1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_SPI1), 1U, CLK_HF51M),
|
||||
|
||||
/** I2S0 clock sourced from 26M */
|
||||
FCLK_I2S0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2S0), 0, CLK_MF_GATED),
|
||||
/** I2S0 clock sourced from 51M */
|
||||
FCLK_I2S0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2S0), 1U, CLK_HF51M),
|
||||
|
||||
/** I2S1 clock sourced from 26M */
|
||||
FCLK_I2S1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2S1), 0, CLK_MF_GATED),
|
||||
/** I2S1 clock sourced from 51M */
|
||||
FCLK_I2S1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2S1), 1U, CLK_HF51M),
|
||||
|
||||
// apb ap func clk sel
|
||||
|
||||
/** WDG clock sourced from 32K */
|
||||
FCLK_WDG_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_WDG), 0, CLK_32K_GATED),
|
||||
/** WDG clock sourced from 26M */
|
||||
FCLK_WDG_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_WDG), 1U, CLK_MF_GATED),
|
||||
|
||||
/** TIMER0 clock sourced from 32K */
|
||||
FCLK_TIMER0_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER0), 0, CLK_32K_GATED),
|
||||
/** TIMER0 clock sourced from 26M */
|
||||
FCLK_TIMER0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER0), 1U, CLK_MF_GATED),
|
||||
|
||||
/** TIMER1 clock sourced from 32K */
|
||||
FCLK_TIMER1_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER1), 0, CLK_32K_GATED),
|
||||
/** TIMER1 clock sourced from 26M */
|
||||
FCLK_TIMER1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER1), 1U, CLK_MF_GATED),
|
||||
|
||||
/** TIMER2 clock sourced from 32K */
|
||||
FCLK_TIMER2_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER2), 0, CLK_32K_GATED),
|
||||
/** TIMER2 clock sourced from 26M */
|
||||
FCLK_TIMER2_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER2), 1U, CLK_MF_GATED),
|
||||
|
||||
/** TIMER3 clock sourced from 32K */
|
||||
FCLK_TIMER3_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER3), 0, CLK_32K_GATED),
|
||||
/** TIMER3 clock sourced from 26M */
|
||||
FCLK_TIMER3_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER3), 1U, CLK_MF_GATED),
|
||||
|
||||
/** TIMER4 clock sourced from 32K */
|
||||
FCLK_TIMER4_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER4), 0, CLK_32K_GATED),
|
||||
/** TIMER4 clock sourced from 26M */
|
||||
FCLK_TIMER4_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER4), 1U, CLK_MF_GATED),
|
||||
|
||||
/** TIMER5 clock sourced from 32K */
|
||||
FCLK_TIMER5_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER5), 0, CLK_32K_GATED),
|
||||
/** TIMER5 clock sourced from 26M */
|
||||
FCLK_TIMER5_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER5), 1U, CLK_MF_GATED),
|
||||
|
||||
/** I2C0 clock sourced from 26M */
|
||||
FCLK_I2C0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2C0), 0, CLK_MF_GATED),
|
||||
/** I2C0 clock sourced from 51M */
|
||||
FCLK_I2C0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2C0), 1U, CLK_HF51M),
|
||||
|
||||
/** I2C1 clock sourced from 26M */
|
||||
FCLK_I2C1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2C1), 0, CLK_MF_GATED),
|
||||
/** I2C1 clock sourced from 51M */
|
||||
FCLK_I2C1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2C1), 1U, CLK_HF51M),
|
||||
|
||||
/** USIM0 clock sourced from 26M */
|
||||
FCLK_USIM0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_USIM0), 0, CLK_MF_GATED),
|
||||
/** USIM0 clock sourced from 51M */
|
||||
FCLK_USIM0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_USIM0), 1U, CLK_HF51M),
|
||||
|
||||
/** USIM1 clock sourced from 26M */
|
||||
FCLK_USIM1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_USIM1), 0, CLK_MF_GATED),
|
||||
/** USIM1 clock sourced from 51M */
|
||||
FCLK_USIM1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_USIM1), 1U, CLK_HF51M),
|
||||
|
||||
/** KPC clock sourced from 26M */
|
||||
FCLK_KPC_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_KPC), 0, CLK_32K_GATED),
|
||||
/** KPC clock sourced from 51M */
|
||||
FCLK_KPC_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_KPC), 1U, CLK_MF_GATED),
|
||||
|
||||
} ClockSelect_e;
|
||||
|
||||
|
||||
#endif //__CLOCK_DECLARATION_DEFINED__
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \name Clock Configuration */
|
||||
/* \{ */
|
||||
|
||||
/**
|
||||
\fn int32_t CLOCK_clockEnable(ClockId_e id)
|
||||
\brief Enable clock for selected module
|
||||
\param[in] id clock item to enable
|
||||
\return ARM_DRIVER_OK if the setting is successful
|
||||
ARM_DRIVER_ERROR_PARAMETER on parameter check failure(setting is not available for specified clock id)
|
||||
*/
|
||||
int32_t CLOCK_clockEnable(ClockId_e id);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_clockReset(ClockId_e id)
|
||||
\brief Reset clock for selected module
|
||||
\param[in] id clock item to reset
|
||||
*/
|
||||
void CLOCK_clockReset(ClockId_e id);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_updateClockTreeElement(ClockId_e id, ClockId_e parentId, uint8_t enableCount)
|
||||
\brief Update clock tree node item value, interrnal used only
|
||||
\param[in] id clock item to update
|
||||
\param[in] parentId parent clock id
|
||||
\param[in] enableCount new enable count
|
||||
*/
|
||||
void CLOCK_updateClockTreeElement(ClockId_e id, ClockId_e parentId, uint8_t enableCount);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_clockDisable(ClockId_e id)
|
||||
\brief Disable clock for selected module
|
||||
\param[in] id clock item to disable
|
||||
*/
|
||||
void CLOCK_clockDisable(ClockId_e id);
|
||||
|
||||
/**
|
||||
\fn int32_t CLOCK_setClockSrc(ClockId_e id, ClockSelect_e select)
|
||||
\brief Set clock source for selected module
|
||||
\param[in] id clock item to set
|
||||
\param[in] select select one of clock sources \ref ClockSelect_e
|
||||
\return ARM_DRIVER_OK if the setting is successful
|
||||
ARM_DRIVER_ERROR_PARAMETER on parameter check failure(setting is not available for specified clock id)
|
||||
ARM_DRIVER_ERROR if specific clock has been enabled
|
||||
*/
|
||||
int32_t CLOCK_setClockSrc(ClockId_e id, ClockSelect_e select);
|
||||
|
||||
/**
|
||||
\fn int32_t CLOCK_setClockDiv(ClockId_e id, uint32 div)
|
||||
\brief Set clock divider for selected module
|
||||
\param[in] id clock item to set
|
||||
\param[in] div divider value
|
||||
\return ARM_DRIVER_OK if the setting is successful
|
||||
ARM_DRIVER_ERROR_PARAMETER on parameter check failure(setting is not available for specified clock id or div value is set to 0)
|
||||
ARM_DRIVER_ERROR if specific clock has been enabled
|
||||
*/
|
||||
int32_t CLOCK_setClockDiv(ClockId_e id, uint32_t div);
|
||||
|
||||
/**
|
||||
\fn uint32_t CLOCK_getClockFreq(ClockId_e id)
|
||||
\brief Get clock frequency for selected module
|
||||
\param[in] id clock item to get
|
||||
\return clock frequency in unit of HZ
|
||||
*/
|
||||
uint32_t CLOCK_getClockFreq(ClockId_e id);
|
||||
|
||||
/**
|
||||
\fn int32_t CLOCK_setFracDivConfig(FracDivConfig_t * config)
|
||||
\brief fracdiv clock config
|
||||
\param[in] config pointer to fracdiv setting
|
||||
\return ARM_DRIVER_OK if the setting is successful
|
||||
ARM_DRIVER_ERROR_PARAMETER on parameter check failure
|
||||
*/
|
||||
int32_t CLOCK_setFracDivConfig(FracDivConfig_t * config);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_fracDivOutCLkEnable(FracDivOutClkId_e id)
|
||||
\brief fracdiv out clock enable
|
||||
\param[in] id fracdiv out clock id
|
||||
*/
|
||||
void CLOCK_fracDivOutCLkEnable(FracDivOutClkId_e id);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_fracDivOutClkDisable(FracDivOutClkId_e id)
|
||||
\brief fracdiv out clock disable
|
||||
\param[in] id fracdiv out clock id
|
||||
*/
|
||||
void CLOCK_fracDivOutClkDisable(FracDivOutClkId_e id);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_setFracDivOutClkDiv(FracDivOutClkId_e id, uint8_t div)
|
||||
\brief set fracdiv out clock divider
|
||||
\param[in] id fracdiv out clock id
|
||||
\param[in] div divider ratio to set
|
||||
*/
|
||||
void CLOCK_setFracDivOutClkDiv(FracDivOutClkId_e id, uint8_t div);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_setBclkSrc(BclkId_e id, BclkSrc_e src)
|
||||
\brief select bclk source
|
||||
\param[in] id bclk id
|
||||
\param[in] src clock source to set
|
||||
*/
|
||||
void CLOCK_setBclkSrc(BclkId_e id, BclkSrc_e src);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_setBclkDiv(BclkId_e id, uint8_t div)
|
||||
\brief set bclk divider
|
||||
\param[in] id bclk id
|
||||
\param[in] div divider ratio to set
|
||||
*/
|
||||
void CLOCK_setBclkDiv(BclkId_e id, uint8_t div);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_bclkEnable(BclkId_e id)
|
||||
\brief enable bclk
|
||||
\param[in] id bclk id
|
||||
*/
|
||||
void CLOCK_bclkEnable(BclkId_e id);
|
||||
|
||||
|
||||
/**
|
||||
\fn void CLOCK_setMclkSrc(MclkId_e id, MclkSrc_e src)
|
||||
\brief select mclk source
|
||||
\param[in] id mclk id
|
||||
\param[in] src clock source to set
|
||||
*/
|
||||
void CLOCK_setMclkSrc(MclkId_e id, MclkSrc_e src);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_mclkEnable(MclkId_e id)
|
||||
\brief mclk enable
|
||||
\param[in] id mclk id
|
||||
*/
|
||||
void CLOCK_mclkEnable(MclkId_e id);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_mclkDisable(MclkId_e id)
|
||||
\brief mclk disable
|
||||
\param[in] id mclk id
|
||||
*/
|
||||
void CLOCK_mclkDisable(MclkId_e id);
|
||||
|
||||
/**
|
||||
\fn void CLOCK_setMclkDiv(MclkId_e id, uint8_t div)
|
||||
\brief set mclk divider
|
||||
\param[in] id mclk id
|
||||
\param[in] div divider ratio to set
|
||||
*/
|
||||
void CLOCK_setMclkDiv(MclkId_e id, uint8_t div);
|
||||
/** \} */
|
||||
|
||||
/** \name HAL Driver declaration */
|
||||
/* \{ */
|
||||
|
||||
extern int32_t GPR_setClockSrc(ClockId_e id, ClockSelect_e select);
|
||||
extern int32_t GPR_setClockDiv(ClockId_e id, uint32_t div);
|
||||
extern void GPR_clockEnable(ClockId_e id);
|
||||
extern void GPR_clockDisable(ClockId_e id);
|
||||
extern uint32_t GPR_getClockFreq(ClockId_e id);
|
||||
|
||||
extern void GPR_setFracDivConfig(FracDivConfig_t * config);
|
||||
extern void GPR_fracDivOutCLkEnable(FracDivOutClkId_e id);
|
||||
extern void GPR_fracDivOutClkDisable(FracDivOutClkId_e id);
|
||||
extern void GPR_setFracDivOutClkDiv(FracDivOutClkId_e id, uint8_t div);
|
||||
|
||||
extern void GPR_setBclkSrc(BclkId_e id, BclkSrc_e src);
|
||||
extern void GPR_setBclkDiv(BclkId_e id, uint8_t div);
|
||||
extern void GPR_BclkEnable(BclkId_e id);
|
||||
|
||||
|
||||
extern void GPR_setMclkSrc(MclkId_e id, MclkSrc_e src);
|
||||
extern void GPR_mclkEnable(MclkId_e id);
|
||||
extern void GPR_mclkDisable(MclkId_e id);
|
||||
extern void GPR_setMclkDiv(MclkId_e id, uint8_t div);
|
||||
|
||||
extern void GPR_swReset(ClockResetId_e id);
|
||||
extern void GPR_swResetModule(const ClockResetVector_t *v);
|
||||
extern void GPR_initialize(void);
|
||||
extern void GPR_setApbGprAcg( void );
|
||||
extern void GPR_lockUpActionCtrl(bool enable);
|
||||
extern uint32_t GPR_getCPLockUpResetCtrl(void);
|
||||
extern ApRstSource_e GPR_apGetRstSrc(void);
|
||||
extern CpRstSource_e GPR_cpGetRstSrc(void);
|
||||
extern void GPR_cpResetCfgSet(bool wdtRstEn, bool sysRstApb, bool lockupRstEn, bool cpAPmuRst);
|
||||
extern void GPR_setApbGprAcg( void );
|
||||
extern void GPR_bootSetting( void );
|
||||
void CLOCK_AssertChkBeforeSlp(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \}*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
/******************************************************************************
|
||||
|
||||
*(C) Copyright 2018 AirM2M International Ltd.
|
||||
|
||||
* All Rights Reserved
|
||||
|
||||
******************************************************************************
|
||||
* Filename:cpxip.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* INCLUDES *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CP_XIP_H
|
||||
#define CP_XIP_H
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* MACROS *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* DATA TYPE DEFINITION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* GLOBAL FUNCTIONS DECLEARATION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void CPXIP_Enable(void);
|
||||
uint8_t CPXIP_QSPI_Erase_Sector(uint32_t SectorAddress);
|
||||
uint8_t CPXIP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
|
||||
uint8_t CPXIP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
#ifndef BSP_CSPI_H
|
||||
#define BSP_CSPI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "ec618.h"
|
||||
#include "bsp.h"
|
||||
|
||||
#define CSPI_TRANSFER_TRUNK_SIZE 7680 ///< Each DMA descriptor data size, fixed to 7680byte
|
||||
|
||||
|
||||
typedef void (*cspiCbEvent_fn) (uint32_t event); ///< cspi callback event.
|
||||
|
||||
|
||||
/** \brief CSPI flags */
|
||||
#define CSPI_FLAG_INITIALIZED (1UL << 0) ///< CSPI initialized
|
||||
#define CSPI_FLAG_POWERED (1UL << 1) ///< CSPI powered on
|
||||
|
||||
|
||||
/** \brief CSPI DMA */
|
||||
typedef struct
|
||||
{
|
||||
DmaInstance_e rxInstance; ///< Receive DMA instance number
|
||||
int8_t rxCh; ///< Receive channel number
|
||||
uint8_t rxReq; ///< Receive DMA request number
|
||||
void (*rxCb)(uint32_t event); ///< Receive callback
|
||||
DmaDescriptor_t *descriptor; ///< Rx descriptor
|
||||
} cspiDma_t;
|
||||
|
||||
// CSPI PINS
|
||||
typedef const struct
|
||||
{
|
||||
PIN *mclk; ///< Main clk Pin identifier
|
||||
PIN *pclk; ///< Pixel clk Pin identifier
|
||||
PIN *cs; ///< Cs Pin identifier
|
||||
PIN *sdo0; ///< Din Pin identifier
|
||||
PIN *sdo1; ///< Dout Pin identifier
|
||||
} cspiPins_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t busy; ///< Transmitter/Receiver busy flag
|
||||
} cspiRteStats_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CAM_8W = 10, ///< 8w use 10 dma descriptor chain
|
||||
CAM_30W = 40, ///< 30w use 40 dma descriptor chain
|
||||
}camResolution_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CAM_6_5_M = 0, ///< camera 6.5M HZ
|
||||
CAM_13_M = 1, ///< camera 13M HZ
|
||||
CAM_25_5_M = 2, ///< camera 25.5M HZ
|
||||
CAM_24_M = 3, ///< camera 24M HZ
|
||||
CAM_20_M = 4, ///< camera 20M HZ
|
||||
}camFrequence_e;
|
||||
|
||||
|
||||
// CSPI information (Run-time)
|
||||
typedef struct
|
||||
{
|
||||
cspiCbEvent_fn cbEvent; ///< Event callback
|
||||
cspiRteStats_t status; ///< CSPI status flags
|
||||
uint8_t flags; ///< CSPI driver flags
|
||||
uint32_t busSpeed; ///< CSPI bus speed
|
||||
uint8_t dataWidth; ///< CSPI data bits select in unit of byte
|
||||
uint32_t targetAddr; ///< CSPI target address
|
||||
camResolution_e resolution; ///< Camera resolution
|
||||
} cspiInfo_t;
|
||||
|
||||
|
||||
// SPI Resources definition
|
||||
typedef struct
|
||||
{
|
||||
CSPI_TypeDef *reg; ///< SPI register pointer
|
||||
cspiPins_t pins; ///< SPI PINS configuration
|
||||
cspiDma_t *dma; ///< SPI DMA configuration pointer
|
||||
cspiInfo_t *info; ///< Run-Time Information
|
||||
} cspiRes_t;
|
||||
|
||||
|
||||
/**
|
||||
\brief General power states
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CSPI_POWER_OFF, ///< Power off: no operation possible
|
||||
CSPI_POWER_FULL ///< Power on: full operation at maximum performance
|
||||
} cspiPowerState_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t slaveModeEn : 1; ///< Slave Mode Enable
|
||||
uint32_t slotSize : 5; ///< Slot Size
|
||||
uint32_t wordSize : 5; ///< Word Size
|
||||
uint32_t alignMode : 1; ///< Align Mode
|
||||
uint32_t endianMode : 1; ///< Endian Mode
|
||||
uint32_t dataDly : 2; ///< Data Delay
|
||||
uint32_t txPad : 2; ///< Tx padding
|
||||
uint32_t rxSignExt : 1; ///< Rx Sign Entension
|
||||
uint32_t txPack : 2; ///< Tx Pack
|
||||
uint32_t rxPack : 2; ///< Rx Pack
|
||||
uint32_t txFifoEndianMode : 1; ///< Tx Fifo Endian Mode
|
||||
uint32_t rxFifoEndianMode : 1; ///< Rx Fifo Endian Mode
|
||||
}cspiDataFmt_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t slotEn : 3; ///< Slot Enable
|
||||
uint32_t slotNum : 8; ///< Slot Num
|
||||
}cspiSlotCtrl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bclkPolarity : 1; ///< Bclk Polarity
|
||||
uint32_t fsPolarity : 1; ///< Frame Synchronization Polarity
|
||||
uint32_t fsWidth : 6; ///< Frame Synchronization Width
|
||||
}cspiBclkFsCtrl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t rxDmaReqEn : 1; ///< Rx Dma Req Enable
|
||||
uint32_t txDmaReqEn : 1; ///< Tx Dma Req Enable
|
||||
uint32_t rxDmaTimeOutEn : 1; ///< Rx Dma Timeout Enable
|
||||
uint32_t dmaWorkWaitCycle : 5; ///< Dma Work Wait Cycle
|
||||
uint32_t rxDmaBurstSizeSub1 : 4; ///< Rx Dma Burst Size subtract 1
|
||||
uint32_t txDmaBurstSizeSub1 : 4; ///< Tx Dma Burst Size subtract 1
|
||||
uint32_t rxDmaThreadHold : 4; ///< Rx Dma Threadhold
|
||||
uint32_t txDmaThreadHold : 4; ///< Tx Dma Threadhold
|
||||
uint32_t rxFifoFlush : 1; ///< Rx Fifo flush
|
||||
uint32_t txFifoFlush : 1; ///< Tx Fifo flush
|
||||
}cspiDmaCtrl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t txUnderRunIntEn : 1; ///< Tx Underrun interrupt Enable
|
||||
uint32_t txDmaErrIntEn : 1; ///< Tx Dma Err Interrupt Enable
|
||||
uint32_t txDatIntEn : 1; ///< Tx Data Interrupt Enable
|
||||
uint32_t rxOverFlowIntEn : 1; ///< Rx Overflow Interrupt Enable
|
||||
uint32_t rxDmaErrIntEn : 1; ///< Rx Dma Err Interrupt Enable
|
||||
uint32_t rxDatIntEn : 1; ///< Rx Data Interrupt Enable
|
||||
uint32_t rxTimeOutIntEn : 1; ///< Rx Timeout Interrupt Enable
|
||||
uint32_t fsErrIntEn : 1; ///< Frame Start Interrupt Enable
|
||||
uint32_t frameStartIntEn : 1; ///< Frame End Interrupt Enable
|
||||
uint32_t frameEndIntEn : 1; ///< Frame End Interrupt Enable
|
||||
uint32_t cspiBusTimeOutIntEn : 1; ///< Not use
|
||||
uint32_t txIntThreshHold : 4; ///< Tx Interrupt Threadhold
|
||||
uint32_t rxIntThreshHold : 4; ///< Rx Interrupt Threadhold
|
||||
}cspiIntCtrl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t rxTimeOutCycle : 24; ///< Rx Timeout Cycle
|
||||
}cspiTimeOutCycle_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t txUnderRun : 1; ///< Tx Underrun
|
||||
uint32_t txDmaErr : 1; ///< Tx Dma Err
|
||||
uint32_t txDataRdy : 1; ///< Tx Data ready, readOnly
|
||||
uint32_t rxOverFlow : 1; ///< Rx OverFlow
|
||||
uint32_t rxDmaErr : 1; ///< Rx Dma Err
|
||||
uint32_t rxDataRdy : 1; ///< Rx Data ready, readOnly
|
||||
uint32_t rxFifoTimeOut : 1; ///< Rx Fifo timeout
|
||||
uint32_t fsErr : 4; ///< Frame synchronization Err
|
||||
uint32_t frameStart : 1; ///< Frame start
|
||||
uint32_t frameEnd : 1; ///< Frame end
|
||||
uint32_t txFifoLevel : 6; ///< Tx Fifo Level, readOnly
|
||||
uint32_t rxFifoLevel : 6; ///< Rx Fifo level, readOnly
|
||||
uint32_t cspiBusTimeOut : 1; ///< Cspi Bus timeout
|
||||
}cspiStats_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t enable : 1; ///< Enable
|
||||
uint32_t csEn : 1; ///< CS signal check
|
||||
uint32_t rxWid : 1; ///< Rx Width
|
||||
uint32_t rxdSeq : 1; ///< Rx Sequence
|
||||
uint32_t cpol : 1; ///< SPI polarity
|
||||
uint32_t cpha : 1; ///< SPI phase
|
||||
uint32_t frameProcEn : 1; ///< Frame Process Enable
|
||||
uint32_t fillYonly : 1; ///< Fill Y Only
|
||||
uint32_t hwInitEn : 1; ///< HW Init Enable
|
||||
uint32_t lsCheckEn : 1; ///< Line Start Check Enable
|
||||
uint32_t dpCheckEn : 1; ///< Data Pcket Check Enable
|
||||
uint32_t frameProcInitEn : 1; ///< Frame Process Init Enable
|
||||
uint32_t rowScaleRatio : 4; ///< Row Scale Ratio
|
||||
uint32_t colScaleRatio : 4; ///< Column Scale Ratio
|
||||
uint32_t scaleBytes : 2; ///< Scale Bytes
|
||||
}cspiCtrl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t autoCgEn : 1; ///< Auto Configure Enable
|
||||
}cspiAutoCgCtrl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t cspiBusTimeOutCycle : 24; ///< Cspi Bus Timeout Cycle
|
||||
uint32_t dataId : 8; ///< Data Indication, readOnly
|
||||
}cspiFrameInfo0_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t cspiInit : 1; ///< Cspi Init
|
||||
}cspiInit_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief Cspi control bits.
|
||||
*/
|
||||
#define CSPI_CTRL_TRANSABORT (1UL << 0) ///< CSPI trans abort
|
||||
#define CSPI_CTRL_BUS_SPEED (1UL << 1) ///< CSPI trans abort
|
||||
#define CSPI_CTRL_DATA_BITS (1UL << 2) ///< CSPI trans abort
|
||||
#define CSPI_CTRL_DATA_FORMAT (1UL << 3) ///< CSPI data format
|
||||
#define CSPI_CTRL_SLOT_CTRL (1UL << 4) ///< CSPI slot ctrl
|
||||
#define CSPI_CTRL_BCLK_FS_CTRL (1UL << 5) ///< CSPI bclk fs ctrl
|
||||
#define CSPI_CTRL_DMA_CTRL (1UL << 6) ///< CSPI dma ctrl
|
||||
#define CSPI_CTRL_INT_CTRL (1UL << 7) ///< CSPI int ctrl
|
||||
#define CSPI_CTRL_TIMEOUT_CYCLE (1UL << 8) ///< CSPI timeout cycle
|
||||
#define CSPI_CTRL_STATUS (1UL << 9) ///< CSPI status
|
||||
#define CSPI_CTRL_CSPICTL (1UL << 10) ///< CSPI control
|
||||
#define CSPI_CTRL_AUTO_CG_CTRL (1UL << 11) ///< CSPI auto cg ctrl
|
||||
#define CSPI_CTRL_FRAME_INFO0 (1UL << 12) ///< CSPI frame info0
|
||||
#define CSPI_CTRL_INIT (1UL << 13) ///< CSPI init
|
||||
#define CSPI_CTRL_RXTOR (1UL << 14) ///< CSPI rx timeout cycle
|
||||
#define CSPI_CTRL_MEM_ADDR (1UL << 15) ///< CSPI memory addr set
|
||||
#define CSPI_CTRL_FLUSH_RX_FIFO (1UL << 16) ///< Flush rx fifo
|
||||
#define CSPI_CTRL_START_STOP (1UL << 17) ///< Start or stop cspi
|
||||
#define CSPI_CTRL_RESOLUTION_SET (1UL << 18) ///< Camera resolution set
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief Access structure of the CSPI Driver.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int32_t (*init) (cspiCbEvent_fn cb_event); ///< Initialize CSPI Interface.
|
||||
int32_t (*deInit) (void); ///< De-initialize CSPI Interface.
|
||||
int32_t (*powerCtrl) (cspiPowerState_e state); ///< Control CSPI Interface Power.
|
||||
int32_t (*recv) (void); ///< Open dma to receive data.
|
||||
int32_t (*ctrl) (uint32_t control, uint32_t arg); ///< Control CSPI Interface.
|
||||
} const cspiDrvInterface_t;
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: dma.h
|
||||
* Description: EC618 dma controller driver header file
|
||||
* History: Rev1.0 2018-08-08
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _DMA_EC618_H
|
||||
#define _DMA_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup dma_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/** \brief List of DMA source/target address increment control options */
|
||||
typedef enum
|
||||
{
|
||||
DMA_ADDRESS_INCREMENT_NONE = 0, /**< Increment neither source or target address */
|
||||
DMA_ADDRESS_INCREMENT_SOURCE = 1U, /**< Increment source address */
|
||||
DMA_ADDRESS_INCREMENT_TARGET = 2U, /**< Increment target address */
|
||||
DMA_ADDRESS_INCREMENT_BOTH = 3U, /**< Increment both source and target address */
|
||||
} DmaAddressIncrement_e;
|
||||
|
||||
/** \brief List of DMA flow control options */
|
||||
typedef enum
|
||||
{
|
||||
DMA_FLOW_CONTROL_NONE = 0U, /**< No flow control */
|
||||
DMA_FLOW_CONTROL_SOURCE = 1U, /**< Only source */
|
||||
DMA_FLOW_CONTROL_TARGET = 2U, /**< Only target */
|
||||
} DmaFlowControl_e;
|
||||
|
||||
/** \brief List of DMA transfer data width in peripheral involved case */
|
||||
typedef enum
|
||||
{
|
||||
DMA_DATA_WIDTH_NO_USE = 0, /**< Data width is set to 0 in memory to memory transfer */
|
||||
DMA_DATA_WIDTH_ONE_BYTE = 1U, /**< Data widath is 1 byte in peripheral involved transfer */
|
||||
DMA_DATA_WIDTH_TWO_BYTES = 2U, /**< Data widath is 2 bytes in peripheral involved transfer */
|
||||
DMA_DATA_WIDTH_FOUR_BYTES = 3U, /**< Data widath is 4 bytes in peripheral involved transfer */
|
||||
} DmaDataWidth_e;
|
||||
|
||||
/** \brief Maximum burst size of each data transfer */
|
||||
typedef enum
|
||||
{
|
||||
DMA_BURST_4_BYTES = 0, /**< Burst size is set to reserved */
|
||||
DMA_BURST_8_BYTES = 1U, /**< Burst size is set to 8 bytes */
|
||||
DMA_BURST_16_BYTES = 2U, /**< Burst size is set to 16 bytes */
|
||||
DMA_BURST_32_BYTES = 3U, /**< Burst size is set to 32 bytes */
|
||||
DMA_BURST_64_BYTES = 4U, /**< Burst size is set to 64 bytes */
|
||||
} DmaBurstSize_e;
|
||||
|
||||
/** \brief DMA transfer configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
void *sourceAddress; /**< Source address */
|
||||
void *targetAddress; /**< Target address */
|
||||
DmaFlowControl_e flowControl; /**< Flow control setting */
|
||||
DmaAddressIncrement_e addressIncrement; /**< Address increment setting */
|
||||
DmaDataWidth_e dataWidth; /**< Data width setting */
|
||||
DmaBurstSize_e burstSize; /**< Burst size setting */
|
||||
uint32_t totalLength; /**< Transfer length onetime, less than 8k bytes. In descriptor chain it means every transfer's size */
|
||||
} DmaTransferConfig_t;
|
||||
|
||||
/** \brief DMA descriptor extra configuration structure for descriptor-chain mode */
|
||||
typedef struct
|
||||
{
|
||||
void *nextDesriptorAddress; /**< Next descriptor address */
|
||||
bool stopDecriptorFetch; /**< Indicate whether this is the last descriptor */
|
||||
bool enableStartInterrupt; /**< Start interrupt control */
|
||||
bool enableEndInterrupt; /**< End interrupt control */
|
||||
} DmaExtraConfig_t;
|
||||
|
||||
/** \brief DMA descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t DAR; /**< DMA Descriptor Address */
|
||||
uint32_t SAR; /**< DMA Source Address */
|
||||
uint32_t TAR; /**< DMA Target Address */
|
||||
uint32_t CMDR; /**< DMA Command */
|
||||
} DmaDescriptor_t;
|
||||
|
||||
/** \brief List of DMA interrupt sources */
|
||||
typedef enum
|
||||
{
|
||||
/** Stop interrupt enable, when enabled, interrupt is triggered after the channel stops */
|
||||
DMA_STOP_INTERRUPT_ENABLE = (1U << 29U),
|
||||
/** EOR interrupt enable, when enabled, interrupt is triggered on End-Of-Receive condition */
|
||||
DMA_EOR_INTERRUPT_ENABLE = (1U << 28U),
|
||||
/** Start interrupt enable, when enabled, interrupt is triggered as soon as descriptor is loaded, valid for descriptor-chain-mode */
|
||||
DMA_START_INTERRUPT_ENABLE = (1U << 22U),
|
||||
/** End interrupt enable, when enabled, interrupt is triggered when transfer length decrements to 0 */
|
||||
DMA_END_INTERRUPT_ENABLE = (1U << 21U),
|
||||
} DmaInterruptEnable_e;
|
||||
|
||||
/** \brief List of DMA available intances */
|
||||
typedef enum
|
||||
{
|
||||
DMA_INSTANCE_AP,
|
||||
DMA_INSTANCE_MP,
|
||||
DMA_INSTANCE_MAX,
|
||||
} DmaInstance_e;
|
||||
|
||||
/** DMA specific error codes */
|
||||
#define ARM_DMA_ERROR_CHANNEL_ALLOC (ARM_DRIVER_ERROR_SPECIFIC - 1) /**< No free channel any more */
|
||||
#define ARM_DMA_ERROR_CHANNEL_NOT_OPEN (ARM_DRIVER_ERROR_SPECIFIC - 2) /**< Specific channel not open */
|
||||
#define ARM_DMA_ERROR_CHANNEL_NOT_STOPPED (ARM_DRIVER_ERROR_SPECIFIC - 3) /**< Specific channel not stopped */
|
||||
#define ARM_DMA_ERROR_ADDRESS_NOT_ALIGNED (ARM_DRIVER_ERROR_SPECIFIC - 4) /**< Address alignment check failure */
|
||||
|
||||
|
||||
/** List of events reported to application */
|
||||
#define DMA_EVENT_ERROR (1) /**< Bus error */
|
||||
#define DMA_EVENT_START (2) /**< Descriptor load successfully */
|
||||
#define DMA_EVENT_END (3) /**< Transaction end */
|
||||
#define DMA_EVENT_EOR (4) /**< Receive EOR signal */
|
||||
#define DMA_EVENT_STOP (5) /**< Channel has stopped */
|
||||
|
||||
/**
|
||||
\brief Defines callback function prototype.
|
||||
Callback function will be called in DMA interrupt service routine after a transaction is complete
|
||||
\param event transaction event for the current transaction, application can get the tansaction
|
||||
result from this paramter, available events: DMA_EVENT_ERROR, DMA_EVENT_START, DMA_EVENT_END, DMA_EVENT_EOR, DMA_EVENT_STOP
|
||||
*/
|
||||
typedef void (*dma_callback_t)(uint32_t event);
|
||||
|
||||
/** \brief timeout value when stopping channel */
|
||||
#define DMA_STOP_TIMEOUT (5000U)
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
\fn void DMA_init(DmaInstance_e instance)
|
||||
\brief Intialize DMA hareware and internal used structure, call this function before any other DMA APIs
|
||||
*/
|
||||
void DMA_init(DmaInstance_e instance);
|
||||
|
||||
/** \name DMA Channel operation API */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn int32_t DMA_openChannel(DmaInstance_e instance)
|
||||
\brief Opens a DMA channel
|
||||
\return Channel on successful allocate
|
||||
ARM_DMA_ERROR_CHANNEL_ALLOC when no free channel is found
|
||||
\note Caller shall check the return code
|
||||
*/
|
||||
int32_t DMA_openChannel(DmaInstance_e instance);
|
||||
|
||||
/**
|
||||
\fn int32_t DMA_closeChannel(DmaInstance_e instance, uint32_t channel)
|
||||
\brief Closes a DMA channel
|
||||
\param[in] instance
|
||||
\param[in] channel DMA channel number
|
||||
\return ARM_DRIVER_OK if no error happens
|
||||
ARM_DMA_ERROR_CHANNEL_NOT_OPEN when channel is not open
|
||||
\note This API will call \ref DMA_stopChannel to stop channel first if channel is running before close
|
||||
*/
|
||||
int32_t DMA_closeChannel(DmaInstance_e instance, uint32_t channel);
|
||||
|
||||
/**
|
||||
\fn void DMA_startChannel(DmaInstance_e instance, uint32_t channel)
|
||||
\brief Activates the DMA channel
|
||||
\param[in] instance
|
||||
\param[in] channel DMA channel number
|
||||
*/
|
||||
void DMA_startChannel(DmaInstance_e instance, uint32_t channel);
|
||||
|
||||
/**
|
||||
\fn int32_t DMA_stopChannel(uint32_t channel, bool waitForStop)
|
||||
\brief Stops the DMA channel from running
|
||||
\param[in] channel DMA channel number
|
||||
\param[in] waitForStop whether to wait channel to fully stop or not
|
||||
\return ARM_DRIVER_OK if stops successfully
|
||||
ARM_DMA_ERROR_CHANNEL_NOT_STOPPED if channel fails to stop until timeout expires
|
||||
\note staus and interrupt flags will be cleared in this function call
|
||||
*/
|
||||
int32_t DMA_stopChannel(DmaInstance_e instance, uint32_t channel, bool waitForStop);
|
||||
|
||||
/**
|
||||
\fn void DMA_resetChannel(uint32_t channel)
|
||||
|
||||
\brief Put the DMA channel to reset state
|
||||
\param[in] channel DMA channel number
|
||||
\note Make sure DMA is stopped before calling this function
|
||||
*/
|
||||
void DMA_resetChannel(DmaInstance_e instance, uint32_t channel);
|
||||
|
||||
/**
|
||||
\fn void DMA_rigisterChannelCallback(uint32_t channel, dma_callback_t callback)
|
||||
\brief Registers a DMA callback
|
||||
\param[in] channel DMA channel number
|
||||
\param[in] callback Given by the application and will be called in DMA interrupt service routine
|
||||
*/
|
||||
void DMA_rigisterChannelCallback(DmaInstance_e instance, uint32_t channel, dma_callback_t callback);
|
||||
|
||||
/**
|
||||
\fn void DMA_enableChannelInterrupts(uint32_t channel, uint32_t mask)
|
||||
\brief Enables DMA interrupts
|
||||
\param[in] channel DMA channel number
|
||||
\param[in] mask Mask of interrupt source to be set, can be ORed by items list in \ref DmaInterruptEnable_e
|
||||
\note In no-descriptor-fetch mode, all interrupt sources can be enabled by calling this API, however, in descritor-fetch
|
||||
mode, only \ref DMA_STOP_INTERRUPT_ENABLE \ref DMA_EOR_INTERRUPT_ENABLE can be done by this function call,
|
||||
the \ref DMA_START_INTERRUPT_ENABLE and \ref DMA_END_INTERRUPT_ENABLE is controlled by setting in \ref DmaExtraConfig_t respectively.
|
||||
*/
|
||||
void DMA_enableChannelInterrupts(DmaInstance_e instance, uint32_t channel, uint32_t mask);
|
||||
|
||||
/**
|
||||
\fn void DMA_disableChannelInterrupts(uint32_t channel, uint32_t mask)
|
||||
\brief Disables DMA interrupts
|
||||
\param[in] channel DMA channel number
|
||||
\param[in] mask Mask of interrupt source to be disabled, can be ORed by items list in \ref DmaInterruptEnable_e
|
||||
\note In no-descriptor-fetch mode, all interrupt sources can be disabled by calling this API, however, in descritor-fetch
|
||||
mode, only \ref DMA_STOP_INTERRUPT_ENABLE \ref DMA_EOR_INTERRUPT_ENABLE can be done by this function call ,
|
||||
the \ref DMA_START_INTERRUPT_ENABLE and \ref DMA_END_INTERRUPT_ENABLE is controlled by setting in \ref DmaExtraConfig_t respectively.
|
||||
*/
|
||||
void DMA_disableChannelInterrupts(DmaInstance_e instance, uint32_t channel, uint32_t mask);
|
||||
|
||||
/**
|
||||
\fn uint32_t DMA_getEnabledInterrupts(uint32_t channel)
|
||||
\brief Gets current enabled DMA channel interrupts
|
||||
\param[in] channel DMA channel number
|
||||
\return The logical OR of members of the enumeration \ref DmaInterruptEnable_e
|
||||
*/
|
||||
uint32_t DMA_getEnabledInterrupts(DmaInstance_e instance, uint32_t channel);
|
||||
|
||||
/**
|
||||
\fn uint32_t DMA_getChannelCount(uint32_t channel)
|
||||
\brief Obtains courrent transferred data length of a transaction in unit of byte
|
||||
\param[in] channel DMA channel number
|
||||
\return Size of data has been transferred
|
||||
\note In descritor-fetch mode, Start Interrupt shall be enabled by enableStartInterrupt setting in \ref DmaExtraConfig_t
|
||||
so that driver can load total transfer number for calculation before transferring.
|
||||
*/
|
||||
uint32_t DMA_getChannelCount(DmaInstance_e instance, uint32_t channel);
|
||||
|
||||
/**
|
||||
\fn void DMA_setChannelRequestSource(uint32_t channel, DmaRequestSource_e request)
|
||||
\brief Configures DMA request source
|
||||
\param[in] channel DMA channel number
|
||||
\param[in] request DMA request binded to this channel
|
||||
*/
|
||||
void DMA_setChannelRequestSource(DmaInstance_e instance, uint32_t channel, DmaRequestSource_e request);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name DMA register mode API */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void DMA_transferSetup(DmaInstance_e instance, uint32_t channel, const DmaTransferConfig_t* config)
|
||||
\brief Setups DMA channel according to user's transfer configuration, usded for register mode
|
||||
\param[in] instance
|
||||
\param[in] channel DMA channel number
|
||||
\param[in] config Pointer to transfer configuration
|
||||
\note user configuration shall be retaining(global variable) for it will be used again after exit from low power
|
||||
*/
|
||||
void DMA_transferSetup(DmaInstance_e instance, uint32_t channel, const DmaTransferConfig_t* config);
|
||||
/** \} */
|
||||
|
||||
/** \name DMA descriptor chain mode API */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void DMA_buildDescriptor(DmaDescriptor_t* descriptor, const DmaTransferConfig_t* config, const DmaExtraConfig_t* extraConfig)
|
||||
\brief Builds a descritor for DMA mode use
|
||||
\param[out] descriptor Pointer to DMA descriptor instance
|
||||
\param[in] config Pointer to transfer configuration
|
||||
\param[in] extraConfig Pointer to extra configuration which is invalid in descriptor-chain-mode only
|
||||
\note descriptor shall be retaining(global variable) for it will be used again after exit from low power
|
||||
*/
|
||||
|
||||
void DMA_buildDescriptor(DmaDescriptor_t* descriptor, const DmaTransferConfig_t* config, const DmaExtraConfig_t* extraConfig);
|
||||
|
||||
/**
|
||||
\fn void DMA_buildDescriptorChain(DmaDescriptor_t* descriptorArray, const DmaTransferConfig_t* config, const uint16_t chainCnt)
|
||||
\brief Builds a descritor for DMA chain mode use
|
||||
\param[out] descriptorArray Pointer to DMA descriptor chain array, should aligned with 16byte
|
||||
\param[in] config Pointer to transfer configuration
|
||||
\param[in] chainCnt The count of descriptor chain
|
||||
\param[in] needStop Need cycling transfer data or not
|
||||
\note descriptor shall be retaining(global variable) for it will be used again after exit from low power
|
||||
*/
|
||||
|
||||
void DMA_buildDescriptorChain(DmaDescriptor_t* descriptorArray, const DmaTransferConfig_t* config, const uint16_t chainCnt, bool needStop);
|
||||
|
||||
/**
|
||||
\fn int32_t DMA_loadChannelFirstDescriptor(DmaInstance_e instance, uint32_t channel, void* descriptorAddress)
|
||||
\brief Loads first descritor
|
||||
\param[in] instance
|
||||
\param[in] channel DMA channel number
|
||||
\param[in] descriptorAddress Address of descriptor from which to load, shall be aligend on a 16-byte boundary in memory
|
||||
\return ARM_DRIVER_OK if success
|
||||
ARM_DMA_ERROR_ADDRESS_NOT_ALIGNED on address alignment check failure
|
||||
*/
|
||||
int32_t DMA_loadChannelFirstDescriptor(DmaInstance_e instance, uint32_t channel, void* descriptorAddress);
|
||||
|
||||
/**
|
||||
\fn void DMA_loadChannelDescriptorAndRun(DmaInstance_e instance, uint32_t channel, void* descriptorAddress)
|
||||
\brief Loads first descritor and run
|
||||
\param[in] instance
|
||||
\param[in] channel DMA channel number
|
||||
\param[in] descriptorAddress Address of descriptor from which to load, shall be aligend on a 16-byte boundary in memory
|
||||
\return ARM_DRIVER_OK if success
|
||||
ARM_DMA_ERROR_ADDRESS_NOT_ALIGNED on address alignment check failure
|
||||
*/
|
||||
void DMA_loadChannelDescriptorAndRun(DmaInstance_e instance, uint32_t channel, void* descriptorAddress);
|
||||
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,80 @@
|
||||
/******************************************************************************
|
||||
|
||||
*(C) Copyright 2018 AirM2M International Ltd.
|
||||
|
||||
* All Rights Reserved
|
||||
|
||||
******************************************************************************
|
||||
* Filename:flash_rt.h
|
||||
*
|
||||
* Description:EC618 flash header file
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef _FLASH_EC618_RT_H
|
||||
#define _FLASH_EC618_RT_H
|
||||
/*----------------------------------------------------------------------------*
|
||||
* INCLUDES *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* MACROS *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/* QSPI Error codes */
|
||||
#define QSPI_OK ((uint8_t)0x00)
|
||||
#define QSPI_ERROR ((uint8_t)0x01)
|
||||
#define QSPI_BUSY ((uint8_t)0x02)
|
||||
#define QSPI_NOT_SUPPORTED ((uint8_t)0x04)
|
||||
#define QSPI_SUSPENDED ((uint8_t)0x08)
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* DATA TYPE DEFINITION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef enum
|
||||
{
|
||||
|
||||
QSPI_OP_ERASE = 0,
|
||||
QSPI_OP_WRITE,
|
||||
}QSPI_OpType_e;
|
||||
|
||||
|
||||
/**
|
||||
\brief definition of the flash operation callback, register using BSP_QSPI_Reg_Operation_Cb
|
||||
call when flash erase and write happens.
|
||||
\param[in] result the QSPI Error codes, listed above
|
||||
\param[in] type to indicate erase or write
|
||||
\param[in] address operation address
|
||||
\param[in] size operation size
|
||||
\return null
|
||||
*/
|
||||
typedef void (*BSP_QSPI_OperCallback_t)(uint8_t result, QSPI_OpType_e type, uint32_t address, uint32_t size);
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* GLOBAL FUNCTIONS DECLEARATION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
uint8_t BSP_QSPI_Cfg_Gran_Size(uint16_t WriteGranSize);
|
||||
uint8_t BSP_QSPI_Erase_Safe(uint32_t SectorAddress, uint32_t Size);
|
||||
uint8_t BSP_QSPI_Write_Safe(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
|
||||
uint8_t BSP_QSPI_Read_Safe(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
|
||||
|
||||
/**
|
||||
\fn void BSP_QSPI_Reg_Operation_Cb(BSP_QSPI_OperCallback_t cb);
|
||||
\brief register a user callback to get flash operation info. No time consuming operation allowed in this callback.
|
||||
*/
|
||||
void BSP_QSPI_Reg_Operation_Cb(BSP_QSPI_OperCallback_t cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: gpio.h
|
||||
* Description: EC618 gpio driver header file
|
||||
* History:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _GPIO_EC618_H
|
||||
#define _GPIO_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup gpio_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/** \brief GPIO pin direction */
|
||||
typedef enum
|
||||
{
|
||||
GPIO_DIRECTION_INPUT = 0U, /**< Set pin as input */
|
||||
GPIO_DIRECTION_OUTPUT = 1U, /**< Set pin as output */
|
||||
} GpioPinDirection_e;
|
||||
|
||||
/** \brief GPIO pin interrupt configuration */
|
||||
typedef enum
|
||||
{
|
||||
GPIO_INTERRUPT_DISABLED = 0U, /**< Disable interrupt */
|
||||
GPIO_INTERRUPT_LOW_LEVEL = 1U, /**< Low-level interrupt */
|
||||
GPIO_INTERRUPT_HIGH_LEVEL = 2U, /**< High-level interrupt */
|
||||
GPIO_INTERRUPT_FALLING_EDGE = 3U, /**< Falling edge interrupt */
|
||||
GPIO_INTERRUPT_RISING_EDGE = 4U, /**< Rising edge interrupt */
|
||||
} GpioInterruptConfig_e;
|
||||
|
||||
/** \brief GPIO pin configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
GpioPinDirection_e pinDirection; /**< GPIO direction, input or output */
|
||||
union
|
||||
{
|
||||
GpioInterruptConfig_e interruptConfig; /**< Pin's interrupt configuration, valid when pinDirection is input */
|
||||
uint32_t initOutput; /**< Initial pin output value, valid when pinDirection is output*/
|
||||
} misc;
|
||||
} GpioPinConfig_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \name GPIO Driver Initialization */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void GPIO_driverInit(void);
|
||||
\brief Intialize GPIO driver internal data
|
||||
\note It is not necessarty to call this function before using GPIO driver since it has been
|
||||
called in \ref GPIO_pinConfig() api.
|
||||
*/
|
||||
void GPIO_driverInit(void);
|
||||
|
||||
/**
|
||||
\fn void GPIO_driverDeInit(void);
|
||||
\brief De-Intialize GPIO driver, disable GPIO clock and perform some clearups
|
||||
*/
|
||||
void GPIO_driverDeInit(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name GPIO Configuration */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void GPIO_pinConfig(uint32_t port, uint16_t pin, const GpioPinConfig_t *config);
|
||||
\brief Configure a GPIO pin
|
||||
\param[in] port GPIO number (0, 1, ...)
|
||||
\param[in] pin GPIO pin number
|
||||
\param[in] config Pointer to GPIO pin configuration
|
||||
*/
|
||||
void GPIO_pinConfig(uint32_t port, uint16_t pin, const GpioPinConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn void GPIO_interruptConfig(uint32_t port, uint16_t pin, GpioInterruptConfig_e config);
|
||||
\brief Configure a GPIO pin's interrupt type(valid when this pin has been set as input)
|
||||
\param[in] port GPIO number (0, 1, ...)
|
||||
\param[in] pin GPIO pin number
|
||||
\param[in] config GPIO interrupt configuration
|
||||
*/
|
||||
void GPIO_interruptConfig(uint32_t port, uint16_t pin, GpioInterruptConfig_e config);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name GPIO Output Operations */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void GPIO_pinWrite(uint32_t port, uint16_t pinMask, uint16_t output);
|
||||
\brief Sets output level of multiple GPIO pins to logic 1 or 0
|
||||
|
||||
\code
|
||||
Example to set bits[15,1:0] to 1 and clear bits[12:11, 7:6]
|
||||
|
||||
// pinMask shall be b10011000 11000011 = 0x98C3
|
||||
// output shall be b10000000 00000011 = 0x8003
|
||||
GPIO_pinWrite(0, 0x98C3, 0x8003);
|
||||
// To set a single pin, let's say, pin 12 of GPIO0
|
||||
GPIO_pinWrite(0, 1 << 12, 1 << 12);
|
||||
// To clear a single pin, let's say, pin 12 of GPIO0
|
||||
GPIO_pinWrite(0, 1 << 12, 0);
|
||||
|
||||
\endcode
|
||||
|
||||
\param[in] port GPIO number (0, 1, ...)
|
||||
\param[in] pinMask GPIO pin mask to set
|
||||
\param[in] output GPIO pin output logic level.
|
||||
- 0: corresponding pin output low-logic level.
|
||||
- 1: corresponding pin output high-logic level.
|
||||
*/
|
||||
void GPIO_pinWrite(uint32_t port, uint16_t pinMask, uint16_t output);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name GPIO Input Operations */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn uint32_t GPIO_pinRead(uint32_t port, uint16_t pin)
|
||||
\brief Reads current input value of GPIO specific pin
|
||||
\param[in] port GPIO number (0, 1, ...)
|
||||
\param[in] pin GPIO pin number
|
||||
\return GPIO corresponding pin input value
|
||||
*/
|
||||
uint32_t GPIO_pinRead(uint32_t port, uint16_t pin);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name GPIO Interrupt */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn uint16_t GPIO_getInterruptFlags(uint32_t port)
|
||||
\brief Reads GPIO port interrupt status flags
|
||||
\param[in] port GPIO number (0, 1, ...)
|
||||
\return current GPIO interrupt status flag
|
||||
*/
|
||||
uint16_t GPIO_getInterruptFlags(uint32_t port);
|
||||
|
||||
/**
|
||||
\fn void GPIO_clearInterruptFlags(uint32_t port, uint16_t mask)
|
||||
\brief Clears multiple GPIO pin interrupt status flags
|
||||
\param[in] port GPIO number (0, 1, ...)
|
||||
\param[in] mask GPIO pin number macro
|
||||
*/
|
||||
void GPIO_clearInterruptFlags(uint32_t port, uint16_t mask);
|
||||
|
||||
/**
|
||||
\fn uint16_t GPIO_saveAndSetIrqMask(uint32_t port)
|
||||
\brief Reads GPIO port interrupt enable mask and diables whole port interrupts
|
||||
\param[in] port GPIO number (0, 1, ...)
|
||||
\return current GPIO port interrupt enable mask
|
||||
\note Used in GPIO ISR to disable GPIO interrupts temporarily
|
||||
*/
|
||||
uint16_t GPIO_saveAndSetIrqMask(uint32_t port);
|
||||
|
||||
/**
|
||||
\fn void GPIO_restoreIrqMask(uint32_t port, uint16_t mask)
|
||||
\brief Restore GPIO port interrupt enable setting
|
||||
\param[in] port GPIO number (0, 1, ...)
|
||||
\param[in] mask GPIO interrupt enable mask
|
||||
\note Used in GPIO ISR to restore GPIO enable setting upon exit
|
||||
*/
|
||||
void GPIO_restoreIrqMask(uint32_t port, uint16_t mask);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GPIO_EC618_H */
|
||||
@@ -0,0 +1,310 @@
|
||||
#define RMI_GPR_TOP_CLKEN_REG_INDEX (0)
|
||||
#define RMI_GPR_XPSYS_CLKEN_REG_INDEX (1)
|
||||
|
||||
#define APB_GPR_TOP_MP_CLKEN_REG_INDEX (2)
|
||||
#define APB_GPR_TOP_AP_CLKEN_REG_INDEX (3)
|
||||
|
||||
#define APB_GPR_APB_MP_PCLK_EN_REG_INDEX (4)
|
||||
#define APB_GPR_APB_AP_PCLK_EN_REG_INDEX (5)
|
||||
|
||||
#define APB_GPR_APB_MP_FCLK_EN_REG_INDEX (6)
|
||||
#define APB_GPR_APB_AP_FCLK_EN_REG_INDEX (7)
|
||||
|
||||
#define APB_GPR_TOP_ALL_CLKEN_REG_INDEX (8)
|
||||
|
||||
#define CLKEN_REG_INDEX_MAX (0xF)
|
||||
|
||||
/**
|
||||
|-----registerAccessIndex-----|-----bitPosition-----|---------index---------|
|
||||
|------------4 bit------------|--------5 bit--------|---------8 bit---------|
|
||||
*/
|
||||
#define CONSTRUCT_CLOCK_ID(registerAccessIndex, bitPosition, index) \
|
||||
(((registerAccessIndex) << 13) | ((bitPosition) << 8) | (index))
|
||||
|
||||
|
||||
/** Macro to extract index from clock id value */
|
||||
#define GET_INDEX_FROM_CLOCK_ID(value) ((value) & 0xFFU)
|
||||
|
||||
/** Macro to extract bitPosition from clock id value */
|
||||
#define GET_BP_FROM_CLOCK_ID(value) ((value >> 8U) & 0x1FU)
|
||||
|
||||
/** Macro to extract registerAccessIndex from clock id value */
|
||||
#define GET_RAI_FROM_CLOCK_ID(value) ((value >> 13U) & 0xFU)
|
||||
|
||||
/**
|
||||
|-----clockIdIndex-----|-----value-----|-----parentClockId-----|
|
||||
|---------8 bit--------|-----4 bit-----|--------17 bit---------|
|
||||
*/
|
||||
/** Macro to compose clock select value */
|
||||
#define MAKE_CLOCK_SEL_VALUE(clockIdIndex, value, parentClockId) \
|
||||
((clockIdIndex << 21U) | value << 17U | parentClockId)
|
||||
|
||||
/** Macro to extract clockId from clock select value */
|
||||
#define GET_CLOCKIDINDEX_FROM_CLOCK_SEL_VALUE(value) ((value >> 21U) & 0xFFUL)
|
||||
|
||||
/** Macro to extract value from clock select value */
|
||||
#define GET_VALUE_FROM_CLOCK_SEL_VALUE(value) ((value >> 17U) & 0xFUL)
|
||||
|
||||
/** Macro to extract parentClockId from clock select value */
|
||||
#define GET_PARENTCLOCKID_FROM_CLOCK_SEL_VALUE(value) (value & 0x1FFFFUL)
|
||||
|
||||
|
||||
#define APB_GPR_TOP_AP_RST_REQ_REG_INDEX (0)
|
||||
#define APB_GPR_APB_MP_PRST_REQ_REG_INDEX (1)
|
||||
|
||||
#define APB_GPR_APB_AP_PRST_REQ_REG_INDEX (2)
|
||||
#define APB_GPR_APB_MP_FRST_REQ_REG_INDEX (3)
|
||||
#define APB_GPR_APB_AP_FRST_REQ_REG_INDEX (4)
|
||||
|
||||
#define RMI_GPR_TOP_RSTREQ_REG_INDEX (5)
|
||||
#define RMI_GPR_XPSYS_RSTREQ_REG_INDEX (6)
|
||||
|
||||
|
||||
/**
|
||||
|-----registerAccessIndex-----|-----bitPosition-----|
|
||||
|------------4 bit------------|--------8 bit--------|
|
||||
*/
|
||||
#define CONSTRUCT_CLOCK_RESET_ID(registerAccessIndex, bitPosition) \
|
||||
(((registerAccessIndex) << 8) | (bitPosition))
|
||||
|
||||
/** Macro to extract bitPosition from clock reset id value */
|
||||
#define GET_BP_FROM_CLOCK_RESET_ID(value) ((value) & 0xFFU)
|
||||
|
||||
/** Macro to extract registerAccessIndex from clock reset id value */
|
||||
#define GET_RAI_FROM_CLOCK_RESET_ID(value) ((value >> 8U) & 0xFU)
|
||||
|
||||
|
||||
/** \brief List of IDs used for sw reset control */
|
||||
typedef enum
|
||||
{
|
||||
/* Top AP Reset */
|
||||
RST_AP_FABSYS_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 0), /**< Ap fab sys AHB reset */
|
||||
RST_AP_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 1), /**< Ap RMI AHB reset */
|
||||
RST_MFAB_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 2), /**< MFAB AHB reset */
|
||||
RST_AFBBR_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 3), /**< AFBBR AHB reset */
|
||||
RST_CFBBR_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 4), /**< CFBBR AHB reset */
|
||||
RST_MSMB_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 5), /**< MSMB AHB reset */
|
||||
RST_FLASH_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 6), /**< Flash AHB reset */
|
||||
RST_PSRAM_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 7), /**< Psram AHB reset */
|
||||
RST_ULOG_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 8), /**< Unilog AHB reset */
|
||||
RST_USBC_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 9), /**< Usbc AHB reset */
|
||||
RST_CLK_FLASH = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 10), /**< Flash Func reset */
|
||||
RST_CLK_PSRAM = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 11), /**< Psram Func reset */
|
||||
RST_AONIF = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 12), /**< Aonif reset */
|
||||
RST_LPUA = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 13), /**< Lpua reset */
|
||||
RST_CLK_FRACDIV = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 14), /**< Fracdiv reset */
|
||||
RST_ULOG_SMP = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 15), /**< Unilog Smp reset */
|
||||
RST_FCLK_FUSE = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 16), /**< Fuse Func reset */
|
||||
RST_UTFC_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 17), /**< UTfc AHB reset */
|
||||
RST_ULDP_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 18), /**< Uldp AHB reset */
|
||||
// reserved = 19~26,
|
||||
RST_USBC_PHY = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 27), /**< Usbc PHY reset */
|
||||
RST_USBP_POR = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 28), /**< USBP Por reset */
|
||||
RST_USBP_UTMI = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 29), /**< USBP Utmi reset */
|
||||
|
||||
/* APB MP Reset */
|
||||
// reserved = 0,
|
||||
RST_PCLK_SIPC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 1), /**< Sipc APB reset */
|
||||
RST_PCLK_AON = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 2), /**< Aon APB reset */
|
||||
RST_PCLK_CPMU = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 3), /**< Cpmu APB reset */
|
||||
RST_PCLK_PMDIG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 4), /**< Pmdig APBreset */
|
||||
RST_PCLK_RFDIG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 5), /**< Rfdig APB reset */
|
||||
RST_PCLK_PAD = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 6), /**< Pad APB reset */
|
||||
RST_PCLK_GPIO = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 7), /**< Gpio APB reset */
|
||||
RST_PCLK_FUSE = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 8), /**< Fuse APB reset */
|
||||
RST_PCLK_TRNG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 9), /**< Trng APB reset */
|
||||
RST_PCLK_USBP = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 10), /**< Usbp APB reset */
|
||||
RST_PCLK_LPUC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 11), /**< Lpuc APB reset */
|
||||
RST_PCLK_UART0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 12), /**< Uart0 APB reset */
|
||||
RST_PCLK_UART1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 13), /**< Uart1 APB reset */
|
||||
RST_PCLK_UART2 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 14), /**< Uart2 APB reset */
|
||||
RST_PCLK_SPI0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 15), /**< Ssp 0 APB reset */
|
||||
RST_PCLK_SPI1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 16), /**< Ssp 1 APB reset */
|
||||
RST_PCLK_I2S0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 17), /**< I2s 0 APB reset */
|
||||
RST_PCLK_I2S1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 18), /**< I2s 1 APB reset */
|
||||
|
||||
/* APB AP Reset */
|
||||
RST_PCLK_WDG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 0), /**< WDG APB reset */
|
||||
RST_PCLK_TIMER0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 1), /**< Timer0 APB reset */
|
||||
RST_PCLK_TIMER1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 2), /**< Timer1 APBreset */
|
||||
RST_PCLK_TIMER2 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 3), /**< Timer2 APB reset */
|
||||
RST_PCLK_TIMER3 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 4), /**< Timer3 APB reset */
|
||||
RST_PCLK_TIMER4 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 5), /**< Timer4 APB reset */
|
||||
RST_PCLK_TIMER5 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 6), /**< Timer5 APB reset */
|
||||
RST_PCLK_IPC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 7), /**< IPC APB reset */
|
||||
RST_PCLK_I2C0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 8), /**< I2C0 APB reset */
|
||||
RST_PCLK_I2C1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 9), /**< I2C1 APB reset */
|
||||
RST_PCLK_USIM0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 10), /**< USIM0 APB reset */
|
||||
RST_PCLK_USIM1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 11), /**< USIM1 APB reset */
|
||||
RST_PCLK_KPC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 12), /**< KPC APB reset */
|
||||
RST_PCLK_ONEW = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 13), /**< ONEW APB reset */
|
||||
|
||||
|
||||
/* APB MP Func Reset */
|
||||
RST_FCLK_UART0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 0), /**< Uart0 Func reset */
|
||||
RST_FCLK_UART1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 1), /**< Uart1 Func reset */
|
||||
RST_FCLK_UART2 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 2), /**< Uart2 Func reset */
|
||||
RST_FCLK_SPI0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 3), /**< SSP0 Func reset */
|
||||
RST_FCLK_SPI1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 4), /**< SSP1 Func reset */
|
||||
RST_FCLK_I2S0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 5), /**< I2S0 Func reset */
|
||||
RST_FCLK_I2S1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 6), /**< I2S1 Func reset */
|
||||
|
||||
/* APB AP Func Reset */
|
||||
RST_FCLK_WDG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 0), /**< WDG Func reset */
|
||||
RST_FCLK_TIMER0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 1), /**< TIMER0 Func reset */
|
||||
RST_FCLK_TIMER1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 2), /**< TIMER1 Func reset */
|
||||
RST_FCLK_TIMER2 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 3), /**< TIMER2 Func reset */
|
||||
RST_FCLK_TIMER3 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 4), /**< TIMER3 Func reset */
|
||||
RST_FCLK_TIMER4 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 5), /**< TIMER4 Func reset */
|
||||
RST_FCLK_TIMER5 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 6), /**< TIMER5 Func reset */
|
||||
RST_FCLK_I2C0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 7), /**< I2C0 Func reset */
|
||||
RST_FCLK_I2C1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 8), /**< I2C1 Func reset */
|
||||
RST_FCLK_USIM0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 9), /**< USIM0 Func reset */
|
||||
RST_FCLK_USIM1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 10), /**< USIM1 Func reset */
|
||||
RST_FCLK_KPC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 11), /**< KPC Func reset */
|
||||
|
||||
/* RMI TOP Reset */
|
||||
RST_TOP_PBRG_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_TOP_RSTREQ_REG_INDEX, 0), /**< DMA AHB domain reset */
|
||||
RST_TOP_PBRG_PCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_TOP_RSTREQ_REG_INDEX, 1), /**< DMA APB domain reset */
|
||||
RST_TOP_GPR_PCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_TOP_RSTREQ_REG_INDEX, 2), /**< GPR APB domain reset */
|
||||
|
||||
/* RMI XPSYS Reset */
|
||||
RST_CACHE_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 0), /**< GPR CACHE AHB domain reset */
|
||||
RST_FABSUB_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 1), /**< GPR FABSUB AHB domain reset */
|
||||
RST_SBU_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 2), /**< GPR SBU AHB domain reset */
|
||||
RST_PBRG_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 3), /**< GPR PDMA AHB domain reset */
|
||||
RST_SPIS_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 4), /**< GPR SPIS AHB domain reset */
|
||||
RST_XIC_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 5), /**< GPR XIC AHB domain reset */
|
||||
RST_ULOG_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 6), /**< GPR ULOG AHB domain reset */
|
||||
RST_TMU_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 7), /**< GPR TMU AHB domain reset */
|
||||
RST_SCT_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 8), /**< GPR SCT AHB domain reset */
|
||||
|
||||
RST_UTFC_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 11), /**< GPR UTFC AHB domain reset */
|
||||
RST_ULDP_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 12), /**< GPR ULDP AHB domain reset */
|
||||
RST_SCT_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 13), /**< GPR SCT AHB reset */
|
||||
RST_PCLK_DMA = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 15), /**< GPR PDMA APB reset */
|
||||
RST_TMU_SMP = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 16), /**< GPR TMU SMP reset */
|
||||
RST_TMU_CLKCAL = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 17), /**< GPR TMU CLKCAL reset */
|
||||
} ClockResetId_e;
|
||||
|
||||
/** \brief typedef for reset whole module */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t idNumber; /**< number of ids this module contains */
|
||||
uint32_t delayCpuCycles; /**< the cycles need to delay after release */
|
||||
const ClockResetId_e* resetReleaseQueue; /**< pointer to the queue(array) of ids, reset & release operation sequence
|
||||
depends on the position of id in the array, so arrange it properly */
|
||||
} ClockResetVector_t;
|
||||
|
||||
#define RESET_RELEASE_DELAY_US (204)
|
||||
|
||||
#define MAKE_RESET_VECTOR(delay, ...) \
|
||||
{ \
|
||||
(sizeof((ClockResetId_e [])__VA_ARGS__) / sizeof(ClockResetId_e)), \
|
||||
(delay), \
|
||||
(const ClockResetId_e [])__VA_ARGS__ \
|
||||
}
|
||||
|
||||
#define RESET_VECTOR_PTR(v) ((ClockResetVector_t [])v)
|
||||
|
||||
#define UART0_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_UART0, RST_FCLK_UART0, RST_PCLK_UART0, RST_FCLK_UART0})
|
||||
#define UART1_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_UART1, RST_FCLK_UART1, RST_PCLK_UART1, RST_FCLK_UART1})
|
||||
#define UART2_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_UART2, RST_FCLK_UART2, RST_PCLK_UART2, RST_FCLK_UART2})
|
||||
|
||||
#define SPI0_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_SPI0, RST_FCLK_SPI0, RST_PCLK_SPI0, RST_FCLK_SPI0})
|
||||
#define SPI1_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_SPI1, RST_FCLK_SPI1, RST_PCLK_SPI1, RST_FCLK_SPI1})
|
||||
|
||||
#define KPC_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_KPC, RST_FCLK_KPC, RST_PCLK_KPC, RST_FCLK_KPC})
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FRACDIV_ROOT_CLK_26M,
|
||||
FRACDIC_ROOT_CLK_408M
|
||||
} FracDivRootClk_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FracDivRootClk_e source;
|
||||
uint32_t fracDiv0DivRatioInteger;
|
||||
uint32_t fracDiv0DivRatioFrac;
|
||||
uint32_t fracDiv1DivRatioInteger;
|
||||
uint32_t fracDiv1DivRatioFrac;
|
||||
} FracDivConfig_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FRACDIV0_OUT0,
|
||||
FRACDIV0_OUT1,
|
||||
FRACDIV0_OUT2,
|
||||
FRACDIV0_OUT3,
|
||||
|
||||
FRACDIV1_OUT0,
|
||||
FRACDIV1_OUT1,
|
||||
FRACDIV1_OUT2,
|
||||
FRACDIV1_OUT3
|
||||
} FracDivOutClkId_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BCLK0,
|
||||
BCLK1
|
||||
} BclkId_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MCLK0,
|
||||
MCLK1,
|
||||
MCLK2
|
||||
} MclkId_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BCLK_SRC_FRACDIV0_OUT0 = 1,
|
||||
BCLK_SRC_FRACDIV0_OUT1 = 2,
|
||||
BCLK_SRC_FRACDIV0_OUT2 = 3,
|
||||
BCLK_SRC_FRACDIV0_OUT3 = 4,
|
||||
|
||||
BCLK_SRC_FRACDIV1_OUT0 = 5,
|
||||
BCLK_SRC_FRACDIV1_OUT1 = 6,
|
||||
BCLK_SRC_FRACDIV1_OUT2 = 7,
|
||||
BCLK_SRC_FRACDIV1_OUT3 = 8,
|
||||
BCLK_SRC_CLK_MFG = 9,
|
||||
BCLK_SRC_19P2M = 10
|
||||
} BclkSrc_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MCLK_SRC_FRACDIV0_OUT0 = 1,
|
||||
MCLK_SRC_FRACDIV0_OUT1 = 2,
|
||||
MCLK_SRC_FRACDIV0_OUT2 = 3,
|
||||
MCLK_SRC_FRACDIV0_OUT3 = 4,
|
||||
|
||||
MCLK_SRC_FRACDIV1_OUT0 = 5,
|
||||
MCLK_SRC_FRACDIV1_OUT1 = 6,
|
||||
MCLK_SRC_FRACDIV1_OUT2 = 7,
|
||||
MCLK_SRC_FRACDIV1_OUT3 = 8,
|
||||
MCLK_SRC_CLK_MFG = 9,
|
||||
MCLK_SRC_19P2M = 10,
|
||||
MCLK_SRC_CLK_SMP = 11,
|
||||
MCLK_SRC_CLK_USBP_12M = 12,
|
||||
MCLK_SRC_CLK_USBP_48M = 13,
|
||||
MCLK_SRC_CLK_USBC_PHY = 14,
|
||||
} MclkSrc_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GPR_APRST_SWRST = 0,
|
||||
GPR_APRST_WDG,
|
||||
GPR_APRST_LOCKUP,
|
||||
GPR_APRST_INVALID,
|
||||
}ApRstSource_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GPR_CPRST_SWRST = 0,
|
||||
GPR_CPRST_WDG,
|
||||
GPR_CPRST_LOCKUP,
|
||||
GPR_CPRST_INVALID,
|
||||
}CpRstSource_e;
|
||||
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
#ifndef BSP_I2S_H
|
||||
#define BSP_I2S_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "ec618.h"
|
||||
#include "bsp.h"
|
||||
#include "hal_i2s.h" // To use some of typedef in this H file and the macro of DMA_CHAIN_NUM(can dynamic array in C99?)
|
||||
|
||||
#define POLLING_MODE 0x1
|
||||
#define DMA_MODE 0x2
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// I2S Setting field Start
|
||||
// All the I2S's parameters that need user to set are all put here
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ES8388_IICADDR 0x11
|
||||
#define NAU88C22_IICADDR 0x1A
|
||||
#define ES8311_IICADDR 0x18
|
||||
|
||||
// Sample rate that 618 supports
|
||||
#define SAMPLE_RATE_8K 0x1
|
||||
#define SAMPLE_RATE_16K 0x2
|
||||
#define SAMPLE_RATE_32K 0x3
|
||||
#define SAMPLE_RATE_22_05K 0x4
|
||||
#define SAMPLE_RATE_44_1K 0x5
|
||||
#define SAMPLE_RATE_48K 0x6
|
||||
#define SAMPLE_RATE_96K 0x7
|
||||
|
||||
|
||||
// I2S0 Configuration
|
||||
#define RTE_I2S0 1
|
||||
#define RTE_I2S0_IO_MODE DMA_MODE
|
||||
|
||||
#define RTE_I2S0_MCLK_PAD_ADDR 39
|
||||
#define RTE_I2S0_MCLK_FUNC PAD_MUX_ALT1
|
||||
|
||||
#define RTE_I2S0_BCLK_PAD_ADDR 35
|
||||
#define RTE_I2S0_BCLK_FUNC PAD_MUX_ALT1
|
||||
|
||||
#define RTE_I2S0_LRCK_PAD_ADDR 36
|
||||
#define RTE_I2S0_LRCK_FUNC PAD_MUX_ALT1
|
||||
|
||||
#define RTE_I2S0_DIN_PAD_ADDR 37
|
||||
#define RTE_I2S0_DIN_FUNC PAD_MUX_ALT1
|
||||
|
||||
#define RTE_I2S0_DOUT_PAD_ADDR 38
|
||||
#define RTE_I2S0_DOUT_FUNC PAD_MUX_ALT1
|
||||
|
||||
// I2S1 Configuration
|
||||
#define RTE_I2S1 0
|
||||
#define RTE_I2S1_IO_MODE DMA_MODE
|
||||
|
||||
#define RTE_I2S1_MCLK_PAD_ADDR 18
|
||||
#define RTE_I2S1_MCLK_FUNC PAD_MUX_ALT1
|
||||
|
||||
#define RTE_I2S1_BCLK_PAD_ADDR 19
|
||||
#define RTE_I2S1_BCLK_FUNC PAD_MUX_ALT1
|
||||
|
||||
#define RTE_I2S1_LRCK_PAD_ADDR 20
|
||||
#define RTE_I2S1_LRCK_FUNC PAD_MUX_ALT1
|
||||
|
||||
#define RTE_I2S1_DIN_PAD_ADDR 21
|
||||
#define RTE_I2S1_DIN_FUNC PAD_MUX_ALT1
|
||||
|
||||
#define RTE_I2S1_DOUT_PAD_ADDR 22
|
||||
#define RTE_I2S1_DOUT_FUNC PAD_MUX_ALT1
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// I2S Setting field End
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
/****** I2S Event *****/
|
||||
#define I2S_EVENT_TRANSFER_COMPLETE (1UL << 0) // Data Transfer completed
|
||||
#define I2S_EVENT_DATA_LOST (1UL << 1) // Data lost: Receive overflow / Transmit underflow
|
||||
#define I2S_EVENT_MODE_FAULT (1UL << 2) // Master Mode Fault (SS deactivated when Master)
|
||||
|
||||
// DMA I2S0 Request ID
|
||||
#define RTE_I2S0_DMA_TX_REQID DMA_REQUEST_I2S0_TX
|
||||
#define RTE_I2S0_DMA_RX_REQID DMA_REQUEST_I2S0_RX
|
||||
|
||||
// DMA I2S1 Request ID
|
||||
#define RTE_I2S1_DMA_TX_REQID DMA_REQUEST_I2S1_TX
|
||||
#define RTE_I2S1_DMA_RX_REQID DMA_REQUEST_I2S1_RX
|
||||
|
||||
typedef void (*i2sCbEvent_fn) (uint32_t event, uint32_t arg); // i2s callback event.
|
||||
|
||||
|
||||
// I2S IRQ
|
||||
typedef struct
|
||||
{
|
||||
IRQn_Type irqNum; // I2S IRQ Number
|
||||
IRQ_Callback_t cbIrq;
|
||||
} i2sIrq_t;
|
||||
|
||||
// I2S DMA
|
||||
typedef struct
|
||||
{
|
||||
DmaInstance_e txInstance; // Transmit DMA instance number
|
||||
int8_t txCh; // Transmit channel number
|
||||
uint8_t txReq; // Transmit DMA request number
|
||||
void (*txCb)(uint32_t event); // Transmit callback
|
||||
DmaDescriptor_t *txDescriptor; // Tx descriptor
|
||||
DmaInstance_e rxInstance; // Receive DMA instance number
|
||||
int8_t rxCh; // Receive channel number
|
||||
uint8_t rxReq; // Receive DMA request number
|
||||
void (*rxCb)(uint32_t event); // Receive callback
|
||||
DmaDescriptor_t *rxDescriptor; // Rx descriptor
|
||||
} i2sDma_t;
|
||||
|
||||
|
||||
// I2S PINS
|
||||
typedef const struct
|
||||
{
|
||||
PIN *mclk; // main clk Pin identifier
|
||||
PIN *bclk; // pixel clk Pin identifier
|
||||
PIN *lrck; // cs Pin identifier
|
||||
PIN *din; // din Pin identifier
|
||||
PIN *dout; // dout Pin identifier
|
||||
} i2sPins_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t busy; // Transmitter/Receiver busy flag
|
||||
uint8_t dataLost; // Data lost: Receive overflow / Transmit underflow (cleared on start of transfer operation)
|
||||
uint8_t modeFault; // Mode fault detected; optional (cleared on start of transfer operation)
|
||||
} i2sStatus_t;
|
||||
|
||||
// I2S Transfer Information (Run-Time)
|
||||
typedef struct
|
||||
{
|
||||
uint32_t num; // Total number of transfers
|
||||
uint8_t *rxBuf; // Pointer to in data buffer
|
||||
uint8_t *txBuf; // Pointer to out data buffer
|
||||
uint32_t rxCnt; // Number of data received
|
||||
uint32_t txCnt; // Number of data sent
|
||||
uint32_t dumpVal; // Variable for dumping DMA data
|
||||
uint16_t defVal; // Default transfer value
|
||||
} i2sTransferInfo_t;
|
||||
|
||||
// I2S information (Run-time)
|
||||
typedef struct
|
||||
{
|
||||
i2sCbEvent_fn txCbEvent; // tx event callback
|
||||
i2sCbEvent_fn rxCbEvent; // rx event callback
|
||||
uint32_t mode; // I2S mode
|
||||
uint32_t busSpeed; // I2S bus speed
|
||||
uint16_t chainCnt;
|
||||
uint32_t totalNum; // Total length of audio source
|
||||
} i2sInfo_t;
|
||||
|
||||
|
||||
// I2S Resources definition
|
||||
typedef struct
|
||||
{
|
||||
I2S_TypeDef *reg; // I2S register pointer
|
||||
i2sPins_t pins; // I2S PINS configuration
|
||||
i2sDma_t *dma; // I2S DMA configuration pointer
|
||||
i2sIrq_t *irq; // I2S IRQ configuration pointer
|
||||
i2sInfo_t *info; // Run-Time Information
|
||||
} i2sResources_t;
|
||||
|
||||
/**
|
||||
\brief General power states
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
I2S_POWER_OFF, // Power off: no operation possible
|
||||
I2S_POWER_FULL // Power on: full operation at maximum performance
|
||||
} i2sPowerState_e;
|
||||
|
||||
|
||||
/**
|
||||
\brief Access structure of the I2S Driver.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int32_t (*init) (i2sCbEvent_fn txCbEvent, i2sCbEvent_fn rxCbEvent); // Initialize I2S Interface.
|
||||
int32_t (*deInit) (void); // De-initialize I2S Interface.
|
||||
int32_t (*powerCtrl) (i2sPowerState_e state); // Control I2S Interface Power.
|
||||
int32_t (*send) (void *data, uint32_t chunkNum); // Start sending data from I2S Interface.
|
||||
int32_t (*recv) (void *data, uint32_t chunkNum); // Start receiving data from I2S Interface.
|
||||
int32_t (*ctrl) (uint32_t control, uint32_t arg); // Control I2S Interface.
|
||||
uint32_t (*getTotalCnt) (void);
|
||||
} const i2sDrvInterface_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t slaveModeEn : 1; // Slave Mode Enable
|
||||
uint32_t slotSize : 5; // Slot Size
|
||||
uint32_t wordSize : 5; // Word Size
|
||||
uint32_t alignMode : 1; // Align Mode
|
||||
uint32_t endianMode : 1; // Endian Mode
|
||||
uint32_t dataDly : 2; // Data Delay
|
||||
uint32_t txPad : 2; // Tx Padding
|
||||
uint32_t rxSignExt : 1; // Rx Sign extention
|
||||
uint32_t txPack : 2; // Tx Pack
|
||||
uint32_t rxPack : 2; // Rx Pack
|
||||
uint32_t txFifoEndianMode : 1; // Tx Fifo Endian Mode
|
||||
uint32_t rxFifoEndianMode : 1; // Rx Fifo Endian Mode
|
||||
}i2sDataFmt_t;
|
||||
|
||||
/** \brief I2S Slot Control */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t slotEn : 8; // Slot Enable
|
||||
uint32_t slotNum : 3; // Slot number per frame synchronization
|
||||
}i2sSlotCtrl_t;
|
||||
|
||||
/** \brief I2S Bclk Frame Synchronization Control */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bclkPolarity : 1; // Bclk Polarity
|
||||
uint32_t fsPolarity : 1; // Frame Synchronization Polarity
|
||||
uint32_t fsWidth : 6; // Frame Synchronization width
|
||||
}i2sBclkFsCtrl_t;
|
||||
|
||||
/** \brief I2S DMA Control */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t rxDmaReqEn : 1; // Rx Dma Req Enable
|
||||
uint32_t txDmaReqEn : 1; // Tx Dma Req Enable
|
||||
uint32_t rxDmaTimeOutEn : 1; // Rx Dma Timeout Enable
|
||||
uint32_t dmaWorkWaitCycle : 5; // Dma Work Wait Cycle
|
||||
uint32_t rxDmaBurstSizeSub1 : 4; // Rx Dma Burst Size subtract 1
|
||||
uint32_t txDmaBurstSizeSub1 : 4; // Tx Dma Burst Size subtract 1
|
||||
uint32_t rxDmaThreadHold : 4; // Rx Dma Threadhold
|
||||
uint32_t txDmaThreadHold : 4; // Tx Dma Threadhold
|
||||
uint32_t rxFifoFlush : 1; // Rx Fifo flush
|
||||
uint32_t txFifoFlush : 1; // Tx Fifo flush
|
||||
}i2sDmaCtrl_t;
|
||||
|
||||
/** \brief I2S Interrupt Control */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t txUnderRunIntEn : 1; // Tx Underrun interrupt Enable
|
||||
uint32_t txDmaErrIntEn : 1; // Tx Dma Err Interrupt Enable
|
||||
uint32_t txDatIntEn : 1; // Tx Data Interrupt Enable
|
||||
uint32_t rxOverFlowIntEn : 1; // Rx Overflow Interrupt Enable
|
||||
uint32_t rxDmaErrIntEn : 1; // Rx Dma Err Interrupt Enable
|
||||
uint32_t rxDatIntEn : 1; // Rx Data Interrupt Enable
|
||||
uint32_t rxTimeOutIntEn : 1; // Rx Timeout Interrupt Enable
|
||||
uint32_t fsErrIntEn : 1; // Frame Start Interrupt Enable
|
||||
uint32_t frameStartIntEn : 1; // Frame End Interrupt Enable
|
||||
uint32_t frameEndIntEn : 1; // Frame End Interrupt Enable
|
||||
uint32_t cspiBusTimeOutIntEn : 1; // Not use
|
||||
uint32_t txIntThreshHold : 4; // Tx Interrupt Threadhold
|
||||
uint32_t rxIntThreshHold : 4; // Rx Interrupt Threadhold
|
||||
}i2sIntCtrl_t;
|
||||
|
||||
/** \brief I2S Timeout Cycle */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t rxTimeOutCycle : 24; // Rx Timeout cycle
|
||||
}i2sTimeOutCycle_t;
|
||||
|
||||
/** \brief I2S Status */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t txUnderRun : 1; // Tx Underrun
|
||||
uint32_t txDmaErr : 1; // Tx Dma Err
|
||||
uint32_t txDataRdy : 1; // Tx Data ready, readOnly
|
||||
uint32_t rxOverFlow : 1; // Rx OverFlow
|
||||
uint32_t rxDmaErr : 1; // Rx Dma Err
|
||||
uint32_t rxDataRdy : 1; // Rx Data ready, readOnly
|
||||
uint32_t rxFifoTimeOut : 1; // Rx Fifo timeout
|
||||
uint32_t fsErr : 4; // Frame synchronization Err
|
||||
uint32_t frameStart : 1; // Frame start
|
||||
uint32_t frameEnd : 1; // Frame end
|
||||
uint32_t txFifoLevel : 6; // Tx Fifo Level, readOnly
|
||||
uint32_t rxFifoLevel : 6; // Rx Fifo level, readOnly
|
||||
uint32_t cspiBusTimeOut : 1; // Not use
|
||||
}i2sStats_t;
|
||||
|
||||
/** \brief I2S Control */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t i2sMode : 2; // I2S Mode
|
||||
}i2sCtrl_t;
|
||||
|
||||
/** \brief I2S Auto Configure Control */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t autoCgEn : 1; // Auto Configure Enable
|
||||
}i2sAutoCgCtrl_t;
|
||||
|
||||
/**
|
||||
\brief I2S control bits.
|
||||
*/
|
||||
#define I2S_CTRL_TRANSABORT (1UL << 0) // I2S trans abort
|
||||
#define I2S_CTRL_SAMPLE_RATE_SLAVE (1UL << 1) // I2S sample rate setting, used in ec618 slave mode
|
||||
#define I2S_CTRL_SAMPLE_RATE_MASTER (1UL << 2) // I2S sample rate setting, used in ec618 master mode
|
||||
#define I2S_CTRL_SET_TOTAL_NUM (1UL << 3) // Audio source total num
|
||||
#define I2S_CTRL_DATA_FORMAT (1UL << 4) // I2S data format
|
||||
#define I2S_CTRL_SLOT_CTRL (1UL << 5) // I2S slot ctrl
|
||||
#define I2S_CTRL_BCLK_FS_CTRL (1UL << 6) // I2S bclk fs ctrl
|
||||
#define I2S_CTRL_DMA_CTRL (1UL << 7) // I2S dma ctrl
|
||||
#define I2S_CTRL_INT_CTRL (1UL << 8) // I2S int ctrl
|
||||
#define I2S_CTRL_TIMEOUT_CYCLE (1UL << 9) // I2S timeout cycle
|
||||
#define I2S_CTRL_STATUS (1UL << 10) // I2S status
|
||||
#define I2S_CTRL_I2SCTL (1UL << 11) // I2S control
|
||||
#define I2S_CTRL_AUTO_CG_CTRL (1UL << 12) // I2S auto cg ctrl
|
||||
#define I2S_CTRL_INIT (1UL << 13) // I2S init
|
||||
#define I2S_CTRL_START_STOP (1UL << 14) // I2S audio play start/stop ctrl
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BSP_I2S_H */
|
||||
@@ -0,0 +1,147 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2018-, Copyrigths of AirM2M Ltd.
|
||||
* File name: ic.h
|
||||
* Description: EC618 interrupt controller header file
|
||||
* History: Rev1.0 2018-11-15
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _IC_EC618_H
|
||||
#define _IC_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup xic_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
#define NUM_APXIC_MODULE (4U) /**< number of XIC module */
|
||||
#define NUM_APXIC0_INT (32U) /**< number of interrupts in XIC0 */
|
||||
#define NUM_APXIC1_INT (32U) /**< number of interrupts in XIC1 */
|
||||
#define NUM_APXIC2_INT (32U) /**< number of interrupts in XIC2 */
|
||||
#define NUM_APXIC3_INT (32U) /**< number of interrupts in XIC3 */
|
||||
|
||||
/** ISR function type define */
|
||||
typedef void ( *ISRFunc_T )(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
\fn void IC_PowupInit(void)
|
||||
\brief Initialize the interrupt controller, including HW configuration and ISR initialization,
|
||||
called when POR or wakeup from Hibernate, in which the SRAM contents have been lost.
|
||||
*/
|
||||
void IC_PowupInit(void);
|
||||
/**
|
||||
\fn void IC_Powoff(void)
|
||||
\brief DeInitialize the interrupt controller, including HW configuration and ISR initialization.
|
||||
*/
|
||||
void IC_Powoff(void);
|
||||
/**
|
||||
\fn void XIC_SetVector(IRQn_Type IRQn, ISRFunc_T vector)
|
||||
\brief Sets an XIC interrupt vector in SRAM based interrupt vector table.
|
||||
Use this function to bind the XIC interrupt and application ISR.
|
||||
\param[in] IRQn Interrupt number
|
||||
\param[in] vector Address of interrupt handler function
|
||||
\note The interrupt number must be positive
|
||||
*/
|
||||
void XIC_SetVector(IRQn_Type IRQn, ISRFunc_T vector);
|
||||
|
||||
/**
|
||||
\fn void XIC_EnableIRQ(IRQn_Type IRQn)
|
||||
\brief Enables a device specific interrupt in the XIC interrupt controller.
|
||||
\param[in] IRQn Interrupt number
|
||||
\note The interrupt number must be positive
|
||||
*/
|
||||
void XIC_EnableIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**
|
||||
\fn void XIC_DisableIRQ(IRQn_Type IRQn)
|
||||
\brief Disables a device specific interrupt in the XIC interrupt controller.
|
||||
\param[in] IRQn Interrupt number
|
||||
\note The interrupt number must be positive
|
||||
*/
|
||||
void XIC_DisableIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**
|
||||
\fn void XIC_BackupIRQSetting(uint32_t *mask_array, uint32_t *clrovf_array)
|
||||
|
||||
\brief backup the interrupt mask and ovf setting before sleep
|
||||
\param[out] mask_array mask0, mask1, clrovf0 to store the irq mask and ovf setting
|
||||
\param[out] clrovf_array
|
||||
\note
|
||||
*/
|
||||
|
||||
void XIC_BackupIRQSetting(uint32_t *mask_array, uint32_t *clrovf_array);
|
||||
|
||||
/**
|
||||
\fn void XIC_RestoreIRQSetting(uint32_t *mask_array, uint32_t *clrovf_array)
|
||||
|
||||
\brief restore the interrupt mask and ovf setting after sleep
|
||||
\param[in] mask_array mask0, mask1, clrovf0 is the stored value before sleep
|
||||
\param[out] clrovf_array
|
||||
\note
|
||||
*/
|
||||
void XIC_RestoreIRQSetting(uint32_t *mask_array, uint32_t *clrovf_array);
|
||||
|
||||
/**
|
||||
\fn void XIC_SetPendingIRQ(IRQn_Type IRQn)
|
||||
\brief Sets the pending bit of a device specific interrupt in the XIC pending register,
|
||||
mainly used for SW generating interrupt.
|
||||
\param[in] IRQn Interrupt number
|
||||
\note The interrupt number must be positive
|
||||
*/
|
||||
void XIC_SetPendingIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**
|
||||
\fn void XIC_ClearPendingIRQ(IRQn_Type IRQn)
|
||||
\brief Clears the pending bit of a device specific interrupt in the XIC pending register.
|
||||
\param[in] IRQn Interrupt number
|
||||
\note The interrupt number must be positive
|
||||
*/
|
||||
void XIC_ClearPendingIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**
|
||||
\fn uint32_t XIC_LatchIRQ(XIC_TypeDef* xic)
|
||||
\brief Latch the pending interrupt status to the latch register and read out.
|
||||
\param[in] xic Pointer to XIC instance
|
||||
\return Interrupt status
|
||||
*/
|
||||
uint32_t XIC_LatchIRQ(XIC_TypeDef* xic);
|
||||
|
||||
/**
|
||||
\fn void XIC_SuppressOvfIRQ(IRQn_Type IRQn)
|
||||
\brief Suppress overflow IRQ
|
||||
\param[in] IRQn Interrupt number
|
||||
\note The interrupt number must be positive
|
||||
*/
|
||||
void XIC_SuppressOvfIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**
|
||||
\fn void XIC_ClearAllPendingIRQ(XIC_TypeDef* xic)
|
||||
\brief Clears all pending bits of a XIC interrupt controller.
|
||||
\param[in] xic Pointer to XIC instance
|
||||
*/
|
||||
void XIC_ClearAllPendingIRQ(XIC_TypeDef* xic);
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
|
||||
* File name: kpc_ec618.h
|
||||
* Description: EC618 kpc driver header file
|
||||
* History: Rev1.0 2021-07-23
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _KPC_EC618_H
|
||||
#define _KPC_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup kpc_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/** \brief List of debounce clock divider ratio */
|
||||
typedef enum
|
||||
{
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_2 = 1U, /**< KPC debounce clock divider ratio select as 2 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_4 = 2U, /**< KPC debounce clock divider ratio select as 4 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_8 = 3U, /**< KPC debounce clock divider ratio select as 8 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_16 = 4U, /**< KPC debounce clock divider ratio select as 16 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_32 = 5U, /**< KPC debounce clock divider ratio select as 32 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_64 = 6U, /**< KPC debounce clock divider ratio select as 64 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_128 = 7U, /**< KPC debounce clock divider ratio select as 128 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_256 = 8U, /**< KPC debounce clock divider ratio select as 256 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_512 = 9U, /**< KPC debounce clock divider ratio select as 512 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_1024 = 10U, /**< KPC debounce clock divider ratio select as 1024 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_2048 = 11U, /**< KPC debounce clock divider ratio select as 2048 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_4096 = 12U, /**< KPC debounce clock divider ratio select as 4096 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_8192 = 13U, /**< KPC debounce clock divider ratio select as 8192 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_16384 = 14U, /**< KPC debounce clock divider ratio select as 16384 */
|
||||
KPC_DEBOUNCE_CLK_DIV_RATIO_32768 = 15U, /**< KPC debounce clock divider ratio select as 32768 */
|
||||
} KpcDebounceClkDivRatio_t;
|
||||
|
||||
/** \brief List of debounce width */
|
||||
typedef enum
|
||||
{
|
||||
KPC_DEBOUNCE_WIDTH_5_CYCLES = 5U, /**< KPC debounce width is 5 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_6_CYCLES = 6U, /**< KPC debounce width is 6 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_7_CYCLES = 7U, /**< KPC debounce width is 7 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_8_CYCLES = 8U, /**< KPC debounce width is 8 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_9_CYCLES = 9U, /**< KPC debounce width is 9 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_10_CYCLES = 10U, /**< KPC debounce width is 10 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_11_CYCLES = 11U, /**< KPC debounce width is 11 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_12_CYCLES = 12U, /**< KPC debounce width is 12 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_13_CYCLES = 13U, /**< KPC debounce width is 13 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_14_CYCLES = 14U, /**< KPC debounce width is 14 Cycles of debounce clock */
|
||||
KPC_DEBOUNCE_WIDTH_15_CYCLES = 15U, /**< KPC debounce width is 15 Cycles of debounce clock */
|
||||
} KpcDebounceWidth_t;
|
||||
|
||||
/** \brief List of key scan polarity */
|
||||
typedef enum
|
||||
{
|
||||
KPC_SCAN_POLARITY_0 = 0U, /**< KPC outputs low level scan waveform for active row while other valid rows is high */
|
||||
KPC_SCAN_POLARITY_1 = 1U, /**< KPC outputs high level scan waveform for active row while other valid rows is low */
|
||||
} KpcScanPolarity_t;
|
||||
|
||||
/** \brief List of key scan divider ratio */
|
||||
typedef enum
|
||||
{
|
||||
KPC_SCAN_DIV_RATIO_2 = 1U, /**< KPC scan frequence divider ratio set as 2 */
|
||||
KPC_SCAN_DIV_RATIO_4 = 2U, /**< KPC scan frequence divider ratio set as 4 */
|
||||
KPC_SCAN_DIV_RATIO_8 = 3U, /**< KPC scan frequence divider ratio set as 8 */
|
||||
KPC_SCAN_DIV_RATIO_16 = 4U, /**< KPC scan frequence divider ratio set as 16 */
|
||||
KPC_SCAN_DIV_RATIO_32 = 5U, /**< KPC scan frequence divider ratio set as 32 */
|
||||
KPC_SCAN_DIV_RATIO_64 = 6U, /**< KPC scan frequence divider ratio set as 64 */
|
||||
KPC_SCAN_DIV_RATIO_128 = 7U, /**< KPC scan frequence divider ratio set as 128 */
|
||||
} KpcScanDivRatio_t;
|
||||
|
||||
/** \brief List of debounce width */
|
||||
typedef enum
|
||||
{
|
||||
KPC_ROW_0 = 1U, /**< KPC row0 enable mask */
|
||||
KPC_ROW_1 = 2U, /**< KPC row1 enable mask */
|
||||
KPC_ROW_2 = 4U, /**< KPC row2 enable mask */
|
||||
KPC_ROW_3 = 8U, /**< KPC row3 enable mask */
|
||||
KPC_ROW_4 = 16U, /**< KPC row4 enable mask */
|
||||
KPC_ROW_ALL = 0x1FU /**< KPC all rows enable mask */
|
||||
} KpcRow_t;
|
||||
|
||||
/** \brief List of debounce width */
|
||||
typedef enum
|
||||
{
|
||||
KPC_COLUMN_0 = 1U, /**< KPC column0 enable mask */
|
||||
KPC_COLUMN_1 = 2U, /**< KPC column1 enable mask */
|
||||
KPC_COLUMN_2 = 4U, /**< KPC column2 enable mask */
|
||||
KPC_COLUMN_3 = 8U, /**< KPC column3 enable mask */
|
||||
KPC_COLUMN_4 = 16U, /**< KPC column4 enable mask */
|
||||
KPC_COLUMN_ALL = 0x1FU /**< KPC all columns enable mask */
|
||||
} KpcColumn_t;
|
||||
|
||||
/** \brief KPC debounce configuration, decounce exits when consecutive debounceWidth scans give the same result */
|
||||
typedef struct
|
||||
{
|
||||
KpcDebounceClkDivRatio_t debounceClkDivRatio; /**< debounce clock divider ratio */
|
||||
KpcDebounceWidth_t debounceWidth; /**< debounce width */
|
||||
} KpcDebounceConfig_t;
|
||||
|
||||
/** \brief KPC auto repeat configuration */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t enable; /**< enable auto repeat or not */
|
||||
uint8_t delay; /**< auto repeat delay cycles of scan period, if scan period is 50ms and this value is set as 10,
|
||||
then autorepeat event will start to be reported 500ms later after key press is detected and key press keeps hold */
|
||||
|
||||
uint8_t period; /**< auto repeat report interval of scan period, if scan period is 50ms and this value is set as 2,
|
||||
then autorepeat event will be reported in interval of 100ms until key is released */
|
||||
} KpcAutoRepeatConfig_t;
|
||||
|
||||
/** \brief KPC configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t validRowMask; /**< Bitmap of valid rows */
|
||||
uint8_t validColumnMask; /**< Bitmap of valid columns */
|
||||
KpcDebounceConfig_t debounceConfig; /**< KPC debounce configuration */
|
||||
KpcAutoRepeatConfig_t autoRepeat; /**< KPC auto repeat configuration */
|
||||
KpcScanPolarity_t scanPolarity; /**< KPC scan polarity */
|
||||
KpcScanDivRatio_t scanDivRatio; /**< KPC scan divider ratio */
|
||||
} KpcConfig_t;
|
||||
|
||||
/** \brief List of kpc report key value */
|
||||
typedef enum
|
||||
{
|
||||
KPC_REPORT_KEY_RELEASE = 0U, /**< Key is released */
|
||||
KPC_REPORT_KEY_PRESS = 1U, /**< Key is pressed */
|
||||
KPC_REPORT_KEY_REPEAT = 2U, /**< Key holds pressed */
|
||||
} KpcReportValue_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t value : 2; /**< Key value */
|
||||
uint8_t column : 3; /**< Key column */
|
||||
uint8_t row : 3; /**< Key row */
|
||||
} KpcReportEvent_t;
|
||||
|
||||
/**
|
||||
\brief Defines callback function prototype.
|
||||
Callback function will be called in KPC interrupt service routine
|
||||
\param report key event value
|
||||
*/
|
||||
|
||||
typedef void (*kpc_callback_t)(KpcReportEvent_t event);
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \name KPC Configuration */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void KPC_getDefaultConfig(KpcConfig_t *config)
|
||||
\brief Gets the KPC default configuartion.
|
||||
This function sets the configuration structure to default values as below:
|
||||
\code
|
||||
config->debounceConfig.debounceClkDivRatio = KPC_DEBOUNCE_CLK_DIV_RATIO_16384;
|
||||
config->debounceConfig.debounceWidth = KPC_DEBOUNCE_WIDTH_7_CYCLES;
|
||||
|
||||
config->validRowMask = KPC_ROW_ALL;
|
||||
config->validColumnMask = KPC_COLUMN_ALL;
|
||||
|
||||
config->scanPolarity = KPC_SCAN_POLARITY_0;
|
||||
config->scanDivRatio = KPC_SCAN_DIV_RATIO_16;
|
||||
|
||||
config->autoRepeat.enable = 1;
|
||||
config->autoRepeat.delay = 10;
|
||||
config->autoRepeat.period = 1;
|
||||
|
||||
\endcode
|
||||
|
||||
\details debouncer and scan setting explaination:
|
||||
KPC input clock is 26M, if debouncer divider is set as KPC_DEBOUNCE_CLK_DIV_RATIO_16384, then one cycle is 16384/26M = 630us,
|
||||
debouncer depth set as 7, means we can filter out 630*7us(4.4ms) jitter
|
||||
|
||||
scan clock is sourced from debouncer clock, which means if scan frequency divider ratio is set as KPC_SCAN_DIV_RATIO_16 and
|
||||
when 5 rows are enabled, the scan frequency is 26M/16384/16/5 = 20HZ, each row scan signal width will be 1/20/5 = 10ms
|
||||
|
||||
\param[in] config Pointer to KPC configuration structure
|
||||
*/
|
||||
void KPC_getDefaultConfig(KpcConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn void KPC_init(const KpcConfig_t *config, kpc_callback_t callback)
|
||||
\brief Initialize KPC
|
||||
\param[in] config Pointer to KPC configuration
|
||||
\param[in] callback Function to be called when KPC interrupt occurs
|
||||
\return ARM_DRIVER_OK if the setting is successful
|
||||
ARM_DRIVER_ERROR_PARAMETER on parameter check failure
|
||||
*/
|
||||
int32_t KPC_init(const KpcConfig_t *config, kpc_callback_t callback);
|
||||
|
||||
/**
|
||||
\fn void KPC_deInit(void)
|
||||
\brief Deinitialize KPC
|
||||
*/
|
||||
void KPC_deInit(void);
|
||||
|
||||
/**
|
||||
\fn void KPC_startScan(void)
|
||||
\brief Starts KPC scan
|
||||
*/
|
||||
void KPC_startScan(void);
|
||||
|
||||
/**
|
||||
\fn void KPC_stopScan(void)
|
||||
\brief Stops KPC scan
|
||||
*/
|
||||
void KPC_stopScan(void);
|
||||
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _KPC_EC618_H */
|
||||
@@ -0,0 +1,143 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
|
||||
* File name: oneWire.h
|
||||
* Description: EC618 one wire bus driver file
|
||||
* History: Rev1.0 2020-12-17
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _ONEWIRE_EC618_H
|
||||
#define _ONEWIRE_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup onewire_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/** \brief OW Mode Select */
|
||||
typedef enum
|
||||
{
|
||||
STANDARD = 0, /**< Stand speed of onewire */
|
||||
OVERDRIVE /**< High speed of onewire */
|
||||
}OwModeSel_e;
|
||||
|
||||
/** \brief OW Status */
|
||||
typedef enum
|
||||
{
|
||||
OW_IDLE = 0x0,
|
||||
OW_RESET_SUCCESS = 0x2,
|
||||
OW_RESETPD_SUCCESS = 0x4,
|
||||
OW_READ_SUCCESS = 0x8,
|
||||
OW_WRITE_SUCCESS = 0x10,
|
||||
OW_TIMEOUT = 0x20,
|
||||
}OwStats_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *dataWrite;
|
||||
uint8_t *dataRead;
|
||||
uint8_t mode;
|
||||
}OwRes_t;
|
||||
|
||||
#define OWDRV_OK (0)
|
||||
#define OWDRV_RESET_ERR (-1)
|
||||
#define OWDRV_RESETPD_ERR (-2)
|
||||
#define OWDRV_READ_ERR (-3)
|
||||
#define OWDRV_WRITE_ERR (-4)
|
||||
#define OWDRV_TIMEOUT (-5)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
\fn void owInit()
|
||||
\brief Initialize ow
|
||||
*/
|
||||
void owInit(void);
|
||||
|
||||
/**
|
||||
\fn void owDeInit()
|
||||
\brief DeInitialize ow
|
||||
*/
|
||||
void owDeInit(void);
|
||||
|
||||
|
||||
/**
|
||||
\fn void owSetMode(OwModeSel_e mode)
|
||||
\brief ow set mode
|
||||
\param[in] mode ow mode
|
||||
*/
|
||||
void owSetMode(OwModeSel_e mode);
|
||||
|
||||
/**
|
||||
\fn int32_t owReset()
|
||||
\brief ow reset
|
||||
\return ow reset status
|
||||
*/
|
||||
int32_t owReset(void);
|
||||
|
||||
/**
|
||||
\fn int32_t owResetPd()
|
||||
\brief ow reset for presence detect
|
||||
\return ow reset presence detect status
|
||||
*/
|
||||
int32_t owResetPd(void);
|
||||
|
||||
/**
|
||||
\fn int32_t owWriteBit(uint8_t data)
|
||||
\brief write 1bit data to ow
|
||||
\param[in] data data to write to ow, LSB is effective
|
||||
\return ow write 1 bit status
|
||||
*/
|
||||
int32_t owWriteBit(uint8_t data);
|
||||
|
||||
/**
|
||||
\fn int32_t owWriteByte(uint8_t data)
|
||||
\brief write 1byte data to ow
|
||||
\param[in] data 1 byte data to write to ow
|
||||
\return ow write 1 byte status
|
||||
*/
|
||||
int32_t owWriteByte(uint8_t data);
|
||||
|
||||
/**
|
||||
\fn int32_t owReadBit()
|
||||
\brief read 1bit data
|
||||
\return ow read 1 bit status
|
||||
*/
|
||||
int32_t owReadBit(uint8_t * dataRead);
|
||||
|
||||
/**
|
||||
\fn int32_t owReadByte()
|
||||
\brief ow read 1 byte
|
||||
\return ow read 1 byte status
|
||||
*/
|
||||
int32_t owReadByte(uint8_t * dataRead);
|
||||
|
||||
/**
|
||||
\fn int32_t owTouchByte(uint8_t data)
|
||||
\brief read and write ow at the same time
|
||||
\return ow touch 1 byte status
|
||||
*/
|
||||
int32_t owTouchByte(uint8_t data);
|
||||
|
||||
/** \} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,173 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: pad.h
|
||||
* Description: EC618 pad driver header file
|
||||
* History:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _PAD_EC618_H_
|
||||
#define _PAD_EC618_H_
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
|
||||
/**
|
||||
\addtogroup pad_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/** \brief PAD pin mux selection */
|
||||
typedef enum
|
||||
{
|
||||
PAD_MUX_ALT0 = 0U, /**< Chip-specific */
|
||||
PAD_MUX_ALT1 = 1U, /**< Chip-specific */
|
||||
PAD_MUX_ALT2 = 2U, /**< Chip-specific */
|
||||
PAD_MUX_ALT3 = 3U, /**< Chip-specific */
|
||||
PAD_MUX_ALT4 = 4U, /**< Chip-specific */
|
||||
PAD_MUX_ALT5 = 5U, /**< Chip-specific */
|
||||
PAD_MUX_ALT6 = 6U, /**< Chip-specific */
|
||||
PAD_MUX_ALT7 = 7U, /**< Chip-specific */
|
||||
} PadMux_e;
|
||||
|
||||
|
||||
/** \brief Internal pull-up resistor configuration */
|
||||
typedef enum
|
||||
{
|
||||
PAD_PULL_UP_DISABLE = 0U, /**< Internal pull-up resistor is disabled */
|
||||
PAD_PULL_UP_ENABLE = 1U, /**< Internal pull-up resistor is enabled */
|
||||
} PadPullUp_e;
|
||||
|
||||
/** \brief Internal pull-down resistor configuration */
|
||||
typedef enum
|
||||
{
|
||||
PAD_PULL_DOWN_DISABLE = 0U, /**< Internal pull-down resistor is disabled */
|
||||
PAD_PULL_DOWN_ENABLE = 1U, /**< Internal pull-down resistor is enabled */
|
||||
} PadPullDown_e;
|
||||
|
||||
/** \brief Pull feature selection */
|
||||
typedef enum
|
||||
{
|
||||
PAD_PULL_AUTO = 0U, /**< Pull up/down is controlled by muxed alt function */
|
||||
PAD_PULL_INTERNAL = 1U, /**< Use internal pull-up/down resistor */
|
||||
} PadPullSel_e;
|
||||
|
||||
/** \brief Input buffer enable/disable */
|
||||
typedef enum
|
||||
{
|
||||
PAD_INPUT_BUFFER_DISABLE = 0U, /**< Input Buffer is disabled */
|
||||
PAD_INPUT_BUFFER_ENABLE = 1U, /**< Input Buffer is enabled */
|
||||
} PadInputBuffer_e;
|
||||
|
||||
/** \brief Configures pull feature */
|
||||
typedef enum
|
||||
{
|
||||
PAD_INTERNAL_PULL_UP = 0U, /**< select internal pull up */
|
||||
PAD_INTERNAL_PULL_DOWN = 1U, /**< select internal pull down */
|
||||
PAD_AUTO_PULL = 2U, /**< Pull up/down is controlled by muxed alt function */
|
||||
} PadPullConfig_e;
|
||||
|
||||
/** \brief PAD configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t : 4;
|
||||
uint32_t mux : 3; /**< Pad mux configuration */
|
||||
uint32_t : 1;
|
||||
uint32_t pullUpEnable : 1; /**< Enable pull-up */
|
||||
uint32_t pullDownEnable : 1; /**< Enable pull-down */
|
||||
uint32_t pullSelect : 1; /**< Pull select, external or internal control */
|
||||
uint32_t : 2;
|
||||
uint32_t inputBufferEnable : 1; /**< Enable/disable input buffer */
|
||||
uint32_t : 18;
|
||||
} PadConfig_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \name PAD Driver Initialization */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void PAD_driverInit(void);
|
||||
\brief Intialize PAD driver internal data, must be called before any other APIs
|
||||
*/
|
||||
void PAD_driverInit(void);
|
||||
|
||||
/**
|
||||
\fn void PAD_driverInit(void);
|
||||
\brief De-Intialize PAD driver, disable PAD clock and perform some clearups
|
||||
*/
|
||||
void PAD_driverDeInit(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name Configuration */
|
||||
/* \{ */
|
||||
|
||||
/**
|
||||
\fn void PAD_getDefaultConfig(PadConfig_t *config)
|
||||
\brief Gets the PAD default configuartion
|
||||
This function sets the configuration structure to default values as below:
|
||||
\code
|
||||
config->mux = PAD_MUX_ALT0;
|
||||
config->inputBufferEnable = PAD_INPUT_BUFFER_DISABLE;
|
||||
config->pullSelect = PAD_PULL_AUTO;
|
||||
config->pullUpEnable = PAD_PULL_UP_DISABLE;
|
||||
config->pullDownEnable = PAD_PULL_DOWN_DISABLE;
|
||||
\endcode
|
||||
\param config Pointer to PAD configuration structure
|
||||
*/
|
||||
void PAD_getDefaultConfig(PadConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn void PAD_setPinConfig(uint32_t pin, const PadConfig_t *config)
|
||||
\brief Sets the pad PCR register
|
||||
\param pin PAD pin number
|
||||
\param config Pointer to PAD configuration structure
|
||||
*/
|
||||
void PAD_setPinConfig(uint32_t paddr, const PadConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn void PAD_setPinMux(uint32_t pin, PadMux_e mux)
|
||||
\brief Configures pin mux
|
||||
\param pin PAD pin number
|
||||
\param mux pin signal source selection
|
||||
*/
|
||||
void PAD_setPinMux(uint32_t paddr, PadMux_e mux);
|
||||
|
||||
/**
|
||||
\fn void PAD_enablePinInputBuffer(uint32_t pin, bool enable)
|
||||
\brief Enable/disable pin's input buffer
|
||||
\param pin PAD pin number
|
||||
\param enable true to enable, false to disable
|
||||
*/
|
||||
void PAD_enablePinInputBuffer(uint32_t paddr, bool enable);
|
||||
|
||||
/**
|
||||
\fn void PAD_setPinPullConfig(uint32_t pin, PadPullConfig_e config)
|
||||
\brief Configures pin's pull feature
|
||||
\param pin PAD pin number
|
||||
\param config PAD pin pull configuration
|
||||
*/
|
||||
void PAD_setPinPullConfig(uint32_t paddr, PadPullConfig_e config);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \}*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PAD_EC618_H_ */
|
||||
@@ -0,0 +1,167 @@
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
*(C) Copyright 2018 AirM2M International Ltd.
|
||||
|
||||
* All Rights Reserved
|
||||
|
||||
******************************************************************************
|
||||
* Filename: pwrkey.h
|
||||
*
|
||||
* Description: header of pwrkey.c, power on/off and software debounce
|
||||
*
|
||||
* History: 2021.04.29 initiated by Zhao Weiqi
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef PWR_KEY_H
|
||||
#define PWR_KEY_H
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* INCLUDES *
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* MACROS *
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define KEY_BUF_SIZE 8
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* DATA TYPE DEFINITION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
int16_t longPressTimeout;
|
||||
int16_t repeatTimeout;
|
||||
int16_t pwrOffTimeout;
|
||||
}pwrKeyDly_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PWRKEY_PWRON_MODE = 0,
|
||||
PWRKEY_WAKEUP_LOWACTIVE_MODE,
|
||||
PWRKEY_WAKEUP_HIGHACTIVE_MODE,
|
||||
PWRKEY_UNKNOW_MODE,
|
||||
}pwrKeyWorkMode;
|
||||
|
||||
/*
|
||||
typedef enum
|
||||
{
|
||||
PWRKEY_SYSTEM_ON = 0,
|
||||
PWRKEY_SYSTEM_OFF,
|
||||
}pwrKeySysStatus;
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PWRKEY_RELEASE = 0,
|
||||
PWRKEY_PRESS,
|
||||
PWRKEY_LONGPRESS,
|
||||
PWRKEY_REPEAT,
|
||||
}pwrKeyPressStatus;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool negEdgeEn;
|
||||
bool posEdgeEn;
|
||||
}pwrKeyWakeupCfg_t;
|
||||
|
||||
|
||||
typedef void(* pwrKeyCallback_t)(pwrKeyPressStatus status);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pwrKeyWorkMode workMode;
|
||||
pwrKeyWakeupCfg_t wakeupCfg;
|
||||
pwrKeyDly_t delayCfg;
|
||||
pwrKeyCallback_t pwrKeyCallback;
|
||||
pwrKeyPressStatus curStatus;
|
||||
pwrKeyPressStatus keyBuf[KEY_BUF_SIZE];
|
||||
uint8_t bufOffset;
|
||||
}pwrKeyInfo_t;
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* GLOBAL FUNCTIONS DECLEARATION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief pwrKeyPushKey
|
||||
* @details push a key to power key buffer
|
||||
*
|
||||
* @param pwrKeyInfo
|
||||
@param status
|
||||
|
||||
* @return null
|
||||
*/
|
||||
void pwrKeyPushKey(pwrKeyInfo_t *pwrKeyInfo, pwrKeyPressStatus status);
|
||||
/**
|
||||
* @brief pwrKeyPopKey
|
||||
* @details pop a key from power key buffer and return the key status
|
||||
*
|
||||
* @param pwrKeyInfo
|
||||
* @return null
|
||||
*/
|
||||
pwrKeyPressStatus pwrKeyPopKey(pwrKeyInfo_t *pwrKeyInfo);
|
||||
/**
|
||||
* @brief pwrKeyStartPowerOff
|
||||
* @details force to enter power off status
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void pwrKeyStartPowerOff(void);
|
||||
/**
|
||||
* @brief pwrkeyPwrOnDebounce
|
||||
* @details power on debounce flow according to the configures
|
||||
*
|
||||
* @param tmpDelay in ms
|
||||
* @return null
|
||||
*/
|
||||
void pwrkeyPwrOnDebounce(int16_t tmpDelay);
|
||||
/**
|
||||
* @brief pwrKeyHwInit
|
||||
* @details power key hardware init
|
||||
*
|
||||
* @param pullUpEn
|
||||
* @return null
|
||||
*/
|
||||
void pwrKeyHwInit(bool pullUpEn);
|
||||
/**
|
||||
* @brief pwrKeyHwDeinit
|
||||
* @details power key hardware deinit
|
||||
*
|
||||
* @param pullUpEn
|
||||
* @return null
|
||||
*/
|
||||
void pwrKeyHwDeinit(bool pullUpEn);
|
||||
/**
|
||||
* @brief pwrKeyGetPinLevel
|
||||
* @details get power key pin value
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
bool pwrKeyGetPinLevel(void);
|
||||
/**
|
||||
* @brief pwrKeyGetPwrKeyMode
|
||||
* @details get power key mode in bootloader
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
pwrKeyWorkMode pwrKeyGetPwrKeyMode(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#ifndef __RNG_EC618_H__
|
||||
#define __RNG_EC618_H__
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
#include "clock.h"
|
||||
#include "ic.h"
|
||||
#include "string.h"
|
||||
|
||||
#define RNG_DEBUG_USING_PRINTF 0
|
||||
#define RNG_DEBUG_USING_UNILOG 0
|
||||
|
||||
#define RNG_IRQ_MODE 0
|
||||
|
||||
#define RNG_MAX_POLL_DELAY_US (8000*2)
|
||||
#define RNG_MAX_TRY_NUM 10
|
||||
#define RNG ((RngDesc_t*)MP_TRNG_BASE_ADDR)
|
||||
#define RNG_R_MAGIC 0xf45a97d4
|
||||
|
||||
|
||||
|
||||
#if (RNG_DEBUG_USING_UNILOG == 1)
|
||||
#include DEBUG_LOG_HEADER_FILE
|
||||
#endif
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
#include "slpman.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if RNG_DEBUG_USING_PRINTF
|
||||
#define RNGDEBUG(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define RNGDEBUG(...)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__IM uint32_t rsvd1[64];
|
||||
__IO uint32_t imrReg; //Interrupt mask reg ,0x100
|
||||
__IO uint32_t isrReg; //Interrupt status reg
|
||||
__OM uint32_t icrReg; //Interrupt clear reg
|
||||
__IO uint32_t cfgReg; //Configuration reg
|
||||
__IM uint32_t validReg; //Valid reg
|
||||
__IM uint32_t dataReg[6];
|
||||
__IO uint32_t srcEnableReg; //Random source enable reg
|
||||
__IO uint32_t sampleCntReg; //Sample Count reg
|
||||
__IO uint32_t autoCorrReg; //Auto correlation reg
|
||||
__IM uint32_t debugCtrlReg; //Debug Control reg
|
||||
__IM uint32_t rsvd2;
|
||||
__OM uint32_t swRstReg; //Reset reg
|
||||
__IM uint32_t rsvd3[29];
|
||||
__IM uint32_t busyReg; //Busy reg
|
||||
__OM uint32_t rstBitsCntReg; //Reset bits counter reg
|
||||
__IM uint32_t rsvd4[8];
|
||||
__IM uint32_t bistCntReg[3]; //BIST Counter reg
|
||||
__IO uint32_t rsvd5[5];
|
||||
}RngDesc_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RNG_SRC_SHORT_TEST_TYPE = 0,
|
||||
RNG_SRC_SHORT_TYPE = 1,
|
||||
RNG_SRC_LONG_TYPE = 2,
|
||||
RNG_SRC_LONGEST_TYPE = 3,
|
||||
}RngSrcSelType_e;
|
||||
|
||||
#define RNGDRV_OK (0)
|
||||
#define RNGDRV_IntErr (-1)
|
||||
#define RNGDRV_TimeOutErr (-2)
|
||||
|
||||
typedef enum{
|
||||
RNG_EHR_VALID_TYPE = 1,
|
||||
RNG_AUTO_CORR_ERR_TYPE = 2,
|
||||
RNG_CRNGT_ERR_TYPE = 4,
|
||||
RNG_VN_ERR_TYPE = 8
|
||||
}RngIntStatType_e;
|
||||
|
||||
/**
|
||||
\brief When rand is null, means generate random number to efuse. If rand isn't null, means generate to this parameter.
|
||||
\param[out] rand Memory address to receive generated random number.
|
||||
\return status
|
||||
*/
|
||||
int32_t rngGenRandom(uint8_t rand[24]);
|
||||
#endif
|
||||
@@ -0,0 +1,543 @@
|
||||
#ifndef __SCT_REG_H__
|
||||
#define __SCT_REG_H__
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
File name: sctreg.h
|
||||
Description: SCT register, Security Top is a HW use to do:
|
||||
* 1) cipher & integrity check
|
||||
* 2) AES/SHA
|
||||
* 3) PPP escape & CRC
|
||||
* 4) USB TX
|
||||
History: 2020/12/04 Originated by Jason
|
||||
******************************************************************************
|
||||
******************************************************************************/
|
||||
#include "ec618.h"
|
||||
|
||||
#if defined(__CC_ARM)
|
||||
#pragma anon_unions
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
* SCT control registers
|
||||
******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Cipher 0x4005-0000~0x4005-FFFF (64KB)
|
||||
*/
|
||||
#define SCT_REG_ADDR 0x40050000
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* SCT enable/disable register
|
||||
******************************************************************************/
|
||||
|
||||
#define SCT_EN_CTRL_REG ((__IO UINT32 *)SCT_REG_ADDR)
|
||||
|
||||
|
||||
/*
|
||||
* __IO UINT32 SCTEN;
|
||||
* Bit WIDTH DESP
|
||||
* 0 1 0 - SCT disable (reset value)
|
||||
* 1- SCT enable
|
||||
* 1:31 31 RSVD
|
||||
*/
|
||||
#define ENABLE_SCT() ((*(SCT_EN_CTRL_REG)) = 1)
|
||||
#define DISABLE_SCT() ((*(SCT_EN_CTRL_REG)) = 0)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
* SCT RNDIS/PPP config register
|
||||
******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* SctRndisCrcCfgReg RNDIS_CRC_CFG
|
||||
* Bit WIDTH DESP
|
||||
* 0 1 rndis_crc_in_bit_swap,
|
||||
* 0 - CRC calc from bit: inByte[0]
|
||||
* 1 - CRC calc from bit: inByte[7] (reset value)
|
||||
* 1 1 rndis_crc_comple_out
|
||||
* 0 - CRC out bit not comple
|
||||
* 1 - CRC out bit comple (reset value)
|
||||
* 2 1 rndis_crc_out_bit_swap
|
||||
* 0 - CRC out bit not swap
|
||||
* 1 - CRC out bit swap (reset value)
|
||||
* 3:6 4 rndis_crc_comple_in_num, how many input bytes need to be compled
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UINT32 crcInBitSwap : 1;
|
||||
UINT32 crcCompleOut : 1;
|
||||
UINT32 crcOutBitSwap : 1;
|
||||
UINT32 crcCompleInNum : 4;
|
||||
UINT32 : 25;
|
||||
};
|
||||
|
||||
UINT32 value32;
|
||||
}SctRndisCrcCfgReg;
|
||||
|
||||
|
||||
/*
|
||||
* SctPPPCrcInitReg PPP_CRC_INIT
|
||||
* Bit WIDTH DESP
|
||||
* 0:15 16 PPP CRC init value, reset value: 0xFFFF
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UINT32 crcInitValue : 16;
|
||||
UINT32 : 16;
|
||||
};
|
||||
|
||||
UINT32 value32;
|
||||
}SctPPPCrcInitReg;
|
||||
|
||||
|
||||
/*
|
||||
* SctPPPCrcCfgReg PPP_CRC_CFG
|
||||
* Bit WIDTH DESP
|
||||
* 0 1 ppp_crc_in_bit_swap
|
||||
* 0 - CRC calc from bit: inByte[0], (reset value)
|
||||
* 1 - CRC calc from bit: inByte[7]
|
||||
* 1 1 ppp_crc_comple_out
|
||||
* 0 - CRC out bit not comple
|
||||
* 1 - CRC out bit comple, (reset value)
|
||||
* 2 1 ppp_crc_out_bit_swap
|
||||
* 0 - CRC out bit not swap
|
||||
* 1 - CRC out bit swap (reset value)
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UINT32 crcInBitSwap : 1;
|
||||
UINT32 crcCompleOut : 1;
|
||||
UINT32 crcOutBitSwap : 1;
|
||||
UINT32 : 29;
|
||||
};
|
||||
|
||||
UINT32 value32;
|
||||
}SctPPPCrcCfgReg;
|
||||
|
||||
/*
|
||||
* PPP escape/deescape bitmap table
|
||||
*/
|
||||
#define SCT_PPP_ESCP_BITMAP_WORD_NUM 8
|
||||
#define SCT_PPP_DE_ESCP_BITMAP_WORD_NUM 8
|
||||
|
||||
|
||||
/*
|
||||
* SCT RNDIS PPP config register struct
|
||||
*/
|
||||
typedef struct SctRndisPPPCfgReg_Tag
|
||||
{
|
||||
__IO UINT32 RNDIS_CRC_INIT; /* RNDIS (802.3) CRC init value, reset value: 0, offset: 0x04 */
|
||||
__IO SctRndisCrcCfgReg RNDIS_CRC_CFG; /* RNDIS (802.3) CRC config. offset: 0x08 */
|
||||
__IO SctPPPCrcInitReg PPP_CRC_INIT; /* PPP CRC init value, reset value: 0xFFFF, offset: 0x0C */
|
||||
__IO SctPPPCrcCfgReg PPP_CRC_CFG; /* PPP CRC config, offset: 0x10 */
|
||||
|
||||
__IO UINT32 PPP_ESCP_BITMAP[SCT_PPP_ESCP_BITMAP_WORD_NUM]; /* PPP escape bitmap, offset: 0x14 */
|
||||
__IO UINT32 PPP_DE_ESCP_BITMAP[SCT_PPP_DE_ESCP_BITMAP_WORD_NUM];/* PPP de-escape bitmap, offset: 0x34 */
|
||||
}SctRndisPPPCfgReg;
|
||||
|
||||
/*
|
||||
* SCT RNDIS PPP config register start address
|
||||
*/
|
||||
#define SCT_RNDIS_PPP_CTRL_REG_ADDR (SCT_REG_ADDR + 0x04)
|
||||
|
||||
/*
|
||||
* SCT RNDIS PPP register pointer
|
||||
*/
|
||||
#define SCT_RNDIS_PPP_CFG_REG ((SctRndisPPPCfgReg *)SCT_RNDIS_PPP_CTRL_REG_ADDR)
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
* SCT (cipher/integrity) common config register
|
||||
******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* SctCommCfgWord0 COMM_CFG0
|
||||
* Bit WIDTH DESP
|
||||
* 0 1 sct_cfg_acg_en_rmi_acg
|
||||
* 0 - not enable auto gate, (reset value)
|
||||
* 1 - enable auto gate
|
||||
* 1 1 sct_cfg_acg_en_ahb_acg
|
||||
* 0 - not enable auto gate, (reset value)
|
||||
* 1 - enable auto gate
|
||||
* 16 1 sct_cfg_unilog_SCT_ChainStart
|
||||
* 0 - no unilog output, (reset value)
|
||||
* 1 - unilog output
|
||||
* 17 1 sct_cfg_unilog_SCT_Descriptor_done
|
||||
* 0 - no unilog output, (reset value)
|
||||
* 1 - unilog output
|
||||
* 18 1 sct_cfg_unilog_SCT_ChainEnd
|
||||
* 0 - no unilog output, (reset value)
|
||||
* 1 - unilog output
|
||||
* 19 1 sct_cfg_unilog_error_int
|
||||
* 0 - no unilog output, (reset value)
|
||||
* 1 - unilog output
|
||||
* 20 1 sct_usb_lb_ind, USB Tx big/Little endian output
|
||||
* 0 - little endian, (reset value)
|
||||
* 1 - big endian
|
||||
* 24:31 8 sct_cfg_high_addr_offst
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UINT32 rmiAcg : 1;
|
||||
UINT32 ahbAcg : 1;
|
||||
UINT32 : 14;
|
||||
UINT32 chainStartUnilog : 1;
|
||||
UINT32 descDoneUnilog : 1;
|
||||
UINT32 chainEndUnilog : 1;
|
||||
UINT32 errorIntUnilog : 1;
|
||||
UINT32 usbLBEndianInd : 1;
|
||||
UINT32 : 3;
|
||||
UINT32 memHighAddrOffset : 8;
|
||||
};
|
||||
|
||||
UINT32 value32;
|
||||
}SctCommCfgWord0;
|
||||
|
||||
|
||||
/*
|
||||
* SctCommCfgWord1 COMM_CFG1
|
||||
* Bit WIDTH DESP
|
||||
* 0:19 20 sct_cfg_d_max_time, (reset value: 0)
|
||||
* descriptor max process time, in unit of 32K ticks, if timeout, tigger interrupt: sct_dscrpt_time_out
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UINT32 descMaxProcTickTime : 20;
|
||||
UINT32 : 12;
|
||||
};
|
||||
|
||||
UINT32 value32;
|
||||
}SctCommCfgWord1;
|
||||
|
||||
|
||||
/*
|
||||
* SCT common config register struct
|
||||
*/
|
||||
typedef struct SctCommCfgReg_Tag
|
||||
{
|
||||
__IO SctCommCfgWord0 COMM_CFG0; /* SCT common CFG0, offset: 0x54 */
|
||||
__IO SctCommCfgWord1 COMM_CFG1; /* SCT common CFG1, offset: 0x58 */
|
||||
}SctCommCfgReg;
|
||||
|
||||
/*
|
||||
* SCT common control register start address
|
||||
*/
|
||||
#define SCT_COMM_CFG_REG_ADDR (SCT_REG_ADDR + 0x54)
|
||||
|
||||
/*
|
||||
* SCT RNDIS PPP register pointer
|
||||
*/
|
||||
#define SCT_COMM_CFG_REG ((SctCommCfgReg *)SCT_COMM_CFG_REG_ADDR)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
* SCT (cipher/integrity) channel config register
|
||||
******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
*
|
||||
* Bit WIDTH DESP
|
||||
* 0:7 8 sct_fifo_len_ch0
|
||||
* Chain FIFO length, MAX set to 255, (reset value: 0)
|
||||
* 8 1 sct_chain_int_en_ch0, (reset value: 0)
|
||||
* Generate interrupt when each chain in this channel is finished
|
||||
* 9 1 sct_fifo_empty_int_en_ch0, (reset value: 0)
|
||||
* FIFO empty interrupt enable, Generate interrupt when chain FIFO is empty (all done)
|
||||
* 10 1 sct_fifo_full_int_en_ch0, (reset value: 0)
|
||||
* FIFI full interrupt enable, Generate interrupt when chain FIFO is full (>sct_fifo_len_ch0)
|
||||
* 11 1 sct_ck_bl_ch0, input CK is big/little endian
|
||||
* 0 - little endian, (reset value: 0)
|
||||
* 1 - big endian
|
||||
* 12 1 sct_aes_iv_bl_ch0, input AES IV is big/little endian
|
||||
* 0 - little endian, (reset value: 0)
|
||||
* 1 - big endian
|
||||
* 13 1 sct_ck_opt_dis_ch0, whether disable CK optimization, whether need to re-load CK from SRAM, when process descriptors in the same chain
|
||||
* 0 - enable CK opt, (reset value: 0)
|
||||
* 1 - disable CK opt
|
||||
* 16:17 1 comm_crc_poly_len_ch0, common CRC poly length
|
||||
* 0 <20>C 8 bits CRC, (reset value: 0)
|
||||
* 1 <20>C 16 bits CRC
|
||||
* 2 <20>C 24 bits CRC
|
||||
* 3 <20>C 32 bits CRC
|
||||
* 19 1 comm_crc_comple_out_ch0
|
||||
* 0 - CRC output not need to comple, (reset value: 0)
|
||||
* 1 - CRC output need to comple
|
||||
* 20:23 4 comm_crc_comple_in_num_ch0, how many input bytes need to comple, before start CRC,
|
||||
* 24 1 comm_crc_out_bit_swap_ch0
|
||||
* 0 <20>C crcbyte from s[x] to s[x+7], s[x+7] is placed in LSB, (reset value: 0)
|
||||
* 1 <20>C crcbyte from s[x+7] to s[x], s[x+7] is placed in MSB
|
||||
* 25 1 comm_crc_in_bit_swap_ch0
|
||||
* 0 <20>C CRC start from bit[0] of input byte, (reset value: 0)
|
||||
* 1 <20>C CRC start from bit[7] of input byte
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UINT32 fifoLen : 8;
|
||||
UINT32 chainIntEn : 1;
|
||||
UINT32 chainEmptyIntEn : 1;
|
||||
UINT32 chainFullIntEn : 1;
|
||||
UINT32 ckBLEndian : 1;
|
||||
UINT32 aesIvBLEndian : 1; /* bit: 12 */
|
||||
UINT32 ckOptDis : 1; /* bit: 13 */
|
||||
UINT32 : 2;
|
||||
UINT32 crcPolyLen : 2; /* bit: 16:17 */
|
||||
UINT32 : 1;
|
||||
UINT32 crcOutComple : 1; /* bit: 19 */
|
||||
UINT32 crcInCompleByteNum : 4; /* bit: 20:23 */
|
||||
UINT32 crcOutBitSwap : 1; /* bit: 24 */
|
||||
UINT32 crcInBitSwap : 1; /* bit: 25 */
|
||||
UINT32 : 6;
|
||||
};
|
||||
|
||||
UINT32 value32;
|
||||
}SctChCfgWord0;
|
||||
|
||||
/*
|
||||
* UINT32 CHA_BASE_ADDR
|
||||
* Chain Base Address. Chain FIFO start address, should be 4 bytes aligned, and with length: 4*CHAINFIFOLEN
|
||||
*/
|
||||
|
||||
/*
|
||||
* UINT32 CK_BASE_ADDR, EEA/EIA CK Base Address
|
||||
* 1. Should be 4 bytes aligned
|
||||
* 2. one CK/IK 16 bytes
|
||||
* 3. Total 8 CK/IK keys, so total byte length: 8*16 = 128
|
||||
*/
|
||||
|
||||
/*
|
||||
* SctChCtrlReg CH_CTRL //write only
|
||||
* Bit WIDTH DESP
|
||||
* 0 1 sct_chain_trigger_ch0
|
||||
* Set 1, Chain trigger, a chain already insert into the chain list, and trigger SCT to process
|
||||
* 1 1 sct_channel_reset_ch0
|
||||
* Set 1, to reset current channel
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UINT32 chainTrg : 1;
|
||||
UINT32 chnReset : 1;
|
||||
UINT32 : 30;
|
||||
};
|
||||
|
||||
UINT32 value32;
|
||||
}SctChCtrlReg;
|
||||
|
||||
/*
|
||||
* SCT channel config register struct
|
||||
*/
|
||||
typedef struct SctChannelCfgReg_Tag
|
||||
{
|
||||
__IO SctChCfgWord0 CH_CFG0; /* SCT channel CFG0, offset: 0x5C */
|
||||
__IO UINT32 CHA_BASE_ADDR; /* SCT channel chain base address, offset: 0x60 */
|
||||
__IO UINT32 CK_BASE_ADDR; /* SCT channel CK/IK base address, offset: 0x64 */
|
||||
__IO UINT32 CRC_POLY; /* SCT channel common CRC poly, offset: 0x68 */
|
||||
__IO UINT32 CRC_INIT; /* SCT channel common CRC init value, offset: 0x6C */
|
||||
__O SctChCtrlReg CH_CTRL; /* SCT channel control register, write only, offset: 0x70 */
|
||||
}SctChannelCfgReg;
|
||||
|
||||
/*
|
||||
* SCT totoal channel number: 6
|
||||
*/
|
||||
#define SCT_CHANNEL_NUM 6
|
||||
|
||||
/*
|
||||
* SCT channels config register struct
|
||||
*/
|
||||
typedef struct SctCHSCfgReg_Tag
|
||||
{
|
||||
SctChannelCfgReg chCfg[SCT_CHANNEL_NUM];
|
||||
}SctCHSCfgReg;
|
||||
|
||||
|
||||
/*
|
||||
* SCT channels config register start address
|
||||
*/
|
||||
#define SCT_CHANNEL_CFG_REG_ADDR (SCT_REG_ADDR + 0x5C)
|
||||
|
||||
|
||||
/*
|
||||
* SCT channels config register pointer
|
||||
*/
|
||||
#define SCT_CHANNELS_CFG_REG ((SctCHSCfgReg *)SCT_CHANNEL_CFG_REG_ADDR)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
* SCT memory guard register
|
||||
******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__IO UINT32 hAddr0; /*sct_mpr_addr_h0, offset: 0xEC */
|
||||
__IO UINT32 lAddr0; /*sct_mpr_addr_l0, offset: 0xF0 */
|
||||
__IO UINT32 hAddr1; /*sct_mpr_addr_h1, offset: 0xF4 */
|
||||
__IO UINT32 lAddr1; /*sct_mpr_addr_l1, offset: 0xF8 */
|
||||
__IO UINT32 hAddr2; /*sct_mpr_addr_h2, offset: 0xFC */
|
||||
__IO UINT32 lAddr2; /*sct_mpr_addr_l2, offset: 0x100 */
|
||||
__IO UINT32 hAddr3; /*sct_mpr_addr_h3, offset: 0x104 */
|
||||
__IO UINT32 lAddr3; /*sct_mpr_addr_l3, offset: 0x108 */
|
||||
}SctMemGuardReg;
|
||||
|
||||
/*
|
||||
* SCT memory guard register start address
|
||||
*/
|
||||
#define SCT_MEM_GUARD_REG_ADDR (SCT_REG_ADDR + 0xEC)
|
||||
|
||||
/*
|
||||
* SCT memory guard register pointer
|
||||
*/
|
||||
#define SCT_MEM_GUARD_CFG_REG ((SctMemGuardReg *)SCT_MEM_GUARD_REG_ADDR)
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
* SCT channel state register
|
||||
******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* SCT channel state register
|
||||
* Bit WIDTH DESP
|
||||
* 0:7 8 sct_cfg_fifo_idx_ch0, Channel next configure index
|
||||
* a) reset/init value: 0
|
||||
* b) increase 1, when chain triggered.
|
||||
* c) Range: [0: fifoLen-1]
|
||||
* 8:15 8 sct_done_fifo_idx_ch0, Channel next done index
|
||||
* a) reset/init value: 0
|
||||
* b) increase 1, when one chain process done.
|
||||
* c) Range: [0: fifoLen-1]
|
||||
* 16:23 8 sct_free_fifo_space_ch0
|
||||
* Channel FIFO free space
|
||||
* 24 1 sct_fifo_full_ch0
|
||||
* Whether chain full (overflow), 0 - not, 1 - full
|
||||
* 25 1 sct_fifo_empty_ch0
|
||||
* Whether chain empty (all done), 0 - not, 1 - empty
|
||||
* 26 1 sct_dscrpt_act_ch0
|
||||
* Whether channel is activate, if descriptor in current channel is ongoing, then set 1, so only one channel could be set to 1
|
||||
* 27 1 sct_rst_done_ch0, Whether channel reset done.
|
||||
* a) SW: "SctChCtrlReg->chnReset" set 1, tigger SCT reset current channel
|
||||
* b) HW: SCT should stop current descriptor, and ignore all the pending chain request
|
||||
* c) HW: After reset done, SCT set this flag, and trigger ISR
|
||||
* d) SW: when process this ISR, if need to write USB EP in this channel, need to reflush/reset USB
|
||||
* e) HW: When this channel config/trigger again (SctChCtrlReg->chainTrg = 1), SCT clear this flag
|
||||
* 28 1 sct_dscrpt_time_out_ch0, whether SCT process this descriptor time out
|
||||
* a) HW: SCT start a guard timer, when start processing a descriptor, and stop it when done
|
||||
* b) HW: When timeout, SCT set this flag, and trigger ISR
|
||||
* c) HW: when SW reset current channel (SctChCtrlReg->chnReset = 1), SCT clear this flag
|
||||
*
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UINT32 chaNextCfgIdx : 8;
|
||||
UINT32 chaNextDoneIdx : 8;
|
||||
UINT32 chnFreeLen : 8;
|
||||
UINT32 chnBeFull : 1;
|
||||
UINT32 chnBeEmpty : 1;
|
||||
UINT32 chnBeAct : 1;
|
||||
UINT32 chnBeRstDone : 1;
|
||||
UINT32 descBeTimeOut : 1;
|
||||
|
||||
UINT32 : 3;
|
||||
};
|
||||
|
||||
UINT32 value32;
|
||||
}SctChannelStateReg;
|
||||
|
||||
/*
|
||||
* SCT channels state registers
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__I SctChannelStateReg chState[SCT_CHANNEL_NUM]; /* SCT channel state, read only, offset: 0x120 */
|
||||
}SctCHSStateReg;
|
||||
|
||||
/*
|
||||
* SCT channels state register start address
|
||||
*/
|
||||
#define SCT_CHS_STATE_REG_ADDR (SCT_REG_ADDR + 0x120)
|
||||
|
||||
/*
|
||||
* SCT channels state register pointer
|
||||
*/
|
||||
#define SCT_CHS_STATE_REG ((SctCHSStateReg *)SCT_CHS_STATE_REG_ADDR)
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
* SCT error status register
|
||||
******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* SctErrStatusWord0 errStatus
|
||||
* Bit WIDTH DESP
|
||||
* 0:5 6 master error (AHB error)
|
||||
* 6:11 6 memory guard error
|
||||
* 12:17 6 descriptor info error (PPP/CRC not byte aligned)
|
||||
*
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UINT32 masterErr : 6;
|
||||
UINT32 mgrErr : 6;
|
||||
UINT32 descErr : 6;
|
||||
UINT32 : 14;
|
||||
};
|
||||
|
||||
UINT32 value32;
|
||||
}SctErrStatusWord0;
|
||||
|
||||
|
||||
/*
|
||||
* SCT error status register struct
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__I SctErrStatusWord0 errStatus; /* sct_err_status, read only, offset: 0x138 */
|
||||
__I UINT32 rdErrMem; /* sct_err_mpr_rd, SCT read error address, offset: 0x13C */
|
||||
__I UINT32 wtErrMem; /* sct_err_mpr_wt, SCT write error address, offset: 0x140 */
|
||||
}SctErrStatusReg;
|
||||
|
||||
/*
|
||||
* SCT error status register start address
|
||||
*/
|
||||
#define SCT_ERR_STATUS_REG_ADDR (SCT_REG_ADDR + 0x138)
|
||||
|
||||
/*
|
||||
* SCT error status register pointer
|
||||
*/
|
||||
#define SCT_ERR_STATUS_REG ((SctErrStatusReg *)SCT_ERR_STATUS_REG_ADDR)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: timer.h
|
||||
* Description: EC618 timer driver header file
|
||||
* History:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _TIMER_EC618_H
|
||||
#define _TIMER_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup timer_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/** \brief List of TIMER clock source */
|
||||
typedef enum
|
||||
{
|
||||
TIMER_INTERNAL_CLOCK = 0U, /**< Internal clock */
|
||||
TIMER_EXTERNAL_CLOCK = 1U, /**< External clock */
|
||||
} TimerClockSource_t;
|
||||
|
||||
/** \brief List of TIMER match value select */
|
||||
typedef enum
|
||||
{
|
||||
TIMER_MATCH0_SELECT = 0U, /**< Select Match0 */
|
||||
TIMER_MATCH1_SELECT = 1U, /**< Select Match1 */
|
||||
TIMER_MATCH2_SELECT = 2U, /**< Select Match2 */
|
||||
} TimerMatchSelect_t;
|
||||
|
||||
/** \brief List of TIMER reload option, counter will be reloaded to init value upon reach it */
|
||||
typedef enum
|
||||
{
|
||||
TIMER_RELOAD_DISABLE = 0U, /**< Counter will run freely */
|
||||
TIMER_RELOAD_ON_MATCH0 = 1U, /**< Counter will be reloaded on reaching match0 value */
|
||||
TIMER_RELOAD_ON_MATCH1 = 2U, /**< Counter will be reloaded on reaching match1 value */
|
||||
TIMER_RELOAD_ON_MATCH2 = 3U, /**< Counter will be reloaded on reaching match1 value */
|
||||
} TimerReloadOption_t;
|
||||
|
||||
/** \brief PWM configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t pwmFreq_HZ; /**< PWM signal frequency in HZ */
|
||||
uint32_t srcClock_HZ; /**< TIMER counter clock in HZ */
|
||||
uint32_t dutyCyclePercent; /**< PWM pulse width, the valid range is 0 to 100 */
|
||||
} TimerPwmConfig_t;
|
||||
|
||||
/** \brief TIMER configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
TimerClockSource_t clockSource; /**< Clock source */
|
||||
TimerReloadOption_t reloadOption; /**< Reload option */
|
||||
uint32_t initValue; /**< Counter init value */
|
||||
uint32_t match0; /**< Match0 value */
|
||||
uint32_t match1; /**< Match1 value */
|
||||
uint32_t match2; /**< Match2 value */
|
||||
} TimerConfig_t;
|
||||
|
||||
/** \brief TIMER interrupt configuration */
|
||||
typedef enum
|
||||
{
|
||||
TIMER_INTERRUPT_DISABLED = 0U, /**< Disable interrupt */
|
||||
TIMER_INTERRUPT_LEVEL = 1U, /**< Level interrupt, a high level interrupt signal is generated */
|
||||
TIMER_INTERRUPT_PULSE = 2U, /**< Pulse interrupt, a pulse of one clock width
|
||||
is generated after counter matches */
|
||||
} TimerInterruptConfig_t;
|
||||
|
||||
|
||||
/** \brief List of TIMER interrupts */
|
||||
typedef enum
|
||||
{
|
||||
TIMER_MATCH0_INTERRUPT_ENABLE = TIMER_TCTLR_IE_0_Msk, /**< Match0 interrupt */
|
||||
TIMER_MATCH1_INTERRUPT_ENABLE = TIMER_TCTLR_IE_1_Msk, /**< Match1 interrupt */
|
||||
TIMER_MATCH2_INTERRUPT_ENABLE = TIMER_TCTLR_IE_2_Msk, /**< Match2 interrupt */
|
||||
} TimerInterruptEnable_t;
|
||||
|
||||
/** \brief List of TIMER interrupt flags */
|
||||
typedef enum
|
||||
{
|
||||
TIMER_MATCH0_INTERRUPT_FLAG = TIMER_TSR_ICLR_0_Msk, /**< Match0 interrupt flag */
|
||||
TIMER_MATCH1_INTERRUPT_FLAG = TIMER_TSR_ICLR_1_Msk, /**< Match1 interrupt flag */
|
||||
TIMER_MATCH2_INTERRUPT_FLAG = TIMER_TSR_ICLR_2_Msk, /**< Match2 interrupt flag */
|
||||
} TimerInterruptFlags_t;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \name TIMER Driver Initialization */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void TIMER_driverInit(void);
|
||||
\brief Intialize TIMER driver internal data, must be called before any other APIs
|
||||
*/
|
||||
void TIMER_driverInit(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name TIMER Configuration */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void TIMER_getDefaultConfig(TimerConfig_t *config)
|
||||
\brief Gets the TIMER default configuartion.
|
||||
This function sets the configuration structure to default values as below:
|
||||
\code
|
||||
config->clockSource = TIMER_INTERNAL_CLOCK;
|
||||
config->reloadOption = TIMER_RELOAD_ON_MATCH1;
|
||||
config->initValue = 0;
|
||||
config->match0 = 0x10000 >> 1;
|
||||
config->match1 = 0x10000;
|
||||
config->match2 = 0xFFFFFFFF;
|
||||
\endcode
|
||||
|
||||
\param[in] config Pointer to TIMER configuration structure
|
||||
*/
|
||||
void TIMER_getDefaultConfig(TimerConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn void TIMER_init(uint32_t instance, const TimerConfig_t *config)
|
||||
\brief Intialize TIMER
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\param[in] config Pointer to TIMER configuration
|
||||
\note PWM out is disabled after this function's call, use \ref TIMER_setupPwm function to eable PWM
|
||||
*/
|
||||
void TIMER_init(uint32_t instance, const TimerConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn void TIMER_deInit(uint32_t instance)
|
||||
\brief Deintialize TIMER
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
*/
|
||||
void TIMER_deInit(uint32_t instance);
|
||||
|
||||
/**
|
||||
\fn void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t match)
|
||||
\brief Sets one of TIMER match values
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\param[in] matchNum TIMER match select
|
||||
\param[in] matchValue TIMER match value
|
||||
*/
|
||||
void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t matchNum, uint32_t matchValue);
|
||||
|
||||
/**
|
||||
\fn void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t match)
|
||||
\brief Sets TIMER counter initial value
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\param[in] initValue TIMER initial value
|
||||
*/
|
||||
void TIMER_setInitValue(uint32_t instance, uint32_t initValue);
|
||||
|
||||
/**
|
||||
\fn void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t match)
|
||||
\brief Sets TIMER counter reload option
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\param[in] option TIMER counter reload option
|
||||
*/
|
||||
void TIMER_setReloadOption(uint32_t instance, TimerReloadOption_t option);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name TIMER Counter */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void TIMER_start(uint32_t instance)
|
||||
\brief Starts TIMER counter
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
*/
|
||||
void TIMER_start(uint32_t instance);
|
||||
|
||||
/**
|
||||
\fn void TIMER_stop(uint32_t instance)
|
||||
\brief Stops TIMER counter
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
*/
|
||||
void TIMER_stop(uint32_t instance);
|
||||
|
||||
/**
|
||||
\fn uint32_t TIMER_getCount(uint32_t instance)
|
||||
\brief Reads current TIMER counter value
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\return current TIMER counter value
|
||||
*/
|
||||
uint32_t TIMER_getCount(uint32_t instance);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name TIMER PWM */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn int32_t TIMER_setupPwm(uint32_t instance, const TimerPwmConfig_t *config)
|
||||
\brief Configures the PWM signals period, mode, etc.
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\param[in] config Pointer to PWM parameter
|
||||
\return ARM_DRIVER_OK if the PWM setup is successful
|
||||
ARM_DRIVER_ERROR_PARAMETER on parameter check failure
|
||||
*/
|
||||
int32_t TIMER_setupPwm(uint32_t instance, const TimerPwmConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn void TIMER_updatePwmDutyCycle(uint32_t instance, uint32_t dutyCyclePercent)
|
||||
\brief Updates the duty cycle of PWM signal
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\param[in] dutyCyclePercent New PWM pulse width, value shall be between 0 to 100,
|
||||
if the value exceeds 100, dutyCyclePercent is set to 100.
|
||||
*/
|
||||
void TIMER_updatePwmDutyCycle(uint32_t instance, uint32_t dutyCyclePercent);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name TIMER Interrupt */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void TIMER_interruptConfig(uint32_t instance, TimerMatchSelect_t match, TimerInterruptConfig_t config)
|
||||
\brief Configures the selected TIMER interrupt
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\param[in] match TIMER match select
|
||||
\param[in] config TIMER interrupt configuration
|
||||
*/
|
||||
void TIMER_interruptConfig(uint32_t instance, TimerMatchSelect_t match, TimerInterruptConfig_t config);
|
||||
|
||||
/**
|
||||
\fn TimerInterruptConfig_t TIMER_getInterruptConfig(uint32_t instance, TimerMatchSelect_t match)
|
||||
\brief Gets current configuration of the selected TIMER interrupt
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\param[in] match TIMER match select
|
||||
\return Current TIMER interrupt configuration
|
||||
*/
|
||||
TimerInterruptConfig_t TIMER_getInterruptConfig(uint32_t instance, TimerMatchSelect_t match);
|
||||
|
||||
/**
|
||||
\fn uint32_t TIMER_getInterruptFlags(uint32_t instance)
|
||||
\brief Reads TIMER interrupt status flags
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\return Interrupt flags. This is the logical OR of members of the
|
||||
enumeration \ref TimerInterruptFlags_t
|
||||
*/
|
||||
uint32_t TIMER_getInterruptFlags(uint32_t instance);
|
||||
|
||||
/**
|
||||
\fn void TIMER_clearInterruptFlags(uint32_t instance, uint32_t mask)
|
||||
\brief Clears TIMER interrupt flags
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
\param[in] mask Interrupt flags to clear. This is a logic OR of members of the
|
||||
enumeration \ref TimerInterruptFlags_t
|
||||
*/
|
||||
void TIMER_clearInterruptFlags(uint32_t instance, uint32_t mask);
|
||||
|
||||
/**
|
||||
\fn void TIMER_netlightEnable(uint32_t instance)
|
||||
\brief Set Netlight Enable, called by user in bsp_custom.c to define specific timer instance for netlight
|
||||
\param[in] instance TIMER instance number (0, 1, ...)
|
||||
*/
|
||||
void TIMER_netlightEnable(uint8_t instance);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TIMER_EC618_H */
|
||||
@@ -0,0 +1,259 @@
|
||||
#ifndef __TLS_H__
|
||||
#define __TLS_H__
|
||||
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "ec618.h"
|
||||
#include "bsp.h"
|
||||
|
||||
#define SCT_BASE_ADDR (0x40050000)
|
||||
|
||||
#define AES_SHA_CH4_CFG_REG (SCT_BASE_ADDR + 0xbc) // AES/SHA uses sct channel4
|
||||
#define AES_SHA_CH4_STATE_REG (SCT_BASE_ADDR + 0x130)
|
||||
|
||||
#define SCT_ENABLE_REG (SCT_BASE_ADDR + 0x00)
|
||||
#define SCT_COMM_CFG0_REG (SCT_BASE_ADDR + 0x54)
|
||||
#define SCT_COMM_CFG1_REG (SCT_BASE_ADDR + 0x58)
|
||||
#define SCT_MEM_GUARD_REG (SCT_BASE_ADDR + 0xec)
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SHA_TYPE_1,
|
||||
SHA_TYPE_224,
|
||||
SHA_TYPE_256,
|
||||
}shaType_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t length : 16;
|
||||
uint32_t dir : 1; // 0 - Encryption, 1 - Decryption
|
||||
uint32_t aesMode : 2; // 0 <20>C ECB, 1 <20>C CBC, 2 <20>C CTR
|
||||
uint32_t paddingMode : 3;
|
||||
uint32_t ckLen : 2; // 0 <20>C 128, 1 <20>C 192, 2 <20>C 256
|
||||
uint32_t aesCkSel : 1; // 0 <20>C from configured CK address, 1 <20>C from efuse
|
||||
uint32_t : 2;
|
||||
uint32_t subType : 2; // 0 <20>C AES descriptor; 1 <20>C SHA descriptor
|
||||
uint32_t type : 3; // Default 101
|
||||
}aesField_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t length : 16; // sha can handle 64k data one time
|
||||
uint32_t shaMode : 2; // 0: sha1; 1: sha224; 2: sha256
|
||||
uint32_t shaBls : 1; // sha output endian. 0: LE; 1: BE
|
||||
uint32_t rcs : 1; // 0: current is last data; 1: current data is continuous
|
||||
uint32_t outEn : 1; // open output
|
||||
uint32_t : 6;
|
||||
uint32_t subType : 2; // // 0: aes; 1:sha
|
||||
uint32_t type : 3; // Default 101
|
||||
}shaField_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t headLen : 16;
|
||||
uint32_t : 16;
|
||||
}shaHeadLen_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union firstWord
|
||||
{
|
||||
aesField_t aesField;
|
||||
shaField_t shaField;
|
||||
}u1;
|
||||
|
||||
uint32_t srcAddr;
|
||||
uint32_t dstAddr;
|
||||
|
||||
union secondWord
|
||||
{
|
||||
uint32_t aesCkAddr;
|
||||
uint32_t shaHeaderAddr;
|
||||
}u2;
|
||||
|
||||
union thirdWord
|
||||
{
|
||||
uint32_t aesIvAddr;
|
||||
shaHeadLen_t shaHeadLen;
|
||||
}u3;
|
||||
}sctDescCfg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t trigger : 1;
|
||||
uint32_t reset : 1;
|
||||
uint32_t : 30;
|
||||
}sctChanCfg_t;
|
||||
|
||||
|
||||
typedef union {
|
||||
struct
|
||||
{
|
||||
uint32_t fifoLen : 8; // chain fifo length, max is 255
|
||||
uint32_t chainIntEn : 1;
|
||||
uint32_t chainEmptyIntEn : 1;
|
||||
uint32_t chainFullIntEn : 1;
|
||||
uint32_t ckBLEndian : 1;
|
||||
uint32_t aesIvBLEndian : 1; // bit: 12
|
||||
uint32_t ckOptDis : 1; // bit: 13
|
||||
uint32_t : 2;
|
||||
uint32_t crcPolyLen : 2; // bit: 16:17
|
||||
uint32_t : 1;
|
||||
uint32_t crcOutComple : 1; // bit: 19
|
||||
uint32_t crcInCompleByteNum: 4; // bit: 20:23
|
||||
uint32_t crcOutBitSwap : 1; // bit: 24
|
||||
uint32_t crcInBitSwap : 1; // bit: 25
|
||||
uint32_t : 6;
|
||||
};
|
||||
uint32_t val;
|
||||
}chanCfgWord0_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
chanCfgWord0_t chanCfgWord0;
|
||||
uint32_t chanCfgWord1; // First desc addr
|
||||
uint32_t rsvd[3];
|
||||
sctChanCfg_t chanCfgWord5;
|
||||
}sctCfgWord_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t chaNextCfgIdx : 8;
|
||||
uint32_t chaNextDoneIdx : 8;
|
||||
uint32_t chaFreeLen : 8;
|
||||
uint32_t chaBeFull : 1;
|
||||
uint32_t chaBeEmpty : 1;
|
||||
uint32_t chaBeAct : 1;
|
||||
uint32_t chaBeRstDone : 1;
|
||||
uint32_t descBeTimeout : 1;
|
||||
uint32_t : 3;
|
||||
}sctChaState_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t hAddr0;
|
||||
uint32_t lAddr0;
|
||||
uint32_t hAddr1;
|
||||
uint32_t lAddr1;
|
||||
uint32_t hAddr2;
|
||||
uint32_t lAddr2;
|
||||
uint32_t hAddr3;
|
||||
uint32_t lAddr3;
|
||||
}sctMemGuard_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t rmiAcg : 1;
|
||||
uint32_t ahbAcg : 1;
|
||||
uint32_t : 14;
|
||||
uint32_t chainStartUnilog : 1;
|
||||
uint32_t descDoneUnilog : 1;
|
||||
uint32_t chainEndUnilog : 1;
|
||||
uint32_t errorIntUnilog : 1;
|
||||
uint32_t usbEndianInd : 1;
|
||||
uint32_t : 3;
|
||||
uint32_t memHighAddrOffset : 8;
|
||||
};
|
||||
uint32_t val;
|
||||
}sctCfgWord0_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t descMaxProcTickTime : 20; // descriptor handle max timeout
|
||||
uint32_t : 12;
|
||||
}sctCfgWord1_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t dir : 1; // 0: encrypt, 1: decrypt
|
||||
uint32_t aesMode : 2; // 0: ecb, 1:cbc, 2:ctr
|
||||
uint32_t paddingMode : 3; // 0: no padding, 1: PKCS7, 2: paddingOneZeros, 3: paddingZerosLen, 4: paddingZeros
|
||||
uint32_t ckLen : 2; // 0:128, 1:192, 2:256
|
||||
uint32_t aesCkSel : 1; // 0: from memory, 1: from efuse
|
||||
uint32_t ckBLEndian : 1; // Ignore it if key is from efuse. If key is from memory, 0: little; 1: big
|
||||
uint32_t aesIvBLEndian : 1; // input AES IV is big/little endian. 0: little; 1: big
|
||||
uint32_t : 23;
|
||||
}aesCtrl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ivAddr;
|
||||
uint32_t srcAddr;
|
||||
uint32_t dstAddr;
|
||||
uint32_t aesCkAddr;
|
||||
uint32_t length;
|
||||
aesCtrl_t aesCtrl;
|
||||
}aesInfo_t;
|
||||
|
||||
/*
|
||||
* SCT memory guard address
|
||||
* SCT could only access MSMB: 0x00400000 ~ 0x0053FFFF
|
||||
*/
|
||||
#define MGR_LOW_ADDR 0x00400000
|
||||
#define MGR_HIGH_ADDR 0x0053FFFF
|
||||
|
||||
/*
|
||||
* SCT memory guard address
|
||||
* USB TX FIFO: 0x00400000 ~ 0x0053FFFF
|
||||
*/
|
||||
#define MGR_LOW_ADDR1 0x1A000000
|
||||
#define MGR_HIGH_ADDR1 0x1AFFFFFF
|
||||
|
||||
/*
|
||||
* AP flash, 4M: 0x0080-0000~0x00BF-FFFF
|
||||
*/
|
||||
#define MGR_LOW_ADDR2 0x00800000
|
||||
#define MGR_HIGH_ADDR2 0x00BFFFFF
|
||||
|
||||
|
||||
/*
|
||||
* CP flash, 1M: 0x0880-0000~0x088F-FFFF
|
||||
*/
|
||||
#define MGR_LOW_ADDR3 0x08800000
|
||||
#define MGR_HIGH_ADDR3 0x088FFFFF
|
||||
|
||||
|
||||
|
||||
#define SCTDRV_OK (0)
|
||||
#define SCTDRV_BUSY (-1)
|
||||
#define SCTDRV_TIMEOUT (-2)
|
||||
#define SCTDRV_PAMERR (-5)
|
||||
|
||||
/**
|
||||
\brief SCT module init.
|
||||
\return
|
||||
*/
|
||||
void sctInit();
|
||||
|
||||
/**
|
||||
\brief SCT module deInit.
|
||||
\return
|
||||
*/
|
||||
void sctDeInit();
|
||||
|
||||
|
||||
/**
|
||||
\brief Aes operation
|
||||
\param[in] aesInfo Aes information.
|
||||
\return status
|
||||
*/
|
||||
int32_t aesUpdate(aesInfo_t* aesInfo);
|
||||
|
||||
/**
|
||||
\brief Sha operation.
|
||||
\param[in] shaMode Choose SHA1, SHA224, SHA256.
|
||||
\param[in] srcAddr SHA input address.
|
||||
\param[in] dstAddr SHA output address.
|
||||
\param[in] length SHA input length.
|
||||
\param[in] lastFlag If you need to loop call this api, "lastFlag" should be 0 for intermediate steps, and last step it should be 1.
|
||||
\return status
|
||||
*/
|
||||
int32_t shaUpdate(shaType_e shaMode, uint32_t srcAddr, uint32_t dstAddr, uint32_t length, uint32_t lastFlag);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
|
||||
* File name: uart.h
|
||||
* Description: EC618 uart driver header file
|
||||
* History:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _UART_EC618_H
|
||||
#define _UART_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup uart_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\fn void UART_init(uint32_t instance, uint32_t baudrate, bool enableFlowCtrl)
|
||||
\brief Initialize UART with specific baudrate
|
||||
\param[in] instance UART instance number (0, 1, ...)
|
||||
\param[in] baudrate The desired baudrate
|
||||
\param[in] enableFlowCtrl Enable flow control or not
|
||||
*/
|
||||
void UART_init(uint32_t instance, uint32_t baudrate, bool enableFlowCtrl);
|
||||
|
||||
/**
|
||||
\fn uint32_t UART_send(uint32_t instance, const uint8_t *data, uint32_t num, uint32_t timeout_us)
|
||||
\brief Start sending data to USART transmitter in polling way
|
||||
\param[in] instance UART instance number (0, 1, ...)
|
||||
\param[in] data Pointer to buffer with data to send to USART transmitter
|
||||
\param[in] num Number of data items to send
|
||||
\param[in] timeout_us timeout value in unit of us
|
||||
\return num of data items sent in the internal of timeout
|
||||
*/
|
||||
uint32_t UART_send(uint32_t instance, const uint8_t *data, uint32_t num, uint32_t timeout_us);
|
||||
|
||||
/**
|
||||
\fn uint32_t UART_receive(uint32_t instance, uint8_t *data, uint32_t num, uint32_t timeout_us)
|
||||
\brief Start receiving data from USART receiver in polling way
|
||||
\param[in] instance UART instance number (0, 1, ...)
|
||||
\param[out] data Pointer to buffer for data to receive from USART receiver
|
||||
\param[in] num Number of data items to receive
|
||||
\param[in] timeout_us timeout value in unit of us
|
||||
\return num of data items received in the internal of timeout
|
||||
*/
|
||||
uint32_t UART_receive(uint32_t instance, uint8_t *data, uint32_t num, uint32_t timeout_us);
|
||||
|
||||
/**
|
||||
\fn void UART_printf(uint32_t instance, const char* fmt, ...)
|
||||
\brief Print formated data to USART transmitter
|
||||
\param[in] instance UART instance number (0, 1, ...)
|
||||
\param[in] fmt C string that contains the text to be sent to UART
|
||||
\param[in] ... __VA__ARGS
|
||||
*/
|
||||
void UART_printf(uint32_t instance, const char* fmt, ...);
|
||||
|
||||
void UART_flush(uint32_t instance);
|
||||
void UART_purgeRx(uint32_t instance);
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UART_EC618_H */
|
||||
@@ -0,0 +1,83 @@
|
||||
/******************************************************************************
|
||||
|
||||
*(C) Copyright 2018 AirM2M International Ltd.
|
||||
|
||||
* All Rights Reserved
|
||||
|
||||
******************************************************************************
|
||||
* Filename:
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _UNILOG_API_H
|
||||
#define _UNILOG_API_H
|
||||
/*----------------------------------------------------------------------------*
|
||||
* INCLUDES *
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* MACROS *
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define UNILOG_TRACE_MAX_MODULE_VALUE (1024)
|
||||
|
||||
#define UNILOG_DMA_REQ_MODE_USB (0x3)
|
||||
#define UNILOG_DMA_REQ_MODE_UART (0x0)
|
||||
|
||||
#define UNILOG_ID_CONSTRUCT(ownerId, moduleId, subId) ((ownerId << 28) | (moduleId << 21) | (subId << 11))
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* DATA TYPE DEFINITION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UART_0_FOR_UNILOG = 0,
|
||||
UART_1_FOR_UNILOG = 1,
|
||||
UART_2_FOR_UNILOG = 2,
|
||||
// SPI_0_FOR_UNILOG = 3,
|
||||
// SPI_1_FOR_UNILOG = 4,
|
||||
USB_FOR_UNILOG = 5
|
||||
} UnilogPeripheralType_e;
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* GLOBAL FUNCTIONS DECLEARATION *
|
||||
*----------------------------------------------------------------------------*/
|
||||
void uniLogModuleAllowTraces(uint16_t moduleID);
|
||||
void uniLogModuleDisableTraces(uint16_t moduleID);
|
||||
void uniLogModuleAllowAllTraces(void);
|
||||
void uniLogModuleDisableAllTraces(void);
|
||||
bool uniLogTraceAllowCheck(uint8_t debugLevel);
|
||||
void uniLogFlushOut(void);
|
||||
void uniLogForceOut(bool waitFifoOut);
|
||||
void uniLogStop(void);
|
||||
void uniLogStopHwLog(void);
|
||||
bool uniLogIsInitialized(void);
|
||||
void uniLogGetSettingFromFlash(void);
|
||||
void swLogExcep(uint32_t swLogID, uint8_t debugLevel, ...);
|
||||
void swLogPrintf(uint32_t swLogID, uint8_t debugLevel, ...);
|
||||
void swLogDump(uint32_t swLogID, uint8_t debugLevel, uint32_t dumpLen, const uint8_t*pDump);
|
||||
void swLogPrintfPolling(uint32_t swLogID, uint8_t debugLevel, ...);
|
||||
void swLogDumpPolling(uint32_t swLogID, uint8_t debugLevel, uint32_t dumpLen, const uint8_t*pDump);
|
||||
void uniLogSetPherType(UnilogPeripheralType_e periphType);
|
||||
UnilogPeripheralType_e uniLogGetPherType(void);
|
||||
bool unilogSwitch2UartLog(void);
|
||||
bool unilogSwitch2UsbLog(void);
|
||||
bool uniLogGetDumpRdyFlag(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//_UNILOG_API_H
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: wdt.h
|
||||
* Description: EC618 wdt driver header file
|
||||
* History:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _WDT_EC618_H
|
||||
#define _WDT_EC618_H
|
||||
|
||||
#include "ec618.h"
|
||||
#include "Driver_Common.h"
|
||||
|
||||
/**
|
||||
\addtogroup wdt_interface_gr
|
||||
\{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/** \brief List of WDT mode */
|
||||
typedef enum
|
||||
{
|
||||
WDT_INTERRUPT_ONLY_MODE = 0U, /**< Only generate an interrupt upon timeout */
|
||||
WDT_INTERRUPT_RESET_MODE = 1U, /**< Reset upon timeout if the first interrupt is not cleared */
|
||||
} WdtMode_e;
|
||||
|
||||
/** \brief WDT configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
WdtMode_e mode;
|
||||
uint16_t timeoutValue;
|
||||
} WdtConfig_t;
|
||||
|
||||
/** \brief List of WDT interrupt flags */
|
||||
typedef enum
|
||||
{
|
||||
WDT_INTERRUPT_FLAG = WDT_STAT_ISTAT_Msk, /**< Wdt interrupt flag */
|
||||
} WdtInterruptFlags_e;
|
||||
|
||||
/*******************************************************************************
|
||||
* API
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \name WDT Configuration */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void WDT_getDefaultConfig(WdtConfig_t *config)
|
||||
\brief Gets the WDT default configuartion.
|
||||
This function sets the configuration structure to default values as below:
|
||||
\code
|
||||
config->mode = WDT_INTERRUPT_ONLY_MODE;
|
||||
config->timeoutValue = 0xFFFF;
|
||||
\endcode
|
||||
|
||||
\param[in] config Pointer to WDT configuration structure
|
||||
*/
|
||||
void WDT_getDefaultConfig(WdtConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn void WDT_init(const WdtConfig_t *config)
|
||||
\brief Initialize WDT
|
||||
\param[in] config Pointer to WDT configuration
|
||||
*/
|
||||
void WDT_init(const WdtConfig_t *config);
|
||||
|
||||
/**
|
||||
\fn void WDT_deInit(void)
|
||||
\brief Deinitialize WDT
|
||||
*/
|
||||
void WDT_deInit(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name WDT Unlock and Kick */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void WDT_unlock(void)
|
||||
\brief Unlocks the WDT register written
|
||||
*/
|
||||
void WDT_unlock(void);
|
||||
|
||||
/**
|
||||
\fn void WDT_kick(void)
|
||||
\brief Refreshes WDT counter
|
||||
*/
|
||||
void WDT_kick(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name WDT Start and Stop */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn void WDT_start(void)
|
||||
\brief Starts WDT counter
|
||||
*/
|
||||
void WDT_start(void);
|
||||
|
||||
/**
|
||||
\fn void WDT_stop(void)
|
||||
\brief Stops WDT counter
|
||||
*/
|
||||
void WDT_stop(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name WDT Interrupt and Status */
|
||||
/** \{ */
|
||||
|
||||
/**
|
||||
\fn uint32_t WDT_getInterruptFlags(void)
|
||||
\brief Reads WDT interrupt status flags
|
||||
\return Interrupt flags. This is the logical OR of members of the
|
||||
enumeration \ref WdtInterruptFlags_e
|
||||
*/
|
||||
uint32_t WDT_getInterruptFlags(void);
|
||||
|
||||
/**
|
||||
\fn void WDTclearInterruptFlags(uint32_t mask)
|
||||
\brief Clears WDT interrupt flags
|
||||
\param[in] mask Interrupt flags to clear. This is a logic OR of members of the
|
||||
enumeration \ref WdtInterruptFlags_e
|
||||
*/
|
||||
void WDTclearInterruptFlags(uint32_t mask);
|
||||
|
||||
/**
|
||||
\fn WdtMode_e WDT_getMode(void)
|
||||
\brief Gets current WDT mode
|
||||
\return WDT mode, see \ref WdtMode_e
|
||||
*/
|
||||
WdtMode_e WDT_getMode(void);
|
||||
|
||||
/**
|
||||
\fn bool WDT_getStartStatus(void)
|
||||
\brief Checks if WDT is started or stopped
|
||||
\return true if WDT is counting
|
||||
false if WDT is stopped
|
||||
*/
|
||||
bool WDT_getStartStatus(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _WDT_EC618_H */
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* $Date: 2. Feb 2017
|
||||
* $Revision: V2.0
|
||||
*
|
||||
* Project: Common Driver definitions
|
||||
*/
|
||||
|
||||
/* History:
|
||||
* Version 2.0
|
||||
* Changed prefix ARM_DRV -> ARM_DRIVER
|
||||
* Added General return codes definitions
|
||||
* Version 1.10
|
||||
* Namespace prefix ARM_ added
|
||||
* Version 1.00
|
||||
* Initial release
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_COMMON_H_
|
||||
#define DRIVER_COMMON_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include "sctdef.h"
|
||||
#ifdef FEATURE_OS_ENABLE
|
||||
#include "exception_process.h"
|
||||
#endif
|
||||
|
||||
#define ARM_DRIVER_VERSION_MAJOR_MINOR(major,minor) (((major) << 8) | (minor))
|
||||
|
||||
/**
|
||||
\brief Driver Version
|
||||
*/
|
||||
typedef struct _ARM_DRIVER_VERSION {
|
||||
uint16_t api; ///< API version
|
||||
uint16_t drv; ///< Driver version
|
||||
} ARM_DRIVER_VERSION;
|
||||
|
||||
/* General return codes */
|
||||
#define ARM_DRIVER_OK 0 ///< Operation succeeded
|
||||
#define ARM_DRIVER_ERROR -1 ///< Unspecified error
|
||||
#define ARM_DRIVER_ERROR_BUSY -2 ///< Driver is busy
|
||||
#define ARM_DRIVER_ERROR_TIMEOUT -3 ///< Timeout occurred
|
||||
#define ARM_DRIVER_ERROR_UNSUPPORTED -4 ///< Operation not supported
|
||||
#define ARM_DRIVER_ERROR_PARAMETER -5 ///< Parameter error
|
||||
#define ARM_DRIVER_ERROR_SPECIFIC -6 ///< Start of driver specific errors
|
||||
|
||||
/**
|
||||
\brief General power states
|
||||
*/
|
||||
typedef enum _ARM_POWER_STATE {
|
||||
ARM_POWER_OFF, ///< Power off: no operation possible
|
||||
ARM_POWER_LOW, ///< Low Power mode: retain state, detect and signal wake-up events
|
||||
ARM_POWER_FULL ///< Power on: full operation at maximum performance
|
||||
} ARM_POWER_STATE;
|
||||
|
||||
typedef struct _PIN {
|
||||
uint8_t pinNum;
|
||||
uint8_t funcNum;
|
||||
} PIN;
|
||||
|
||||
#ifndef ASSERT
|
||||
#ifdef FEATURE_OS_ENABLE
|
||||
#define ASSERT(X) EC_ASSERT(X,0,0,0)
|
||||
#else
|
||||
#define ASSERT(X) assert(X)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(n) ((unsigned int) 1 << (n))
|
||||
#define BITS2(m,n) (BIT(m) | BIT(n))
|
||||
#define BITS(m,n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b) ? (a) : (b)))
|
||||
#endif
|
||||
|
||||
#endif /* DRIVER_COMMON_H_ */
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* $Date: 2. Feb 2017
|
||||
* $Revision: V2.3
|
||||
*
|
||||
* Project: I2C (Inter-Integrated Circuit) Driver definitions
|
||||
*/
|
||||
|
||||
/* History:
|
||||
* Version 2.3
|
||||
* ARM_I2C_STATUS made volatile
|
||||
* Version 2.2
|
||||
* Removed function ARM_I2C_MasterTransfer in order to simplify drivers
|
||||
* and added back parameter "xfer_pending" to functions
|
||||
* ARM_I2C_MasterTransmit and ARM_I2C_MasterReceive
|
||||
* Version 2.1
|
||||
* Added function ARM_I2C_MasterTransfer and removed parameter "xfer_pending"
|
||||
* from functions ARM_I2C_MasterTransmit and ARM_I2C_MasterReceive
|
||||
* Added function ARM_I2C_GetDataCount
|
||||
* Removed flag "address_nack" from ARM_I2C_STATUS
|
||||
* Replaced events ARM_I2C_EVENT_MASTER_DONE and ARM_I2C_EVENT_SLAVE_DONE
|
||||
* with event ARM_I2C_EVENT_TRANSFER_DONE
|
||||
* Added event ARM_I2C_EVENT_TRANSFER_INCOMPLETE
|
||||
* Removed parameter "arg" from function ARM_I2C_SignalEvent
|
||||
* Version 2.0
|
||||
* New simplified driver:
|
||||
* complexity moved to upper layer (especially data handling)
|
||||
* more unified API for different communication interfaces
|
||||
* Added:
|
||||
* Slave Mode
|
||||
* Changed prefix ARM_DRV -> ARM_DRIVER
|
||||
* Version 1.10
|
||||
* Namespace prefix ARM_ added
|
||||
* Version 1.00
|
||||
* Initial release
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_I2C_H_
|
||||
#define DRIVER_I2C_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "Driver_Common.h"
|
||||
|
||||
#define ARM_I2C_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,3) /* API version */
|
||||
|
||||
|
||||
/****** I2C Control Codes *****/
|
||||
|
||||
#define ARM_I2C_OWN_ADDRESS (0x01) ///< Set Own Slave Address; arg = address
|
||||
#define ARM_I2C_BUS_SPEED (0x02) ///< Set Bus Speed; arg = speed
|
||||
#define ARM_I2C_BUS_CLEAR (0x03) ///< Execute Bus clear: send nine clock pulses
|
||||
#define ARM_I2C_ABORT_TRANSFER (0x04) ///< Abort Master/Slave Transmit/Receive
|
||||
|
||||
/*----- I2C Bus Speed -----*/
|
||||
#define ARM_I2C_BUS_SPEED_STANDARD (0x01) ///< Standard Speed (100kHz)
|
||||
#define ARM_I2C_BUS_SPEED_FAST (0x02) ///< Fast Speed (400kHz)
|
||||
#define ARM_I2C_BUS_SPEED_FAST_PLUS (0x03) ///< Fast+ Speed ( 1MHz)
|
||||
#define ARM_I2C_BUS_SPEED_HIGH (0x04) ///< High Speed (3.4MHz)
|
||||
|
||||
|
||||
/****** I2C Address Flags *****/
|
||||
|
||||
#define ARM_I2C_ADDRESS_10BIT (0x0400) ///< 10-bit address flag
|
||||
#define ARM_I2C_ADDRESS_GC (0x8000) ///< General Call flag
|
||||
|
||||
|
||||
/**
|
||||
\brief I2C Status
|
||||
*/
|
||||
typedef volatile struct _ARM_I2C_STATUS {
|
||||
uint32_t busy : 1; ///< Busy flag
|
||||
uint32_t mode : 1; ///< Mode: 0=Slave, 1=Master
|
||||
uint32_t direction : 1; ///< Direction: 0=Transmitter, 1=Receiver
|
||||
uint32_t general_call : 1; ///< General Call indication (cleared on start of next Slave operation)
|
||||
uint32_t arbitration_lost : 1; ///< Master lost arbitration (cleared on start of next Master operation)
|
||||
uint32_t bus_error : 1; ///< Bus error detected (cleared on start of next Master/Slave operation)
|
||||
uint32_t rx_nack : 1; ///< NACK detected (cleared on start of next Master/Slave operation)
|
||||
uint32_t reserved : 25;
|
||||
} ARM_I2C_STATUS;
|
||||
|
||||
|
||||
/****** I2C Event *****/
|
||||
#define ARM_I2C_EVENT_TRANSFER_DONE (1UL << 0) ///< Master/Slave Transmit/Receive finished
|
||||
#define ARM_I2C_EVENT_TRANSFER_INCOMPLETE (1UL << 1) ///< Master/Slave Transmit/Receive incomplete transfer
|
||||
#define ARM_I2C_EVENT_SLAVE_TRANSMIT (1UL << 2) ///< Addressed as Slave Transmitter but transmit operation is not set.
|
||||
#define ARM_I2C_EVENT_SLAVE_RECEIVE (1UL << 3) ///< Addressed as Slave Receiver but receive operation is not set.
|
||||
#define ARM_I2C_EVENT_ADDRESS_NACK (1UL << 4) ///< Address not acknowledged from Slave
|
||||
#define ARM_I2C_EVENT_GENERAL_CALL (1UL << 5) ///< Slave addressed with general call address
|
||||
#define ARM_I2C_EVENT_ARBITRATION_LOST (1UL << 6) ///< Master lost arbitration
|
||||
#define ARM_I2C_EVENT_BUS_ERROR (1UL << 7) ///< Bus error detected (START/STOP at illegal position)
|
||||
#define ARM_I2C_EVENT_BUS_CLEAR (1UL << 8) ///< Bus clear finished
|
||||
|
||||
|
||||
// Function documentation
|
||||
/**
|
||||
\fn ARM_DRIVER_VERSION ARM_I2C_GetVersion (void)
|
||||
\brief Get driver version.
|
||||
\return \ref ARM_DRIVER_VERSION
|
||||
|
||||
\fn ARM_I2C_CAPABILITIES ARM_I2C_GetCapabilities (void)
|
||||
\brief Get driver capabilities.
|
||||
\return \ref ARM_I2C_CAPABILITIES
|
||||
|
||||
\fn int32_t ARM_I2C_Initialize (ARM_I2C_SignalEvent_t cb_event)
|
||||
\brief Initialize I2C Interface.
|
||||
\param[in] cb_event Pointer to \ref ARM_I2C_SignalEvent
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_I2C_Uninitialize (void)
|
||||
\brief De-initialize I2C Interface.
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_I2C_PowerControl (ARM_POWER_STATE state)
|
||||
\brief Control I2C Interface Power.
|
||||
\param[in] state Power state
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_I2C_MasterTransmit (uint32_t addr, const uint8_t *data, uint32_t num, bool xfer_pending)
|
||||
\brief Start transmitting data as I2C Master.
|
||||
\param[in] addr Slave address (7-bit or 10-bit)
|
||||
\param[in] data Pointer to buffer with data to transmit to I2C Slave
|
||||
\param[in] num Number of data bytes to transmit
|
||||
\param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_I2C_MasterReceive (uint32_t addr, uint8_t *data, uint32_t num, bool xfer_pending)
|
||||
\brief Start receiving data as I2C Master.
|
||||
\param[in] addr Slave address (7-bit or 10-bit)
|
||||
\param[out] data Pointer to buffer for data to receive from I2C Slave
|
||||
\param[in] num Number of data bytes to receive
|
||||
\param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_I2C_SlaveTransmit (const uint8_t *data, uint32_t num)
|
||||
\brief Start transmitting data as I2C Slave.
|
||||
\param[in] data Pointer to buffer with data to transmit to I2C Master
|
||||
\param[in] num Number of data bytes to transmit
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_I2C_SlaveReceive (uint8_t *data, uint32_t num)
|
||||
\brief Start receiving data as I2C Slave.
|
||||
\param[out] data Pointer to buffer for data to receive from I2C Master
|
||||
\param[in] num Number of data bytes to receive
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_I2C_GetDataCount (void)
|
||||
\brief Get transferred data count.
|
||||
\return number of data bytes transferred; -1 when Slave is not addressed by Master
|
||||
|
||||
\fn int32_t ARM_I2C_Control (uint32_t control, uint32_t arg)
|
||||
\brief Control I2C Interface.
|
||||
\param[in] control Operation
|
||||
\param[in] arg Argument of operation (optional)
|
||||
\return \ref execution_status
|
||||
|
||||
\fn ARM_I2C_STATUS ARM_I2C_GetStatus (void)
|
||||
\brief Get I2C status.
|
||||
\return I2C status \ref ARM_I2C_STATUS
|
||||
|
||||
\fn void ARM_I2C_SignalEvent (uint32_t event)
|
||||
\brief Signal I2C Events.
|
||||
\param[in] event \ref I2C_events notification mask
|
||||
*/
|
||||
|
||||
typedef void (*ARM_I2C_SignalEvent_t) (uint32_t event); ///< Pointer to \ref ARM_I2C_SignalEvent : Signal I2C Event.
|
||||
|
||||
|
||||
/**
|
||||
\brief I2C Driver Capabilities.
|
||||
*/
|
||||
typedef struct _ARM_I2C_CAPABILITIES {
|
||||
uint32_t address_10_bit : 1; ///< supports 10-bit addressing
|
||||
uint32_t reserved : 31; ///< Reserved (must be zero)
|
||||
} ARM_I2C_CAPABILITIES;
|
||||
|
||||
|
||||
/**
|
||||
\brief Access structure of the I2C Driver.
|
||||
*/
|
||||
typedef struct _ARM_DRIVER_I2C {
|
||||
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_I2C_GetVersion : Get driver version.
|
||||
ARM_I2C_CAPABILITIES (*GetCapabilities)(void); ///< Pointer to \ref ARM_I2C_GetCapabilities : Get driver capabilities.
|
||||
int32_t (*Initialize) (ARM_I2C_SignalEvent_t cb_event); ///< Pointer to \ref ARM_I2C_Initialize : Initialize I2C Interface.
|
||||
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_I2C_Uninitialize : De-initialize I2C Interface.
|
||||
int32_t (*PowerControl) (ARM_POWER_STATE state); ///< Pointer to \ref ARM_I2C_PowerControl : Control I2C Interface Power.
|
||||
int32_t (*MasterTransmit) (uint32_t addr, const uint8_t *data, uint32_t num, bool xfer_pending); ///< Pointer to \ref ARM_I2C_MasterTransmit : Start transmitting data as I2C Master.
|
||||
int32_t (*MasterReceive) (uint32_t addr, uint8_t *data, uint32_t num, bool xfer_pending); ///< Pointer to \ref ARM_I2C_MasterReceive : Start receiving data as I2C Master.
|
||||
int32_t (*SlaveTransmit) ( const uint8_t *data, uint32_t num); ///< Pointer to \ref ARM_I2C_SlaveTransmit : Start transmitting data as I2C Slave.
|
||||
int32_t (*SlaveReceive) ( uint8_t *data, uint32_t num); ///< Pointer to \ref ARM_I2C_SlaveReceive : Start receiving data as I2C Slave.
|
||||
int32_t (*GetDataCount) (void); ///< Pointer to \ref ARM_I2C_GetDataCount : Get transferred data count.
|
||||
int32_t (*Control) (uint32_t control, uint32_t arg); ///< Pointer to \ref ARM_I2C_Control : Control I2C Interface.
|
||||
ARM_I2C_STATUS (*GetStatus) (void); ///< Pointer to \ref ARM_I2C_GetStatus : Get I2C status.
|
||||
} const ARM_DRIVER_I2C;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DRIVER_I2C_H_ */
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* $Date: 2. Feb 2017
|
||||
* $Revision: V2.2
|
||||
*
|
||||
* Project: SPI (Serial Peripheral Interface) Driver definitions
|
||||
*/
|
||||
|
||||
/* History:
|
||||
* Version 2.2
|
||||
* ARM_SPI_STATUS made volatile
|
||||
* Version 2.1
|
||||
* Renamed status flag "tx_rx_busy" to "busy"
|
||||
* Version 2.0
|
||||
* New simplified driver:
|
||||
* complexity moved to upper layer (especially data handling)
|
||||
* more unified API for different communication interfaces
|
||||
* Added:
|
||||
* Slave Mode
|
||||
* Half-duplex Modes
|
||||
* Configurable number of data bits
|
||||
* Support for TI Mode and Microwire
|
||||
* Changed prefix ARM_DRV -> ARM_DRIVER
|
||||
* Version 1.10
|
||||
* Namespace prefix ARM_ added
|
||||
* Version 1.01
|
||||
* Added "send_done_event" to Capabilities
|
||||
* Version 1.00
|
||||
* Initial release
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_SPI_H_
|
||||
#define DRIVER_SPI_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "Driver_Common.h"
|
||||
|
||||
#define ARM_SPI_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,2) /* API version */
|
||||
|
||||
|
||||
/****** SPI Control Codes *****/
|
||||
|
||||
#define ARM_SPI_CONTROL_Pos 0
|
||||
#define ARM_SPI_CONTROL_Msk (0xFFUL << ARM_SPI_CONTROL_Pos)
|
||||
|
||||
/*----- SPI Control Codes: Mode -----*/
|
||||
#define ARM_SPI_MODE_INACTIVE (0x00UL << ARM_SPI_CONTROL_Pos) ///< SPI Inactive
|
||||
#define ARM_SPI_MODE_MASTER (0x01UL << ARM_SPI_CONTROL_Pos) ///< SPI Master (Output on MOSI, Input on MISO); arg = Bus Speed in bps
|
||||
#define ARM_SPI_MODE_SLAVE (0x02UL << ARM_SPI_CONTROL_Pos) ///< SPI Slave (Output on MISO, Input on MOSI)
|
||||
#define ARM_SPI_MODE_MASTER_SIMPLEX (0x03UL << ARM_SPI_CONTROL_Pos) ///< SPI Master (Output/Input on MOSI); arg = Bus Speed in bps
|
||||
#define ARM_SPI_MODE_SLAVE_SIMPLEX (0x04UL << ARM_SPI_CONTROL_Pos) ///< SPI Slave (Output/Input on MISO)
|
||||
|
||||
/*----- SPI Control Codes: Mode Parameters: Frame Format -----*/
|
||||
#define ARM_SPI_FRAME_FORMAT_Pos 8
|
||||
#define ARM_SPI_FRAME_FORMAT_Msk (7UL << ARM_SPI_FRAME_FORMAT_Pos)
|
||||
#define ARM_SPI_CPOL0_CPHA0 (0UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Clock Polarity 0, Clock Phase 0 (default)
|
||||
#define ARM_SPI_CPOL0_CPHA1 (1UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Clock Polarity 0, Clock Phase 1
|
||||
#define ARM_SPI_CPOL1_CPHA0 (2UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Clock Polarity 1, Clock Phase 0
|
||||
#define ARM_SPI_CPOL1_CPHA1 (3UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Clock Polarity 1, Clock Phase 1
|
||||
#define ARM_SPI_TI_SSI (4UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Texas Instruments Frame Format
|
||||
#define ARM_SPI_MICROWIRE (5UL << ARM_SPI_FRAME_FORMAT_Pos) ///< National Microwire Frame Format
|
||||
|
||||
/*----- SPI Control Codes: Mode Parameters: Data Bits -----*/
|
||||
#define ARM_SPI_DATA_BITS_Pos 12
|
||||
#define ARM_SPI_DATA_BITS_Msk (0x3FUL << ARM_SPI_DATA_BITS_Pos)
|
||||
#define ARM_SPI_DATA_BITS(n) (((n) & 0x3F) << ARM_SPI_DATA_BITS_Pos) ///< Number of Data bits
|
||||
|
||||
/*----- SPI Control Codes: Mode Parameters: Bit Order -----*/
|
||||
#define ARM_SPI_BIT_ORDER_Pos 18
|
||||
#define ARM_SPI_BIT_ORDER_Msk (1UL << ARM_SPI_BIT_ORDER_Pos)
|
||||
#define ARM_SPI_MSB_LSB (0UL << ARM_SPI_BIT_ORDER_Pos) ///< SPI Bit order from MSB to LSB (default)
|
||||
#define ARM_SPI_LSB_MSB (1UL << ARM_SPI_BIT_ORDER_Pos) ///< SPI Bit order from LSB to MSB
|
||||
|
||||
/*----- SPI Control Codes: Mode Parameters: Slave Select Mode -----*/
|
||||
#define ARM_SPI_SS_MASTER_MODE_Pos 19
|
||||
#define ARM_SPI_SS_MASTER_MODE_Msk (3UL << ARM_SPI_SS_MASTER_MODE_Pos)
|
||||
#define ARM_SPI_SS_MASTER_UNUSED (0UL << ARM_SPI_SS_MASTER_MODE_Pos) ///< SPI Slave Select when Master: Not used (default)
|
||||
#define ARM_SPI_SS_MASTER_SW (1UL << ARM_SPI_SS_MASTER_MODE_Pos) ///< SPI Slave Select when Master: Software controlled
|
||||
#define ARM_SPI_SS_MASTER_HW_OUTPUT (2UL << ARM_SPI_SS_MASTER_MODE_Pos) ///< SPI Slave Select when Master: Hardware controlled Output
|
||||
#define ARM_SPI_SS_MASTER_HW_INPUT (3UL << ARM_SPI_SS_MASTER_MODE_Pos) ///< SPI Slave Select when Master: Hardware monitored Input
|
||||
#define ARM_SPI_SS_SLAVE_MODE_Pos 21
|
||||
#define ARM_SPI_SS_SLAVE_MODE_Msk (1UL << ARM_SPI_SS_SLAVE_MODE_Pos)
|
||||
#define ARM_SPI_SS_SLAVE_HW (0UL << ARM_SPI_SS_SLAVE_MODE_Pos) ///< SPI Slave Select when Slave: Hardware monitored (default)
|
||||
#define ARM_SPI_SS_SLAVE_SW (1UL << ARM_SPI_SS_SLAVE_MODE_Pos) ///< SPI Slave Select when Slave: Software controlled
|
||||
|
||||
|
||||
/*----- SPI Control Codes: Miscellaneous Controls -----*/
|
||||
#define ARM_SPI_SET_BUS_SPEED (0x10UL << ARM_SPI_CONTROL_Pos) ///< Set Bus Speed in bps; arg = value
|
||||
#define ARM_SPI_GET_BUS_SPEED (0x11UL << ARM_SPI_CONTROL_Pos) ///< Get Bus Speed in bps
|
||||
#define ARM_SPI_SET_DEFAULT_TX_VALUE (0x12UL << ARM_SPI_CONTROL_Pos) ///< Set default Transmit value; arg = value
|
||||
#define ARM_SPI_CONTROL_SS (0x13UL << ARM_SPI_CONTROL_Pos) ///< Control Slave Select; arg: 0=inactive, 1=active
|
||||
#define ARM_SPI_ABORT_TRANSFER (0x14UL << ARM_SPI_CONTROL_Pos) ///< Abort current data transfer
|
||||
|
||||
|
||||
/****** SPI Slave Select Signal definitions *****/
|
||||
#define ARM_SPI_SS_INACTIVE 0 ///< SPI Slave Select Signal Inactive
|
||||
#define ARM_SPI_SS_ACTIVE 1 ///< SPI Slave Select Signal Active
|
||||
|
||||
|
||||
/****** SPI specific error codes *****/
|
||||
#define ARM_SPI_ERROR_MODE (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< Specified Mode not supported
|
||||
#define ARM_SPI_ERROR_FRAME_FORMAT (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Specified Frame Format not supported
|
||||
#define ARM_SPI_ERROR_DATA_BITS (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Specified number of Data bits not supported
|
||||
#define ARM_SPI_ERROR_BIT_ORDER (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< Specified Bit order not supported
|
||||
#define ARM_SPI_ERROR_SS_MODE (ARM_DRIVER_ERROR_SPECIFIC - 5) ///< Specified Slave Select Mode not supported
|
||||
|
||||
|
||||
/**
|
||||
\brief SPI Status
|
||||
*/
|
||||
typedef volatile struct _ARM_SPI_STATUS {
|
||||
uint32_t busy : 1; ///< Transmitter/Receiver busy flag
|
||||
uint32_t data_lost : 1; ///< Data lost: Receive overflow / Transmit underflow (cleared on start of transfer operation)
|
||||
uint32_t mode_fault : 1; ///< Mode fault detected; optional (cleared on start of transfer operation)
|
||||
uint32_t reserved : 29;
|
||||
} ARM_SPI_STATUS;
|
||||
|
||||
|
||||
/****** SPI Event *****/
|
||||
#define ARM_SPI_EVENT_TRANSFER_COMPLETE (1UL << 0) ///< Data Transfer completed
|
||||
#define ARM_SPI_EVENT_DATA_LOST (1UL << 1) ///< Data lost: Receive overflow / Transmit underflow
|
||||
#define ARM_SPI_EVENT_MODE_FAULT (1UL << 2) ///< Master Mode Fault (SS deactivated when Master)
|
||||
|
||||
|
||||
// Function documentation
|
||||
/**
|
||||
\fn ARM_DRIVER_VERSION ARM_SPI_GetVersion (void)
|
||||
\brief Get driver version.
|
||||
\return \ref ARM_DRIVER_VERSION
|
||||
|
||||
\fn ARM_SPI_CAPABILITIES ARM_SPI_GetCapabilities (void)
|
||||
\brief Get driver capabilities.
|
||||
\return \ref ARM_SPI_CAPABILITIES
|
||||
|
||||
\fn int32_t ARM_SPI_Initialize (ARM_SPI_SignalEvent_t cb_event)
|
||||
\brief Initialize SPI Interface.
|
||||
\param[in] cb_event Pointer to \ref ARM_SPI_SignalEvent
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_SPI_Uninitialize (void)
|
||||
\brief De-initialize SPI Interface.
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_SPI_PowerControl (ARM_POWER_STATE state)
|
||||
\brief Control SPI Interface Power.
|
||||
\param[in] state Power state
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_SPI_Send (const void *data, uint32_t num)
|
||||
\brief Start sending data to SPI transmitter.
|
||||
\param[in] data Pointer to buffer with data to send to SPI transmitter
|
||||
\param[in] num Number of data items to send
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_SPI_Receive (void *data, uint32_t num)
|
||||
\brief Start receiving data from SPI receiver.
|
||||
\param[out] data Pointer to buffer for data to receive from SPI receiver
|
||||
\param[in] num Number of data items to receive
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_SPI_Transfer (const void *data_out,
|
||||
void *data_in,
|
||||
uint32_t num)
|
||||
\brief Start sending/receiving data to/from SPI transmitter/receiver.
|
||||
\param[in] data_out Pointer to buffer with data to send to SPI transmitter
|
||||
\param[out] data_in Pointer to buffer for data to receive from SPI receiver
|
||||
\param[in] num Number of data items to transfer
|
||||
\return \ref execution_status
|
||||
|
||||
\fn uint32_t ARM_SPI_GetDataCount (void)
|
||||
\brief Get transferred data count.
|
||||
\return number of data items transferred
|
||||
|
||||
\fn int32_t ARM_SPI_Control (uint32_t control, uint32_t arg)
|
||||
\brief Control SPI Interface.
|
||||
\param[in] control Operation
|
||||
\param[in] arg Argument of operation (optional)
|
||||
\return common \ref execution_status and driver specific \ref spi_execution_status
|
||||
|
||||
\fn ARM_SPI_STATUS ARM_SPI_GetStatus (void)
|
||||
\brief Get SPI status.
|
||||
\return SPI status \ref ARM_SPI_STATUS
|
||||
|
||||
\fn void ARM_SPI_SignalEvent (uint32_t event)
|
||||
\brief Signal SPI Events.
|
||||
\param[in] event \ref SPI_events notification mask
|
||||
\return none
|
||||
*/
|
||||
|
||||
typedef void (*ARM_SPI_SignalEvent_t) (uint32_t event); ///< Pointer to \ref ARM_SPI_SignalEvent : Signal SPI Event.
|
||||
|
||||
|
||||
/**
|
||||
\brief SPI Driver Capabilities.
|
||||
*/
|
||||
typedef struct _ARM_SPI_CAPABILITIES {
|
||||
uint32_t simplex : 1; ///< supports Simplex Mode (Master and Slave)
|
||||
uint32_t ti_ssi : 1; ///< supports TI Synchronous Serial Interface
|
||||
uint32_t microwire : 1; ///< supports Microwire Interface
|
||||
uint32_t event_mode_fault : 1; ///< Signal Mode Fault event: \ref ARM_SPI_EVENT_MODE_FAULT
|
||||
uint32_t reserved : 28; ///< Reserved (must be zero)
|
||||
} ARM_SPI_CAPABILITIES;
|
||||
|
||||
|
||||
/**
|
||||
\brief Access structure of the SPI Driver.
|
||||
*/
|
||||
typedef struct _ARM_DRIVER_SPI {
|
||||
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_SPI_GetVersion : Get driver version.
|
||||
ARM_SPI_CAPABILITIES (*GetCapabilities) (void); ///< Pointer to \ref ARM_SPI_GetCapabilities : Get driver capabilities.
|
||||
int32_t (*Initialize) (ARM_SPI_SignalEvent_t cb_event); ///< Pointer to \ref ARM_SPI_Initialize : Initialize SPI Interface.
|
||||
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_SPI_Uninitialize : De-initialize SPI Interface.
|
||||
int32_t (*PowerControl) (ARM_POWER_STATE state); ///< Pointer to \ref ARM_SPI_PowerControl : Control SPI Interface Power.
|
||||
int32_t (*Send) (const void *data, uint32_t num); ///< Pointer to \ref ARM_SPI_Send : Start sending data to SPI Interface.
|
||||
int32_t (*Receive) ( void *data, uint32_t num); ///< Pointer to \ref ARM_SPI_Receive : Start receiving data from SPI Interface.
|
||||
int32_t (*Transfer) (const void *data_out,
|
||||
void *data_in,
|
||||
uint32_t num); ///< Pointer to \ref ARM_SPI_Transfer : Start sending/receiving data to/from SPI.
|
||||
uint32_t (*GetDataCount) (void); ///< Pointer to \ref ARM_SPI_GetDataCount : Get transferred data count.
|
||||
int32_t (*Control) (uint32_t control, uint32_t arg); ///< Pointer to \ref ARM_SPI_Control : Control SPI Interface.
|
||||
ARM_SPI_STATUS (*GetStatus) (void); ///< Pointer to \ref ARM_SPI_GetStatus : Get SPI status.
|
||||
} const ARM_DRIVER_SPI;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DRIVER_SPI_H_ */
|
||||
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* $Date: 2. Feb 2017
|
||||
* $Revision: V2.3
|
||||
*
|
||||
* Project: USART (Universal Synchronous Asynchronous Receiver Transmitter)
|
||||
* Driver definitions
|
||||
*/
|
||||
|
||||
/* History:
|
||||
* Version 2.3
|
||||
* ARM_USART_STATUS and ARM_USART_MODEM_STATUS made volatile
|
||||
* Version 2.2
|
||||
* Corrected ARM_USART_CPOL_Pos and ARM_USART_CPHA_Pos definitions
|
||||
* Version 2.1
|
||||
* Removed optional argument parameter from Signal Event
|
||||
* Version 2.0
|
||||
* New simplified driver:
|
||||
* complexity moved to upper layer (especially data handling)
|
||||
* more unified API for different communication interfaces
|
||||
* renamed driver UART -> USART (Asynchronous & Synchronous)
|
||||
* Added modes:
|
||||
* Synchronous
|
||||
* Single-wire
|
||||
* IrDA
|
||||
* Smart Card
|
||||
* Changed prefix ARM_DRV -> ARM_DRIVER
|
||||
* Version 1.10
|
||||
* Namespace prefix ARM_ added
|
||||
* Version 1.01
|
||||
* Added events:
|
||||
* ARM_UART_EVENT_TX_EMPTY, ARM_UART_EVENT_RX_TIMEOUT
|
||||
* ARM_UART_EVENT_TX_THRESHOLD, ARM_UART_EVENT_RX_THRESHOLD
|
||||
* Added functions: SetTxThreshold, SetRxThreshold
|
||||
* Added "rx_timeout_event" to capabilities
|
||||
* Version 1.00
|
||||
* Initial release
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_USART_H_
|
||||
#define DRIVER_USART_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "Driver_Common.h"
|
||||
|
||||
#define ARM_USART_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,3) /* API version */
|
||||
|
||||
|
||||
/****** USART Control Codes *****/
|
||||
|
||||
#define ARM_USART_CONTROL_Pos 0
|
||||
#define ARM_USART_CONTROL_Msk (0xFFUL << ARM_USART_CONTROL_Pos)
|
||||
|
||||
/*----- USART Control Codes: Mode -----*/
|
||||
#define ARM_USART_MODE_ASYNCHRONOUS (0x01UL << ARM_USART_CONTROL_Pos) ///< UART (Asynchronous); arg = Baudrate
|
||||
#define ARM_USART_MODE_SYNCHRONOUS_MASTER (0x02UL << ARM_USART_CONTROL_Pos) ///< Synchronous Master (generates clock signal); arg = Baudrate
|
||||
#define ARM_USART_MODE_SYNCHRONOUS_SLAVE (0x03UL << ARM_USART_CONTROL_Pos) ///< Synchronous Slave (external clock signal)
|
||||
#define ARM_USART_MODE_SINGLE_WIRE (0x04UL << ARM_USART_CONTROL_Pos) ///< UART Single-wire (half-duplex); arg = Baudrate
|
||||
#define ARM_USART_MODE_IRDA (0x05UL << ARM_USART_CONTROL_Pos) ///< UART IrDA; arg = Baudrate
|
||||
#define ARM_USART_MODE_SMART_CARD (0x06UL << ARM_USART_CONTROL_Pos) ///< UART Smart Card; arg = Baudrate
|
||||
|
||||
/*----- USART Control Codes: Mode Parameters: Data Bits -----*/
|
||||
#define ARM_USART_DATA_BITS_Pos 8
|
||||
#define ARM_USART_DATA_BITS_Msk (7UL << ARM_USART_DATA_BITS_Pos)
|
||||
#define ARM_USART_DATA_BITS_5 (5UL << ARM_USART_DATA_BITS_Pos) ///< 5 Data bits
|
||||
#define ARM_USART_DATA_BITS_6 (6UL << ARM_USART_DATA_BITS_Pos) ///< 6 Data bit
|
||||
#define ARM_USART_DATA_BITS_7 (7UL << ARM_USART_DATA_BITS_Pos) ///< 7 Data bits
|
||||
#define ARM_USART_DATA_BITS_8 (0UL << ARM_USART_DATA_BITS_Pos) ///< 8 Data bits (default)
|
||||
#define ARM_USART_DATA_BITS_9 (1UL << ARM_USART_DATA_BITS_Pos) ///< 9 Data bits
|
||||
|
||||
/*----- USART Control Codes: Mode Parameters: Parity -----*/
|
||||
#define ARM_USART_PARITY_Pos 12
|
||||
#define ARM_USART_PARITY_Msk (3UL << ARM_USART_PARITY_Pos)
|
||||
#define ARM_USART_PARITY_NONE (0UL << ARM_USART_PARITY_Pos) ///< No Parity (default)
|
||||
#define ARM_USART_PARITY_EVEN (1UL << ARM_USART_PARITY_Pos) ///< Even Parity
|
||||
#define ARM_USART_PARITY_ODD (2UL << ARM_USART_PARITY_Pos) ///< Odd Parity
|
||||
|
||||
/*----- USART Control Codes: Mode Parameters: Stop Bits -----*/
|
||||
#define ARM_USART_STOP_BITS_Pos 14
|
||||
#define ARM_USART_STOP_BITS_Msk (3UL << ARM_USART_STOP_BITS_Pos)
|
||||
#define ARM_USART_STOP_BITS_1 (0UL << ARM_USART_STOP_BITS_Pos) ///< 1 Stop bit (default)
|
||||
#define ARM_USART_STOP_BITS_2 (1UL << ARM_USART_STOP_BITS_Pos) ///< 2 Stop bits
|
||||
#define ARM_USART_STOP_BITS_1_5 (2UL << ARM_USART_STOP_BITS_Pos) ///< 1.5 Stop bits
|
||||
#define ARM_USART_STOP_BITS_0_5 (3UL << ARM_USART_STOP_BITS_Pos) ///< 0.5 Stop bits
|
||||
|
||||
/*----- USART Control Codes: Mode Parameters: Flow Control -----*/
|
||||
#define ARM_USART_FLOW_CONTROL_Pos 16
|
||||
#define ARM_USART_FLOW_CONTROL_Msk (3UL << ARM_USART_FLOW_CONTROL_Pos)
|
||||
#define ARM_USART_FLOW_CONTROL_NONE (0UL << ARM_USART_FLOW_CONTROL_Pos) ///< No Flow Control (default)
|
||||
#define ARM_USART_FLOW_CONTROL_RTS (1UL << ARM_USART_FLOW_CONTROL_Pos) ///< RTS Flow Control
|
||||
#define ARM_USART_FLOW_CONTROL_CTS (2UL << ARM_USART_FLOW_CONTROL_Pos) ///< CTS Flow Control
|
||||
#define ARM_USART_FLOW_CONTROL_RTS_CTS (3UL << ARM_USART_FLOW_CONTROL_Pos) ///< RTS/CTS Flow Control
|
||||
|
||||
/*----- USART Control Codes: Mode Parameters: Clock Polarity (Synchronous mode) -----*/
|
||||
#define ARM_USART_CPOL_Pos 18
|
||||
#define ARM_USART_CPOL_Msk (1UL << ARM_USART_CPOL_Pos)
|
||||
#define ARM_USART_CPOL0 (0UL << ARM_USART_CPOL_Pos) ///< CPOL = 0 (default)
|
||||
#define ARM_USART_CPOL1 (1UL << ARM_USART_CPOL_Pos) ///< CPOL = 1
|
||||
|
||||
/*----- USART Control Codes: Mode Parameters: Clock Phase (Synchronous mode) -----*/
|
||||
#define ARM_USART_CPHA_Pos 19
|
||||
#define ARM_USART_CPHA_Msk (1UL << ARM_USART_CPHA_Pos)
|
||||
#define ARM_USART_CPHA0 (0UL << ARM_USART_CPHA_Pos) ///< CPHA = 0 (default)
|
||||
#define ARM_USART_CPHA1 (1UL << ARM_USART_CPHA_Pos) ///< CPHA = 1
|
||||
|
||||
|
||||
/*----- USART Control Codes: Miscellaneous Controls -----*/
|
||||
#define ARM_USART_SET_DEFAULT_TX_VALUE (0x10UL << ARM_USART_CONTROL_Pos) ///< Set default Transmit value (Synchronous Receive only); arg = value
|
||||
#define ARM_USART_SET_IRDA_PULSE (0x11UL << ARM_USART_CONTROL_Pos) ///< Set IrDA Pulse in ns; arg: 0=3/16 of bit period
|
||||
#define ARM_USART_SET_SMART_CARD_GUARD_TIME (0x12UL << ARM_USART_CONTROL_Pos) ///< Set Smart Card Guard Time; arg = number of bit periods
|
||||
#define ARM_USART_SET_SMART_CARD_CLOCK (0x13UL << ARM_USART_CONTROL_Pos) ///< Set Smart Card Clock in Hz; arg: 0=Clock not generated
|
||||
#define ARM_USART_CONTROL_SMART_CARD_NACK (0x14UL << ARM_USART_CONTROL_Pos) ///< Smart Card NACK generation; arg: 0=disabled, 1=enabled
|
||||
#define ARM_USART_CONTROL_TX (0x15UL << ARM_USART_CONTROL_Pos) ///< Transmitter; arg: 0=disabled, 1=enabled
|
||||
#define ARM_USART_CONTROL_RX (0x16UL << ARM_USART_CONTROL_Pos) ///< Receiver; arg: 0=disabled, 1=enabled
|
||||
#define ARM_USART_CONTROL_BREAK (0x17UL << ARM_USART_CONTROL_Pos) ///< Continuous Break transmission; arg: 0=disabled, 1=enabled
|
||||
#define ARM_USART_ABORT_SEND (0x18UL << ARM_USART_CONTROL_Pos) ///< Abort \ref ARM_USART_Send
|
||||
#define ARM_USART_ABORT_RECEIVE (0x19UL << ARM_USART_CONTROL_Pos) ///< Abort \ref ARM_USART_Receive
|
||||
#define ARM_USART_ABORT_TRANSFER (0x1AUL << ARM_USART_CONTROL_Pos) ///< Abort \ref ARM_USART_Transfer
|
||||
#define ARM_USART_CONTROL_FLUSH_TX (0x1BUL << ARM_USART_CONTROL_Pos) ///< FLUSH TX FIFO
|
||||
#define ARM_USART_CONTROL_PURGE_COMM (0x1CUL << ARM_USART_CONTROL_Pos) ///< Purge communition(clear rx & tx fifo)
|
||||
|
||||
|
||||
/****** USART specific error codes *****/
|
||||
#define ARM_USART_ERROR_MODE (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< Specified Mode not supported
|
||||
#define ARM_USART_ERROR_BAUDRATE (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Specified baudrate not supported
|
||||
#define ARM_USART_ERROR_DATA_BITS (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Specified number of Data bits not supported
|
||||
#define ARM_USART_ERROR_PARITY (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< Specified Parity not supported
|
||||
#define ARM_USART_ERROR_STOP_BITS (ARM_DRIVER_ERROR_SPECIFIC - 5) ///< Specified number of Stop bits not supported
|
||||
#define ARM_USART_ERROR_FLOW_CONTROL (ARM_DRIVER_ERROR_SPECIFIC - 6) ///< Specified Flow Control not supported
|
||||
#define ARM_USART_ERROR_CPOL (ARM_DRIVER_ERROR_SPECIFIC - 7) ///< Specified Clock Polarity not supported
|
||||
#define ARM_USART_ERROR_CPHA (ARM_DRIVER_ERROR_SPECIFIC - 8) ///< Specified Clock Phase not supported
|
||||
|
||||
|
||||
/**
|
||||
\brief USART Status
|
||||
*/
|
||||
typedef volatile struct _ARM_USART_STATUS {
|
||||
uint32_t tx_busy : 1; ///< Transmitter busy flag
|
||||
uint32_t rx_busy : 1; ///< Receiver busy flag
|
||||
uint32_t tx_underflow : 1; ///< Transmit data underflow detected (cleared on start of next send operation)
|
||||
uint32_t rx_overflow : 1; ///< Receive data overflow detected (cleared on start of next receive operation)
|
||||
uint32_t rx_break : 1; ///< Break detected on receive (cleared on start of next receive operation)
|
||||
uint32_t rx_framing_error : 1; ///< Framing error detected on receive (cleared on start of next receive operation)
|
||||
uint32_t rx_parity_error : 1; ///< Parity error detected on receive (cleared on start of next receive operation)
|
||||
uint32_t is_send_block : 1; ///< Whether Send API works in blocking way
|
||||
uint32_t reserved : 24;
|
||||
} ARM_USART_STATUS;
|
||||
|
||||
/**
|
||||
\brief USART Modem Control
|
||||
*/
|
||||
typedef enum _ARM_USART_MODEM_CONTROL {
|
||||
ARM_USART_RTS_CLEAR, ///< Deactivate RTS
|
||||
ARM_USART_RTS_SET, ///< Activate RTS
|
||||
ARM_USART_DTR_CLEAR, ///< Deactivate DTR
|
||||
ARM_USART_DTR_SET ///< Activate DTR
|
||||
} ARM_USART_MODEM_CONTROL;
|
||||
|
||||
/**
|
||||
\brief USART Modem Status
|
||||
*/
|
||||
typedef volatile struct _ARM_USART_MODEM_STATUS {
|
||||
uint32_t cts : 1; ///< CTS state: 1=Active, 0=Inactive
|
||||
uint32_t dsr : 1; ///< DSR state: 1=Active, 0=Inactive
|
||||
uint32_t dcd : 1; ///< DCD state: 1=Active, 0=Inactive
|
||||
uint32_t ri : 1; ///< RI state: 1=Active, 0=Inactive
|
||||
uint32_t reserved : 28;
|
||||
} ARM_USART_MODEM_STATUS;
|
||||
|
||||
|
||||
/****** USART Event *****/
|
||||
#define ARM_USART_EVENT_SEND_COMPLETE (1UL << 0) ///< Send completed; however USART may still transmit data
|
||||
#define ARM_USART_EVENT_RECEIVE_COMPLETE (1UL << 1) ///< Receive completed
|
||||
#define ARM_USART_EVENT_TRANSFER_COMPLETE (1UL << 2) ///< Transfer completed
|
||||
#define ARM_USART_EVENT_TX_COMPLETE (1UL << 3) ///< Transmit completed (optional)
|
||||
#define ARM_USART_EVENT_TX_UNDERFLOW (1UL << 4) ///< Transmit data not available (Synchronous Slave)
|
||||
#define ARM_USART_EVENT_RX_OVERFLOW (1UL << 5) ///< Receive data overflow
|
||||
#define ARM_USART_EVENT_RX_TIMEOUT (1UL << 6) ///< Receive character timeout (optional)
|
||||
#define ARM_USART_EVENT_RX_BREAK (1UL << 7) ///< Break detected on receive
|
||||
#define ARM_USART_EVENT_RX_FRAMING_ERROR (1UL << 8) ///< Framing error detected on receive
|
||||
#define ARM_USART_EVENT_RX_PARITY_ERROR (1UL << 9) ///< Parity error detected on receive
|
||||
#define ARM_USART_EVENT_CTS (1UL << 10) ///< CTS state changed (optional)
|
||||
#define ARM_USART_EVENT_DSR (1UL << 11) ///< DSR state changed (optional)
|
||||
#define ARM_USART_EVENT_DCD (1UL << 12) ///< DCD state changed (optional)
|
||||
#define ARM_USART_EVENT_RI (1UL << 13) ///< RI state changed (optional)
|
||||
#define ARM_USART_EVENT_AUTO_BAUDRATE_DONE (1UL << 14) ///< Auto baudrate dection completed
|
||||
|
||||
|
||||
// Function documentation
|
||||
/**
|
||||
\fn ARM_DRIVER_VERSION ARM_USART_GetVersion (void)
|
||||
\brief Get driver version.
|
||||
\return \ref ARM_DRIVER_VERSION
|
||||
|
||||
\fn ARM_USART_CAPABILITIES ARM_USART_GetCapabilities (void)
|
||||
\brief Get driver capabilities
|
||||
\return \ref ARM_USART_CAPABILITIES
|
||||
|
||||
\fn int32_t ARM_USART_Initialize (ARM_USART_SignalEvent_t cb_event)
|
||||
\brief Initialize USART Interface.
|
||||
\param[in] cb_event Pointer to \ref ARM_USART_SignalEvent
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_USART_Uninitialize (void)
|
||||
\brief De-initialize USART Interface.
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_USART_PowerControl (ARM_POWER_STATE state)
|
||||
\brief Control USART Interface Power.
|
||||
\param[in] state Power state
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_USART_Send (const void *data, uint32_t num)
|
||||
\brief Start sending data to USART transmitter.
|
||||
\param[in] data Pointer to buffer with data to send to USART transmitter
|
||||
\param[in] num Number of data items to send
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_USART_Receive (void *data, uint32_t num)
|
||||
\brief Start receiving data from USART receiver.
|
||||
\param[out] data Pointer to buffer for data to receive from USART receiver
|
||||
\param[in] num Number of data items to receive
|
||||
\return \ref execution_status
|
||||
|
||||
\fn int32_t ARM_USART_Transfer (const void *data_out,
|
||||
void *data_in,
|
||||
uint32_t num)
|
||||
\brief Start sending/receiving data to/from USART transmitter/receiver.
|
||||
\param[in] data_out Pointer to buffer with data to send to USART transmitter
|
||||
\param[out] data_in Pointer to buffer for data to receive from USART receiver
|
||||
\param[in] num Number of data items to transfer
|
||||
\return \ref execution_status
|
||||
|
||||
\fn uint32_t ARM_USART_GetTxCount (void)
|
||||
\brief Get transmitted data count.
|
||||
\return number of data items transmitted
|
||||
|
||||
\fn uint32_t ARM_USART_GetRxCount (void)
|
||||
\brief Get received data count.
|
||||
\return number of data items received
|
||||
|
||||
\fn int32_t ARM_USART_Control (uint32_t control, uint32_t arg)
|
||||
\brief Control USART Interface.
|
||||
\param[in] control Operation
|
||||
\param[in] arg Argument of operation (optional)
|
||||
\return common \ref execution_status and driver specific \ref usart_execution_status
|
||||
|
||||
\fn ARM_USART_STATUS ARM_USART_GetStatus (void)
|
||||
\brief Get USART status.
|
||||
\return USART status \ref ARM_USART_STATUS
|
||||
|
||||
\fn int32_t ARM_USART_SetModemControl (ARM_USART_MODEM_CONTROL control)
|
||||
\brief Set USART Modem Control line state.
|
||||
\param[in] control \ref ARM_USART_MODEM_CONTROL
|
||||
\return \ref execution_status
|
||||
|
||||
\fn ARM_USART_MODEM_STATUS ARM_USART_GetModemStatus (void)
|
||||
\brief Get USART Modem Status lines state.
|
||||
\return modem status \ref ARM_USART_MODEM_STATUS
|
||||
|
||||
\fn uint32_t ARM_USART_GetBaudRate (void)
|
||||
\brief Get current baud rate.
|
||||
\return current baud rate
|
||||
|
||||
\fn void ARM_USART_SignalEvent (uint32_t event)
|
||||
\brief Signal USART Events.
|
||||
\param[in] event \ref USART_events notification mask
|
||||
\return none
|
||||
|
||||
\fn int32_t ARM_USART_SendPolling (const void *data, uint32_t num)
|
||||
\brief Start sending data to USART transmitter in polling way.
|
||||
\param[in] data Pointer to buffer with data to send to USART transmitter
|
||||
\param[in] num Number of data items to send
|
||||
\return \ref execution_status
|
||||
*/
|
||||
|
||||
typedef void (*ARM_USART_SignalEvent_t) (uint32_t event); ///< Pointer to \ref ARM_USART_SignalEvent : Signal USART Event.
|
||||
|
||||
|
||||
/**
|
||||
\brief USART Device Driver Capabilities.
|
||||
*/
|
||||
typedef struct _ARM_USART_CAPABILITIES {
|
||||
uint32_t asynchronous : 1; ///< supports UART (Asynchronous) mode
|
||||
uint32_t synchronous_master : 1; ///< supports Synchronous Master mode
|
||||
uint32_t synchronous_slave : 1; ///< supports Synchronous Slave mode
|
||||
uint32_t single_wire : 1; ///< supports UART Single-wire mode
|
||||
uint32_t irda : 1; ///< supports UART IrDA mode
|
||||
uint32_t smart_card : 1; ///< supports UART Smart Card mode
|
||||
uint32_t smart_card_clock : 1; ///< Smart Card Clock generator available
|
||||
uint32_t flow_control_rts : 1; ///< RTS Flow Control available
|
||||
uint32_t flow_control_cts : 1; ///< CTS Flow Control available
|
||||
uint32_t event_tx_complete : 1; ///< Transmit completed event: \ref ARM_USART_EVENT_TX_COMPLETE
|
||||
uint32_t event_rx_timeout : 1; ///< Signal receive character timeout event: \ref ARM_USART_EVENT_RX_TIMEOUT
|
||||
uint32_t rts : 1; ///< RTS Line: 0=not available, 1=available
|
||||
uint32_t cts : 1; ///< CTS Line: 0=not available, 1=available
|
||||
uint32_t dtr : 1; ///< DTR Line: 0=not available, 1=available
|
||||
uint32_t dsr : 1; ///< DSR Line: 0=not available, 1=available
|
||||
uint32_t dcd : 1; ///< DCD Line: 0=not available, 1=available
|
||||
uint32_t ri : 1; ///< RI Line: 0=not available, 1=available
|
||||
uint32_t event_cts : 1; ///< Signal CTS change event: \ref ARM_USART_EVENT_CTS
|
||||
uint32_t event_dsr : 1; ///< Signal DSR change event: \ref ARM_USART_EVENT_DSR
|
||||
uint32_t event_dcd : 1; ///< Signal DCD change event: \ref ARM_USART_EVENT_DCD
|
||||
uint32_t event_ri : 1; ///< Signal RI change event: \ref ARM_USART_EVENT_RI
|
||||
uint32_t reserved : 11; ///< Reserved (must be zero)
|
||||
} ARM_USART_CAPABILITIES;
|
||||
|
||||
|
||||
/**
|
||||
\brief Access structure of the USART Driver.
|
||||
*/
|
||||
typedef struct _ARM_DRIVER_USART {
|
||||
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_USART_GetVersion : Get driver version.
|
||||
ARM_USART_CAPABILITIES (*GetCapabilities) (void); ///< Pointer to \ref ARM_USART_GetCapabilities : Get driver capabilities.
|
||||
int32_t (*Initialize) (ARM_USART_SignalEvent_t cb_event); ///< Pointer to \ref ARM_USART_Initialize : Initialize USART Interface.
|
||||
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_USART_Uninitialize : De-initialize USART Interface.
|
||||
int32_t (*PowerControl) (ARM_POWER_STATE state); ///< Pointer to \ref ARM_USART_PowerControl : Control USART Interface Power.
|
||||
int32_t (*Send) (const void *data, uint32_t num); ///< Pointer to \ref ARM_USART_Send : Start sending data to USART transmitter.
|
||||
int32_t (*Receive) ( void *data, uint32_t num); ///< Pointer to \ref ARM_USART_Receive : Start receiving data from USART receiver.
|
||||
int32_t (*Transfer) (const void *data_out,
|
||||
void *data_in,
|
||||
uint32_t num); ///< Pointer to \ref ARM_USART_Transfer : Start sending/receiving data to/from USART.
|
||||
uint32_t (*GetTxCount) (void); ///< Pointer to \ref ARM_USART_GetTxCount : Get transmitted data count.
|
||||
uint32_t (*GetRxCount) (void); ///< Pointer to \ref ARM_USART_GetRxCount : Get received data count.
|
||||
int32_t (*Control) (uint32_t control, uint32_t arg); ///< Pointer to \ref ARM_USART_Control : Control USART Interface.
|
||||
ARM_USART_STATUS (*GetStatus) (void); ///< Pointer to \ref ARM_USART_GetStatus : Get USART status.
|
||||
int32_t (*SetModemControl) (ARM_USART_MODEM_CONTROL control); ///< Pointer to \ref ARM_USART_SetModemControl : Set USART Modem Control line state.
|
||||
ARM_USART_MODEM_STATUS (*GetModemStatus) (void); ///< Pointer to \ref ARM_USART_GetModemStatus : Get USART Modem Status lines state.
|
||||
uint32_t (*GetBaudRate) (void); ///< Pointer to \ref ARM_USART_GetBaudRate : Get current baud rate.
|
||||
int32_t (*SendPolling) (const void *data, uint32_t num); ///< Pointer to \ref ARM_USART_SendPolling : Start sending data to USART transmitter in polling way. <b> This is an extended API not inlcuded in original CMSIS driver version.</b>
|
||||
} const ARM_DRIVER_USART;
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DRIVER_USART_H_ */
|
||||
@@ -0,0 +1,93 @@
|
||||
#ifndef BSP_I2C_H
|
||||
#define BSP_I2C_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "ec618.h"
|
||||
#include "bsp.h"
|
||||
|
||||
|
||||
// I2C Driver state flags
|
||||
#define I2C_FLAG_INIT BIT(0) // Driver initialized
|
||||
#define I2C_FLAG_POWER BIT(1) // Driver power on
|
||||
#define I2C_FLAG_SETUP BIT(2) // Master configured, clock set
|
||||
#define I2C_FLAG_MASTER_TX BIT(3) // Master tx
|
||||
#define I2C_FLAG_MASTER_RX BIT(4) // Master rx
|
||||
#define I2C_FLAG_SLAVE_TX BIT(5) // Slave tx
|
||||
#define I2C_FLAG_SLAVE_RX BIT(6) // Slave rx
|
||||
|
||||
#define I2C_NO_STARTSTOP (0x00000000U)
|
||||
#define I2C_GENERATE_STOP (I2C_SCR_STOP_Msk)
|
||||
#define I2C_GENERATE_START_READ (I2C_SCR_START_Msk | I2C_SCR_TARGET_RWN_Msk)
|
||||
#define I2C_GENERATE_START_WRITE (I2C_SCR_START_Msk)
|
||||
#define I2C_GENERATE_RESTART_READ (I2C_SCR_RESTART_Msk | I2C_SCR_TARGET_RWN_Msk)
|
||||
#define I2C_GENERATE_RESTART_WRITE (I2C_SCR_RESTART_Msk)
|
||||
|
||||
|
||||
#define I2C_MEMADD_SIZE_8BIT (0x00000001U)
|
||||
#define I2C_MEMADD_SIZE_16BIT (0x00000002U)
|
||||
|
||||
#define I2C_AUTOMATIC_MODE1 (0x01) // byte_num_unknown = 0
|
||||
#define I2C_AUTOMATIC_MODE2 (0x02) // byte_num_unknown = 1
|
||||
#define I2C_DEDICATED_MODE (0x03)
|
||||
|
||||
// I2C IRQ
|
||||
typedef const struct _I2C_IRQ {
|
||||
IRQn_Type irq_num; // I2C IRQ Number
|
||||
IRQ_Callback_t cb_irq;
|
||||
} I2C_IRQ;
|
||||
|
||||
// I2C PINS
|
||||
typedef const struct _I2C_PIN {
|
||||
PIN *pin_scl; // SCL Pin identifier
|
||||
PIN *pin_sda; // SDA Pin identifier
|
||||
} I2C_PINS;
|
||||
|
||||
// I2C DMA
|
||||
typedef struct _I2C_DMA {
|
||||
DmaInstance_e tx_instance; // Transmit DMA instance
|
||||
int8_t tx_ch; // Transmit channel number
|
||||
uint8_t tx_req; // Transmit DMA request number
|
||||
void (*tx_callback)(uint32_t event); // Transmit callback
|
||||
DmaInstance_e rx_instance; // Receive DMA instance
|
||||
int8_t rx_ch; // Receive channel number
|
||||
uint8_t rx_req; // Receive DMA request number
|
||||
void (*rx_callback)(uint32_t event); // Receive callback
|
||||
} I2C_DMA;
|
||||
|
||||
|
||||
// I2C Control Information
|
||||
typedef struct {
|
||||
ARM_I2C_SignalEvent_t cb_event; // Event callback
|
||||
ARM_I2C_STATUS status; // Status flags
|
||||
uint8_t flags; // Control and state flags
|
||||
uint8_t sla_rw; // Slave address and RW bit
|
||||
bool pending; // Transfer pending (no STOP)
|
||||
uint8_t stalled; // Stall mode status flags
|
||||
uint8_t con_aa; // I2C slave CON flag
|
||||
uint32_t cnt; // Master transfer count
|
||||
uint8_t *data; // Master data to transfer
|
||||
uint32_t num; // Number of bytes to transfer
|
||||
uint8_t *sdata; // Slave data to transfer
|
||||
uint32_t snum; // Number of bytes to transfer
|
||||
} I2C_CTRL;
|
||||
|
||||
|
||||
// I2C Resources definition
|
||||
typedef struct {
|
||||
I2C_TypeDef *reg; // I2C peripheral register interface
|
||||
I2C_PINS pins; // I2C PINS config
|
||||
I2C_DMA* dma; // I2C DMA configuration
|
||||
I2C_IRQ* irq; // I2C IRQ
|
||||
I2C_CTRL *ctrl; // Run-Time control information
|
||||
} const I2C_RESOURCES;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BSP_I2C_H */
|
||||
@@ -0,0 +1,116 @@
|
||||
#ifndef BSP_LPUSART_H
|
||||
#define BSP_LPUSART_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "ec618.h"
|
||||
#include "bsp.h"
|
||||
|
||||
|
||||
// LPUSART flags
|
||||
#define LPUSART_FLAG_INITIALIZED (1U << 0) // LPUSARTinitialized
|
||||
#define LPUSART_FLAG_POWER_FULL (1U << 1) // LPUSART powered FULL
|
||||
#define LPUSART_FLAG_POWER_LOW (1U << 2) // LPUSART powered LOW
|
||||
#define LPUSART_FLAG_CONFIGURED (1U << 3) // LPUSART configured
|
||||
#define LPUSART_FLAG_TX_ENABLED (1U << 4) // LPUSART TX enabled
|
||||
#define LPUSART_FLAG_RX_ENABLED (1U << 5) // LPUSART RX enabled
|
||||
#define LPUSART_FLAG_SEND_ACTIVE (1U << 6) // LPUSART send active
|
||||
|
||||
#define LPUSART_FLAG_POWER_MSK (LPUSART_FLAG_POWER_LOW | LPUSART_FLAG_POWER_FULL)
|
||||
|
||||
// LPUSART IRQ
|
||||
typedef const struct _LPUSART_IRQ {
|
||||
IRQn_Type irq_num; // LPUSART IRQ Number
|
||||
IRQ_Callback_t cb_irq;
|
||||
} LPUSART_IRQ;
|
||||
|
||||
// LPUSART TX DMA
|
||||
typedef struct _LPUSART_TX_DMA {
|
||||
DmaInstance_e instance; // DMA instance
|
||||
int8_t channel; // Channel number
|
||||
uint8_t request; // DMA request number
|
||||
void (*callback)(uint32_t event); // Tx callback
|
||||
} LPUSART_TX_DMA;
|
||||
|
||||
// LPUSART RX DMA
|
||||
typedef struct _LPUSART_RX_DMA {
|
||||
DmaInstance_e instance; // DMA instance
|
||||
int8_t channel; // Channel number
|
||||
uint8_t request; // DMA request number
|
||||
DmaDescriptor_t *descriptor; // Rx descriptor
|
||||
void (*callback)(uint32_t event); // Rx callback
|
||||
} LPUSART_RX_DMA;
|
||||
|
||||
// LPUSART PINS
|
||||
typedef const struct _LPUSART_PIN {
|
||||
const PIN *pin_tx; // TX Pin identifier
|
||||
const PIN *pin_rx; // RX Pin identifier
|
||||
const PIN *pin_cts; // CTS Pin identifier
|
||||
const PIN *pin_rts; // RTS Pin identifier
|
||||
} LPUSART_PINS;
|
||||
|
||||
|
||||
typedef struct _LPUSART_TRANSFER_INFO {
|
||||
uint32_t rx_num; // Total number of receive data
|
||||
uint32_t tx_num; // Total number of transmit data
|
||||
uint8_t *rx_buf; // Pointer to in data buffer
|
||||
uint8_t *tx_buf; // Pointer to out data buffer
|
||||
uint32_t rx_cnt; // Number of data received
|
||||
uint32_t tx_cnt; // Number of data sent
|
||||
uint16_t tx_def_val; // Default transmit value
|
||||
uint16_t rx_dump_val; // Receive dump value
|
||||
uint8_t send_active; // Send active flag
|
||||
uint32_t sync_mode; // Synchronous mode flag
|
||||
} LPUSART_TRANSFER_INFO;
|
||||
|
||||
typedef struct _LPUSART_STATUS {
|
||||
uint8_t rx_busy; // Receiver busy flag
|
||||
uint8_t rx_dma_triggered; // Receive DMA transfer triggered (cleared on start of next receive operation)
|
||||
uint8_t rx_overflow; // Receive data overflow detected (cleared on start of next receive operation)
|
||||
uint8_t aon_rx_overflow; // AON FIFO receive data overflow detected (cleared on start of next receive operation)
|
||||
uint8_t rx_break; // Break detected on receive (cleared on start of next receive operation)
|
||||
uint8_t rx_framing_error; // Framing error detected on receive (cleared on start of next receive operation)
|
||||
uint8_t rx_parity_error; // Parity error detected on receive (cleared on start of next receive operation)
|
||||
} LPUSART_STATUS;
|
||||
|
||||
typedef struct _LPUSART_INFO {
|
||||
ARM_USART_SignalEvent_t cb_event; // Event Callback
|
||||
LPUSART_STATUS rx_status; // Recieve Status flags
|
||||
LPUSART_TRANSFER_INFO xfer; // LPUSART transfer information
|
||||
uint8_t flags; // Current LPUSART flags
|
||||
uint32_t frame_code; // Current LPUSART frame setting code
|
||||
uint32_t baudrate; // Baudrate
|
||||
} LPUSART_INFO;
|
||||
|
||||
// LPUSART Resources definition
|
||||
typedef const struct {
|
||||
USART_TypeDef *co_usart_regs; // LPUSART cooperating uart registers pointer
|
||||
LPUSARTAON_TypeDef *aon_regs; // LPUSART AON part registers pointer
|
||||
LPUSARTCORE_TypeDef *core_regs; // LPUSART CORE part registers pointer
|
||||
LPUSART_PINS pins; // LPUSART PINS config
|
||||
LPUSART_RX_DMA *dma_rx; // LPUSART DMA register interface
|
||||
LPUSART_TX_DMA *co_usart_dma_tx; // LPUSART DMA register interface
|
||||
LPUSART_RX_DMA *co_usart_dma_rx; // LPUSART DMA register interface
|
||||
LPUSART_IRQ *irq; // LPUSART IRQ
|
||||
LPUSART_IRQ *co_usart_irq; // LPUSART cooperating uart IRQ
|
||||
LPUSART_INFO *info; // Run-Time Information
|
||||
} LPUSART_RESOURCES;
|
||||
|
||||
|
||||
void LPUSART_ClearStopFlag(void);
|
||||
void LPUSART_SetStopFlag(void);
|
||||
/*
|
||||
* Check whether rx is ongoing, return true if rx is ongoing at this moment, otherwise false
|
||||
*/
|
||||
bool LPUSART_IsRxActive(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BSP_LPLPUSART_H */
|
||||
@@ -0,0 +1,89 @@
|
||||
#ifndef BSP_SPI_H
|
||||
#define BSP_SPI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "ec618.h"
|
||||
#include "bsp.h"
|
||||
|
||||
|
||||
// SPI flags
|
||||
#define SPI_FLAG_INITIALIZED (1UL << 0) // SPI initialized
|
||||
#define SPI_FLAG_POWERED (1UL << 1) // SPI powered on
|
||||
#define SPI_FLAG_CONFIGURED (1UL << 2) // SPI configured
|
||||
#define SPI_FLAG_DATA_LOST (1UL << 3) // SPI data lost occurred
|
||||
#define SPI_FLAG_MODE_FAULT (1UL << 4) // SPI mode fault occurred
|
||||
|
||||
// SPI IRQ
|
||||
typedef const struct _SPI_IRQ {
|
||||
IRQn_Type irq_num; // SPI IRQ Number
|
||||
IRQ_Callback_t cb_irq;
|
||||
} SPI_IRQ;
|
||||
|
||||
// SPI DMA
|
||||
typedef struct _SPI_DMA {
|
||||
DmaInstance_e tx_instance; // Transmit DMA instance number
|
||||
int8_t tx_ch; // Transmit channel number
|
||||
uint8_t tx_req; // Transmit DMA request number
|
||||
void (*tx_callback)(uint32_t event); // Transmit callback
|
||||
DmaInstance_e rx_instance; // Receive DMA instance number
|
||||
int8_t rx_ch; // Receive channel number
|
||||
uint8_t rx_req; // Receive DMA request number
|
||||
void (*rx_callback)(uint32_t event); // Receive callback
|
||||
} SPI_DMA;
|
||||
|
||||
// SPI PINS
|
||||
typedef const struct _SPI_PIN {
|
||||
const PIN *pin_sclk; // SCLK Pin identifier
|
||||
const PIN *pin_ssn; // SSn Pin identifier
|
||||
const PIN *pin_mosi; // MOSI Pin identifier
|
||||
const PIN *pin_miso; // MISO Pin identifier
|
||||
} SPI_PINS;
|
||||
|
||||
typedef struct _SPI_STATUS {
|
||||
uint8_t busy; // Transmitter/Receiver busy flag
|
||||
uint8_t data_lost; // Data lost: Receive overflow / Transmit underflow (cleared on start of transfer operation)
|
||||
uint8_t mode_fault; // Mode fault detected; optional (cleared on start of transfer operation)
|
||||
} SPI_STATUS;
|
||||
|
||||
// SPI Transfer Information (Run-Time)
|
||||
typedef struct _SPI_TRANSFER_INFO {
|
||||
uint32_t num; // Total number of transfers
|
||||
uint8_t *rx_buf; // Pointer to in data buffer
|
||||
uint8_t *tx_buf; // Pointer to out data buffer
|
||||
uint32_t rx_cnt; // Number of data received
|
||||
uint32_t tx_cnt; // Number of data sent
|
||||
uint32_t dump_val; // Variable for dumping DMA data
|
||||
uint16_t def_val; // Default transfer value
|
||||
} SPI_TRANSFER_INFO;
|
||||
|
||||
// SPI information (Run-time)
|
||||
typedef struct _SPI_INFO {
|
||||
ARM_SPI_SignalEvent_t cb_event; // event callback
|
||||
SPI_STATUS status; // SPI status flags
|
||||
SPI_TRANSFER_INFO xfer; // SPI transfer information
|
||||
uint8_t flags; // SPI driver flags
|
||||
uint32_t mode; // SPI mode
|
||||
uint32_t bus_speed; // SPI bus speed
|
||||
uint8_t data_width; // SPI data bits select in unit of byte
|
||||
} SPI_INFO;
|
||||
|
||||
|
||||
// SPI Resources definition
|
||||
typedef struct {
|
||||
SPI_TypeDef *reg; // SPI register pointer
|
||||
SPI_PINS pins; // SPI PINS configuration
|
||||
SPI_DMA *dma; // SPI DMA configuration pointer
|
||||
SPI_IRQ *irq; // SPI IRQ configuration pointer
|
||||
SPI_INFO *info; // Run-Time Information
|
||||
} SPI_RESOURCES;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BSP_SPI_H */
|
||||
@@ -0,0 +1,108 @@
|
||||
#ifndef BSP_USART_H
|
||||
#define BSP_USART_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "ec618.h"
|
||||
#include "bsp.h"
|
||||
|
||||
|
||||
// USART flags
|
||||
#define USART_FLAG_INITIALIZED (1U << 0) // USARTinitialized
|
||||
#define USART_FLAG_POWERED (1U << 1) // USART powered on
|
||||
#define USART_FLAG_CONFIGURED (1U << 2) // USART configured
|
||||
#define USART_FLAG_TX_ENABLED (1U << 3) // USART TX enabled
|
||||
#define USART_FLAG_RX_ENABLED (1U << 4) // USART RX enabled
|
||||
#define USART_FLAG_SEND_ACTIVE (1U << 5) // USART send active
|
||||
|
||||
#define USART_TFE_INT (0x2<<USART_IIR_INT_ID_Pos)
|
||||
#define USART_RDA_INT (0x4<<USART_IIR_INT_ID_Pos)
|
||||
#define USART_RLS_INT (0x6<<USART_IIR_INT_ID_Pos)
|
||||
#define USART_CTI_INT (0xC<<USART_IIR_INT_ID_Pos)
|
||||
#define USART_INT_TYPE_MSK (0xF<<USART_IIR_INT_ID_Pos)
|
||||
|
||||
// USART IRQ
|
||||
typedef const struct _USART_IRQ {
|
||||
IRQn_Type irq_num; // USART IRQ Number
|
||||
IRQ_Callback_t cb_irq;
|
||||
} USART_IRQ;
|
||||
|
||||
// USART TX DMA
|
||||
typedef struct _USART_TX_DMA {
|
||||
DmaInstance_e instance; // DMA instance
|
||||
int8_t channel; // Channel number
|
||||
uint8_t request; // DMA request number
|
||||
void (*callback)(uint32_t event); // Tx callback
|
||||
} USART_TX_DMA;
|
||||
|
||||
// USART RX DMA
|
||||
typedef struct _USART_RX_DMA {
|
||||
DmaInstance_e instance; // DMA instance
|
||||
int8_t channel; // Channel number
|
||||
uint8_t request; // DMA request number
|
||||
DmaDescriptor_t *descriptor; // Rx descriptor
|
||||
void (*callback)(uint32_t event); // Rx callback
|
||||
} USART_RX_DMA;
|
||||
|
||||
// USART PINS
|
||||
typedef const struct _USART_PIN {
|
||||
const PIN *pin_tx; // TX Pin identifier
|
||||
const PIN *pin_rx; // RX Pin identifier
|
||||
const PIN *pin_cts; // CTS Pin identifier
|
||||
const PIN *pin_rts; // RTS Pin identifier
|
||||
} USART_PINS;
|
||||
|
||||
|
||||
typedef struct _USART_TRANSFER_INFO {
|
||||
uint32_t rx_num; // Total number of receive data
|
||||
uint32_t tx_num; // Total number of transmit data
|
||||
uint8_t *rx_buf; // Pointer to in data buffer
|
||||
uint8_t *tx_buf; // Pointer to out data buffer
|
||||
uint32_t rx_cnt; // Number of data received
|
||||
uint32_t tx_cnt; // Number of data sent
|
||||
uint16_t tx_def_val; // Default transmit value
|
||||
uint16_t rx_dump_val; // Receive dump value
|
||||
uint8_t send_active; // Send active flag
|
||||
uint32_t sync_mode; // Synchronous mode flag
|
||||
} USART_TRANSFER_INFO;
|
||||
|
||||
typedef struct _USART_STATUS {
|
||||
uint8_t rx_busy; // Receiver busy flag
|
||||
uint8_t rx_dma_triggered; // Receive DMA transfer triggered (cleared on start of next receive operation)
|
||||
uint8_t rx_overflow; // Receive data overflow detected (cleared on start of next receive operation)
|
||||
uint8_t rx_break; // Break detected on receive (cleared on start of next receive operation)
|
||||
uint8_t rx_framing_error; // Framing error detected on receive (cleared on start of next receive operation)
|
||||
uint8_t rx_parity_error; // Parity error detected on receive (cleared on start of next receive operation)
|
||||
} USART_STATUS;
|
||||
|
||||
typedef struct _USART_INFO {
|
||||
ARM_USART_SignalEvent_t cb_event; // Event Callback
|
||||
USART_STATUS rx_status; // Recieve Status flags
|
||||
USART_TRANSFER_INFO xfer; // USART transfer information
|
||||
uint8_t flags; // Current USART flags
|
||||
uint32_t frame_code; // Current USART frame setting code
|
||||
uint32_t baudrate; // Baudrate
|
||||
} USART_INFO;
|
||||
|
||||
// USART Resources definition
|
||||
typedef const struct {
|
||||
USART_TypeDef *reg; // USART peripheral pointer
|
||||
USART_PINS pins; // USART PINS config
|
||||
USART_TX_DMA *dma_tx; // USART DMA register interface
|
||||
USART_RX_DMA *dma_rx; // USART DMA register interface
|
||||
USART_IRQ *usart_irq; // USART IRQ
|
||||
uint32_t tx_fifo_trig_lvl; // USART TX FIFO trigger level
|
||||
uint32_t rx_fifo_trig_lvl; // USART RX FIFO trigger level
|
||||
USART_INFO *info; // Run-Time Information
|
||||
uint8_t is_unilog_mode; // Act as unilog output
|
||||
} USART_RESOURCES;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BSP_USART_H */
|
||||
@@ -0,0 +1,463 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
|
||||
* File name: adc.c
|
||||
* Description: EC618 adc driver source file
|
||||
* History:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "adc.h"
|
||||
#include "ic.h"
|
||||
#include "slpman.h"
|
||||
#include "ec618.h"
|
||||
#include "alarm.h"
|
||||
|
||||
#define LDO_AIO_CTRL_REG_ADDR (0x4D020180)
|
||||
|
||||
#define ADC_ENABLE() do \
|
||||
{ \
|
||||
ADC->CTRL |= ADC_CTRL_LDO_EN_Msk; \
|
||||
*(uint32_t*)(LDO_AIO_CTRL_REG_ADDR) = 1; \
|
||||
while((*(uint32_t*)(LDO_AIO_CTRL_REG_ADDR)) == 0); \
|
||||
} while(0)
|
||||
|
||||
#define ADC_DISABLE() do \
|
||||
{ \
|
||||
ADC->CTRL &= ~ADC_CTRL_LDO_EN_Msk; \
|
||||
*(uint32_t*)(LDO_AIO_CTRL_REG_ADDR) = 0; \
|
||||
while((*(uint32_t*)(LDO_AIO_CTRL_REG_ADDR)) == 1); \
|
||||
} while(0)
|
||||
|
||||
#define ADC_CHANNEL_NUMBER (6)
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
#define LOCK_SLEEP() do \
|
||||
{ \
|
||||
slpManDrvVoteSleep(SLP_VOTE_ADC, SLP_ACTIVE_STATE); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define UNLOCK_SLEEP() do \
|
||||
{ \
|
||||
slpManDrvVoteSleep(SLP_VOTE_ADC, SLP_SLP1_STATE); \
|
||||
} \
|
||||
while(0)
|
||||
#endif
|
||||
|
||||
#define ADC_DEFAULT_CLOCK_DIVIDER (ADC_CLOCK_DIV_8)
|
||||
|
||||
#define ADC_CHANNEL_ENABLE_BIT_POSITION (ADC_AIOCFG_THM_EN_Pos)
|
||||
|
||||
/**
|
||||
\brief size of ADC request queue, value shall be integer power of 2 for fast calcualtion of MOD.
|
||||
\note The valid number of requests is (this_macro_value - 1)
|
||||
*/
|
||||
#define ADC_REQUEST_QUEUE_SIZE (8)
|
||||
#define ADC_REQUEST_QUEUE_SIZE_MASK (ADC_REQUEST_QUEUE_SIZE - 1)
|
||||
|
||||
/**
|
||||
\brief ADC conversion request queue typedef
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t requestArray[ADC_REQUEST_QUEUE_SIZE];
|
||||
uint32_t head;
|
||||
uint32_t tail;
|
||||
} AdcReqeustQueue_t;
|
||||
|
||||
static AdcReqeustQueue_t gAdcRequestqueue;
|
||||
|
||||
/**
|
||||
\brief variable for keeping track the index of current request bitmap, see below bitmap layout
|
||||
*/
|
||||
static volatile uint32_t gCurrentRequestIndex;
|
||||
|
||||
/** \brief Internal used data structure */
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t AIOCFG; /**< AIO configuration Register */
|
||||
uint32_t CFG; /**< ADC configuration Register */
|
||||
} configRegisters;
|
||||
|
||||
adcCallback_t eventCallback; /**< Callback function passed in by application */
|
||||
} AdcChannelDatabase_t;
|
||||
|
||||
/**
|
||||
****************************** Bitmap layout *****************************
|
||||
*
|
||||
* 18 17 15 14 12 11 9 8 6 5 3 2 0
|
||||
*+-----------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*| VREF OUT | CH AIO1 | CH AIO2 | CH AIO3 | CH AIO4 | CH Vbat | CH thermal|
|
||||
*+-----------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* |APP | PLAT | PHY|
|
||||
*/
|
||||
#define CHANNEL_ID_TO_INDEX(channel, userID) ((userID & 0x3U) + (channel & 0x7U) * 3U)
|
||||
|
||||
#define ADC_MAX_LOGIC_CHANNELS (ADC_CHANNEL_NUMBER * ADC_USER_MAX)
|
||||
|
||||
/** \brief Internal used data structure */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t channelConfigValidBitMap; /**< Bitmap of channel configuration valid flag */
|
||||
AdcChannelDatabase_t channelDataBase[ADC_MAX_LOGIC_CHANNELS]; /**< Array of channel database, each element represents one configuration */
|
||||
} AdcDatabase_t;
|
||||
|
||||
static AdcDatabase_t g_adcDataBase = {0};
|
||||
void delay_us(uint32_t us);
|
||||
|
||||
static void ADC_requestQueueInit(void)
|
||||
{
|
||||
gAdcRequestqueue.head = 0;
|
||||
gAdcRequestqueue.tail = 0;
|
||||
gCurrentRequestIndex = ADC_MAX_LOGIC_CHANNELS;
|
||||
}
|
||||
|
||||
// no need to perform atomic access since this function is called only in ISR
|
||||
static int32_t ADC_requestQueueRead(uint32_t *request)
|
||||
{
|
||||
if(gAdcRequestqueue.tail == gAdcRequestqueue.head)
|
||||
{
|
||||
// queue is empty
|
||||
return -1;
|
||||
}
|
||||
|
||||
*request = gAdcRequestqueue.requestArray[gAdcRequestqueue.head];
|
||||
gAdcRequestqueue.head = (gAdcRequestqueue.head + 1) & ADC_REQUEST_QUEUE_SIZE_MASK;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int32_t ADC_requestQueueWrite(uint32_t *request)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
if(((gAdcRequestqueue.tail + 1) & ADC_REQUEST_QUEUE_SIZE_MASK) == gAdcRequestqueue.head)
|
||||
{
|
||||
// queue is full
|
||||
RestoreIRQMask(mask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
gAdcRequestqueue.requestArray[gAdcRequestqueue.tail] = *request;
|
||||
gAdcRequestqueue.tail = (gAdcRequestqueue.tail + 1) & ADC_REQUEST_QUEUE_SIZE_MASK;
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ADC_loadConfigAndStartConversion(uint32_t requestIndex)
|
||||
{
|
||||
uint32_t aiocfg;
|
||||
// clear status first
|
||||
// LDO has been enabled during initialization phase, here we shall keep this bit set
|
||||
ADC->CTRL = ADC_CTRL_LDO_EN_Msk | ADC_CTRL_EN_Msk;
|
||||
|
||||
// Protect VREF2AIO1 control bit, take care not to overwrite!!!
|
||||
aiocfg = (ADC->AIOCFG & ADC_AIOCFG_VREF2AIO1_EN_Msk) | g_adcDataBase.channelDataBase[requestIndex].configRegisters.AIOCFG;
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
// thermmal comparator close when sample thm channel
|
||||
if(aiocfg & ADC_AIOCFG_THM_EN_Msk)
|
||||
{
|
||||
alarmThmDisableInAdc();
|
||||
}
|
||||
#endif
|
||||
// Protect VREF2AIO1 control bit, take care not to overwrite!!!
|
||||
ADC->AIOCFG = aiocfg;
|
||||
ADC->CFG = g_adcDataBase.channelDataBase[requestIndex].configRegisters.CFG;
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
// thermal channel closed
|
||||
if((ADC->AIOCFG & ADC_AIOCFG_THM_EN_Msk) == 0)
|
||||
{
|
||||
if(alarmThmEnableInAdc() == false)
|
||||
{
|
||||
delay_us(10);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
delay_us(10);
|
||||
|
||||
// start conversion
|
||||
ADC->CTRL = (ADC_CTRL_LDO_EN_Msk | ADC_CTRL_EN_Msk | ADC_CTRL_RSTN_Msk);
|
||||
}
|
||||
|
||||
|
||||
static void ADC_interruptHandler(void)
|
||||
{
|
||||
uint32_t requestIndex;
|
||||
|
||||
int32_t ret;
|
||||
|
||||
ADC->AIOCFG &= ~(ADC_AIOCFG_THM_EN_Msk | ADC_AIOCFG_BATSENS_EN_Msk | ADC_AIOCFG_AIO4_EN_Msk |
|
||||
ADC_AIOCFG_AIO3_EN_Msk | ADC_AIOCFG_AIO2_EN_Msk | ADC_AIOCFG_AIO1_EN_Msk |
|
||||
ADC_AIOCFG_AIO4_NO_DIVR_EN_Msk | ADC_AIOCFG_AIO3_NO_DIVR_EN_Msk |
|
||||
ADC_AIOCFG_AIO2_NO_DIVR_EN_Msk | ADC_AIOCFG_AIO1_NO_DIVR_EN_Msk);
|
||||
|
||||
if(g_adcDataBase.channelDataBase[gCurrentRequestIndex].eventCallback != NULL)
|
||||
{
|
||||
g_adcDataBase.channelDataBase[gCurrentRequestIndex].eventCallback(ADC->RESULT);
|
||||
}
|
||||
|
||||
// Shall check config validation here since config could be changed in user callback(Deinit is called)
|
||||
/*
|
||||
R1 R2 R1 (3 request at once) R1 deInit R2 deInit (validBitMap change to 0 and ADC is disabled)
|
||||
APP ------------------------------------\ /--------------\ /------------\
|
||||
| | | | x
|
||||
v | v | x
|
||||
--------- --------- xxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
ADC ISR R1 R2 R1 is still in queue, stuck here(interrupt never occurs)
|
||||
*/
|
||||
|
||||
|
||||
if(g_adcDataBase.channelConfigValidBitMap != 0)
|
||||
{
|
||||
ret = ADC_requestQueueRead(&requestIndex);
|
||||
|
||||
// Start next round conversion
|
||||
if(ret == 0)
|
||||
{
|
||||
// there is pending request
|
||||
gCurrentRequestIndex = requestIndex;
|
||||
|
||||
ADC_loadConfigAndStartConversion(gCurrentRequestIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
gCurrentRequestIndex = ADC_MAX_LOGIC_CHANNELS;
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
alarmThmEnableInAdc();
|
||||
UNLOCK_SLEEP();
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ADC_requestQueueInit();
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
alarmThmEnableInAdc();
|
||||
UNLOCK_SLEEP();
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ADC_getDefaultConfig(AdcConfig_t *config)
|
||||
{
|
||||
ASSERT(config);
|
||||
|
||||
config->clockDivider = ADC_DEFAULT_CLOCK_DIVIDER;
|
||||
config->channelConfig.aioResDiv = ADC_AIO_RESDIV_BYPASS;
|
||||
}
|
||||
|
||||
int32_t ADC_channelInit(AdcChannel_e channel, AdcUser_t userID, const AdcConfig_t *config, adcCallback_t callback)
|
||||
{
|
||||
uint32_t mask, configValue, requestIndex;
|
||||
|
||||
configValue = 0;
|
||||
|
||||
requestIndex = CHANNEL_ID_TO_INDEX(channel, userID);
|
||||
|
||||
if(requestIndex >= ADC_MAX_LOGIC_CHANNELS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
|
||||
// AIO1 conflict check
|
||||
if((channel == ADC_CHANNEL_AIO1) && ((g_adcDataBase.channelConfigValidBitMap & (1 << ADC_MAX_LOGIC_CHANNELS)) != 0))
|
||||
{
|
||||
RestoreIRQMask(mask);
|
||||
return -2;
|
||||
}
|
||||
|
||||
// First Initialization
|
||||
if(g_adcDataBase.channelConfigValidBitMap == 0)
|
||||
{
|
||||
// enable ADC
|
||||
ADC_ENABLE();
|
||||
XIC_SetVector(PXIC1_AUXADC_IRQn, ADC_interruptHandler);
|
||||
XIC_EnableIRQ(PXIC1_AUXADC_IRQn);
|
||||
ADC_requestQueueInit();
|
||||
}
|
||||
g_adcDataBase.channelConfigValidBitMap |= ( 1 << requestIndex);
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
configValue |= ( EIGEN_VAL2FLD(ADC_CFG_WAIT_CTRL, 1) | \
|
||||
EIGEN_VAL2FLD(ADC_CFG_OFFSET_CTRL, 5) | \
|
||||
EIGEN_VAL2FLD(ADC_CFG_SAMPLE_AVG, 0) | \
|
||||
EIGEN_VAL2FLD(ADC_CFG_CLKIN_DIV, config ? config->clockDivider : ADC_DEFAULT_CLOCK_DIVIDER) | \
|
||||
EIGEN_VAL2FLD(ADC_CFG_VREF_BS, 1) | \
|
||||
EIGEN_VAL2FLD(ADC_CFG_VREF_SEL, 4) | \
|
||||
EIGEN_VAL2FLD(ADC_CFG_LDO_SEL, 4) | \
|
||||
EIGEN_VAL2FLD(ADC_CFG_IBIAS_SEL, 1)
|
||||
);
|
||||
g_adcDataBase.channelDataBase[requestIndex].configRegisters.CFG = configValue;
|
||||
|
||||
configValue = 0;
|
||||
|
||||
switch(channel)
|
||||
{
|
||||
case ADC_CHANNEL_THERMAL:
|
||||
configValue = 1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION) | EIGEN_VAL2FLD(ADC_AIOCFG_THM_SEL, 2);
|
||||
break;
|
||||
|
||||
case ADC_CHANNEL_VBAT:
|
||||
configValue = (1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION)) | EIGEN_VAL2FLD(ADC_AIOCFG_VBATSEN_RDIV, config->channelConfig.vbatResDiv);
|
||||
break;
|
||||
|
||||
case ADC_CHANNEL_AIO1:
|
||||
case ADC_CHANNEL_AIO2:
|
||||
case ADC_CHANNEL_AIO3:
|
||||
case ADC_CHANNEL_AIO4:
|
||||
|
||||
if(config->channelConfig.aioResDiv == ADC_AIO_RESDIV_BYPASS)
|
||||
{
|
||||
configValue = 1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION + 4);
|
||||
}
|
||||
else if(config->channelConfig.aioResDiv < ADC_AIO_RESDIV_RATIO_8OVER16)
|
||||
{
|
||||
configValue = (1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION)) | ADC_AIOCFG_RDIV_BYP_Msk | EIGEN_VAL2FLD(ADC_AIOCFG_RDIV, config->channelConfig.aioResDiv);
|
||||
}
|
||||
else
|
||||
{
|
||||
configValue = (1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION)) | (EIGEN_VAL2FLD(ADC_AIOCFG_RDIV, (config->channelConfig.aioResDiv - ADC_AIO_RESDIV_RATIO_8OVER16)));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_adcDataBase.channelDataBase[requestIndex].configRegisters.AIOCFG = configValue;
|
||||
g_adcDataBase.channelDataBase[requestIndex].eventCallback = callback;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ADC_channelDeInit(AdcChannel_e channel, AdcUser_t userID)
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
g_adcDataBase.channelConfigValidBitMap &= ~(1 << CHANNEL_ID_TO_INDEX(channel, userID));
|
||||
|
||||
if(g_adcDataBase.channelConfigValidBitMap == 0)
|
||||
{
|
||||
// diable ADC
|
||||
ADC->CTRL = ADC->CTRL & ADC_CTRL_LDO_EN_Msk;
|
||||
// disable clock
|
||||
ADC_DISABLE();
|
||||
XIC_DisableIRQ(PXIC1_AUXADC_IRQn);
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
|
||||
int32_t ADC_startConversion(AdcChannel_e channel, AdcUser_t userID)
|
||||
{
|
||||
uint32_t mask, requestIndex;
|
||||
int32_t ret;
|
||||
|
||||
requestIndex = CHANNEL_ID_TO_INDEX(channel, userID);
|
||||
|
||||
ASSERT(requestIndex < ADC_MAX_LOGIC_CHANNELS);
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
|
||||
// validation check
|
||||
if((g_adcDataBase.channelConfigValidBitMap & (1 << requestIndex)) == 0)
|
||||
{
|
||||
RestoreIRQMask(mask);
|
||||
return -2;
|
||||
}
|
||||
|
||||
// A conversion is ongoing, pending the request
|
||||
if(gCurrentRequestIndex != ADC_MAX_LOGIC_CHANNELS)
|
||||
{
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
ret = ADC_requestQueueWrite(&requestIndex);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
// request queue is full
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gCurrentRequestIndex = requestIndex;
|
||||
ADC_loadConfigAndStartConversion(gCurrentRequestIndex);
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
LOCK_SLEEP();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int32_t ADC_enableVrefOutput(void)
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
// AIO1 conflict check
|
||||
if((g_adcDataBase.channelConfigValidBitMap & (0x7 << (ADC_CHANNEL_AIO1*3U))) != 0)
|
||||
{
|
||||
RestoreIRQMask(mask);
|
||||
return -2;
|
||||
}
|
||||
|
||||
// First Initialization
|
||||
if(g_adcDataBase.channelConfigValidBitMap == 0)
|
||||
{
|
||||
// enable ADC
|
||||
ADC_ENABLE();
|
||||
XIC_SetVector(PXIC1_AUXADC_IRQn, ADC_interruptHandler);
|
||||
XIC_EnableIRQ(PXIC1_AUXADC_IRQn);
|
||||
ADC_requestQueueInit();
|
||||
}
|
||||
ADC->AIOCFG |= ADC_AIOCFG_VREF2AIO1_EN_Msk;
|
||||
g_adcDataBase.channelConfigValidBitMap |= ( 1 << ADC_MAX_LOGIC_CHANNELS);
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ADC_disableVrefOutput(void)
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
g_adcDataBase.channelConfigValidBitMap &= ~(1 << ADC_MAX_LOGIC_CHANNELS);
|
||||
|
||||
ADC->AIOCFG &= ~ADC_AIOCFG_VREF2AIO1_EN_Msk;
|
||||
|
||||
if(g_adcDataBase.channelConfigValidBitMap == 0)
|
||||
{
|
||||
// diable ADC
|
||||
ADC->CTRL = ADC->CTRL & ADC_CTRL_LDO_EN_Msk;
|
||||
// disable clock
|
||||
ADC_DISABLE();
|
||||
XIC_DisableIRQ(PXIC1_AUXADC_IRQn);
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
#include "ic.h"
|
||||
#include "apmu2Peripheral.h"
|
||||
#ifdef __USER_CODE__
|
||||
#include "RTE_Device.h"
|
||||
#else
|
||||
#include "RTE_Device.h"
|
||||
#endif
|
||||
#include "timer.h"
|
||||
#include "clock.h"
|
||||
#include DEBUG_LOG_HEADER_FILE
|
||||
#if (RTE_USB_EN == 1)
|
||||
void usblpw_enter_start_proc(bool force_cfg_pwr_down);
|
||||
void usblpw_enter_abort_proc(bool force_cfg_pwr_down);
|
||||
void usblpw_susp2vbustbl_guard_dlychk(uint32_t cur_tick);
|
||||
void usblpw_susp2hib_guard_dlychk(uint32_t cur_tick);
|
||||
void usblpw_retwkup_sleep1_later_recovery(void);
|
||||
void usblpw_retwkup_sleep1_pre_recovery(void);
|
||||
#endif
|
||||
|
||||
#if (RTE_LPUART_EN == 1)
|
||||
#include "bsp_lpusart.h"
|
||||
#endif
|
||||
|
||||
// to wakeup in paging wfi for hib timer, should only use in paging.(timer4 can use in app)
|
||||
#define AP_NEARHIBTIME_INSTANCE (4)
|
||||
#define AP_NEARHIBTIME_IRQ (PXIC0_TIMER4_IRQn)
|
||||
#define AP_NEARHIBTIME_MAXIMUM (4294967) // 0xffffffff/1000 ms
|
||||
|
||||
// do not use timer5 in app
|
||||
#define CP_STARTTIME_INSTANCE (5)
|
||||
#define CP_STARTTIME_IRQ (PXIC0_TIMER5_IRQn)
|
||||
#define CP_STARTTIME_MAXIMUM (4294967) // 0xffffffff/1000 ms
|
||||
|
||||
void apmuPeriUsbEnterStartProc(bool forceCfgPwrDown)
|
||||
{
|
||||
#if (RTE_USB_EN == 1)
|
||||
usblpw_enter_start_proc(forceCfgPwrDown);
|
||||
#endif
|
||||
}
|
||||
|
||||
void apmuPeriUsbEnterAbortProc(bool forceCfgPwrDown)
|
||||
{
|
||||
#if (RTE_USB_EN == 1)
|
||||
usblpw_enter_abort_proc(forceCfgPwrDown);
|
||||
#endif
|
||||
}
|
||||
|
||||
void apmuPeriUsbSusp2VbusTblGuardDlyChk(uint32_t cur_tick)
|
||||
{
|
||||
#if (RTE_USB_EN == 1)
|
||||
usblpw_susp2vbustbl_guard_dlychk(cur_tick);
|
||||
#endif
|
||||
}
|
||||
|
||||
void apmuPeriUsbSusp2HibGuardDlyChk(uint32_t cur_tick)
|
||||
{
|
||||
#if (RTE_USB_EN == 1)
|
||||
usblpw_susp2hib_guard_dlychk(cur_tick);
|
||||
#endif
|
||||
}
|
||||
|
||||
void apmuPeriUsbSleep1LateRecoverFlow(bool sleepSuccess)
|
||||
{
|
||||
#if (RTE_USB_EN == 1)
|
||||
if(sleepSuccess)
|
||||
{
|
||||
usblpw_retwkup_sleep1_later_recovery();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void apmuPeriUsbSleep1PreRecoverFlow(bool sleepSuccess)
|
||||
{
|
||||
#if (RTE_USB_EN == 1)
|
||||
if(sleepSuccess)
|
||||
{
|
||||
usblpw_retwkup_sleep1_pre_recovery();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool apmuPeriLpuartPreSleepProcess(void)
|
||||
{
|
||||
#ifdef __USER_CODE__
|
||||
extern int soc_uart_sleep_check(uint8_t *result);
|
||||
uint8_t result;
|
||||
if (!soc_uart_sleep_check(&result))
|
||||
{
|
||||
return result?true:false;
|
||||
}
|
||||
#endif
|
||||
#if (RTE_LPUART_EN == 1)
|
||||
LPUSART_SetStopFlag();
|
||||
if(LPUSART_IsRxActive())
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, apmuPeriLpuartPreSleepProcess_1, P_WARNING, "lpuart status, iir: 0x%x, fcsr: 0x%x, tcr: 0x%x, tsr: 0x%x", LPUSART_CORE->IIR, LPUSART_CORE->FCSR, LPUSART_CORE->TCR, LPUSART_CORE->TSR);
|
||||
LPUSART_ClearStopFlag();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
extern void AonRegSetWakeupEdge(uint8_t index, bool posEnable, bool negEnable);
|
||||
AonRegSetWakeupEdge(6, false, true);
|
||||
NVIC_EnableIRQ(LpuartWakeup_IRQn);
|
||||
}
|
||||
LPUSART_ClearStopFlag();
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool apmuPeriLpuartIsRxActive(void)
|
||||
{
|
||||
#ifdef __USER_CODE__
|
||||
extern int soc_uart_rx_check(uint8_t *result);
|
||||
uint8_t result;
|
||||
if (!soc_uart_rx_check(&result))
|
||||
{
|
||||
return result?true:false;
|
||||
}
|
||||
#endif
|
||||
#if (RTE_LPUART_EN == 1)
|
||||
return LPUSART_IsRxActive();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void apmuPeriWFITimerExp(void)
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PMU, apmu2PeriWFITimerExp_0, P_VALUE, "apmu2PeriWFITimerExp Enter");
|
||||
if (TIMER_getInterruptFlags(CP_STARTTIME_INSTANCE) & TIMER_MATCH0_INTERRUPT_FLAG)
|
||||
{
|
||||
TIMER_clearInterruptFlags(CP_STARTTIME_INSTANCE, TIMER_MATCH0_INTERRUPT_FLAG);
|
||||
}
|
||||
TIMER_stop(AP_NEARHIBTIME_INSTANCE);
|
||||
TIMER_deInit(AP_NEARHIBTIME_INSTANCE);
|
||||
}
|
||||
|
||||
|
||||
void apmuPeriStartWFITimer(uint32_t ms)
|
||||
{
|
||||
int32_t clkRet1,clkRet2;
|
||||
if(ms<10)
|
||||
return;
|
||||
|
||||
CLOCK_clockReset(FCLK_TIMER4); // to protect setClock error
|
||||
|
||||
// TIMER config
|
||||
// Config TIMER clock, source from 26MHz and divide by 1
|
||||
clkRet1 = CLOCK_setClockSrc(FCLK_TIMER4, FCLK_TIMER4_SEL_26M);
|
||||
clkRet2 = CLOCK_setClockDiv(FCLK_TIMER4, 26);
|
||||
|
||||
if((clkRet1 != 0) || (clkRet2 != 0))
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PMU, apmuPeriStartWFITimer_0, P_ERROR, "clkRet1=%d, clkRet2=%d, CLKFREQ=0x%x", clkRet1, clkRet2, CLOCK_getClockFreq(FCLK_TIMER4));
|
||||
EC_ASSERT(0, clkRet1, clkRet2, CLOCK_getClockFreq(FCLK_TIMER4));
|
||||
}
|
||||
|
||||
TimerConfig_t timerConfig;
|
||||
TIMER_getDefaultConfig(&timerConfig);
|
||||
timerConfig.reloadOption = TIMER_RELOAD_ON_MATCH0;
|
||||
|
||||
if(ms > AP_NEARHIBTIME_MAXIMUM)
|
||||
{
|
||||
ms = AP_NEARHIBTIME_MAXIMUM;
|
||||
}
|
||||
timerConfig.match0 = (ms-5)*1000;
|
||||
|
||||
ECPLAT_PRINTF(UNILOG_PMU, apmuPeriStartWFITimer_1, P_VALUE, "apmuPeriStartWFITimer set to %u ms", (ms-5));
|
||||
|
||||
TIMER_init(AP_NEARHIBTIME_INSTANCE, &timerConfig);
|
||||
|
||||
TIMER_interruptConfig(AP_NEARHIBTIME_INSTANCE, TIMER_MATCH0_SELECT, TIMER_INTERRUPT_LEVEL);
|
||||
TIMER_interruptConfig(AP_NEARHIBTIME_INSTANCE, TIMER_MATCH1_SELECT, TIMER_INTERRUPT_DISABLED);
|
||||
TIMER_interruptConfig(AP_NEARHIBTIME_INSTANCE, TIMER_MATCH2_SELECT, TIMER_INTERRUPT_DISABLED);
|
||||
|
||||
// Enable TIMER IRQ
|
||||
XIC_SetVector(AP_NEARHIBTIME_IRQ, apmuPeriWFITimerExp);
|
||||
XIC_EnableIRQ(AP_NEARHIBTIME_IRQ);
|
||||
|
||||
TIMER_start(AP_NEARHIBTIME_INSTANCE);
|
||||
}
|
||||
|
||||
void apmuPeriDeleteWFITimer(void)
|
||||
{
|
||||
TIMER_stop(AP_NEARHIBTIME_INSTANCE);
|
||||
TIMER_deInit(AP_NEARHIBTIME_INSTANCE);
|
||||
}
|
||||
|
||||
void apmuPeriDeleteCPTimer(void)
|
||||
{
|
||||
TIMER_stop(CP_STARTTIME_INSTANCE);
|
||||
TIMER_deInit(CP_STARTTIME_INSTANCE);
|
||||
}
|
||||
|
||||
void apmuPeriClearCPTimerInterrupt(void)
|
||||
{
|
||||
if (TIMER_getInterruptFlags(CP_STARTTIME_INSTANCE) & TIMER_MATCH0_INTERRUPT_FLAG)
|
||||
{
|
||||
TIMER_clearInterruptFlags(CP_STARTTIME_INSTANCE, TIMER_MATCH0_INTERRUPT_FLAG);
|
||||
}
|
||||
}
|
||||
|
||||
void apmuPeriStartCPTimer(uint32_t cpStartTime, void* expFunc)
|
||||
{
|
||||
int32_t clkRet1,clkRet2;
|
||||
|
||||
CLOCK_clockReset(FCLK_TIMER5); // to protect setClock error, can not reproduce easily
|
||||
|
||||
// TIMER config
|
||||
// Config TIMER clock, source from 26MHz and divide by 1
|
||||
clkRet1 = CLOCK_setClockSrc(FCLK_TIMER5, FCLK_TIMER5_SEL_26M);
|
||||
clkRet2 = CLOCK_setClockDiv(FCLK_TIMER5, 26);
|
||||
|
||||
if((clkRet1 != 0) || (clkRet2 != 0))
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PMU, apmuPeriStartCPTimer_0, P_ERROR, "clkRet1=%d, clkRet2=%d, CLKFREQ=0x%x", clkRet1, clkRet2, CLOCK_getClockFreq(FCLK_TIMER5));
|
||||
EC_ASSERT(0, clkRet1, clkRet2, CLOCK_getClockFreq(FCLK_TIMER5));
|
||||
}
|
||||
TimerConfig_t timerConfig;
|
||||
TIMER_getDefaultConfig(&timerConfig);
|
||||
timerConfig.reloadOption = TIMER_RELOAD_ON_MATCH0;
|
||||
|
||||
if(cpStartTime > CP_STARTTIME_MAXIMUM)
|
||||
{
|
||||
cpStartTime = CP_STARTTIME_MAXIMUM;
|
||||
}
|
||||
timerConfig.match0 = (cpStartTime-1)*1000;
|
||||
|
||||
ECPLAT_PRINTF(UNILOG_PMU, apmuPeriStartCPTimer_1, P_VALUE, "apmuCreateModemStartTimer set to %u ms", (cpStartTime-1));
|
||||
|
||||
TIMER_init(CP_STARTTIME_INSTANCE, &timerConfig);
|
||||
|
||||
TIMER_interruptConfig(CP_STARTTIME_INSTANCE, TIMER_MATCH0_SELECT, TIMER_INTERRUPT_LEVEL);
|
||||
TIMER_interruptConfig(CP_STARTTIME_INSTANCE, TIMER_MATCH1_SELECT, TIMER_INTERRUPT_DISABLED);
|
||||
TIMER_interruptConfig(CP_STARTTIME_INSTANCE, TIMER_MATCH2_SELECT, TIMER_INTERRUPT_DISABLED);
|
||||
|
||||
// Enable TIMER IRQ
|
||||
XIC_SetVector(CP_STARTTIME_IRQ, expFunc);
|
||||
XIC_EnableIRQ(CP_STARTTIME_IRQ);
|
||||
TIMER_start(CP_STARTTIME_INSTANCE);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,469 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
|
||||
* File name: clock.c
|
||||
* Description: EC618 clock driver source file
|
||||
* History: Rev1.0 2019-02-20
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "clock.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "Driver_Common.h"
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
#include DEBUG_LOG_HEADER_FILE
|
||||
#endif
|
||||
|
||||
extern bool GPR_clockEnableCheck(ClockId_e id);
|
||||
extern ClockId_e CLOCK_checkClkID(void);
|
||||
|
||||
|
||||
/** \brief support clock driver full feature or not */
|
||||
#define ENABLE_CLK_TREE_PARENT
|
||||
|
||||
/** \brief definition of clk tree element for clock management */
|
||||
typedef struct _clk_tree_element
|
||||
{
|
||||
uint32_t enableCount : 8; /**< counter of each clk has been enabled */
|
||||
uint32_t parentId : 17; /**< id of this clock's parent clk */
|
||||
uint32_t hasExtraDependency : 1; /**< whether or not this clock has extra dependent clock */
|
||||
uint32_t canChangeSrcForcely : 1; /**< whether or not the source of this clock can be changed in enabled state */
|
||||
} ClkTreeElement_t;
|
||||
|
||||
/** \brief clock tree Array */
|
||||
static ClkTreeElement_t g_clkTreeArray[] =
|
||||
{
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_CC)] = {1, CLK_MF, 0, 1},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_APB_MP)] = {1, CLK_MF, 0, 1},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_APB_XP)] = {1, CLK_MF, 0, 1},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_SMP)] = {1, INVALID_CLK, 0, 1},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_SYSTICK)] = {1, CLK_32K, 0, 1},
|
||||
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_UART0)] = {0, CLK_MF_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_UART1)] = {0, CLK_MF_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_UART2)] = {0, CLK_MF_GATED, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_SPI0)] = {0, CLK_MF_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_SPI1)] = {0, CLK_MF_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_I2S0)] = {0, CLK_MF_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_I2S1)] = {0, CLK_MF_GATED, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_WDG)] = {0, CLK_32K_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER0)] = {0, CLK_32K_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER1)] = {0, CLK_32K_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER2)] = {0, CLK_32K_GATED, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER3)] = {0, CLK_32K_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER4)] = {0, CLK_32K_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER5)] = {0, CLK_32K_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_I2C0)] = {0, CLK_MF_GATED, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_I2C1)] = {0, CLK_MF_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_USIM0)] = {0, CLK_MF_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_USIM1)] = {0, CLK_MF_GATED, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FCLK_KPC)] = {0, CLK_32K_GATED, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_FLASH)] = {1, CLK_MF, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_PSRAM)] = {0, CLK_MF, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_MF)] = {1, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_32K)] = {1, INVALID_CLK, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_HF408M)] = {1, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_HF204M)] = {1, CLK_HF408M, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_HF102M)] = {0, CLK_HF204M, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_HF51M)] = {0, CLK_HF102M, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_32K_GATED)] = {1, CLK_32K, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_MF_GATED)] = {1, CLK_MF, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_CC_MP)] = {1, CLK_CC, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_CC_AP)] = {1, CLK_CC, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_CC_CP)] = {1, CLK_CC, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_AON)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_SMP_MP)] = {0, CLK_SMP, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(MFAB_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(AFBBR_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(MSMB_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FLASH_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(PSRAM_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(ULOG_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(UTFC_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(ULDP_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(USBC_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(USBC_PMU_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(USBC_REF_CLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(USBP_REF_CLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(USBC_UTMI_CLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_DAP_AP)] = {1, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_TRACE_AP)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_SYSTICK_AP)] = {0, CLK_SYSTICK, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_APB_AP)] = {1, CLK_APB_XP, 1, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_SMP_AP)] = {1, CLK_SMP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CLK_CLKCAL)] = {0, CLK_MF, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_SIPC)] = {0, CLK_APB_MP, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_AON)] = {1, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_CPMU)] = {1, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_PMDIG)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_RFDIG)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_PAD)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_GPIO)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_FUSE)] = {1, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_TRNG)] = {0, CLK_APB_MP, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_USBP)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_LPUC)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_UART0)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_UART1)] = {0, CLK_APB_MP, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_UART2)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_SPI0)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_SPI1)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_I2S0)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_I2S1)] = {0, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_WDG)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER0)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER1)] = {0, CLK_APB_AP, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER2)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER3)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER4)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER5)] = {0, CLK_APB_AP, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_IPC)] = {1, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_I2C0)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_I2C1)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_USIM0)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_USIM1)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_KPC)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(PCLK_ONEW)] = {0, CLK_APB_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(TOP_PBRG_HCLK)] = {1, CLK_CC_MP, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(TOP_PBRG_PCLK)] = {1, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(TOP_GPR_PCLK)] = {1, CLK_APB_MP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(TRACE_CLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(ETM_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(ROMTABLE_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(TPIU_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(CACHE_HCLK)] = {1, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(FABSUB_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(SBU_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(PBRG_HCLK)] = {1, CLK_CC_AP, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(SPIS_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(XIC_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(ULOG_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(TMU_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(SCT_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(UTFC_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
[GET_INDEX_FROM_CLOCK_ID(ULDP_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
|
||||
[GET_INDEX_FROM_CLOCK_ID(SCT_HCLK)] = {0, INVALID_CLK, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
PLAT_PA_RAMCODE void CLOCK_Trace(ClockId_e id, bool isEnable, void *func)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
ClockId_e checkId = CLOCK_checkClkID();
|
||||
uint32_t indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
|
||||
|
||||
if(id == checkId)
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, CLOCK_Trace_1, P_WARNING, "Clock Trace, id=0x%x isEnable=%d counter=%d, funcPtr=%x", id, isEnable, g_clkTreeArray[indexFromId].enableCount, func);
|
||||
}
|
||||
|
||||
if (g_clkTreeArray[indexFromId].enableCount > 128)
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, CLOCK_Trace_2, P_WARNING, "Clock Trace, id=0x%x counter=%d may overflow, funcPtr=%x", id, g_clkTreeArray[indexFromId].enableCount, func);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CLOCK_AssertChkBeforeSlp(void)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
if(CLOCK_checkClkID() == INVALID_CLK)
|
||||
return;
|
||||
uint32_t indexFromId = GET_INDEX_FROM_CLOCK_ID(CLOCK_checkClkID());
|
||||
if(g_clkTreeArray[indexFromId].enableCount != 0)
|
||||
EC_ASSERT(0, g_clkTreeArray[indexFromId].enableCount, indexFromId, 0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
PLAT_PA_RAMCODE int32_t CLOCK_clockEnable(ClockId_e id)
|
||||
{
|
||||
|
||||
#if defined(ENABLE_CLK_TREE_PARENT)
|
||||
int32_t ret;
|
||||
#endif
|
||||
|
||||
uint32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
|
||||
|
||||
if(indexFromId > GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
else if(indexFromId == GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
|
||||
return ARM_DRIVER_OK;
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
|
||||
CLOCK_Trace(id, true, __GET_RETURN_ADDRESS());
|
||||
|
||||
if(g_clkTreeArray[indexFromId].enableCount++ == 0)
|
||||
{
|
||||
GPR_clockEnable(id);
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
#if defined(ENABLE_CLK_TREE_PARENT)
|
||||
if(g_clkTreeArray[indexFromId].hasExtraDependency)
|
||||
{
|
||||
ret = CLOCK_clockEnable(PBRG_HCLK);
|
||||
ASSERT(ret == ARM_DRIVER_OK);
|
||||
}
|
||||
|
||||
ret = CLOCK_clockEnable((ClockId_e)g_clkTreeArray[indexFromId].parentId);
|
||||
ASSERT(ret == ARM_DRIVER_OK);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if(GPR_clockEnableCheck(id) == false)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, CLOCK_clockEnable_1, P_WARNING, "Clock Enable Failed, id=0x%x counter=%d", id, g_clkTreeArray[indexFromId].enableCount);
|
||||
#endif
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
PLAT_PA_RAMCODE void CLOCK_clockDisable(ClockId_e id)
|
||||
{
|
||||
uint32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
|
||||
|
||||
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
|
||||
return;
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
|
||||
CLOCK_Trace(id, false, __GET_RETURN_ADDRESS());
|
||||
|
||||
if(g_clkTreeArray[indexFromId].enableCount == 0)
|
||||
{
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, CLOCK_clockDisable_0, P_WARNING, "Clock Disable check failed, id=0x%x", id);
|
||||
#endif
|
||||
ASSERT(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!(--g_clkTreeArray[indexFromId].enableCount))
|
||||
{
|
||||
GPR_clockDisable(id);
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
#if defined(ENABLE_CLK_TREE_PARENT)
|
||||
if(g_clkTreeArray[indexFromId].hasExtraDependency)
|
||||
{
|
||||
CLOCK_clockDisable(PBRG_HCLK);
|
||||
}
|
||||
CLOCK_clockDisable((ClockId_e)g_clkTreeArray[indexFromId].parentId);
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
}
|
||||
|
||||
PLAT_PA_RAMCODE void CLOCK_clockReset(ClockId_e id)
|
||||
{
|
||||
uint32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
|
||||
uint8_t count = 0;
|
||||
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
|
||||
return;
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
|
||||
count = g_clkTreeArray[indexFromId].enableCount;
|
||||
|
||||
g_clkTreeArray[indexFromId].enableCount = 0;
|
||||
|
||||
GPR_clockDisable(id);
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
/* here, maybe not right */
|
||||
#if defined(ENABLE_CLK_TREE_PARENT)
|
||||
if(count > 0)
|
||||
{
|
||||
CLOCK_clockDisable((ClockId_e)g_clkTreeArray[indexFromId].parentId);
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t CLOCK_setClockSrc(ClockId_e id, ClockSelect_e select)
|
||||
{
|
||||
int32_t ret, mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
|
||||
|
||||
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
|
||||
if((g_clkTreeArray[indexFromId].enableCount == 0) || (g_clkTreeArray[indexFromId].canChangeSrcForcely == 1))
|
||||
{
|
||||
ret = GPR_setClockSrc(id, select);
|
||||
if(ret == ARM_DRIVER_OK)
|
||||
{
|
||||
g_clkTreeArray[indexFromId].parentId = (ClockId_e)(GET_PARENTCLOCKID_FROM_CLOCK_SEL_VALUE(select));
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
return ARM_DRIVER_ERROR;
|
||||
}
|
||||
|
||||
int32_t CLOCK_setClockDiv(ClockId_e id, uint32_t div)
|
||||
{
|
||||
int32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
|
||||
|
||||
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
|
||||
if(g_clkTreeArray[indexFromId].enableCount == 0)
|
||||
{
|
||||
RestoreIRQMask(mask);
|
||||
return GPR_setClockDiv(id, div);
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
return ARM_DRIVER_ERROR;
|
||||
|
||||
}
|
||||
|
||||
uint32_t CLOCK_getClockFreq(ClockId_e id)
|
||||
{
|
||||
return GPR_getClockFreq(id);
|
||||
}
|
||||
|
||||
int32_t CLOCK_setFracDivConfig(FracDivConfig_t * config)
|
||||
{
|
||||
if(config == NULL)
|
||||
{
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((config->fracDiv0DivRatioInteger == 256) && (config->fracDiv0DivRatioFrac != 0))
|
||||
{
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
if((config->fracDiv1DivRatioInteger == 256) && (config->fracDiv1DivRatioFrac != 0))
|
||||
{
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
GPR_setFracDivConfig(config);
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CLOCK_bclkEnable(BclkId_e id)
|
||||
{
|
||||
GPR_BclkEnable(id);
|
||||
}
|
||||
|
||||
|
||||
void CLOCK_fracDivOutCLkEnable(FracDivOutClkId_e id)
|
||||
{
|
||||
GPR_fracDivOutCLkEnable(id);
|
||||
}
|
||||
|
||||
void CLOCK_fracDivOutClkDisable(FracDivOutClkId_e id)
|
||||
{
|
||||
GPR_fracDivOutClkDisable(id);
|
||||
}
|
||||
|
||||
void CLOCK_setFracDivOutClkDiv(FracDivOutClkId_e id, uint8_t div)
|
||||
{
|
||||
GPR_setFracDivOutClkDiv(id, div);
|
||||
}
|
||||
|
||||
void CLOCK_setBclkSrc(BclkId_e id, BclkSrc_e src)
|
||||
{
|
||||
GPR_setBclkSrc(id, src);
|
||||
}
|
||||
|
||||
void CLOCK_setBclkDiv(BclkId_e id, uint8_t div)
|
||||
{
|
||||
GPR_setBclkDiv(id, div);
|
||||
}
|
||||
|
||||
void CLOCK_setMclkSrc(MclkId_e id, MclkSrc_e src)
|
||||
{
|
||||
GPR_setMclkSrc(id, src);
|
||||
}
|
||||
|
||||
void CLOCK_mclkEnable(MclkId_e id)
|
||||
{
|
||||
GPR_mclkEnable(id);
|
||||
}
|
||||
|
||||
void CLOCK_mclkDisable(MclkId_e id)
|
||||
{
|
||||
GPR_mclkDisable(id);
|
||||
}
|
||||
|
||||
void CLOCK_setMclkDiv(MclkId_e id, uint8_t div)
|
||||
{
|
||||
GPR_setMclkDiv(id, div);
|
||||
}
|
||||
|
||||
void CLOCK_updateClockTreeElement(ClockId_e id, ClockId_e parentId, uint8_t enableCount)
|
||||
{
|
||||
int32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
|
||||
|
||||
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
|
||||
return;
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
|
||||
g_clkTreeArray[indexFromId].parentId = parentId;
|
||||
g_clkTreeArray[indexFromId].enableCount = enableCount;
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,878 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
|
||||
* File name: cspi.c
|
||||
* Description: Dedicated spi for camera use in EC618. The interface is similar with CMSIS Driver API V2.0.
|
||||
* History: Rev1.0 2021-03-18
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cspi.h"
|
||||
#include "slpman.h"
|
||||
#include "cameraDrv.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CSPI Setting field Start
|
||||
// All the CSPI's parameters that need user to set are all put here
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static DmaTransferConfig_t g_dmaRxConfig =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
DMA_FLOW_CONTROL_SOURCE,
|
||||
DMA_ADDRESS_INCREMENT_TARGET,
|
||||
DMA_DATA_WIDTH_FOUR_BYTES,
|
||||
DMA_BURST_32_BYTES,
|
||||
0
|
||||
};
|
||||
|
||||
#if (RTE_CSPI0)
|
||||
static PIN cspi0PinMCLK = {RTE_CSPI0_MCLK_PAD_ADDR, RTE_CSPI0_MCLK_FUNC};
|
||||
static PIN cspi0PinPCLK = {RTE_CSPI0_PCLK_PAD_ADDR, RTE_CSPI0_PCLK_FUNC};
|
||||
static PIN cspi0PinCS = {RTE_CSPI0_CS_PAD_ADDR, RTE_CSPI0_CS_FUNC};
|
||||
static PIN cspi0PinSdo0 = {RTE_CSPI0_SDO0_PAD_ADDR, RTE_CSPI0_SDO0_FUNC};
|
||||
static PIN cspi0PinSdo1 = {RTE_CSPI0_SDO1_PAD_ADDR, RTE_CSPI0_SDO1_FUNC};
|
||||
|
||||
#elif (RTE_CSPI1)
|
||||
static PIN cspi1PinMCLK = {RTE_CSPI1_MCLK_PAD_ADDR, RTE_CSPI1_MCLK_FUNC};
|
||||
static PIN cspi1PinPCLK = {RTE_CSPI1_PCLK_PAD_ADDR, RTE_CSPI1_PCLK_FUNC};
|
||||
static PIN cspi1PinCS = {RTE_CSPI1_CS_PAD_ADDR, RTE_CSPI1_CS_FUNC};
|
||||
static PIN cspi1PinSdo0 = {RTE_CSPI1_SDO0_PAD_ADDR, RTE_CSPI1_SDO0_FUNC};
|
||||
static PIN cspi1PinSdo1 = {RTE_CSPI1_SDO1_PAD_ADDR, RTE_CSPI1_SDO1_FUNC};
|
||||
#endif
|
||||
|
||||
// Data Format
|
||||
cspiDataFmt_t cspiDataFmt =
|
||||
{
|
||||
.slaveModeEn = 1,
|
||||
.slotSize = 7,
|
||||
.wordSize = 7,
|
||||
.alignMode = 0,
|
||||
.endianMode = 0, // 0:LSB 1: MSB.
|
||||
.dataDly = 0,
|
||||
.txPad = 0,
|
||||
.rxSignExt = 0,
|
||||
.txPack = 0,
|
||||
.rxPack = 2,
|
||||
.txFifoEndianMode = 0,
|
||||
.rxFifoEndianMode = 0
|
||||
};
|
||||
|
||||
// Frame Info0
|
||||
cspiFrameInfo0_t cspiFrameInfo0 =
|
||||
{
|
||||
.cspiBusTimeOutCycle = 0x1000,
|
||||
.dataId = 0, // readOnly
|
||||
};
|
||||
|
||||
// RX Fifo timeout Cycle
|
||||
cspiTimeOutCycle_t cspiRxTimeOutCycle =
|
||||
{
|
||||
.rxTimeOutCycle = 20,
|
||||
};
|
||||
|
||||
// INT Control
|
||||
cspiIntCtrl_t cspiIntCtrl =
|
||||
{
|
||||
.txUnderRunIntEn = 0,
|
||||
.txDmaErrIntEn = 0,
|
||||
.txDatIntEn = 0,
|
||||
.rxOverFlowIntEn = 0,
|
||||
.rxDmaErrIntEn = 0,
|
||||
.rxDatIntEn = 0,
|
||||
.rxTimeOutIntEn = 0,
|
||||
.fsErrIntEn = 0,
|
||||
.frameStartIntEn = 0,
|
||||
.frameEndIntEn = 0,
|
||||
.cspiBusTimeOutIntEn = 0,
|
||||
.txIntThreshHold = 8,
|
||||
.rxIntThreshHold = 8,
|
||||
};
|
||||
|
||||
|
||||
// DMA Control
|
||||
cspiDmaCtrl_t cspiDmaCtrl =
|
||||
{
|
||||
.rxDmaReqEn = 1,
|
||||
.txDmaReqEn = 0,
|
||||
.rxDmaTimeOutEn = 0,
|
||||
.dmaWorkWaitCycle = 31,
|
||||
.rxDmaBurstSizeSub1 = 7,
|
||||
.txDmaBurstSizeSub1 = 7,
|
||||
.rxDmaThreadHold = 7,
|
||||
.txDmaThreadHold = 8,
|
||||
.rxFifoFlush = 0,
|
||||
.txFifoFlush = 0
|
||||
};
|
||||
|
||||
cspiCtrl_t cspiCtrl =
|
||||
{
|
||||
.enable = 0,
|
||||
.csEn = 0,
|
||||
.rxWid = 1, // 0: 1bit; 1: 2bit
|
||||
.rxdSeq = 1, // gc032a 0, sp0a39 1
|
||||
.cpol = 0,
|
||||
.cpha = 1,
|
||||
.frameProcEn = 1,
|
||||
.fillYonly = 1,
|
||||
.hwInitEn = 1,
|
||||
.lsCheckEn = 1,
|
||||
.dpCheckEn = 1,
|
||||
.frameProcInitEn = 0,
|
||||
.rowScaleRatio = 0,
|
||||
.colScaleRatio = 0,
|
||||
.scaleBytes = 0,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CSPI Setting field End
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
static CSPI_TypeDef* const cspiInstance[CSPI_INSTANCE_NUM] = {CSPI0, CSPI1};
|
||||
|
||||
static ClockId_e cspiClk[CSPI_INSTANCE_NUM * 2] =
|
||||
{
|
||||
PCLK_I2S0,
|
||||
FCLK_I2S0,
|
||||
PCLK_I2S1,
|
||||
FCLK_I2S1
|
||||
};
|
||||
|
||||
static ClockResetId_e cspiRstClk[CSPI_INSTANCE_NUM * 2] =
|
||||
{
|
||||
RST_PCLK_I2S0,
|
||||
RST_FCLK_I2S0,
|
||||
RST_PCLK_I2S1,
|
||||
RST_FCLK_I2S1
|
||||
};
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
/**
|
||||
\brief spi initialization counter, for lower power callback register/de-register
|
||||
*/
|
||||
static uint32_t cspiInitCnt = 0;
|
||||
|
||||
/**
|
||||
\brief Bitmap of CSPI working status, each instance is assigned 2 bits representing tx and rx status,
|
||||
when all CSPI instances are not working, we can vote to enter to low power state.
|
||||
*/
|
||||
static uint32_t cspiWorkingStats = 0;
|
||||
|
||||
/** \brief Internal used data structure */
|
||||
typedef struct
|
||||
{
|
||||
bool isInited; /**< Whether spi has been initialized */
|
||||
struct
|
||||
{
|
||||
__IO uint32_t DFMT; /**< Data Format Register, offset: 0x0 */
|
||||
__IO uint32_t SLOTCTL; /**< Slot Control Register, offset: 0x4 */
|
||||
__IO uint32_t CLKCTL; /**< Clock Control Register, offset: 0x8 */
|
||||
__IO uint32_t DMACTL; /**< DMA Control Register, offset: 0xC */
|
||||
__IO uint32_t INTCTL; /**< Interrupt Control Register, offset: 0x10 */
|
||||
__IO uint32_t TIMEOUTCTL; /**< Timeout Control Register, offset: 0x14 */
|
||||
__IO uint32_t STAS; /**< Status Register, offset: 0x18 */
|
||||
__IO uint32_t RFIFO; /**< Rx Buffer Register, offset: 0x1c */
|
||||
__IO uint32_t TFIFO; /**< Tx Buffer Register, offset: 0x20 */
|
||||
__IO uint32_t CSPICTL; /**< Camera SPI Control Register, offset: 0x28 */
|
||||
__IO uint32_t CCTL; /**< Auto Cg Control Register, offset: 0x2c */
|
||||
__IO uint32_t CSPIINFO0; /**< Cspi Frame info0 Register, offset: 0x30 */
|
||||
__IO uint32_t CSPIINFO1; /**< Cspi Frame info1 Register, offset: 0x34 */
|
||||
__IO uint32_t CSPIDBG; /**< Cspi Debug Register, offset: 0x38 */
|
||||
__IO uint32_t CSPINIT; /**< Cspi Init Register, offset: 0x3c */
|
||||
__IO uint32_t CLSP; /**< Cspi Line Start Register, offset: 0x40 */
|
||||
__IO uint32_t CDATP; /**< Cspi Data Packet Register, offset: 0x44 */
|
||||
__IO uint32_t CLINFO; /**< Cspi Line Info Register, offset: 0x48 */
|
||||
}regsBackup;
|
||||
} cspiDataBase_t;
|
||||
|
||||
static cspiDataBase_t cspiDataBase[CSPI_INSTANCE_NUM] = {0};
|
||||
|
||||
/**
|
||||
\fn static void cspiEnterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
\brief Perform necessary preparations before sleep.
|
||||
After recovering from SLPMAN_SLEEP1_STATE, CSPI hareware is repowered, we backup
|
||||
some registers here first so that we can restore user's configurations after exit.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
static void cspiEnterLpStatePrepare(void* pdata, slpManLpState state)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
for(i = 0; i < CSPI_INSTANCE_NUM; i++)
|
||||
{
|
||||
if(cspiDataBase[i].isInited == true)
|
||||
{
|
||||
cspiDataBase[i].regsBackup.DFMT = cspiInstance[i]->DFMT;
|
||||
cspiDataBase[i].regsBackup.SLOTCTL = cspiInstance[i]->SLOTCTL;
|
||||
cspiDataBase[i].regsBackup.CLKCTL = cspiInstance[i]->CLKCTL;
|
||||
cspiDataBase[i].regsBackup.DMACTL = cspiInstance[i]->DMACTL;
|
||||
cspiDataBase[i].regsBackup.INTCTL = cspiInstance[i]->INTCTL;
|
||||
cspiDataBase[i].regsBackup.TIMEOUTCTL = cspiInstance[i]->TIMEOUTCTL;
|
||||
cspiDataBase[i].regsBackup.STAS = cspiInstance[i]->STAS;
|
||||
cspiDataBase[i].regsBackup.CSPICTL = cspiInstance[i]->CSPICTL;
|
||||
cspiDataBase[i].regsBackup.CCTL = cspiInstance[i]->CCTL;
|
||||
cspiDataBase[i].regsBackup.CSPIINFO0 = cspiInstance[i]->CSPIINFO0;
|
||||
cspiDataBase[i].regsBackup.CSPIINFO1 = cspiInstance[i]->CSPIINFO1;
|
||||
cspiDataBase[i].regsBackup.CSPIDBG = cspiInstance[i]->CSPIDBG;
|
||||
cspiDataBase[i].regsBackup.CSPINIT = cspiInstance[i]->CSPINIT;
|
||||
cspiDataBase[i].regsBackup.CLSP = cspiInstance[i]->CLSP;
|
||||
cspiDataBase[i].regsBackup.CDATP = cspiInstance[i]->CDATP;
|
||||
cspiDataBase[i].regsBackup.CLINFO = cspiInstance[i]->CLINFO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\fn static void cspiExitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
\brief Restore after exit from sleep.
|
||||
After recovering from SLPMAN_SLEEP1_STATE, CSPI hareware is repowered, we restore user's configurations
|
||||
by aidding of the stored registers.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
static void cspiExitLpStateRestore(void* pdata, slpManLpState state)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
for(i = 0; i < CSPI_INSTANCE_NUM; i++)
|
||||
{
|
||||
if(cspiDataBase[i].isInited == true)
|
||||
{
|
||||
GPR_clockEnable(cspiClk[2*i]);
|
||||
GPR_clockEnable(cspiClk[2*i+1]);
|
||||
|
||||
cspiInstance[i]->DFMT = cspiDataBase[i].regsBackup.DFMT;
|
||||
cspiInstance[i]->SLOTCTL = cspiDataBase[i].regsBackup.SLOTCTL;
|
||||
cspiInstance[i]->CLKCTL = cspiDataBase[i].regsBackup.CLKCTL;
|
||||
cspiInstance[i]->DMACTL = cspiDataBase[i].regsBackup.DMACTL;
|
||||
cspiInstance[i]->INTCTL = cspiDataBase[i].regsBackup.INTCTL;
|
||||
cspiInstance[i]->TIMEOUTCTL = cspiDataBase[i].regsBackup.TIMEOUTCTL;
|
||||
cspiInstance[i]->STAS = cspiDataBase[i].regsBackup.STAS;
|
||||
cspiInstance[i]->CSPICTL = cspiDataBase[i].regsBackup.CSPICTL;
|
||||
cspiInstance[i]->CCTL = cspiDataBase[i].regsBackup.CCTL;
|
||||
cspiInstance[i]->CSPIINFO0 = cspiDataBase[i].regsBackup.CSPIINFO0;
|
||||
cspiInstance[i]->CSPIINFO1 = cspiDataBase[i].regsBackup.CSPIINFO1;
|
||||
cspiInstance[i]->CSPIDBG = cspiDataBase[i].regsBackup.CSPIDBG;
|
||||
cspiInstance[i]->CSPINIT = cspiDataBase[i].regsBackup.CSPINIT;
|
||||
cspiInstance[i]->CLSP = cspiDataBase[i].regsBackup.CLSP;
|
||||
cspiInstance[i]->CDATP = cspiDataBase[i].regsBackup.CDATP;
|
||||
cspiInstance[i]->CLINFO = cspiDataBase[i].regsBackup.CLINFO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define LOCK_SLEEP(instance) \
|
||||
do \
|
||||
{ \
|
||||
cspiWorkingStats |= (1U << instance); \
|
||||
slpManDrvVoteSleep(SLP_VOTE_I2S, SLP_ACTIVE_STATE); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define CHECK_TO_UNLOCK_SLEEP(instance) \
|
||||
do \
|
||||
{ \
|
||||
cspiWorkingStats &= ~(1U << instance); \
|
||||
if(cspiWorkingStats == 0) \
|
||||
slpManDrvVoteSleep(SLP_VOTE_I2S, SLP_SLP1_STATE); \
|
||||
} \
|
||||
while(0)
|
||||
#endif
|
||||
|
||||
#if (RTE_CSPI0)
|
||||
static cspiInfo_t cspi0Info = {0};
|
||||
void cspi0DmaRxEvent(uint32_t event);
|
||||
static DmaDescriptor_t __ALIGNED(16) cspi0DmaRxDesc[CAM_CHAIN_COUNT];
|
||||
static cspiDma_t cspi0Dma =
|
||||
{
|
||||
DMA_INSTANCE_MP,
|
||||
-1,
|
||||
RTE_CSPI0_DMA_RX_REQID,
|
||||
cspi0DmaRxEvent,
|
||||
cspi0DmaRxDesc
|
||||
};
|
||||
|
||||
static cspiRes_t cspi0Res = {
|
||||
CSPI0,
|
||||
{
|
||||
&cspi0PinMCLK,
|
||||
&cspi0PinPCLK,
|
||||
&cspi0PinCS,
|
||||
&cspi0PinSdo0,
|
||||
&cspi0PinSdo1,
|
||||
},
|
||||
&cspi0Dma,
|
||||
&cspi0Info
|
||||
};
|
||||
#endif
|
||||
|
||||
#if (RTE_CSPI1)
|
||||
static cspiInfo_t cspi1Info = {0};
|
||||
void cspi1DmaRxEvent(uint32_t event);
|
||||
static DmaDescriptor_t __ALIGNED(16) cspi1DmaRxDesc[CAM_CHAIN_COUNT];
|
||||
static cspiDma_t cspi1Dma =
|
||||
{
|
||||
DMA_INSTANCE_MP,
|
||||
-1,
|
||||
RTE_CSPI1_DMA_RX_REQID,
|
||||
cspi1DmaRxEvent,
|
||||
cspi1DmaRxDesc
|
||||
};
|
||||
|
||||
static cspiRes_t cspi1Res = {
|
||||
CSPI1,
|
||||
{
|
||||
&cspi1PinMCLK,
|
||||
&cspi1PinPCLK,
|
||||
&cspi1PinCS,
|
||||
&cspi1PinSdo0,
|
||||
&cspi1PinSdo1,
|
||||
},
|
||||
&cspi1Dma,
|
||||
&cspi1Info
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
\fn static uint32_t cspiGetInstanceNum(cspiRes_t *cspi)
|
||||
\brief Get instance number
|
||||
\param[in] spi Pointer to CSPI resources
|
||||
\returns instance number
|
||||
*/
|
||||
static uint32_t cspiGetInstanceNum(cspiRes_t *cspi)
|
||||
{
|
||||
return ((uint32_t)cspi->reg - (uint32_t)CSPI0) >> 12U;
|
||||
}
|
||||
|
||||
/**
|
||||
\fn static int32_t cspiSetBusSpeed(uint32_t bps, cspiRes_t *cspi)
|
||||
\brief Set bus speed
|
||||
\param[in] bps bus speed to set
|
||||
\param[in] spi Pointer to SPI resources
|
||||
\return \ref execution_status
|
||||
*/
|
||||
static int32_t cspiSetBusSpeed(camFrequence_e freq, cspiRes_t *cspi)
|
||||
{
|
||||
uint32_t instance = cspiGetInstanceNum(cspi);
|
||||
uint32_t freqDivInteger = 0;
|
||||
uint32_t freqDivRatio = 0;
|
||||
|
||||
switch(freq)
|
||||
{
|
||||
case CAM_6_5_M:
|
||||
freqDivInteger = 0x40;
|
||||
freqDivRatio = 0;
|
||||
break;
|
||||
|
||||
case CAM_13_M:
|
||||
freqDivInteger = 0x20;
|
||||
freqDivRatio = 0;
|
||||
break;
|
||||
|
||||
case CAM_25_5_M:
|
||||
freqDivInteger = 0x10;
|
||||
freqDivRatio = 0;
|
||||
break;
|
||||
|
||||
case CAM_24_M:
|
||||
freqDivInteger = 0x11;
|
||||
freqDivRatio = 0;
|
||||
break;
|
||||
|
||||
case CAM_20_M:
|
||||
freqDivInteger = 0x14;
|
||||
freqDivRatio = 0x666666;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (instance == 0) // i2s0
|
||||
{
|
||||
GPR_clockEnable(FCLK_I2S0);
|
||||
|
||||
GPR_fracDivOutCLkEnable(FRACDIV0_OUT0); // Fracdiv1_en
|
||||
GPR_setFracDivOutClkDiv(FRACDIV0_OUT0, 1); // 4 div, from 408M -> 102M
|
||||
#if 1
|
||||
GPR_setMclkSrc(MCLK0, MCLK_SRC_FRACDIV0_OUT0); // Bmclk_sel1
|
||||
GPR_mclkEnable(MCLK0); // Mclk_oe1
|
||||
#else
|
||||
GPR_setMclkSrc(MCLK2, MCLK_SRC_FRACDIV1_OUT0); // Bmclk_sel1
|
||||
GPR_mclkEnable(MCLK2);
|
||||
#endif
|
||||
GPR_setClockSrc(CLK_CC, CLK_CC_SEL_204M); // 0x4d000020 = 0x201
|
||||
|
||||
// Fracdiv clk selects 408M and set frac and integer clk
|
||||
FracDivConfig_t fracdivCfg;
|
||||
fracdivCfg.source = FRACDIC_ROOT_CLK_408M;
|
||||
fracdivCfg.fracDiv0DivRatioInteger = freqDivInteger;//0x10;//51M 0x10; // 25.5M
|
||||
fracdivCfg.fracDiv0DivRatioFrac = freqDivRatio;
|
||||
GPR_setFracDivConfig(&fracdivCfg);
|
||||
}
|
||||
else // i2s1
|
||||
{
|
||||
GPR_clockEnable(FCLK_I2S1);
|
||||
GPR_fracDivOutCLkEnable(FRACDIV1_OUT0); // Fracdiv1_en
|
||||
GPR_setFracDivOutClkDiv(FRACDIV1_OUT0, 1); // 4 div, from 408M -> 102M
|
||||
#if 1
|
||||
GPR_setMclkSrc(MCLK1, MCLK_SRC_FRACDIV1_OUT0); // Bmclk_sel1
|
||||
GPR_mclkEnable(MCLK1); // Mclk_oe1
|
||||
#else
|
||||
GPR_setMclkSrc(MCLK2, MCLK_SRC_FRACDIV1_OUT0); // Bmclk_sel1
|
||||
GPR_mclkEnable(MCLK2);
|
||||
#endif
|
||||
GPR_setClockSrc(CLK_CC, CLK_CC_SEL_204M); // 0x4d000020 = 0x201
|
||||
|
||||
// Fracdiv clk selects 408M and set frac and integer clk
|
||||
FracDivConfig_t fracdivCfg;
|
||||
fracdivCfg.source = FRACDIC_ROOT_CLK_408M;
|
||||
fracdivCfg.fracDiv1DivRatioInteger = freqDivInteger;//0x10;//51M 0x10; // 25.5M
|
||||
fracdivCfg.fracDiv1DivRatioFrac = freqDivRatio;
|
||||
GPR_setFracDivConfig(&fracdivCfg);
|
||||
}
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
\fn int32_t cspiInit(cspiCbEvent_fn cbEvent, cspiRes_t *cspi)
|
||||
\brief Initialize SPI Interface.
|
||||
\param[in] cbEvent Pointer to \ref cspiCbEvent_fn
|
||||
\param[in] spi Pointer to CSPI resources
|
||||
\return \ref execution_status
|
||||
*/
|
||||
int32_t cspiInit(cspiCbEvent_fn cbEvent, cspiRes_t *cspi)
|
||||
{
|
||||
int32_t returnCode;
|
||||
PadConfig_t config;
|
||||
uint32_t instance = cspiGetInstanceNum(cspi);
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
cspiDataBase[instance].isInited = true;
|
||||
#endif
|
||||
|
||||
// Initialize CSPI PINS
|
||||
PAD_getDefaultConfig(&config);
|
||||
#if 1 // I2S1
|
||||
config.mux = cspi->pins.mclk->funcNum;
|
||||
PAD_setPinConfig(cspi->pins.mclk->pinNum, &config);
|
||||
#else // MCLK2
|
||||
config.mux = PAD_MUX_ALT1;
|
||||
PAD_setPinConfig(14, &config);
|
||||
#endif
|
||||
config.mux = cspi->pins.pclk->funcNum;
|
||||
PAD_setPinConfig(cspi->pins.pclk->pinNum, &config);
|
||||
config.mux = cspi->pins.cs->funcNum;
|
||||
PAD_setPinConfig(cspi->pins.cs->pinNum, &config);
|
||||
config.mux = cspi->pins.sdo0->funcNum;
|
||||
PAD_setPinConfig(cspi->pins.sdo0->pinNum, &config);
|
||||
config.mux = cspi->pins.sdo1->funcNum;
|
||||
PAD_setPinConfig(cspi->pins.sdo1->pinNum, &config);
|
||||
|
||||
// Initialize SPI run-time resources
|
||||
cspi->info->cbEvent = cbEvent;
|
||||
|
||||
// Configure DMA if necessary
|
||||
if (cspi->dma)
|
||||
{
|
||||
DMA_init(cspi->dma->rxInstance);
|
||||
returnCode = DMA_openChannel(cspi->dma->rxInstance);
|
||||
|
||||
if (returnCode == ARM_DMA_ERROR_CHANNEL_ALLOC)
|
||||
return ARM_DRIVER_ERROR;
|
||||
else
|
||||
cspi->dma->rxCh = returnCode;
|
||||
|
||||
DMA_setChannelRequestSource(cspi->dma->rxInstance, cspi->dma->rxCh, (DmaRequestSource_e)cspi->dma->rxReq);
|
||||
DMA_rigisterChannelCallback(cspi->dma->rxInstance, cspi->dma->rxCh, cspi->dma->rxCb);
|
||||
|
||||
// Configure rx DMA and start it
|
||||
g_dmaRxConfig.sourceAddress = (void *)&(cspiInstance[instance]->RFIFO);
|
||||
g_dmaRxConfig.totalLength = CSPI_TRANSFER_TRUNK_SIZE;
|
||||
|
||||
DMA_enableChannelInterrupts(cspi->dma->rxInstance, cspi->dma->rxCh, DMA_END_INTERRUPT_ENABLE);
|
||||
DMA_startChannel(cspi->dma->rxInstance, cspi->dma->rxCh);
|
||||
}
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
cspiInitCnt++;
|
||||
|
||||
if(cspiInitCnt == 1U)
|
||||
{
|
||||
cspiWorkingStats = 0;
|
||||
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_I2S_MODULE, cspiEnterLpStatePrepare, NULL);
|
||||
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_I2S_MODULE, cspiExitLpStateRestore, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\fn int32_t cspiDeInit(cspiRes_t *cspi)
|
||||
\brief De-initialize CSPI Interface.
|
||||
\param[in] spi Pointer to CSPI resources
|
||||
\return \ref execution_status
|
||||
*/
|
||||
int32_t cspiDeInit(cspiRes_t *cspi)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
uint32_t instance;
|
||||
|
||||
instance = cspiGetInstanceNum(cspi);
|
||||
|
||||
cspiDataBase[instance].isInited = false;
|
||||
|
||||
cspiInitCnt--;
|
||||
|
||||
if(cspiInitCnt == 0)
|
||||
{
|
||||
cspiWorkingStats = 0;
|
||||
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_I2S_MODULE);
|
||||
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_I2S_MODULE);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\fn int32_t cspiPowerControl(cspiPowerState_e state, cspiRes_t *cspi)
|
||||
\brief Control CSPI Interface Power.
|
||||
\param[in] state Power state
|
||||
\param[in] cspi Pointer to CSPI resources
|
||||
\return \ref execution_status
|
||||
*/
|
||||
int32_t cspiPowerCtrl(cspiPowerState_e state, cspiRes_t *cspi)
|
||||
{
|
||||
uint32_t instance = cspiGetInstanceNum(cspi);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CSPI_POWER_OFF:
|
||||
// DMA disable
|
||||
if(cspi->dma)
|
||||
{
|
||||
DMA_stopChannel(cspi->dma->rxInstance, cspi->dma->rxCh, true);
|
||||
}
|
||||
|
||||
// Reset register values
|
||||
if (instance == 0)
|
||||
{
|
||||
CLOCK_setClockSrc(FCLK_I2S0, FCLK_I2S0_SEL_26M);
|
||||
GPR_swReset(RST_PCLK_I2S0);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLOCK_setClockSrc(FCLK_I2S1, FCLK_I2S1_SEL_26M);
|
||||
GPR_swReset(RST_PCLK_I2S1);
|
||||
}
|
||||
|
||||
|
||||
// Disable CSPI clock
|
||||
GPR_clockDisable(cspiClk[instance*2]);
|
||||
GPR_clockDisable(cspiClk[instance*2+1]);
|
||||
|
||||
cspi->info->flags &= ~CSPI_FLAG_POWERED;
|
||||
break;
|
||||
|
||||
case CSPI_POWER_FULL:
|
||||
//if ((cspi->info->flags & CSPI_FLAG_INITIALIZED) == 0)
|
||||
//return ARM_DRIVER_ERROR;
|
||||
|
||||
if (cspi->info->flags & CSPI_FLAG_POWERED)
|
||||
return ARM_DRIVER_OK;
|
||||
|
||||
// Enable CSPI clock
|
||||
GPR_clockEnable(cspiClk[instance*2]);
|
||||
GPR_clockEnable(cspiClk[instance*2+1]);
|
||||
|
||||
GPR_swReset(cspiRstClk[instance*2]);
|
||||
GPR_swReset(cspiRstClk[instance*2+1]);
|
||||
|
||||
// Set power flag
|
||||
cspi->info->flags |= CSPI_FLAG_POWERED;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return ARM_DRIVER_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
\fn int32_t cspiReceive(void *data, uint32_t num, cspiRes_t *cspi)
|
||||
\brief Start receiving data from SPI receiver.
|
||||
\param[out] dataIn Pointer to buffer for data to receive from CSPI receiver
|
||||
\param[in] num Number of data items to receive
|
||||
\param[in] cspi Pointer to CSPI resources
|
||||
\return \ref execution_status
|
||||
*/
|
||||
int32_t cspiRecv(cspiRes_t *cspi)
|
||||
{
|
||||
DMA_buildDescriptorChain(cspi->dma->descriptor, &g_dmaRxConfig, cspi->info->resolution, true);
|
||||
DMA_loadChannelDescriptorAndRun(cspi->dma->rxInstance, cspi->dma->rxCh, cspi->dma->descriptor);
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
\fn int32_t cspiControl(uint32_t control, uint32_t arg, cspiRes_t *cspi)
|
||||
\brief Control CSPI Interface.
|
||||
\param[in] control Operation
|
||||
\param[in] arg Argument of operation (optional)
|
||||
\param[in] cspi Pointer to CSPI resources
|
||||
\return common \ref execution_status and driver specific \ref spi_execution_status
|
||||
*/
|
||||
int32_t cspiControl(uint32_t control, uint32_t arg, cspiRes_t *cspi)
|
||||
{
|
||||
uint32_t instance = cspiGetInstanceNum(cspi);
|
||||
|
||||
switch(control & 0xFFFFFFFF)
|
||||
{
|
||||
// Set transport abort
|
||||
case CSPI_CTRL_TRANSABORT:
|
||||
{
|
||||
// If DMA mode, disable DMA channel
|
||||
if(cspi->dma)
|
||||
{
|
||||
DMA_stopChannel(cspi->dma->rxInstance, cspi->dma->rxCh, true);
|
||||
}
|
||||
|
||||
// clear SPI run-time resources
|
||||
cspi->reg->CSPICTL &= ~CSPI_ENABLE_Msk;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Bus Speed in bps; arg = value
|
||||
case CSPI_CTRL_BUS_SPEED:
|
||||
{
|
||||
if(cspiSetBusSpeed((camFrequence_e)arg, cspi) != ARM_DRIVER_OK)
|
||||
{
|
||||
return ARM_DRIVER_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Data Format
|
||||
case CSPI_CTRL_DATA_FORMAT:
|
||||
{
|
||||
memcpy((void*)&(cspiInstance[instance]->DFMT), &cspiDataFmt, sizeof(cspiDataFmt_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Flush rx fifo
|
||||
case CSPI_CTRL_FLUSH_RX_FIFO:
|
||||
{
|
||||
cspiInstance[instance]->DMACTL |= 0x1000000;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Set Int En
|
||||
case CSPI_CTRL_INT_CTRL:
|
||||
{
|
||||
memcpy((void*)&(cspiInstance[instance]->INTCTL), &cspiIntCtrl, sizeof(cspiIntCtrl_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Set recv mem addr
|
||||
case CSPI_CTRL_MEM_ADDR:
|
||||
{
|
||||
g_dmaRxConfig.targetAddress = (void*)arg; // dma gloval val. After this need call "CSPI_CTRL_DMA_CTRL"
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Rx Timeout Cycle
|
||||
case CSPI_CTRL_RXTOR:
|
||||
{
|
||||
memcpy((void*)&(cspiInstance[instance]->TIMEOUTCTL), &cspiRxTimeOutCycle, sizeof(cspiTimeOutCycle_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Set DMA Control
|
||||
case CSPI_CTRL_DMA_CTRL:
|
||||
{
|
||||
//dmaInit(cspi);
|
||||
memcpy((void*)&(cspiInstance[instance]->DMACTL), &cspiDmaCtrl, sizeof(cspiDmaCtrl_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Set CSPI Control
|
||||
case CSPI_CTRL_CSPICTL:
|
||||
{
|
||||
memcpy((void*)&(cspiInstance[instance]->CSPICTL), &cspiCtrl, sizeof(cspiCtrl_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Enable or disable cspi
|
||||
case CSPI_CTRL_START_STOP:
|
||||
{
|
||||
if (arg > 0)
|
||||
{
|
||||
cspiInstance[instance]->CSPICTL |= CSPI_ENABLE_Msk;
|
||||
}
|
||||
else
|
||||
{
|
||||
cspiInstance[instance]->CSPICTL &= ~CSPI_ENABLE_Msk;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Frame Info0
|
||||
case CSPI_CTRL_FRAME_INFO0:
|
||||
{
|
||||
memcpy((void*)&(cspiInstance[instance]->CSPIINFO0), &cspiFrameInfo0, sizeof(cspiFrameInfo0_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Camera resolution set
|
||||
case CSPI_CTRL_RESOLUTION_SET:
|
||||
{
|
||||
cspi->info->resolution = (camResolution_e)arg; // this will interface the dma descriptor chain count
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return ARM_DRIVER_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\fn void cspiDmaRxEvent(uint32_t event, cspiRes_t *cspi)
|
||||
\brief CSPI DMA Rx Event handler.
|
||||
\param[in] event DMA Rx Event
|
||||
\param[in] spi Pointer to CSPI resources
|
||||
*/
|
||||
void cspiDmaRxEvent(uint32_t event, cspiRes_t *cspi)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
uint32_t instance = cspiGetInstanceNum(cspi);
|
||||
#endif
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case DMA_EVENT_END:
|
||||
//cspi->reg->CSPICTL &= ~CSPI_ENABLE_Msk; // must close cspi here
|
||||
|
||||
if(cspi->info->cbEvent)
|
||||
{
|
||||
cspi->info->cbEvent(ARM_SPI_EVENT_TRANSFER_COMPLETE);
|
||||
}
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
CHECK_TO_UNLOCK_SLEEP(instance);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if (RTE_CSPI0)
|
||||
|
||||
static int32_t cspi0Init(cspiCbEvent_fn cbEvent)
|
||||
{
|
||||
return cspiInit(cbEvent, &cspi0Res);
|
||||
}
|
||||
static int32_t cspi0Deinit(void)
|
||||
{
|
||||
return cspiDeInit(&cspi0Res);
|
||||
}
|
||||
static int32_t cspi0PowerCtrl(cspiPowerState_e state)
|
||||
{
|
||||
return cspiPowerCtrl(state, &cspi0Res);
|
||||
}
|
||||
|
||||
static int32_t cspi0Recv(void)
|
||||
{
|
||||
return cspiRecv(&cspi0Res);
|
||||
}
|
||||
|
||||
static int32_t cspi0Ctrl(uint32_t control, uint32_t arg)
|
||||
{
|
||||
return cspiControl(control, arg, &cspi0Res);
|
||||
}
|
||||
|
||||
void cspi0DmaRxEvent(uint32_t event)
|
||||
{
|
||||
cspiDmaRxEvent(event, &cspi0Res);
|
||||
}
|
||||
|
||||
// CSPI0 Driver Control Block
|
||||
cspiDrvInterface_t cspiDrvInterface0 = {
|
||||
cspi0Init,
|
||||
cspi0Deinit,
|
||||
cspi0PowerCtrl,
|
||||
cspi0Recv,
|
||||
cspi0Ctrl,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if (RTE_CSPI1)
|
||||
static int32_t cspi1Init(cspiCbEvent_fn cbEvent)
|
||||
{
|
||||
return cspiInit(cbEvent, &cspi1Res);
|
||||
}
|
||||
static int32_t cspi1Deinit(void)
|
||||
{
|
||||
return cspiDeInit(&cspi1Res);
|
||||
}
|
||||
static int32_t cspi1PowerCtrl(cspiPowerState_e state)
|
||||
{
|
||||
return cspiPowerCtrl(state, &cspi1Res);
|
||||
}
|
||||
|
||||
static int32_t cspi1Recv(void)
|
||||
{
|
||||
return cspiRecv(&cspi1Res);
|
||||
}
|
||||
|
||||
static int32_t cspi1Ctrl(uint32_t control, uint32_t arg)
|
||||
{
|
||||
return cspiControl(control, arg, &cspi1Res);
|
||||
}
|
||||
|
||||
void cspi1DmaRxEvent(uint32_t event)
|
||||
{
|
||||
cspiDmaRxEvent(event, &cspi1Res);
|
||||
}
|
||||
|
||||
// CSPI1 Driver Control Block
|
||||
cspiDrvInterface_t cspiDrvInterface1 = {
|
||||
cspi1Init,
|
||||
cspi1Deinit,
|
||||
cspi1PowerCtrl,
|
||||
cspi1Recv,
|
||||
cspi1Ctrl,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: gpio.c
|
||||
* Description: EC618 gpio driver source file
|
||||
* History:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "gpio.h"
|
||||
#include "clock.h"
|
||||
#include "slpman.h"
|
||||
|
||||
#define EIGEN_GPIO(n) ((GPIO_TypeDef *) (MP_GPIO_BASE_ADDR + 0x1000*n))
|
||||
|
||||
/**
|
||||
\brief GPIO stutas flag
|
||||
*/
|
||||
static uint32_t gGpioStatus = 0;
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
/**
|
||||
\fn void GPIO_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
\brief Backup gpio configurations before sleep.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
void GPIO_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
\fn void GPIO_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
\brief Restore gpio configurations after exit from sleep.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
void GPIO_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
{
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
if(gGpioStatus & 0x1U)
|
||||
{
|
||||
GPR_clockEnable(PCLK_GPIO);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void GPIO_driverInit(void)
|
||||
{
|
||||
if((gGpioStatus & 0x1U) == 0)
|
||||
{
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_GPIO_MODULE, GPIO_enterLowPowerStatePrepare, NULL);
|
||||
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_GPIO_MODULE, GPIO_exitLowPowerStateRestore, NULL);
|
||||
#endif
|
||||
CLOCK_clockEnable(PCLK_GPIO);
|
||||
|
||||
gGpioStatus = 0x1U;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GPIO_driverDeInit(void)
|
||||
{
|
||||
gGpioStatus = 0;
|
||||
|
||||
// disable clock
|
||||
CLOCK_clockDisable(PCLK_GPIO);
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_GPIO_MODULE);
|
||||
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_GPIO_MODULE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void GPIO_pinConfig(uint32_t port, uint16_t pin, const GpioPinConfig_t *config)
|
||||
{
|
||||
ASSERT(port < GPIO_INSTANCE_NUM);
|
||||
|
||||
uint16_t pinMask = 0x1U << pin;
|
||||
GPIO_TypeDef *base = EIGEN_GPIO(port);
|
||||
|
||||
GPIO_driverInit();
|
||||
|
||||
switch(config->pinDirection)
|
||||
{
|
||||
case GPIO_DIRECTION_INPUT:
|
||||
|
||||
base->OUTENCLR = pinMask;
|
||||
|
||||
GPIO_interruptConfig(port, pin, config->misc.interruptConfig);
|
||||
|
||||
break;
|
||||
case GPIO_DIRECTION_OUTPUT:
|
||||
|
||||
GPIO_pinWrite(port, pinMask, ((uint16_t)config->misc.initOutput) << pin);
|
||||
|
||||
base->OUTENSET = pinMask;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GPIO_interruptConfig(uint32_t port, uint16_t pin, GpioInterruptConfig_e config)
|
||||
{
|
||||
uint16_t pinMask = 0x1U << pin;
|
||||
GPIO_TypeDef *base = EIGEN_GPIO(port);
|
||||
|
||||
switch(config)
|
||||
{
|
||||
case GPIO_INTERRUPT_DISABLED:
|
||||
|
||||
base->INTENCLR = pinMask;
|
||||
|
||||
break;
|
||||
case GPIO_INTERRUPT_LOW_LEVEL:
|
||||
|
||||
base->INTPOLCLR = pinMask;
|
||||
base->INTTYPECLR = pinMask;
|
||||
base->INTENSET = pinMask;
|
||||
|
||||
break;
|
||||
case GPIO_INTERRUPT_HIGH_LEVEL:
|
||||
|
||||
base->INTPOLSET = pinMask;
|
||||
base->INTTYPECLR = pinMask;
|
||||
base->INTENSET = pinMask;
|
||||
|
||||
break;
|
||||
case GPIO_INTERRUPT_FALLING_EDGE:
|
||||
|
||||
base->INTPOLCLR = pinMask;
|
||||
base->INTTYPESET = pinMask;
|
||||
base->INTENSET = pinMask;
|
||||
|
||||
break;
|
||||
case GPIO_INTERRUPT_RISING_EDGE:
|
||||
|
||||
base->INTPOLSET = pinMask;
|
||||
base->INTTYPESET = pinMask;
|
||||
base->INTENSET = pinMask;
|
||||
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GPIO_pinWrite(uint32_t port, uint16_t pinMask, uint16_t output)
|
||||
{
|
||||
EIGEN_GPIO(port)->MASKLOWBYTE[pinMask & 0xFFU] = output;
|
||||
EIGEN_GPIO(port)->MASKHIGHBYTE[pinMask >> 8U] = output;
|
||||
}
|
||||
|
||||
uint32_t GPIO_pinRead(uint32_t port, uint16_t pin)
|
||||
{
|
||||
return (((EIGEN_GPIO(port)->DATA) >> pin) & 0x01U);
|
||||
}
|
||||
|
||||
uint16_t GPIO_getInterruptFlags(uint32_t port)
|
||||
{
|
||||
return EIGEN_GPIO(port)->INTSTATUS;
|
||||
}
|
||||
|
||||
void GPIO_clearInterruptFlags(uint32_t port, uint16_t mask)
|
||||
{
|
||||
EIGEN_GPIO(port)->INTSTATUS = mask;
|
||||
}
|
||||
|
||||
uint16_t GPIO_saveAndSetIrqMask(uint32_t port)
|
||||
{
|
||||
uint16_t mask = EIGEN_GPIO(port)->INTENSET;
|
||||
EIGEN_GPIO(port)->INTENCLR = 0xFFFFU;
|
||||
return mask;
|
||||
}
|
||||
|
||||
void GPIO_restoreIrqMask(uint32_t port, uint16_t mask)
|
||||
{
|
||||
EIGEN_GPIO(port)->INTENSET = mask;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,962 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
|
||||
* File name: i2s.c
|
||||
* Description: Audio use in EC618. The interface is similar with CMSIS Driver API V2.0.
|
||||
* History: Rev1.0 2021-06-23
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "i2s.h"
|
||||
#include "slpman.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// I2S Setting field Start
|
||||
// All the I2S's parameters that need user to set are all put here
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static DmaTransferConfig_t g_dmaTxConfig =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
DMA_FLOW_CONTROL_TARGET,
|
||||
DMA_ADDRESS_INCREMENT_SOURCE,
|
||||
DMA_DATA_WIDTH_FOUR_BYTES,
|
||||
DMA_BURST_64_BYTES,
|
||||
0
|
||||
};
|
||||
|
||||
static DmaTransferConfig_t g_dmaRxConfig =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
DMA_FLOW_CONTROL_SOURCE,
|
||||
DMA_ADDRESS_INCREMENT_TARGET,
|
||||
DMA_DATA_WIDTH_TWO_BYTES,
|
||||
DMA_BURST_8_BYTES,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
#if (RTE_I2S0)
|
||||
static PIN i2s0PinMCLK = {RTE_I2S0_MCLK_PAD_ADDR, RTE_I2S0_MCLK_FUNC};
|
||||
static PIN i2s0PinBCLK = {RTE_I2S0_BCLK_PAD_ADDR, RTE_I2S0_BCLK_FUNC};
|
||||
static PIN i2s0PinLRCK = {RTE_I2S0_LRCK_PAD_ADDR, RTE_I2S0_LRCK_FUNC};
|
||||
static PIN i2s0PinDin = {RTE_I2S0_DIN_PAD_ADDR, RTE_I2S0_DIN_FUNC};
|
||||
static PIN i2s0PinDout = {RTE_I2S0_DOUT_PAD_ADDR, RTE_I2S0_DOUT_FUNC};
|
||||
#elif (RTE_I2S1)
|
||||
static PIN i2s1PinMCLK = {RTE_I2S1_MCLK_PAD_ADDR, RTE_I2S1_MCLK_FUNC};
|
||||
static PIN i2s1PinBCLK = {RTE_I2S1_BCLK_PAD_ADDR, RTE_I2S1_BCLK_FUNC};
|
||||
static PIN i2s1PinLRCK = {RTE_I2S1_LRCK_PAD_ADDR, RTE_I2S1_LRCK_FUNC};
|
||||
static PIN i2s1PinDin = {RTE_I2S1_DIN_PAD_ADDR, RTE_I2S1_DIN_FUNC};
|
||||
static PIN i2s1PinDout = {RTE_I2S1_DOUT_PAD_ADDR, RTE_I2S1_DOUT_FUNC};
|
||||
#endif
|
||||
|
||||
|
||||
// Sample rate, fs, fracdiv part, integer part. Generate MClk accoding to the sample rate.
|
||||
const uint32_t i2sSampleRateTbl[][4] =
|
||||
{
|
||||
{SAMPLE_RATE_8K, 256, 0xCE0000, 0x31}, // 256fs, 8k
|
||||
{SAMPLE_RATE_16K, 256, 0xE70000, 0x18}, // 256fs, 16k
|
||||
{SAMPLE_RATE_32K, 256, 0x738000, 0x0C}, // 256fs, 32k
|
||||
{SAMPLE_RATE_22_05K,256, 0x11D9B0, 0x12}, // 256fs, 22.05k
|
||||
{SAMPLE_RATE_44_1K, 256, 0x08ECD8, 0x09}, // 256fs, 44.1k
|
||||
{SAMPLE_RATE_48K, 256, 0x4D0000, 0x08}, // 256fs, 48k
|
||||
{SAMPLE_RATE_96K, 256, 0x268000, 0x04}, // 256fs, 96k
|
||||
};
|
||||
|
||||
|
||||
// Data Format
|
||||
i2sDataFmt_t i2sDataFmt =
|
||||
{
|
||||
.slaveModeEn = 0x1, // 0:Master; 1:Slave mode
|
||||
.slotSize = 0xf, // Slot size
|
||||
.wordSize = 0xf, // Real word size
|
||||
.alignMode = 0, // 1: Right alignment; 0: Left alignment
|
||||
.endianMode = 0x1, // 1: MSB; 0: LSB
|
||||
.dataDly = 0, // Used by I2S format
|
||||
.txPad = 0, // Tx padding
|
||||
.rxSignExt = 0, // Rx sign external
|
||||
.txPack = 1, // 0: not compress; 1: 1word; 2: 2word
|
||||
.rxPack = 0, // 0: not compress; 1: 1word; 2: 2word
|
||||
.txFifoEndianMode = 0, // I2s use or cspi use?
|
||||
.rxFifoEndianMode = 0, // I2s use or cspi use?
|
||||
};
|
||||
|
||||
// Slot Control
|
||||
i2sSlotCtrl_t i2sSlotCtrl =
|
||||
{
|
||||
.slotEn = 0x1, // Total 8 channels
|
||||
.slotNum = 0x1 // For I2S, this value should be 1; For PCM, it can change
|
||||
};
|
||||
|
||||
// BclkFs Control
|
||||
i2sBclkFsCtrl_t i2sBclkFsCtrl =
|
||||
{
|
||||
.bclkPolarity = 1, // 0: Rising edge send, falling edge sample; 1: falling edge send, rising edge sample
|
||||
.fsPolarity = 0, // 0: rising edge start; 1: falling edge start
|
||||
.fsWidth = 0xf // fsWidth = slotNum * slotSize
|
||||
};
|
||||
|
||||
// I2S Control
|
||||
i2sCtrl_t i2sCtrl =
|
||||
{
|
||||
.i2sMode = 1, // 0: disable; 1: Only send; 2: Only receive; 3: Send and Receive
|
||||
};
|
||||
|
||||
// DMA Control
|
||||
i2sDmaCtrl_t i2sDmaCtrl =
|
||||
{
|
||||
.rxDmaReqEn = 0, // rx dma enable
|
||||
.txDmaReqEn = 1, // tx dma enable
|
||||
.rxDmaTimeOutEn = 0, // rx dma timeout enable
|
||||
.dmaWorkWaitCycle = 31, // dma wait cycle number
|
||||
.rxDmaBurstSizeSub1 = 7, // rx dma burst size -1
|
||||
.txDmaBurstSizeSub1 = 15, // tx dma burst size -1
|
||||
.rxDmaThreadHold = 8, // rx dma threshold
|
||||
.txDmaThreadHold = 15, // tx dma threshold
|
||||
.rxFifoFlush = 0, // flush rx fifo
|
||||
.txFifoFlush = 0 // flush tx fifo
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// I2S Setting field End
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if (RTE_I2S0)
|
||||
static i2sInfo_t i2s0Info = {0};
|
||||
void i2s0DmaRxEvent(uint32_t event);
|
||||
void i2s0DmaTxEvent(uint32_t event);
|
||||
DmaDescriptor_t __ALIGNED(16) i2s0DmaTxDesc[I2S_DMA_TX_DESCRIPTOR_CHAIN_NUM];
|
||||
DmaDescriptor_t __ALIGNED(16) i2s0DmaRxDesc[I2S_DMA_RX_DESCRIPTOR_CHAIN_NUM];
|
||||
|
||||
#if (RTE_I2S0_IO_MODE == DMA_MODE)
|
||||
static i2sDma_t i2s0Dma =
|
||||
{
|
||||
DMA_INSTANCE_MP,
|
||||
-1,
|
||||
RTE_I2S0_DMA_TX_REQID,
|
||||
i2s0DmaTxEvent,
|
||||
i2s0DmaTxDesc,
|
||||
|
||||
DMA_INSTANCE_MP,
|
||||
-1,
|
||||
RTE_I2S0_DMA_RX_REQID,
|
||||
i2s0DmaRxEvent,
|
||||
i2s0DmaRxDesc
|
||||
};
|
||||
#endif
|
||||
|
||||
static i2sResources_t i2s0Res = {
|
||||
I2S0,
|
||||
{
|
||||
&i2s0PinMCLK,
|
||||
&i2s0PinBCLK,
|
||||
&i2s0PinLRCK,
|
||||
&i2s0PinDin,
|
||||
&i2s0PinDout,
|
||||
},
|
||||
#if (RTE_I2S0_IO_MODE == DMA_MODE)
|
||||
&i2s0Dma,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
NULL,
|
||||
&i2s0Info
|
||||
};
|
||||
#endif
|
||||
|
||||
#if (RTE_I2S1)
|
||||
|
||||
static i2sInfo_t i2s1Info = {0};
|
||||
void i2s1DmaRxEvent(uint32_t event);
|
||||
void i2s1DmaTxEvent(uint32_t event);
|
||||
static DmaDescriptor_t __ALIGNED(16) i2s1DmaTxDesc[I2S_DMA_TX_DESCRIPTOR_CHAIN_NUM];
|
||||
static DmaDescriptor_t __ALIGNED(16) i2s1DmaRxDesc[I2S_DMA_RX_DESCRIPTOR_CHAIN_NUM];
|
||||
|
||||
static i2sDma_t i2s1Dma =
|
||||
{
|
||||
DMA_INSTANCE_MP,
|
||||
-1,
|
||||
RTE_I2S1_DMA_TX_REQID,
|
||||
i2s1DmaTxEvent,
|
||||
i2s1DmaTxDesc,
|
||||
|
||||
DMA_INSTANCE_MP,
|
||||
-1,
|
||||
RTE_I2S1_DMA_RX_REQID,
|
||||
i2s1DmaRxEvent,
|
||||
i2s1DmaRxDesc
|
||||
};
|
||||
|
||||
static i2sResources_t i2s1Res = {
|
||||
I2S1,
|
||||
{
|
||||
&i2s1PinMCLK,
|
||||
&i2s1PinBCLK,
|
||||
&i2s1PinLRCK,
|
||||
&i2s1PinDin,
|
||||
&i2s1PinDout,
|
||||
},
|
||||
#if (RTE_I2S1_IO_MODE == DMA_MODE)
|
||||
&i2s1Dma,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
NULL,
|
||||
&i2s1Info
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
static I2S_TypeDef* const i2sInstance[I2S_INSTANCE_NUM] = {I2S0, I2S1};
|
||||
|
||||
static ClockId_e i2sClk[I2S_INSTANCE_NUM * 2] =
|
||||
{
|
||||
PCLK_I2S0,
|
||||
FCLK_I2S0,
|
||||
PCLK_I2S1,
|
||||
FCLK_I2S1
|
||||
};
|
||||
|
||||
static ClockId_e i2sMClk[I2S_INSTANCE_NUM] =
|
||||
{
|
||||
MCLK0,
|
||||
MCLK1,
|
||||
};
|
||||
|
||||
static ClockResetId_e i2sRstClk[I2S_INSTANCE_NUM * 2] =
|
||||
{
|
||||
RST_PCLK_I2S0,
|
||||
RST_FCLK_I2S0,
|
||||
RST_PCLK_I2S1,
|
||||
RST_FCLK_I2S1
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
|
||||
/** \brief Internal used data structure */
|
||||
typedef struct
|
||||
{
|
||||
bool isInited; /**< Whether spi has been initialized */
|
||||
bool mclkHasBeenClosed; /**< 1: mclk has been closed; 0: mclk hasn't been closed */
|
||||
struct
|
||||
{
|
||||
__IO uint32_t DFMT; /**< Data Format Register, offset: 0x0 */
|
||||
__IO uint32_t SLOTCTL; /**< Slot Control Register, offset: 0x4 */
|
||||
__IO uint32_t CLKCTL; /**< Clock Control Register, offset: 0x8 */
|
||||
__IO uint32_t DMACTL; /**< DMA Control Register, offset: 0xC */
|
||||
__IO uint32_t INTCTL; /**< Interrupt Control Register, offset: 0x10 */
|
||||
__IO uint32_t TIMEOUTCTL; /**< Timeout Control Register, offset: 0x14 */
|
||||
__IO uint32_t STAS; /**< Status Register, offset: 0x18 */
|
||||
__IO uint32_t RFIFO; /**< Rx Buffer Register, offset: 0x1c */
|
||||
__IO uint32_t TFIFO; /**< Tx Buffer Register, offset: 0x20 */
|
||||
__IO uint32_t I2SCTL; /**< I2S Control Register, offset: 0x28 */
|
||||
}regsBackup;
|
||||
} i2sDataBase_t;
|
||||
|
||||
static i2sDataBase_t i2sDataBase[I2S_INSTANCE_NUM] = {0};
|
||||
/**
|
||||
\brief i2s initialization counter, for lower power callback register/de-register
|
||||
*/
|
||||
static uint32_t i2sInitCnt = 0;
|
||||
|
||||
/**
|
||||
\brief Bitmap of I2S working status, each instance is assigned 2 bits representing tx and rx status,
|
||||
when all I2S instances are not working, we can vote to enter to low power state.
|
||||
*/
|
||||
|
||||
volatile uint32_t i2sWorkingStats = 0;
|
||||
|
||||
|
||||
/**
|
||||
\fn static void i2sEnterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
\brief Perform necessary preparations before sleep.
|
||||
After recovering from SLPMAN_SLEEP1_STATE, I2S hareware is repowered, we backup
|
||||
some registers here first so that we can restore user's configurations after exit.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
static void i2sEnterLpStatePrepare(void* pdata, slpManLpState state)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
for(i = 0; i < I2S_INSTANCE_NUM; i++)
|
||||
{
|
||||
if(i2sDataBase[i].isInited == true)
|
||||
{
|
||||
GPR_mclkDisable(i2sMClk[i]); // before sleep, disable MCLK
|
||||
i2sDataBase[i].mclkHasBeenClosed = true;
|
||||
|
||||
i2sDataBase[i].regsBackup.DFMT = i2sInstance[i]->DFMT;
|
||||
i2sDataBase[i].regsBackup.SLOTCTL = i2sInstance[i]->SLOTCTL;
|
||||
i2sDataBase[i].regsBackup.CLKCTL = i2sInstance[i]->CLKCTL;
|
||||
i2sDataBase[i].regsBackup.DMACTL = i2sInstance[i]->DMACTL;
|
||||
i2sDataBase[i].regsBackup.INTCTL = i2sInstance[i]->INTCTL;
|
||||
i2sDataBase[i].regsBackup.TIMEOUTCTL = i2sInstance[i]->TIMEOUTCTL;
|
||||
i2sDataBase[i].regsBackup.STAS = i2sInstance[i]->STAS;
|
||||
i2sDataBase[i].regsBackup.I2SCTL = i2sInstance[i]->I2SCTL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\fn static void i2sExitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
\brief Restore after exit from sleep.
|
||||
After recovering from SLPMAN_SLEEP1_STATE, I2S hareware is repowered, we restore user's configurations
|
||||
by aidding of the stored registers.
|
||||
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
static void i2sExitLpStateRestore(void* pdata, slpManLpState state)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
for(i = 0; i < I2S_INSTANCE_NUM; i++)
|
||||
{
|
||||
if(i2sDataBase[i].isInited == true)
|
||||
{
|
||||
GPR_clockEnable(i2sClk[i*2]);
|
||||
GPR_clockEnable(i2sClk[i*2 + 1]);
|
||||
|
||||
i2sInstance[i]->DFMT = i2sDataBase[i].regsBackup.DFMT;
|
||||
i2sInstance[i]->SLOTCTL = i2sDataBase[i].regsBackup.SLOTCTL;
|
||||
i2sInstance[i]->CLKCTL = i2sDataBase[i].regsBackup.CLKCTL;
|
||||
i2sInstance[i]->DMACTL = i2sDataBase[i].regsBackup.DMACTL;
|
||||
i2sInstance[i]->INTCTL = i2sDataBase[i].regsBackup.INTCTL;
|
||||
i2sInstance[i]->TIMEOUTCTL = i2sDataBase[i].regsBackup.TIMEOUTCTL;
|
||||
i2sInstance[i]->STAS = i2sDataBase[i].regsBackup.STAS;
|
||||
i2sInstance[i]->I2SCTL = i2sDataBase[i].regsBackup.I2SCTL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define LOCK_SLEEP(instance) \
|
||||
do \
|
||||
{ \
|
||||
i2sWorkingStats |= (1U << instance); \
|
||||
slpManDrvVoteSleep(SLP_VOTE_I2S, SLP_ACTIVE_STATE); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define CHECK_TO_UNLOCK_SLEEP(instance) \
|
||||
do \
|
||||
{ \
|
||||
i2sWorkingStats &= ~(1U << instance); \
|
||||
if(i2sWorkingStats == 0) \
|
||||
slpManDrvVoteSleep(SLP_VOTE_I2S, SLP_SLP1_STATE); \
|
||||
} \
|
||||
while(0)
|
||||
#endif
|
||||
|
||||
static uint32_t i2sGetInstanceNum(i2sResources_t *i2s)
|
||||
{
|
||||
return ((uint32_t)i2s->reg - (uint32_t)I2S0) >> 12U;
|
||||
}
|
||||
|
||||
int32_t i2sInit(i2sCbEvent_fn txCbEvent, i2sCbEvent_fn rxCbEvent, i2sResources_t *i2s)
|
||||
{
|
||||
int32_t returnCode;
|
||||
PadConfig_t config;
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
uint32_t instance = i2sGetInstanceNum(i2s);
|
||||
i2sDataBase[instance].isInited = true;
|
||||
#endif
|
||||
|
||||
// Initialize I2S PINS
|
||||
PAD_getDefaultConfig(&config);
|
||||
config.mux = i2s->pins.mclk->funcNum;
|
||||
PAD_setPinConfig(i2s->pins.mclk->pinNum, &config);
|
||||
config.mux = i2s->pins.bclk->funcNum;
|
||||
PAD_setPinConfig(i2s->pins.bclk->pinNum, &config);
|
||||
config.mux = i2s->pins.lrck->funcNum;
|
||||
PAD_setPinConfig(i2s->pins.lrck->pinNum, &config);
|
||||
config.mux = i2s->pins.din->funcNum;
|
||||
PAD_setPinConfig(i2s->pins.din->pinNum, &config);
|
||||
config.mux = i2s->pins.dout->funcNum;
|
||||
PAD_setPinConfig(i2s->pins.dout->pinNum, &config);
|
||||
|
||||
// Initialize I2S run-time resources
|
||||
i2s->info->txCbEvent = txCbEvent;
|
||||
i2s->info->rxCbEvent = rxCbEvent;
|
||||
|
||||
// Configure DMA if necessary
|
||||
if (i2s->dma)
|
||||
{
|
||||
// Tx config
|
||||
DMA_init(i2s->dma->txInstance);
|
||||
returnCode = DMA_openChannel(i2s->dma->txInstance);
|
||||
|
||||
if (returnCode == ARM_DMA_ERROR_CHANNEL_ALLOC)
|
||||
return ARM_DRIVER_ERROR;
|
||||
else
|
||||
i2s->dma->txCh = returnCode;
|
||||
|
||||
DMA_setChannelRequestSource(i2s->dma->txInstance, i2s->dma->txCh, (DmaRequestSource_e)i2s->dma->txReq);
|
||||
DMA_rigisterChannelCallback(i2s->dma->txInstance, i2s->dma->txCh, i2s->dma->txCb);
|
||||
|
||||
// Rx config
|
||||
DMA_init(i2s->dma->rxInstance);
|
||||
returnCode = DMA_openChannel(i2s->dma->rxInstance);
|
||||
|
||||
if (returnCode == ARM_DMA_ERROR_CHANNEL_ALLOC)
|
||||
return ARM_DRIVER_ERROR;
|
||||
else
|
||||
i2s->dma->rxCh = returnCode;
|
||||
|
||||
DMA_setChannelRequestSource(i2s->dma->rxInstance, i2s->dma->rxCh, (DmaRequestSource_e)i2s->dma->rxReq);
|
||||
DMA_rigisterChannelCallback(i2s->dma->rxInstance, i2s->dma->rxCh, i2s->dma->rxCb);
|
||||
}
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
i2sInitCnt++;
|
||||
|
||||
if(i2sInitCnt == 1U)
|
||||
{
|
||||
i2sWorkingStats = 0;
|
||||
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_I2S_MODULE, i2sEnterLpStatePrepare, NULL);
|
||||
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_I2S_MODULE, i2sExitLpStateRestore, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
|
||||
int32_t i2sDeInit(i2sResources_t *i2s)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
uint32_t instance = i2sGetInstanceNum(i2s);
|
||||
i2sDataBase[instance].isInited = false;
|
||||
|
||||
i2sInitCnt--;
|
||||
|
||||
if(i2sInitCnt == 0)
|
||||
{
|
||||
i2sWorkingStats = 0;
|
||||
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_I2S_MODULE);
|
||||
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_I2S_MODULE);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
int32_t i2sPowerCtrl(i2sPowerState_e state, i2sResources_t *i2s)
|
||||
{
|
||||
uint32_t instance = i2sGetInstanceNum(i2s);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
// when need to enter sleep, do not call this api. PMU will manage all the clocks by default.
|
||||
case I2S_POWER_OFF:
|
||||
if(i2s->dma)
|
||||
{
|
||||
DMA_stopChannel(i2s->dma->txInstance, i2s->dma->txCh, false);
|
||||
}
|
||||
|
||||
// Reset register values
|
||||
if (instance == 0)
|
||||
{
|
||||
CLOCK_setClockSrc(FCLK_I2S0, FCLK_I2S0_SEL_26M);
|
||||
GPR_swReset(RST_PCLK_I2S0);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLOCK_setClockSrc(FCLK_I2S1, FCLK_I2S1_SEL_26M);
|
||||
GPR_swReset(RST_PCLK_I2S1);
|
||||
}
|
||||
|
||||
// Disable I2S clock
|
||||
CLOCK_clockDisable(i2sClk[instance*2]);
|
||||
CLOCK_clockDisable(i2sClk[instance*2+1]);
|
||||
|
||||
break;
|
||||
|
||||
case I2S_POWER_FULL:
|
||||
|
||||
// Enable I2S clock
|
||||
CLOCK_clockEnable(i2sClk[instance*2]); // pclk
|
||||
CLOCK_clockEnable(i2sClk[instance*2+1]); // fclk
|
||||
|
||||
GPR_swReset(i2sRstClk[instance*2]); // pclk
|
||||
GPR_swReset(i2sRstClk[instance*2+1]); // fclk
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return ARM_DRIVER_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
int32_t i2sSend(const void *data, uint32_t chunkNum, i2sResources_t *i2s)
|
||||
{
|
||||
uint32_t instance = i2sGetInstanceNum(i2s);
|
||||
|
||||
if ((data == NULL) || (chunkNum == 0))
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
|
||||
// dma mode
|
||||
if(i2s->dma)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
LOCK_SLEEP(instance);
|
||||
#endif
|
||||
|
||||
// Configure tx DMA and start it
|
||||
g_dmaTxConfig.sourceAddress = (void *)data;
|
||||
g_dmaTxConfig.targetAddress = (void *)&(i2sInstance[instance]->TFIFO);
|
||||
g_dmaTxConfig.totalLength = chunkNum;
|
||||
DMA_buildDescriptorChain(i2s->dma->txDescriptor, &g_dmaTxConfig, I2S_DMA_TX_DESCRIPTOR_CHAIN_NUM, true);
|
||||
DMA_loadChannelDescriptorAndRun(i2s->dma->txInstance, i2s->dma->txCh, i2s->dma->txDescriptor);
|
||||
}
|
||||
// polling mode
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < chunkNum; i++)
|
||||
{
|
||||
// Flow control. Make sure TX have empty fifo
|
||||
while (((16 - (i2s->reg->STAS & I2S_STATS_CTRL_TX_FIFO_LEVEL_Msk))
|
||||
>> I2S_STATS_CTRL_TX_FIFO_LEVEL_Pos) == 0){};
|
||||
|
||||
i2s->reg->TFIFO = *(uint32_t*)data;
|
||||
}
|
||||
}
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
|
||||
int32_t i2sRecv(void *data, uint32_t chunkNum, i2sResources_t *i2s)
|
||||
{
|
||||
uint32_t instance = i2sGetInstanceNum(i2s);;
|
||||
|
||||
if ((data == NULL) || (chunkNum == 0))
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
|
||||
// dma mode
|
||||
if(i2s->dma)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
LOCK_SLEEP(instance);
|
||||
#endif
|
||||
|
||||
// Configure rx DMA and start it
|
||||
g_dmaRxConfig.sourceAddress = (void *)&(i2sInstance[instance]->RFIFO);
|
||||
g_dmaRxConfig.targetAddress = (void *)data;
|
||||
g_dmaRxConfig.totalLength = chunkNum;
|
||||
DMA_buildDescriptorChain(i2s->dma->rxDescriptor, &g_dmaRxConfig, I2S_DMA_RX_DESCRIPTOR_CHAIN_NUM, true);
|
||||
DMA_loadChannelDescriptorAndRun(i2s->dma->rxInstance, i2s->dma->rxCh, i2s->dma->rxDescriptor);
|
||||
}
|
||||
// polling mode
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < chunkNum; i++)
|
||||
{
|
||||
while (((i2s->reg->STAS >> I2S_STATS_CTRL_RX_DAT_RDY_Pos) & 0x1) == 0); // Wait until RxFifo have data
|
||||
*((uint32_t*)data + i) = i2s->reg->RFIFO;
|
||||
}
|
||||
}
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\fn static int32_t i2sSetBusSpeed(uint32_t bps, i2sResources_t *i2s)
|
||||
\brief Set bus speed
|
||||
\param[in] bps bus speed to set
|
||||
\param[in] spi Pointer to SPI resources
|
||||
\return \ref execution_status
|
||||
*/
|
||||
static int32_t i2sSetSampleRate(uint32_t bps, i2sResources_t *i2s, i2sRole_e i2sRole)
|
||||
{
|
||||
uint32_t instance = i2sGetInstanceNum(i2s);
|
||||
|
||||
if (instance == 0) // i2s0
|
||||
{
|
||||
CLOCK_clockEnable(FCLK_I2S0);
|
||||
}
|
||||
else // i2s1
|
||||
{
|
||||
CLOCK_clockEnable(FCLK_I2S1);
|
||||
}
|
||||
|
||||
CLOCK_setClockSrc(CLK_CC, CLK_CC_SEL_204M); // Core clk selects 204M
|
||||
|
||||
if (instance == 0) // i2s0
|
||||
{
|
||||
CLOCK_fracDivOutCLkEnable(FRACDIV0_OUT0); // Fracdiv0 out0 enable
|
||||
CLOCK_setMclkSrc(MCLK0, MCLK_SRC_FRACDIV0_OUT0); // Choose Fracdiv0 out0 as MClk source
|
||||
CLOCK_mclkEnable(MCLK0); // Mclk enable
|
||||
CLOCK_setFracDivOutClkDiv(FRACDIV0_OUT0, 4); // First step to generate MClk clock. 4 div, from 408M -> 102M
|
||||
|
||||
// need to add gpr api for fracdiv
|
||||
int sampleRateIdx;
|
||||
for (sampleRateIdx = 0; sampleRateIdx < sizeof(i2sSampleRateTbl) / sizeof(i2sSampleRateTbl[0]); sampleRateIdx++)
|
||||
{
|
||||
if (bps == i2sSampleRateTbl[sampleRateIdx][0])
|
||||
{
|
||||
// Fracdiv clk selects 408M and set frac and integer clk
|
||||
FracDivConfig_t fracdivCfg;
|
||||
memset(&fracdivCfg, 0, sizeof(FracDivConfig_t));
|
||||
fracdivCfg.source = FRACDIC_ROOT_CLK_408M;
|
||||
fracdivCfg.fracDiv0DivRatioInteger = i2sSampleRateTbl[sampleRateIdx][3];
|
||||
fracdivCfg.fracDiv0DivRatioFrac = i2sSampleRateTbl[sampleRateIdx][2];
|
||||
CLOCK_setFracDivConfig(&fracdivCfg); // Second step to generate MClk
|
||||
}
|
||||
}
|
||||
}
|
||||
else // i2s1
|
||||
{
|
||||
CLOCK_fracDivOutCLkEnable(FRACDIV1_OUT0); // Fracdiv1 out0 enable
|
||||
CLOCK_setMclkSrc(MCLK1, MCLK_SRC_FRACDIV1_OUT0); // Choose Fracdiv1 out0 as MClk source
|
||||
CLOCK_mclkEnable(MCLK1); // Mclk enable
|
||||
CLOCK_setFracDivOutClkDiv(FRACDIV1_OUT0, 4); // First step to generate MClk clock. 4 div, from 408M -> 102M
|
||||
|
||||
// need to add gpr api for fracdiv
|
||||
int sampleRateIdx;
|
||||
for (sampleRateIdx = 0; sampleRateIdx < sizeof(i2sSampleRateTbl) / sizeof(i2sSampleRateTbl[0]); sampleRateIdx++)
|
||||
{
|
||||
if (bps == i2sSampleRateTbl[sampleRateIdx][0])
|
||||
{
|
||||
// Fracdiv clk selects 408M and set frac and integer clk
|
||||
FracDivConfig_t fracdivCfg;
|
||||
memset(&fracdivCfg, 0, sizeof(FracDivConfig_t));
|
||||
fracdivCfg.source = FRACDIC_ROOT_CLK_408M;
|
||||
fracdivCfg.fracDiv1DivRatioInteger = i2sSampleRateTbl[sampleRateIdx][3];
|
||||
fracdivCfg.fracDiv1DivRatioFrac = i2sSampleRateTbl[sampleRateIdx][2];
|
||||
CLOCK_setFracDivConfig(&fracdivCfg); // Second step to generate MClk
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (instance == 0)
|
||||
{
|
||||
// I2S master mode need to genetate LRCLK by MCU
|
||||
if (i2sRole == CODEC_SLAVE_MODE) // I2S controller act as master, codec is slave
|
||||
{
|
||||
CLOCK_fracDivOutCLkEnable(FRACDIV0_OUT1); // Enable fracdiv0 out1
|
||||
CLOCK_setBclkSrc(BCLK0, BCLK_SRC_FRACDIV0_OUT1); // Use fracdiv0 out1 to generate bclk
|
||||
CLOCK_setFracDivOutClkDiv(FRACDIV0_OUT1, 8); // First step to generate BClk clock. 8 div, from 408M->51M
|
||||
CLOCK_setBclkDiv(BCLK0, 4); // Second step to generate BClk clock. Bclk enable and divide by 4(256fs)
|
||||
CLOCK_bclkEnable(BCLK0); // Enable bclk
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// I2S master mode need to genetate LRCLK by MCU
|
||||
if (i2sRole == CODEC_SLAVE_MODE) // I2S controller act as master, codec is slave
|
||||
{
|
||||
CLOCK_fracDivOutCLkEnable(FRACDIV1_OUT1); // Enable fracdiv1 out1
|
||||
CLOCK_setBclkSrc(BCLK1, BCLK_SRC_FRACDIV1_OUT1); // Use fracdiv1 out1 to generate bclk
|
||||
CLOCK_setFracDivOutClkDiv(FRACDIV1_OUT1, 8); // First step to generate BClk clock. 8 div, from 408M->51M
|
||||
CLOCK_setBclkDiv(BCLK1, 4); // Second step to generate BClk clock. Bclk enable and divide by 4(256fs)
|
||||
CLOCK_bclkEnable(BCLK1); // Enable bclk
|
||||
}
|
||||
}
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\fn int32_t i2sControl(uint32_t control, uint32_t arg, i2sRes_t *i2s)
|
||||
\brief Control I2S Interface.
|
||||
\param[in] control Operation
|
||||
\param[in] arg Argument of operation (optional)
|
||||
\param[in] i2s Pointer to I2S resources
|
||||
\return common \ref execution_status and driver specific \ref spi_execution_status
|
||||
*/
|
||||
int32_t i2sControl(uint32_t control, uint32_t arg, i2sResources_t *i2s)
|
||||
{
|
||||
uint32_t instance = i2sGetInstanceNum(i2s);
|
||||
|
||||
switch(control & 0xFFFF)
|
||||
{
|
||||
// Set transport abort
|
||||
case I2S_CTRL_TRANSABORT:
|
||||
{
|
||||
// If DMA mode, disable DMA channel
|
||||
if(i2s->dma)
|
||||
{
|
||||
DMA_stopChannel(i2s->dma->txInstance, i2s->dma->txCh, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case I2S_CTRL_SET_TOTAL_NUM:
|
||||
{
|
||||
i2s->info->totalNum = arg;
|
||||
}
|
||||
|
||||
// Set Bus Speed in bps; arg = value
|
||||
case I2S_CTRL_SAMPLE_RATE_SLAVE:
|
||||
{
|
||||
if(i2sSetSampleRate(arg, i2s, CODEC_MASTER_MODE) != ARM_DRIVER_OK)
|
||||
{
|
||||
return ARM_DRIVER_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case I2S_CTRL_SAMPLE_RATE_MASTER:
|
||||
{
|
||||
if(i2sSetSampleRate(arg, i2s, CODEC_SLAVE_MODE) != ARM_DRIVER_OK)
|
||||
{
|
||||
return ARM_DRIVER_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Data Format
|
||||
case I2S_CTRL_DATA_FORMAT:
|
||||
{
|
||||
memcpy((void*)&(i2sInstance[instance]->DFMT), &i2sDataFmt, sizeof(i2sDataFmt_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Slot
|
||||
case I2S_CTRL_SLOT_CTRL:
|
||||
{
|
||||
memcpy((void*)&(i2sInstance[instance]->SLOTCTL), &i2sSlotCtrl, sizeof(i2sSlotCtrl_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Set DMA Control
|
||||
case I2S_CTRL_DMA_CTRL:
|
||||
{
|
||||
memcpy((void*)&(i2sInstance[instance]->DMACTL), &i2sDmaCtrl, sizeof(i2sDmaCtrl_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Set I2S Control
|
||||
case I2S_CTRL_I2SCTL:
|
||||
{
|
||||
memcpy((void*)&(i2sInstance[instance]->I2SCTL), &i2sCtrl, sizeof(i2sCtrl_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Frame Info0
|
||||
case I2S_CTRL_BCLK_FS_CTRL:
|
||||
{
|
||||
memcpy((void*)&(i2sInstance[instance]->CLKCTL), &i2sBclkFsCtrl, sizeof(i2sBclkFsCtrl_t));
|
||||
break;
|
||||
}
|
||||
|
||||
// Start or stop audio play
|
||||
case I2S_CTRL_START_STOP:
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
if (i2sDataBase[instance].mclkHasBeenClosed == true)
|
||||
{
|
||||
GPR_mclkEnable(i2sMClk[instance]);
|
||||
i2sDataBase[instance].mclkHasBeenClosed = false; // already opened MCLK now
|
||||
}
|
||||
#endif
|
||||
i2sInstance[instance]->I2SCTL = arg; // 0: disable i2s; 1: enable send; 2: enable recv; 3: enable send/recv
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return ARM_DRIVER_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
void i2sDmaRxEvent(uint32_t event, i2sResources_t *i2s)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
uint32_t instance = i2sGetInstanceNum(i2s);
|
||||
#endif
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case DMA_EVENT_END:
|
||||
//DMA_stopChannel(i2s->dma->rxInstance, i2s->dma->rxCh, true);
|
||||
//i2s->reg->I2SCTL &= ~I2S_CTL_MODE_Msk;
|
||||
|
||||
if(i2s->info->rxCbEvent)
|
||||
{
|
||||
i2s->info->rxCbEvent(I2S_EVENT_TRANSFER_COMPLETE, 0);
|
||||
}
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
CHECK_TO_UNLOCK_SLEEP(instance);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void i2sDmaTxEvent(uint32_t event, i2sResources_t *i2s)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
uint32_t instance = i2sGetInstanceNum(i2s);
|
||||
#endif
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case DMA_EVENT_END:
|
||||
#if 0 // If you want to loop the audio, don't stop DMA here
|
||||
DMA_stopChannel(i2s->dma->txInstance, i2s->dma->txCh, true);
|
||||
i2s->info->status.busy = 0;
|
||||
i2s->reg->I2SCTL &= ~I2S_CTL_MODE_Msk;
|
||||
#endif
|
||||
if(i2s->info->txCbEvent)
|
||||
{
|
||||
i2s->info->txCbEvent(I2S_EVENT_TRANSFER_COMPLETE, i2s->info->totalNum);
|
||||
}
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
CHECK_TO_UNLOCK_SLEEP(instance);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t i2sGetTotalCnt(i2sResources_t *i2s)
|
||||
{
|
||||
return i2s->info->totalNum;
|
||||
}
|
||||
|
||||
|
||||
#if (RTE_I2S0)
|
||||
|
||||
static int32_t i2s0Init(i2sCbEvent_fn txCbEvent, i2sCbEvent_fn rxCbEvent)
|
||||
{
|
||||
return i2sInit(txCbEvent, rxCbEvent, &i2s0Res);
|
||||
}
|
||||
static int32_t i2s0Deinit(void)
|
||||
{
|
||||
return i2sDeInit(&i2s0Res);
|
||||
}
|
||||
static int32_t i2s0PowerCtrl(i2sPowerState_e state)
|
||||
{
|
||||
return i2sPowerCtrl(state, &i2s0Res);
|
||||
}
|
||||
|
||||
static int32_t i2s0Send(void *data, uint32_t num)
|
||||
{
|
||||
return i2sSend(data, num, &i2s0Res);
|
||||
}
|
||||
|
||||
static int32_t i2s0Recv(void *data, uint32_t num)
|
||||
{
|
||||
return i2sRecv(data, num, &i2s0Res);
|
||||
}
|
||||
|
||||
static int32_t i2s0Ctrl(uint32_t control, uint32_t arg)
|
||||
{
|
||||
return i2sControl(control, arg, &i2s0Res);
|
||||
}
|
||||
|
||||
void i2s0DmaTxEvent(uint32_t event)
|
||||
{
|
||||
i2sDmaTxEvent(event, &i2s0Res);
|
||||
}
|
||||
|
||||
void i2s0DmaRxEvent(uint32_t event)
|
||||
{
|
||||
i2sDmaRxEvent(event, &i2s0Res);
|
||||
}
|
||||
|
||||
uint32_t i2s0GetTotalCnt(void)
|
||||
{
|
||||
return i2sGetTotalCnt(&i2s0Res);
|
||||
}
|
||||
|
||||
// I2S0 Driver Control Block
|
||||
i2sDrvInterface_t i2sDrvInterface0 =
|
||||
{
|
||||
i2s0Init,
|
||||
i2s0Deinit,
|
||||
i2s0PowerCtrl,
|
||||
i2s0Send,
|
||||
i2s0Recv,
|
||||
i2s0Ctrl,
|
||||
i2s0GetTotalCnt,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if (RTE_I2S1)
|
||||
static int32_t i2s1Init(i2sCbEvent_fn txCbEvent, i2sCbEvent_fn rxCbEvent)
|
||||
{
|
||||
return i2sInit(txCbEvent, rxCbEvent, &i2s1Res);
|
||||
}
|
||||
static int32_t i2s1Deinit(void)
|
||||
{
|
||||
return i2sDeInit(&i2s1Res);
|
||||
}
|
||||
static int32_t i2s1PowerCtrl(i2sPowerState_e state)
|
||||
{
|
||||
return i2sPowerCtrl(state, &i2s1Res);
|
||||
}
|
||||
|
||||
static int32_t i2s1Send(void *data, uint32_t num)
|
||||
{
|
||||
return i2sSend(data, num, &i2s1Res);
|
||||
}
|
||||
|
||||
static int32_t i2s1Recv(void *data, uint32_t num)
|
||||
{
|
||||
return i2sRecv(data, num, &i2s1Res);
|
||||
}
|
||||
|
||||
static int32_t i2s1Ctrl(uint32_t control, uint32_t arg)
|
||||
{
|
||||
return i2sControl(control, arg, &i2s1Res);
|
||||
}
|
||||
|
||||
uint32_t i2s1GetTotalCnt(void)
|
||||
{
|
||||
return i2sGetTotalCnt(&i2s1Res);
|
||||
}
|
||||
|
||||
void i2s1DmaRxEvent(uint32_t event)
|
||||
{
|
||||
i2sDmaRxEvent(event, &i2s1Res);
|
||||
}
|
||||
|
||||
void i2s1DmaTxEvent(uint32_t event)
|
||||
{
|
||||
i2sDmaTxEvent(event, &i2s1Res);
|
||||
}
|
||||
|
||||
// I2S1 Driver Control Block
|
||||
i2sDrvInterface_t i2sDrvInterface1 =
|
||||
{
|
||||
i2s1Init,
|
||||
i2s1Deinit,
|
||||
i2s1PowerCtrl,
|
||||
i2s1Send,
|
||||
i2s1Recv,
|
||||
i2s1Ctrl,
|
||||
i2s1GetTotalCnt,
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
|
||||
* File name: kpc_ec616.c
|
||||
* Description: EC618 kpc driver source file
|
||||
* History: Rev1.0 2021-07-23
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "kpc.h"
|
||||
#include "ic.h"
|
||||
#include "clock.h"
|
||||
#include "slpman.h"
|
||||
|
||||
//#define KPC_DEBUG
|
||||
|
||||
/** \brief Internal used data structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t isInited; /**< flag indicating intialized or not */
|
||||
|
||||
uint8_t scanState; /**< For key release detect */
|
||||
|
||||
uint8_t enableAutoRepeat; /**< autorepeat feature is enabled */
|
||||
|
||||
uint8_t padding0;
|
||||
|
||||
uint32_t keyEnableMask; /**< Bitmap of enabled keys */
|
||||
uint32_t keyState; /**< Bitmap of key state, 0-release, 1-press */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t repeatCount; /**< counter for autorepeat */
|
||||
uint8_t delay; /**< autorepeat event delay */
|
||||
uint8_t period; /**< autorepeat event period */
|
||||
uint16_t padding1;
|
||||
} autoRepeat;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t DEBCTL; /**< Debounce Control Register */
|
||||
uint32_t KPCTL; /**< Keypad Control Register */
|
||||
uint32_t DICTL; /**< Direct Input Control Register */
|
||||
uint32_t KPENCTL; /**< Keypad Enable Register */
|
||||
uint32_t DIENCTL; /**< Direct Input Enable Register */
|
||||
} configRegisters;
|
||||
|
||||
kpc_callback_t eventCallback; /**< Callback function passed in by application */
|
||||
} KpcDataBase_t;
|
||||
|
||||
static KpcDataBase_t gKpcDataBase = {0};
|
||||
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
/**
|
||||
\fn void KPC_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
\brief Backup KPC configurations before sleep.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
void KPC_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
if(gKpcDataBase.isInited == 1)
|
||||
{
|
||||
gKpcDataBase.configRegisters.DEBCTL = KPC->DEBCTL;
|
||||
gKpcDataBase.configRegisters.KPCTL = KPC->KPCTL;
|
||||
gKpcDataBase.configRegisters.DICTL = KPC->DICTL;
|
||||
gKpcDataBase.configRegisters.KPENCTL = KPC->KPENCTL;
|
||||
gKpcDataBase.configRegisters.DIENCTL = KPC->DIENCTL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
\fn void KPC_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
\brief Restore KPC configurations after exit from sleep.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
void KPC_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
if(gKpcDataBase.isInited == 1)
|
||||
{
|
||||
KPC->DEBCTL = gKpcDataBase.configRegisters.DEBCTL;
|
||||
KPC->KPCTL = gKpcDataBase.configRegisters.KPCTL;
|
||||
KPC->DICTL = gKpcDataBase.configRegisters.DICTL;
|
||||
KPC->KPENCTL = gKpcDataBase.configRegisters.KPENCTL;
|
||||
KPC->DIENCTL = gKpcDataBase.configRegisters.DIENCTL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static __FORCEINLINE uint32_t KPC_findFirstSet(uint32_t value)
|
||||
{
|
||||
return __CLZ(__RBIT(value));
|
||||
}
|
||||
|
||||
/**
|
||||
construct key enable bitmap
|
||||
|
||||
24 20 19 15 14 10 9 5 4 0
|
||||
+------------------+------------------+------------------+------------------+------------------+
|
||||
| row 4, col[4:0] | row 3, col[4:0] | row 2, col[4:0] | row 1,col[4:0] | row 0, col[4:0] |
|
||||
+------------------+------------------+------------------+------------------+------------------+
|
||||
|
||||
*/
|
||||
static void KPC_setKeyMask(uint32_t rowMask, uint32_t colMask, uint32_t* keyEnableMask, uint32_t* rowMsb, uint32_t* rowCounts)
|
||||
{
|
||||
uint32_t keyMask = 0;
|
||||
uint32_t rowIndex = 0;
|
||||
uint32_t cnt = 0;
|
||||
|
||||
// Max 5x5 matrix keypad
|
||||
rowMask &= 0x1f;
|
||||
colMask &= 0x1f;
|
||||
|
||||
while(rowMask)
|
||||
{
|
||||
rowIndex = KPC_findFirstSet(rowMask);
|
||||
keyMask |= (colMask << (rowIndex * 5));
|
||||
rowMask &= (rowMask - 1);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
*keyEnableMask = keyMask;
|
||||
*rowMsb = rowIndex;
|
||||
*rowCounts = cnt;
|
||||
}
|
||||
|
||||
static void KPC_eventReport(void)
|
||||
{
|
||||
uint32_t lsb, keyScanResult, keyScanResultBackup, changed, report = 0;
|
||||
|
||||
KpcReportEvent_t event;
|
||||
|
||||
// Get current key scan result
|
||||
keyScanResult = KPC->KPSTAT & gKpcDataBase.keyEnableMask;
|
||||
|
||||
keyScanResultBackup = keyScanResult;
|
||||
|
||||
// Find out changed key
|
||||
changed = keyScanResult ^ gKpcDataBase.keyState;
|
||||
|
||||
#ifdef KPC_DEBUG
|
||||
printf("report: [%x]-[%x]-[%x]\r\n", keyScanResult, gKpcDataBase.keyState, changed);
|
||||
#endif
|
||||
|
||||
// First to handle key release
|
||||
if(changed)
|
||||
{
|
||||
lsb = KPC_findFirstSet(changed);
|
||||
|
||||
// Check key released during two consecutive rounds of scan
|
||||
if((keyScanResultBackup & ( 1 << lsb)) == 0)
|
||||
{
|
||||
event.row = lsb / 5;
|
||||
event.column = lsb % 5;
|
||||
event.value = KPC_REPORT_KEY_RELEASE;
|
||||
|
||||
gKpcDataBase.autoRepeat.repeatCount = 0;
|
||||
|
||||
if(gKpcDataBase.eventCallback)
|
||||
{
|
||||
gKpcDataBase.eventCallback(event);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Check key press
|
||||
if(keyScanResult)
|
||||
{
|
||||
lsb = KPC_findFirstSet(keyScanResult);
|
||||
|
||||
// repeat key?
|
||||
if((gKpcDataBase.keyState & (1 << lsb)) && (gKpcDataBase.enableAutoRepeat == 1))
|
||||
{
|
||||
gKpcDataBase.autoRepeat.repeatCount++;
|
||||
|
||||
if((gKpcDataBase.autoRepeat.repeatCount >= gKpcDataBase.autoRepeat.delay) && ((gKpcDataBase.autoRepeat.repeatCount - gKpcDataBase.autoRepeat.delay) % gKpcDataBase.autoRepeat.period == 0))
|
||||
{
|
||||
event.row = lsb / 5;
|
||||
event.column = lsb % 5;
|
||||
event.value = KPC_REPORT_KEY_REPEAT;
|
||||
report = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
event.row = lsb / 5;
|
||||
event.column = lsb % 5;
|
||||
event.value = KPC_REPORT_KEY_PRESS;
|
||||
gKpcDataBase.autoRepeat.repeatCount = 0;
|
||||
report = 1;
|
||||
}
|
||||
|
||||
if(gKpcDataBase.eventCallback && report)
|
||||
{
|
||||
gKpcDataBase.eventCallback(event);
|
||||
}
|
||||
}
|
||||
|
||||
// save current result
|
||||
gKpcDataBase.keyState = keyScanResultBackup;
|
||||
}
|
||||
|
||||
static void KPC_keyPadModeIsr(void)
|
||||
{
|
||||
KPC_eventReport();
|
||||
|
||||
// If any key is pressed, enable direct input interrupt which works as a periodic timer for key release detect purpose
|
||||
KPC->DIENCTL = KPC_DIENCTL_ENABLE_Msk;
|
||||
KPC->KPENCTL = KPC_KPENCTL_ENABLE_Msk;
|
||||
|
||||
gKpcDataBase.scanState = 1; // Indicating at least one key is pressed
|
||||
|
||||
}
|
||||
|
||||
// Enter at the end of one round of scan period
|
||||
static void KPC_directInputModeIsr(void)
|
||||
{
|
||||
KPC->CLRCTL = KPC_CLRCTL_INPUT_INT_CLR_Msk;
|
||||
|
||||
// Check if all keys are released
|
||||
if((KPC->KPSTAT == 0) && (gKpcDataBase.scanState == 2))
|
||||
{
|
||||
KPC->DIENCTL = 0;
|
||||
gKpcDataBase.scanState = 0;
|
||||
|
||||
#ifdef KPC_DEBUG
|
||||
printf("release,%x\r\n", KPC->DISTAT);
|
||||
#endif
|
||||
KPC_eventReport();
|
||||
}
|
||||
|
||||
gKpcDataBase.scanState = 2;
|
||||
|
||||
}
|
||||
|
||||
void KPC_getDefaultConfig(KpcConfig_t *config)
|
||||
{
|
||||
ASSERT(config);
|
||||
|
||||
config->debounceConfig.debounceClkDivRatio = KPC_DEBOUNCE_CLK_DIV_RATIO_16384;
|
||||
config->debounceConfig.debounceWidth = KPC_DEBOUNCE_WIDTH_7_CYCLES;
|
||||
|
||||
config->validRowMask = KPC_ROW_ALL;
|
||||
config->validColumnMask = KPC_COLUMN_ALL;
|
||||
|
||||
config->scanPolarity = KPC_SCAN_POLARITY_0;
|
||||
config->scanDivRatio = KPC_SCAN_DIV_RATIO_16;
|
||||
|
||||
config->autoRepeat.enable = 1;
|
||||
config->autoRepeat.delay = 10;
|
||||
config->autoRepeat.period = 1;
|
||||
}
|
||||
|
||||
int32_t KPC_init(const KpcConfig_t *config, kpc_callback_t callback)
|
||||
{
|
||||
ASSERT(config);
|
||||
|
||||
uint32_t mask, validRowCounts, msbOfValidRows;
|
||||
|
||||
mask = SaveAndSetIRQMask();
|
||||
|
||||
// Initialization
|
||||
if(gKpcDataBase.isInited == 0)
|
||||
{
|
||||
CLOCK_setClockSrc(FCLK_KPC, FCLK_KPC_SEL_26M);
|
||||
|
||||
CLOCK_clockEnable(FCLK_KPC);
|
||||
CLOCK_clockEnable(PCLK_KPC);
|
||||
|
||||
GPR_swResetModule(RESET_VECTOR_PTR(KPC_RESET_VECTOR));
|
||||
|
||||
// enable KPC IRQ
|
||||
XIC_SetVector(PXIC0_KPC_DIRECT_IRQn, KPC_directInputModeIsr);
|
||||
XIC_EnableIRQ(PXIC0_KPC_DIRECT_IRQn);
|
||||
|
||||
XIC_SetVector(PXIC0_KPC_KEYPAD_IRQn, KPC_keyPadModeIsr);
|
||||
XIC_EnableIRQ(PXIC0_KPC_KEYPAD_IRQn);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
RestoreIRQMask(mask);
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
KPC_setKeyMask(config->validRowMask, config->validColumnMask, &gKpcDataBase.keyEnableMask, &msbOfValidRows, &validRowCounts);
|
||||
|
||||
if(validRowCounts < 2)
|
||||
{
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
KPC->DEBCTL = EIGEN_VAL2FLD(KPC_DEBCTL_DEBOUNCER_DEPTH, config->debounceConfig.debounceWidth) | \
|
||||
EIGEN_VAL2FLD(KPC_DEBCTL_DEBOUNCER_TO0_THRD, config->debounceConfig.debounceWidth) | \
|
||||
EIGEN_VAL2FLD(KPC_DEBCTL_DEBOUNCER_TO1_THRD, config->debounceConfig.debounceWidth) | \
|
||||
EIGEN_VAL2FLD(KPC_DEBCTL_DEBOUNCER_TO_MCLK_RATIO, config->debounceConfig.debounceClkDivRatio);
|
||||
|
||||
KPC->KPCTL = EIGEN_VAL2FLD(KPC_KPCTL_POLARITY, config->scanPolarity) | \
|
||||
EIGEN_VAL2FLD(KPC_KPCTL_ROW_VLD_BITMAP, config->validRowMask & 0x1FU) | \
|
||||
EIGEN_VAL2FLD(KPC_KPCTL_COL_VLD_BITMAP, config->validColumnMask & 0x1FU) | \
|
||||
EIGEN_VAL2FLD(KPC_KPCTL_SCAN_TO_DEBOUNCE_RATIO, config->scanDivRatio);
|
||||
|
||||
// Enable rising/falling edge interrupt of ending row for key release detect
|
||||
if(config->scanPolarity == KPC_SCAN_POLARITY_0)
|
||||
{
|
||||
KPC->DICTL = EIGEN_VAL2FLD(KPC_DICTL_INT_EN, 1 << (msbOfValidRows + 5)) | EIGEN_VAL2FLD(KPC_DICTL_INT_MODE, 0x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
KPC->DICTL = EIGEN_VAL2FLD(KPC_DICTL_INT_EN, 1 << (msbOfValidRows + 5)) | EIGEN_VAL2FLD(KPC_DICTL_INT_MODE, 0x2);
|
||||
}
|
||||
|
||||
KPC->AUTOCG = KPC_AUTOCG_ENABLE_Msk;
|
||||
|
||||
gKpcDataBase.eventCallback = callback;
|
||||
|
||||
gKpcDataBase.enableAutoRepeat = config->autoRepeat.enable;
|
||||
gKpcDataBase.autoRepeat.delay = config->autoRepeat.delay;
|
||||
gKpcDataBase.autoRepeat.period = config->autoRepeat.period;
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_KPC_MODULE, KPC_enterLowPowerStatePrepare, NULL);
|
||||
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_KPC_MODULE, KPC_exitLowPowerStateRestore, NULL);
|
||||
#endif
|
||||
|
||||
gKpcDataBase.isInited = 1;
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
}
|
||||
|
||||
void KPC_deInit(void)
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
if(gKpcDataBase.isInited == 1)
|
||||
{
|
||||
KPC_stopScan();
|
||||
|
||||
// disable clock
|
||||
CLOCK_clockDisable(FCLK_KPC);
|
||||
CLOCK_clockDisable(PCLK_KPC);
|
||||
|
||||
XIC_DisableIRQ(PXIC0_KPC_DIRECT_IRQn);
|
||||
XIC_DisableIRQ(PXIC0_KPC_KEYPAD_IRQn);
|
||||
XIC_ClearPendingIRQ(PXIC0_KPC_DIRECT_IRQn);
|
||||
XIC_ClearPendingIRQ(PXIC0_KPC_KEYPAD_IRQn);
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_KPC_MODULE);
|
||||
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_KPC_MODULE);
|
||||
#endif
|
||||
|
||||
gKpcDataBase.isInited = 0;
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
|
||||
void KPC_startScan(void)
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
if(gKpcDataBase.isInited == 1)
|
||||
{
|
||||
KPC->KPENCTL = KPC_KPENCTL_ENABLE_Msk;
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
|
||||
void KPC_stopScan(void)
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
if(gKpcDataBase.isInited == 1)
|
||||
{
|
||||
KPC->DIENCTL = 0;
|
||||
KPC->CLRCTL = KPC_CLRCTL_INPUT_INT_CLR_Msk;
|
||||
KPC->DICTL = 0;
|
||||
}
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,420 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
|
||||
* File name: oneWire.c
|
||||
* Description: EC618 one wire bus driver source file
|
||||
* History: Rev1.0 2020-12-17
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "ec618.h"
|
||||
#include "bsp.h"
|
||||
#include "oneWire.h"
|
||||
#include "hal_misc.h"
|
||||
|
||||
extern void delay_us(uint32_t us);
|
||||
|
||||
|
||||
#if OW_DEBUG_EN
|
||||
#define OW_DEBUG(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define OW_DEBUG(...)
|
||||
#endif
|
||||
|
||||
#define OW_IRQ_MODE 1
|
||||
|
||||
static volatile OwStats_e owStats = OW_IDLE;
|
||||
|
||||
#define OW_PAD_ADDR (17) //(19)->gpio4 (17)->gpio2 (48)->gpio28 (22)->gpio7
|
||||
#define OW_PAD_FUNC PAD_MUX_ALT4 //PAD_MUX_ALT3 PAD_MUX_ALT4 PAD_MUX_ALT4 PAD_MUX_ALT4
|
||||
|
||||
|
||||
uint8_t *readBuf = NULL;
|
||||
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
void owIrqHandler(void);
|
||||
#else
|
||||
int A, B, C, D, E, F, G, H, I, J;
|
||||
#endif
|
||||
|
||||
void owSetMode(OwModeSel_e mode)
|
||||
{
|
||||
if (mode == STANDARD)
|
||||
{
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
#if 0
|
||||
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_SEND_DIV10, 50);
|
||||
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_WAIT_DIV10, 50);
|
||||
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_RDDLY_MIN, 15);
|
||||
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_RDDLY_MAX_DIV10, 10);
|
||||
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_RECO, 2);
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_SLOT_DIV10, 7);
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_START, 1);
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_WRDLY, 14);
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_RDDLY, 11);
|
||||
#endif
|
||||
#else
|
||||
OW->ECR |= OW_ECR_RXD_MJR_Msk;
|
||||
|
||||
A = 2; // 6us
|
||||
B = 12; // 64us
|
||||
C = 16; // 60us
|
||||
D = 1; // 10us
|
||||
E = 5; // 9us
|
||||
F = 28; // 55us
|
||||
G = 0;
|
||||
H = 120;// 480us
|
||||
I = 35; // 70us
|
||||
J = 150;// 410us
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_SEND_DIV10, 50);
|
||||
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_WAIT_DIV10, 50);
|
||||
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_RDDLY_MIN, 15);
|
||||
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_RDDLY_MAX_DIV10, 10);
|
||||
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_RECO, 2);
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_SLOT_DIV10, 7);
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_START, 1);
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_WRDLY, 14);
|
||||
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_RDDLY, 11);
|
||||
#else
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if (OW_IRQ_MODE != 1)
|
||||
void write(uint8_t val)
|
||||
{
|
||||
if (val == 1)
|
||||
{
|
||||
OW->IOR |= OW_IOR_IO_SWOEN_Msk;
|
||||
OW->IOR |= OW_IOR_IO_SWOUT_Msk;
|
||||
}
|
||||
else
|
||||
{
|
||||
OW->IOR |= OW_IOR_IO_SWOEN_Msk;
|
||||
OW->IOR &= ~OW_IOR_IO_SWOUT_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t read()
|
||||
{
|
||||
uint8_t retData, rmjData;
|
||||
|
||||
OW->IOR &= ~OW_IOR_IO_SWOEN_Msk;
|
||||
rmjData = EIGEN_FLD2VAL(OW_ECR_RXD_MJR, OW->ECR);
|
||||
|
||||
if (rmjData > 0)
|
||||
{
|
||||
retData = EIGEN_FLD2VAL(OW_IOR_IO_SWIN_SYNC, OW->IOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
retData = EIGEN_FLD2VAL(OW_IOR_IO_SWIN, OW->IOR);
|
||||
}
|
||||
|
||||
return retData;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void owInit()
|
||||
{
|
||||
GPR_clockEnable(PCLK_ONEW);
|
||||
|
||||
// configure onew pins
|
||||
PadConfig_t padConfig;
|
||||
PAD_getDefaultConfig(&padConfig);
|
||||
padConfig.mux = OW_PAD_FUNC;
|
||||
PAD_setPinConfig(OW_PAD_ADDR, &padConfig);
|
||||
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
OW->IOR &= ~OW_IOR_IO_SWMODE_Msk;
|
||||
XIC_SetVector(PXIC0_ONEW_IRQn, owIrqHandler);
|
||||
XIC_EnableIRQ(PXIC0_ONEW_IRQn);
|
||||
#else
|
||||
OW->IOR |= OW_IOR_IO_SWMODE_Msk;
|
||||
#endif
|
||||
|
||||
OW->ECR |= OW_ECR_ENABLE_Msk; // enable onewire
|
||||
}
|
||||
|
||||
void owDeInit()
|
||||
{
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
XIC_DisableIRQ(PXIC0_ONEW_IRQn);
|
||||
#endif
|
||||
|
||||
GPR_clockDisable(PCLK_ONEW);
|
||||
}
|
||||
|
||||
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
volatile uint32_t irqNo;
|
||||
volatile uint16_t count = 0;
|
||||
void owIrqHandler()
|
||||
{
|
||||
++count;
|
||||
irqNo = OW->IIR;
|
||||
|
||||
// Disable ONEW IRQ
|
||||
XIC_DisableIRQ(PXIC0_ONEW_IRQn);
|
||||
|
||||
// Clear pending ONEW interrupts
|
||||
XIC_ClearPendingIRQ(PXIC0_ONEW_IRQn);
|
||||
|
||||
if ((OW->IIR & OW_IIR_INT_RESET_PD_Msk) && ((OW->IIR & OW_IIR_INT_RESET_Msk)!=OW_IIR_INT_RESET_Msk))
|
||||
{
|
||||
OW->IER &= ~OW_IER_INTEN_RESET_PD_Msk;
|
||||
|
||||
owStats |= OW_RESET_SUCCESS;
|
||||
|
||||
OW->IIR |= OW_IIR_INT_CLR_Msk;
|
||||
}
|
||||
else if ((OW->IIR & OW_IIR_INT_RESET_Msk) && (OW->IIR & OW_IIR_INT_RESET_PD_Msk))
|
||||
{
|
||||
if (OW->IIR & OW_IIR_RESET_PD_RES_Msk)
|
||||
{
|
||||
owStats |= OW_RESETPD_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
owStats &= ~OW_RESETPD_SUCCESS;
|
||||
}
|
||||
|
||||
OW->IIR |= OW_IIR_INT_CLR_Msk;
|
||||
OW->IER &= ~OW_IER_INTEN_RESET_PD_Msk;
|
||||
}
|
||||
else if (OW->IIR & OW_IIR_INT_WRITE_Msk)
|
||||
{
|
||||
if (OW->IIR & OW_IIR_INT_WRITE_Msk)
|
||||
{
|
||||
owStats |= OW_WRITE_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
owStats &= ~OW_WRITE_SUCCESS;
|
||||
}
|
||||
|
||||
OW->IIR |= OW_IIR_INT_CLR_Msk;
|
||||
OW->IER &= ~OW_IER_INTEN_WRITE_Msk;
|
||||
}
|
||||
else if (OW->IIR & OW_IIR_INT_READ_Msk)
|
||||
{
|
||||
*readBuf = OW->RBR;
|
||||
|
||||
if (OW->IIR & OW_IIR_INT_READ_Msk)
|
||||
{
|
||||
owStats |= OW_READ_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
owStats &= ~OW_READ_SUCCESS;
|
||||
}
|
||||
|
||||
OW->IIR |= OW_IIR_INT_CLR_Msk;
|
||||
OW->IER &= ~OW_IER_INTEN_READ_Msk;
|
||||
}
|
||||
|
||||
OW->OCR |= OW_OCR_CMD_FLUSH_Msk;
|
||||
|
||||
XIC_EnableIRQ(PXIC0_ONEW_IRQn);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int32_t owReset()
|
||||
{
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
OW->IER |= OW_IER_INTEN_RESET_PD_Msk;
|
||||
OW->IER |= OW_IER_INTEN_RESET_Msk;
|
||||
OW->OCR |= OW_OCR_CMD_RESET_Msk;
|
||||
while ((owStats & OW_RESET_SUCCESS) != OW_RESET_SUCCESS);
|
||||
|
||||
owStats &= ~OW_RESET_SUCCESS;
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
return OWDRV_OK;
|
||||
}
|
||||
int32_t owResetPd()
|
||||
{
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
OW->IER |= OW_IER_INTEN_RESET_Msk;
|
||||
delay_us(20); // wait until former irq finish
|
||||
OW->OCR |= OW_OCR_CMD_RESET_Msk;
|
||||
|
||||
while ((owStats & OW_RESETPD_SUCCESS) != OW_RESETPD_SUCCESS);
|
||||
owStats &= ~OW_RESETPD_SUCCESS;
|
||||
|
||||
return OWDRV_OK;
|
||||
#else
|
||||
delay_us(50);
|
||||
//owDelay(G);
|
||||
write(0);
|
||||
delay_us(H);
|
||||
write(1);
|
||||
delay_us(I);
|
||||
int ret = read();
|
||||
delay_us(J);
|
||||
if (ret == 1)
|
||||
{
|
||||
owStats |= OW_RESETPD_SUCCESS;
|
||||
return OWDRV_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
owStats &= ~OW_RESETPD_SUCCESS;
|
||||
return OWDRV_RESETPD_ERR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t owWriteBit(uint8_t data)
|
||||
{
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
OW->DFR &= ~OW_DFR_MODE_BYTE_Msk;
|
||||
OW->TBR = data;
|
||||
OW->IER |= OW_IER_INTEN_WRITE_Msk;
|
||||
OW->OCR |= OW_OCR_CMD_WRITE_Msk;
|
||||
|
||||
while ((owStats & OW_WRITE_SUCCESS) != OW_WRITE_SUCCESS);
|
||||
owStats &= ~OW_WRITE_SUCCESS;
|
||||
#else
|
||||
if (data == 1)
|
||||
{
|
||||
write(0);
|
||||
delay_us(A);
|
||||
write(1);
|
||||
delay_us(B);
|
||||
}
|
||||
else
|
||||
{
|
||||
write(0);
|
||||
delay_us(C);
|
||||
write(1);
|
||||
delay_us(D);
|
||||
}
|
||||
#endif
|
||||
|
||||
return OWDRV_OK;
|
||||
}
|
||||
|
||||
int32_t owReadBit(uint8_t * dataRead)
|
||||
{
|
||||
if (dataRead != NULL)
|
||||
{
|
||||
readBuf = dataRead;
|
||||
}
|
||||
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
OW->DFR &= ~OW_DFR_MODE_BYTE_Msk;
|
||||
OW->IER |= OW_IER_INTEN_READ_Msk;
|
||||
OW->OCR |= OW_OCR_CMD_READ_Msk;
|
||||
|
||||
while ((owStats & OW_READ_SUCCESS) != OW_READ_SUCCESS);
|
||||
owStats &= ~OW_READ_SUCCESS;
|
||||
#else
|
||||
write(0);
|
||||
delay_us(1);
|
||||
write(1);
|
||||
delay_us(2);
|
||||
*dataRead = read();
|
||||
delay_us(14);
|
||||
#endif
|
||||
|
||||
return OWDRV_OK;
|
||||
}
|
||||
|
||||
int32_t owWriteByte(uint8_t data)
|
||||
{
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
OW->DFR |= OW_DFR_MODE_BYTE_Msk;
|
||||
OW->TBR = data;
|
||||
OW->IER |= OW_IER_INTEN_WRITE_Msk;
|
||||
OW->OCR |= OW_OCR_CMD_WRITE_Msk;
|
||||
|
||||
while ((owStats & OW_WRITE_SUCCESS) != OW_WRITE_SUCCESS);
|
||||
owStats &= ~OW_WRITE_SUCCESS;
|
||||
#else
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
owWriteBit(data & 0x01);
|
||||
data >>= 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return OWDRV_OK;
|
||||
}
|
||||
|
||||
int32_t owReadByte(uint8_t * dataRead)
|
||||
{
|
||||
if (dataRead != NULL)
|
||||
{
|
||||
readBuf = dataRead;
|
||||
}
|
||||
|
||||
#if (OW_IRQ_MODE == 1)
|
||||
OW->DFR |= OW_DFR_MODE_BYTE_Msk;
|
||||
|
||||
OW->IER |= OW_IER_INTEN_READ_Msk;
|
||||
OW->OCR |= OW_OCR_CMD_READ_Msk;
|
||||
|
||||
while ((owStats & OW_READ_SUCCESS) != OW_READ_SUCCESS);
|
||||
|
||||
owStats &= ~OW_READ_SUCCESS;
|
||||
#else
|
||||
uint8_t result=0;
|
||||
uint8_t readBitVal[8];
|
||||
memset(readBitVal, 0, 8);
|
||||
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
result >>= 1;
|
||||
owReadBit(readBitVal+i);
|
||||
|
||||
if (readBitVal[i] == 1)
|
||||
{
|
||||
result |= 0x80;
|
||||
}
|
||||
}
|
||||
*dataRead = result;
|
||||
#endif
|
||||
|
||||
return OWDRV_OK;
|
||||
}
|
||||
|
||||
int32_t owTouchByte(uint8_t data)
|
||||
{
|
||||
int32_t result = 0;
|
||||
|
||||
for (uint8_t i=0; i<8; i++)
|
||||
{
|
||||
result >>= 1;
|
||||
|
||||
// if sending a '1' then read a bit, else write a '0'
|
||||
if (data & 0x01)
|
||||
{
|
||||
if (owReadBit(NULL))
|
||||
{
|
||||
result |= 0x80;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
owWriteBit(0);
|
||||
}
|
||||
|
||||
data >>= 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: pad.c
|
||||
* Description: EC618 pad driver source file
|
||||
* History: Rev1.0 2018-11-14
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "pad.h"
|
||||
#include "clock.h"
|
||||
#include "slpman.h"
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
|
||||
static uint32_t gPadBackupRegs[PAD_ADDR_MAX_NUM] = {0};
|
||||
|
||||
/**
|
||||
\fn void PAD_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
\brief Backup pad configurations before sleep.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
void PAD_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
GPR_clockEnable(PCLK_PAD);
|
||||
|
||||
for(i = 0; i < PAD_ADDR_MAX_NUM; i++)
|
||||
{
|
||||
gPadBackupRegs[i] = PAD->PCR[i];
|
||||
}
|
||||
|
||||
GPR_clockDisable(PCLK_PAD);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
\fn void PAD_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
\brief Restore PAD configurations after exit from sleep.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
void PAD_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
GPR_clockEnable(PCLK_PAD);
|
||||
|
||||
for(i = 0; i < PAD_ADDR_MAX_NUM; i++)
|
||||
{
|
||||
PAD->PCR[i] = gPadBackupRegs[i];
|
||||
}
|
||||
|
||||
GPR_clockDisable(PCLK_PAD);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void PAD_driverInit(void)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_PAD_MODULE, PAD_enterLowPowerStatePrepare, NULL);
|
||||
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_PAD_MODULE, PAD_exitLowPowerStateRestore, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PAD_driverDeInit(void)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_PAD_MODULE);
|
||||
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_PAD_MODULE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void PAD_getDefaultConfig(PadConfig_t *config)
|
||||
{
|
||||
ASSERT(config);
|
||||
|
||||
config->mux = PAD_MUX_ALT0;
|
||||
config->inputBufferEnable = PAD_INPUT_BUFFER_DISABLE;
|
||||
config->pullSelect = PAD_PULL_AUTO;
|
||||
config->pullUpEnable = PAD_PULL_UP_DISABLE;
|
||||
config->pullDownEnable = PAD_PULL_DOWN_DISABLE;
|
||||
}
|
||||
|
||||
void PAD_setPinConfig(uint32_t paddr, const PadConfig_t *config)
|
||||
{
|
||||
ASSERT(config);
|
||||
ASSERT(paddr < PAD_ADDR_MAX_NUM);
|
||||
|
||||
CLOCK_clockEnable(PCLK_PAD);
|
||||
PAD->PCR[paddr] = *((const uint32_t *)config);
|
||||
CLOCK_clockDisable(PCLK_PAD);
|
||||
}
|
||||
|
||||
void PAD_setPinMux(uint32_t paddr, PadMux_e mux)
|
||||
{
|
||||
ASSERT(paddr < PAD_ADDR_MAX_NUM);
|
||||
|
||||
CLOCK_clockEnable(PCLK_PAD);
|
||||
PAD->PCR[paddr] = (PAD->PCR[paddr] & ~PAD_PCR_MUX_Msk) | EIGEN_VAL2FLD(PAD_PCR_MUX, mux);
|
||||
CLOCK_clockDisable(PCLK_PAD);
|
||||
|
||||
}
|
||||
|
||||
void PAD_enablePinInputBuffer(uint32_t paddr, bool enable)
|
||||
{
|
||||
ASSERT(paddr < PAD_ADDR_MAX_NUM);
|
||||
|
||||
CLOCK_clockEnable(PCLK_PAD);
|
||||
|
||||
if (enable == true)
|
||||
{
|
||||
PAD->PCR[paddr] |= PAD_PCR_INPUT_BUFFER_ENABLE_Msk;
|
||||
}
|
||||
else
|
||||
{
|
||||
PAD->PCR[paddr] &= ~PAD_PCR_INPUT_BUFFER_ENABLE_Msk;
|
||||
}
|
||||
|
||||
CLOCK_clockDisable(PCLK_PAD);
|
||||
}
|
||||
|
||||
void PAD_setPinPullConfig(uint32_t paddr, PadPullConfig_e config)
|
||||
{
|
||||
ASSERT(paddr < PAD_ADDR_MAX_NUM);
|
||||
|
||||
CLOCK_clockEnable(PCLK_PAD);
|
||||
|
||||
switch(config)
|
||||
{
|
||||
case PAD_INTERNAL_PULL_UP:
|
||||
PAD->PCR[paddr] = (PAD->PCR[paddr] & ~PAD_PCR_PULL_DOWN_ENABLE_Msk) | PAD_PCR_PULL_UP_ENABLE_Msk | PAD_PCR_PULL_SELECT_Msk;
|
||||
break;
|
||||
case PAD_INTERNAL_PULL_DOWN:
|
||||
PAD->PCR[paddr] = (PAD->PCR[paddr] & ~PAD_PCR_PULL_UP_ENABLE_Msk) | PAD_PCR_PULL_DOWN_ENABLE_Msk | PAD_PCR_PULL_SELECT_Msk;
|
||||
break;
|
||||
case PAD_AUTO_PULL:
|
||||
PAD->PCR[paddr] = (PAD->PCR[paddr] & ~PAD_PCR_PULL_SELECT_Msk);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
CLOCK_clockDisable(PCLK_PAD);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,509 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: timer.c
|
||||
* Description: EC618 timer driver source file
|
||||
* History: Rev1.0 2018-07-18
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "timer.h"
|
||||
#include "clock.h"
|
||||
#include "slpman.h"
|
||||
#include DEBUG_LOG_HEADER_FILE
|
||||
|
||||
#define EIGEN_TIMER(n) ((TIMER_TypeDef *) (AP_TIMER0_BASE_ADDR + 0x1000*n))
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
|
||||
/** \brief Internal used data structure */
|
||||
typedef struct
|
||||
{
|
||||
bool isInited; /**< Whether timer has been initialized */
|
||||
struct
|
||||
{
|
||||
uint32_t TCTLR; /**< Timer Control Register */
|
||||
uint32_t TIVR; /**< Timer Init Value Register */
|
||||
uint32_t TMR[3]; /**< Timer Match N Register */
|
||||
} backupRegisters; /**< Backup registers for low power restore */
|
||||
} TimerDatabase_t;
|
||||
|
||||
static bool gIsTimerDriverInited = false;
|
||||
|
||||
static TimerDatabase_t gTimerDataBase[TIMER_INSTANCE_NUM];
|
||||
|
||||
#endif
|
||||
|
||||
static ClockId_e gTimerClocks[TIMER_INSTANCE_NUM*2] = {PCLK_TIMER0, FCLK_TIMER0,
|
||||
PCLK_TIMER1, FCLK_TIMER1,
|
||||
PCLK_TIMER2, FCLK_TIMER2,
|
||||
PCLK_TIMER3, FCLK_TIMER3,
|
||||
PCLK_TIMER4, FCLK_TIMER4,
|
||||
PCLK_TIMER5, FCLK_TIMER5
|
||||
};
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
|
||||
/**
|
||||
\brief Bitmap of TIMER working status,
|
||||
when all TIMER instances are not working, we can vote to enter to low power state.
|
||||
*/
|
||||
static uint32_t gTimerWorkingStatus;
|
||||
|
||||
/**
|
||||
\fn static void TIMER_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
\brief Perform necessary preparations before sleep.
|
||||
After recovering from SLPMAN_SLEEP1_STATE, TIMER hareware is repowered, we backup
|
||||
some registers here first so that we can restore user's configurations after exit.
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
static void TIMER_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
for(i = 0; i < TIMER_INSTANCE_NUM; i++)
|
||||
{
|
||||
if(gTimerDataBase[i].isInited == true)
|
||||
{
|
||||
gTimerDataBase[i].backupRegisters.TCTLR = EIGEN_TIMER(i)->TCTLR;
|
||||
gTimerDataBase[i].backupRegisters.TIVR = EIGEN_TIMER(i)->TIVR;
|
||||
gTimerDataBase[i].backupRegisters.TMR[0] = EIGEN_TIMER(i)->TMR[0];
|
||||
gTimerDataBase[i].backupRegisters.TMR[1] = EIGEN_TIMER(i)->TMR[1];
|
||||
gTimerDataBase[i].backupRegisters.TMR[2] = EIGEN_TIMER(i)->TMR[2];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
\fn static void TIMER_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
\brief Restore after exit from sleep.
|
||||
After recovering from SLPMAN_SLEEP1_STATE, TIMER hareware is repowered, we restore user's configurations
|
||||
by aidding of the stored registers.
|
||||
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
|
||||
*/
|
||||
static void TIMER_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
for(i = 0; i < TIMER_INSTANCE_NUM; i++)
|
||||
{
|
||||
if(gTimerDataBase[i].isInited == true)
|
||||
{
|
||||
GPR_clockEnable(gTimerClocks[i*2]);
|
||||
GPR_clockEnable(gTimerClocks[i*2+1]);
|
||||
|
||||
EIGEN_TIMER(i)->TCTLR = gTimerDataBase[i].backupRegisters.TCTLR;
|
||||
EIGEN_TIMER(i)->TIVR = gTimerDataBase[i].backupRegisters.TIVR;
|
||||
EIGEN_TIMER(i)->TMR[0] = gTimerDataBase[i].backupRegisters.TMR[0];
|
||||
EIGEN_TIMER(i)->TMR[1] = gTimerDataBase[i].backupRegisters.TMR[1];
|
||||
EIGEN_TIMER(i)->TMR[2] = gTimerDataBase[i].backupRegisters.TMR[2];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void TIMER_driverInit(void)
|
||||
{
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
uint32_t i;
|
||||
|
||||
if(gIsTimerDriverInited == false)
|
||||
{
|
||||
for(i = 0; i < TIMER_INSTANCE_NUM; i++)
|
||||
{
|
||||
gTimerDataBase[i].isInited = false;
|
||||
}
|
||||
|
||||
gTimerWorkingStatus = 0;
|
||||
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_TIMER_MODULE, TIMER_enterLowPowerStatePrepare, NULL);
|
||||
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_TIMER_MODULE, TIMER_exitLowPowerStateRestore, NULL);
|
||||
|
||||
gIsTimerDriverInited = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void TIMER_getDefaultConfig(TimerConfig_t *config)
|
||||
{
|
||||
ASSERT(config);
|
||||
|
||||
config->clockSource = TIMER_INTERNAL_CLOCK;
|
||||
config->reloadOption = TIMER_RELOAD_ON_MATCH1;
|
||||
config->initValue = 0;
|
||||
config->match0 = 0x10000 >> 1U;
|
||||
config->match1 = 0x10000;
|
||||
config->match2 = 0xFFFFFFFFU;
|
||||
}
|
||||
|
||||
void TIMER_init(uint32_t instance, const TimerConfig_t *config)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
ASSERT(config);
|
||||
|
||||
TIMER_driverInit();
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
if(gTimerDataBase[instance].isInited == false)
|
||||
{
|
||||
#endif
|
||||
|
||||
CLOCK_clockEnable(gTimerClocks[instance*2]);
|
||||
CLOCK_clockEnable(gTimerClocks[instance*2+1]);
|
||||
|
||||
/* Stop timer counter */
|
||||
EIGEN_TIMER(instance)->TCCR = 0;
|
||||
|
||||
EIGEN_TIMER(instance)->TCTLR = EIGEN_VAL2FLD(TIMER_TCTLR_MODE, config->clockSource) | \
|
||||
EIGEN_VAL2FLD(TIMER_TCTLR_MCS, config->reloadOption);
|
||||
EIGEN_TIMER(instance)->TIVR = config->initValue;
|
||||
EIGEN_TIMER(instance)->TMR[0] = config->match0;
|
||||
EIGEN_TIMER(instance)->TMR[1] = config->match1;
|
||||
EIGEN_TIMER(instance)->TMR[2] = config->match2;
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
gTimerDataBase[instance].isInited = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TIMER_deInit(uint32_t instance)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
if(gTimerDataBase[instance].isInited == true)
|
||||
{
|
||||
#endif
|
||||
CLOCK_clockDisable(gTimerClocks[instance*2]);
|
||||
CLOCK_clockDisable(gTimerClocks[instance*2+1]);
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
gTimerDataBase[instance].isInited = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t matchNum, uint32_t matchValue)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
EIGEN_TIMER(instance)->TMR[matchNum] = matchValue;
|
||||
}
|
||||
|
||||
void TIMER_setInitValue(uint32_t instance, uint32_t initValue)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
EIGEN_TIMER(instance)->TIVR = initValue;
|
||||
}
|
||||
|
||||
void TIMER_setReloadOption(uint32_t instance, TimerReloadOption_t option)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
EIGEN_TIMER(instance)->TCTLR = (EIGEN_TIMER(instance)->TCTLR &~ TIMER_TCTLR_MCS_Msk) | EIGEN_VAL2FLD(TIMER_TCTLR_MCS, option);
|
||||
}
|
||||
|
||||
void TIMER_start(uint32_t instance)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
if(instance != 5) // timer 5 do not vote sleep
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
gTimerWorkingStatus |= (1U << instance);
|
||||
slpManDrvVoteSleep(SLP_VOTE_TIMER, SLP_ACTIVE_STATE);
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
#endif
|
||||
EIGEN_TIMER(instance)->TCCR = 1U;
|
||||
}
|
||||
|
||||
void TIMER_stop(uint32_t instance)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
EIGEN_TIMER(instance)->TCCR = 0;
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
if(instance != 5) // timer 5 do not vote sleep
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
gTimerWorkingStatus &= ~(1U << instance);
|
||||
if (gTimerWorkingStatus == 0)
|
||||
slpManDrvVoteSleep(SLP_VOTE_TIMER, SLP_SLP1_STATE);
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
uint32_t TIMER_getCount(uint32_t instance)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
EIGEN_TIMER(instance)->TCLR = TIMER_TCLR_LATCH_Msk;
|
||||
|
||||
while((EIGEN_TIMER(instance)->TCLR & TIMER_TCLR_LATCH_Msk) == TIMER_TCLR_LATCH_Msk);
|
||||
|
||||
return EIGEN_TIMER(instance)->TCR;
|
||||
}
|
||||
|
||||
int32_t TIMER_setupPwm(uint32_t instance, const TimerPwmConfig_t *config)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
ASSERT(config);
|
||||
|
||||
uint32_t period;
|
||||
|
||||
CLOCK_clockEnable(gTimerClocks[instance*2]);
|
||||
CLOCK_clockEnable(gTimerClocks[instance*2+1]);
|
||||
|
||||
if(config->srcClock_HZ == 0 || config->pwmFreq_HZ == 0 || config->srcClock_HZ <= config->pwmFreq_HZ)
|
||||
return ARM_DRIVER_ERROR_PARAMETER;
|
||||
|
||||
period = config->srcClock_HZ / config->pwmFreq_HZ;
|
||||
|
||||
/* Set PWM period */
|
||||
EIGEN_TIMER(instance)->TMR[1] = period - 1;
|
||||
|
||||
/* Set duty cycle */
|
||||
if(config->dutyCyclePercent == 0)
|
||||
{
|
||||
EIGEN_TIMER(instance)->TMR[0] = period; // if TMR[0] > TMR[1], PWM output keeps low
|
||||
}
|
||||
else if(config->dutyCyclePercent == 100)
|
||||
{
|
||||
EIGEN_TIMER(instance)->TMR[0] = period - 1; // let TMR[0] == TMR[1]
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Note the higher pwm frequency is, the lower reslution of dutyCycle we'll get.
|
||||
Below calculation may overflow for specific dutyCyclePercent and in such case, TMR[0] > TMR[1], PWM output keeps low
|
||||
*/
|
||||
EIGEN_TIMER(instance)->TMR[0] = ((uint64_t)period) * (100U - config->dutyCyclePercent) / 100U - 1;
|
||||
}
|
||||
EIGEN_TIMER(instance)->TIVR = 0;
|
||||
|
||||
/* Enable PWM out */
|
||||
EIGEN_TIMER(instance)->TCTLR = (EIGEN_TIMER(instance)->TCTLR & ~ TIMER_TCTLR_MCS_Msk) | \
|
||||
EIGEN_VAL2FLD(TIMER_TCTLR_MCS, 2U) | TIMER_TCTLR_PWMOUT_Msk;
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
gTimerDataBase[instance].isInited = true;
|
||||
#endif
|
||||
|
||||
return ARM_DRIVER_OK;
|
||||
|
||||
}
|
||||
|
||||
void TIMER_updatePwmDutyCycle(uint32_t instance, uint32_t dutyCyclePercent)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
if(dutyCyclePercent == 0)
|
||||
{
|
||||
EIGEN_TIMER(instance)->TMR[0] = EIGEN_TIMER(instance)->TMR[1] + 1; // if TMR[0] > TMR[1], PWM output keeps low
|
||||
}
|
||||
else if(dutyCyclePercent >= 100)
|
||||
{
|
||||
EIGEN_TIMER(instance)->TMR[0] = EIGEN_TIMER(instance)->TMR[1]; // let TMR[0] == TMR[1]
|
||||
}
|
||||
else
|
||||
{
|
||||
EIGEN_TIMER(instance)->TMR[0] = ((uint64_t)EIGEN_TIMER(instance)->TMR[1] + 1) * (100U - dutyCyclePercent) / 100U - 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TIMER_interruptConfig(uint32_t instance, TimerMatchSelect_t match, TimerInterruptConfig_t config)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
uint32_t enableMask, typeMask, registerValue;
|
||||
|
||||
enableMask = 1U << (match + TIMER_TCTLR_IE_0_Pos);
|
||||
typeMask = 1U << (match + TIMER_TCTLR_IT_0_Pos);
|
||||
registerValue = EIGEN_TIMER(instance)->TCTLR;
|
||||
|
||||
switch(config)
|
||||
{
|
||||
case TIMER_INTERRUPT_DISABLED:
|
||||
|
||||
registerValue &= ~enableMask;
|
||||
EIGEN_TIMER(instance)->TCTLR = registerValue;
|
||||
break;
|
||||
|
||||
case TIMER_INTERRUPT_LEVEL:
|
||||
|
||||
registerValue |= enableMask;
|
||||
registerValue &= ~typeMask;
|
||||
EIGEN_TIMER(instance)->TCTLR = registerValue;
|
||||
break;
|
||||
|
||||
case TIMER_INTERRUPT_PULSE:
|
||||
|
||||
registerValue |= enableMask;
|
||||
registerValue |= typeMask;
|
||||
EIGEN_TIMER(instance)->TCTLR = registerValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TimerInterruptConfig_t TIMER_getInterruptConfig(uint32_t instance, TimerMatchSelect_t match)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
uint32_t enableMask, typeMask, registerValue;
|
||||
|
||||
enableMask = 1U << (match + TIMER_TCTLR_IE_0_Pos);
|
||||
typeMask = 1U << (match + TIMER_TCTLR_IT_0_Pos);
|
||||
registerValue = EIGEN_TIMER(instance)->TCTLR;
|
||||
|
||||
if ((enableMask & registerValue) == 0)
|
||||
return TIMER_INTERRUPT_DISABLED;
|
||||
else if ((typeMask & registerValue) == 0)
|
||||
return TIMER_INTERRUPT_LEVEL;
|
||||
else
|
||||
return TIMER_INTERRUPT_PULSE;
|
||||
}
|
||||
|
||||
uint32_t TIMER_getInterruptFlags(uint32_t instance)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
return EIGEN_TIMER(instance)->TSR;
|
||||
}
|
||||
|
||||
void TIMER_clearInterruptFlags(uint32_t instance, uint32_t mask)
|
||||
{
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
EIGEN_TIMER(instance)->TSR = mask;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t gNetLightInstance = 0xff;
|
||||
void TIMER_netlightEnable(uint8_t instance) // call by user in bsp_custom.c
|
||||
{
|
||||
gNetLightInstance = instance;
|
||||
}
|
||||
|
||||
/////// Internal use for Netlight Function /////////////////
|
||||
void TIMER_netlightPWM(uint8_t mode)
|
||||
{
|
||||
extern void delay_us(uint32_t us);
|
||||
uint8_t instance = gNetLightInstance;
|
||||
static uint8_t curMode;
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
uint32_t mask;
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, TIMER_netlightPWM_1, P_SIG, "Netlight mode=%u Instance=%d",mode, instance);
|
||||
#endif
|
||||
|
||||
if(instance == 0xff)
|
||||
return;
|
||||
|
||||
ASSERT(instance < TIMER_INSTANCE_NUM);
|
||||
|
||||
if(curMode == mode) // do nothing if mode not change
|
||||
return;
|
||||
|
||||
EIGEN_TIMER(instance)->TCCR = 0;
|
||||
|
||||
if(mode == 0)
|
||||
{
|
||||
EIGEN_TIMER(instance)->TMR[0] = 0xFFFFFFFF;
|
||||
EIGEN_TIMER(instance)->TMR[1] = 0; // TMR[0] > TMR[1], PWM output keeps low
|
||||
EIGEN_TIMER(instance)->TCCR = 1;
|
||||
delay_us(10);
|
||||
EIGEN_TIMER(instance)->TCCR = 0;
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
if(gTimerWorkingStatus & (1U << instance))
|
||||
{
|
||||
CLOCK_clockDisable(gTimerClocks[instance*2]);
|
||||
CLOCK_clockDisable(gTimerClocks[instance*2+1]);
|
||||
}
|
||||
mask = SaveAndSetIRQMask();
|
||||
gTimerWorkingStatus &= ~(1U << instance);
|
||||
if (gTimerWorkingStatus == 0)
|
||||
slpManDrvVoteSleep(SLP_VOTE_TIMER, SLP_SLP1_STATE);
|
||||
RestoreIRQMask(mask);
|
||||
#endif
|
||||
curMode = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
if((gTimerWorkingStatus & (1U << instance)) == 0)
|
||||
{
|
||||
CLOCK_clockEnable(gTimerClocks[instance*2]);
|
||||
CLOCK_clockEnable(gTimerClocks[instance*2+1]);
|
||||
}
|
||||
mask = SaveAndSetIRQMask();
|
||||
gTimerWorkingStatus |= (1U << instance);
|
||||
slpManDrvVoteSleep(SLP_VOTE_TIMER, SLP_ACTIVE_STATE);
|
||||
RestoreIRQMask(mask);
|
||||
#endif
|
||||
|
||||
/* Enable PWM out */
|
||||
EIGEN_TIMER(instance)->TCTLR = (EIGEN_TIMER(instance)->TCTLR & ~ TIMER_TCTLR_MCS_Msk) | \
|
||||
EIGEN_VAL2FLD(TIMER_TCTLR_MCS, 2U) | TIMER_TCTLR_PWMOUT_Msk;
|
||||
|
||||
if(mode == 1) // fast flash: 64ms high and 800ms low
|
||||
{
|
||||
EIGEN_TIMER(instance)->TMR[0] = 0x13D61FF;
|
||||
|
||||
EIGEN_TIMER(instance)->TMR[1] = 0x156C5FE;
|
||||
|
||||
EIGEN_TIMER(instance)->TCCR = 1;
|
||||
|
||||
curMode = mode;
|
||||
}
|
||||
else if(mode == 2) // slow flash: 64ms high and 2000ms low
|
||||
{
|
||||
EIGEN_TIMER(instance)->TMR[0] = 0x31974FF;
|
||||
|
||||
EIGEN_TIMER(instance)->TMR[1] = 0x332D8FE;
|
||||
|
||||
EIGEN_TIMER(instance)->TCCR = 1;
|
||||
|
||||
curMode = mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
|
||||
* File name: tls.c
|
||||
* Description: This driver is part of SCT(Security Top) module, only focus on AES and SHA functions which are
|
||||
* mostly used in TLS(transport layer security) area.
|
||||
* History: Rev1.0 2021-12-3
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "tls.h"
|
||||
|
||||
static __attribute__((aligned(4))) sctDescCfg_t sctDescCfg;
|
||||
|
||||
void sctInit()
|
||||
{
|
||||
// open clock
|
||||
CLOCK_clockEnable(SCT_RMI_HCLK);
|
||||
|
||||
GPR_swReset(RST_SCT_RMI_HCLK);
|
||||
GPR_swReset(RST_SCT_HCLK);
|
||||
|
||||
memset(&sctDescCfg, 0, sizeof(sctDescCfg_t));
|
||||
|
||||
// enable sct
|
||||
*(uint32_t *)SCT_ENABLE_REG = 1;
|
||||
|
||||
// set memory guard
|
||||
sctMemGuard_t *sctMemGuard = (sctMemGuard_t*)SCT_MEM_GUARD_REG;
|
||||
sctMemGuard->hAddr0 = MGR_HIGH_ADDR;
|
||||
sctMemGuard->lAddr0 = MGR_LOW_ADDR;
|
||||
sctMemGuard->hAddr1 = MGR_HIGH_ADDR1;
|
||||
sctMemGuard->lAddr1 = MGR_LOW_ADDR1;
|
||||
sctMemGuard->hAddr2 = MGR_HIGH_ADDR2;
|
||||
sctMemGuard->lAddr2 = MGR_LOW_ADDR2;
|
||||
sctMemGuard->hAddr3 = MGR_HIGH_ADDR3;
|
||||
sctMemGuard->lAddr3 = MGR_LOW_ADDR3;
|
||||
|
||||
// sct common config
|
||||
sctCfgWord0_t *cfgWord0 = (sctCfgWord0_t*)SCT_COMM_CFG0_REG;
|
||||
sctCfgWord1_t *cfgWord1 = (sctCfgWord1_t*)SCT_COMM_CFG1_REG;
|
||||
sctCfgWord0_t word0;
|
||||
cfgWord0->val = 0;
|
||||
cfgWord1->descMaxProcTickTime = 0x4fffb;
|
||||
|
||||
word0.ahbAcg = 0;
|
||||
word0.rmiAcg = 1;
|
||||
word0.chainStartUnilog = 1;
|
||||
word0.descDoneUnilog = 1;
|
||||
word0.chainEndUnilog = 1;
|
||||
word0.errorIntUnilog = 1;
|
||||
word0.usbEndianInd = 0;
|
||||
word0.memHighAddrOffset = 0;
|
||||
cfgWord0->val = word0.val;
|
||||
}
|
||||
|
||||
static uint32_t sctCheckBusy()
|
||||
{
|
||||
sctChaState_t *state = (sctChaState_t*)AES_SHA_CH4_STATE_REG;
|
||||
if (state->chaBeEmpty)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sctTrigger(sctDescCfg_t* sctDescCfg)
|
||||
{
|
||||
if (sctCheckBusy())
|
||||
{
|
||||
return SCTDRV_BUSY;
|
||||
}
|
||||
|
||||
sctCfgWord_t* sctCfgWord = (sctCfgWord_t*)AES_SHA_CH4_CFG_REG;
|
||||
sctCfgWord->chanCfgWord1 = (uint32_t)sctDescCfg;
|
||||
CLOCK_clockEnable(SCT_HCLK);
|
||||
sctCfgWord->chanCfgWord5.trigger = 1;
|
||||
|
||||
return SCTDRV_OK;
|
||||
}
|
||||
|
||||
static int sctPollDone(uint32_t timeOutCycle)
|
||||
{
|
||||
while (timeOutCycle--)
|
||||
{
|
||||
delay_us(1);
|
||||
|
||||
if (!sctCheckBusy())
|
||||
{
|
||||
return SCTDRV_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return SCTDRV_TIMEOUT;
|
||||
}
|
||||
|
||||
|
||||
int32_t aesUpdate(aesInfo_t* aesInfo)
|
||||
{
|
||||
uint32_t ret = SCTDRV_OK;
|
||||
|
||||
sctDescCfg_t* sctDescCfgPtr = &sctDescCfg;
|
||||
sctDescCfgPtr->u1.aesField.length = aesInfo->length;
|
||||
sctDescCfgPtr->u1.aesField.dir = aesInfo->aesCtrl.dir;
|
||||
sctDescCfgPtr->u1.aesField.aesMode = aesInfo->aesCtrl.aesMode;
|
||||
sctDescCfgPtr->u1.aesField.paddingMode = aesInfo->aesCtrl.paddingMode;
|
||||
sctDescCfgPtr->u1.aesField.ckLen = aesInfo->aesCtrl.ckLen;
|
||||
sctDescCfgPtr->u1.aesField.aesCkSel = aesInfo->aesCtrl.aesCkSel;
|
||||
sctDescCfgPtr->u1.aesField.subType = 0; // aes
|
||||
sctDescCfgPtr->u1.aesField.type = 5; // default value is 5
|
||||
sctDescCfgPtr->srcAddr = aesInfo->srcAddr;
|
||||
sctDescCfgPtr->dstAddr = aesInfo->dstAddr;
|
||||
|
||||
if (aesInfo->aesCtrl.aesCkSel == 0) // from memory
|
||||
{
|
||||
sctDescCfgPtr->u2.aesCkAddr = aesInfo->aesCkAddr;;
|
||||
}
|
||||
|
||||
if (aesInfo->aesCtrl.aesMode == 1 || aesInfo->aesCtrl.aesMode == 2) // aes cbc, ctr mode
|
||||
{
|
||||
sctDescCfgPtr->u3.aesIvAddr = aesInfo->ivAddr;
|
||||
}
|
||||
|
||||
sctCfgWord_t* sctCfgWord = (sctCfgWord_t*)AES_SHA_CH4_CFG_REG;
|
||||
chanCfgWord0_t cfgWord0;
|
||||
cfgWord0.val = 0;
|
||||
if (aesInfo->aesCtrl.ckBLEndian == 1) // key is big endian
|
||||
{
|
||||
cfgWord0.ckBLEndian = 1;
|
||||
}
|
||||
|
||||
if (aesInfo->aesCtrl.aesIvBLEndian == 1) // iv is big endian
|
||||
{
|
||||
cfgWord0.aesIvBLEndian = 1;
|
||||
}
|
||||
|
||||
cfgWord0.fifoLen = 1; // only 1 descriptor(aes)
|
||||
sctCfgWord->chanCfgWord0.val = cfgWord0.val;
|
||||
|
||||
ret = sctTrigger(sctDescCfgPtr);
|
||||
if (ret != SCTDRV_OK)
|
||||
{
|
||||
return SCTDRV_BUSY;
|
||||
}
|
||||
|
||||
ret = sctPollDone(50000);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// if you need to loop call this api, "lastFlag" should be 0 for intermediate steps, and last step it should be 1.
|
||||
int32_t shaUpdate(shaType_e shaMode, uint32_t srcAddr, uint32_t dstAddr, uint32_t length, uint32_t lastFlag)
|
||||
{
|
||||
uint32_t ret = SCTDRV_OK;
|
||||
|
||||
// sha input should 64bytes aligned, if not, you need to padding it first
|
||||
if ((length & 0x3f) != 0)
|
||||
{
|
||||
return SCTDRV_PAMERR;
|
||||
}
|
||||
|
||||
sctDescCfg_t* sctDescCfgPtr = &sctDescCfg;
|
||||
sctDescCfgPtr->srcAddr = srcAddr; // sha input
|
||||
sctDescCfgPtr->dstAddr = dstAddr; // sha output
|
||||
sctDescCfgPtr->u1.shaField.length = length; // sha input length, should 64bytes aligned
|
||||
sctDescCfgPtr->u1.shaField.subType = 1; // 0: aes; 1:sha
|
||||
sctDescCfgPtr->u1.shaField.shaMode = shaMode;
|
||||
sctDescCfgPtr->u1.shaField.type = 5; // default value 5
|
||||
sctDescCfgPtr->u1.shaField.shaBls = 1; // sha output endian. 0: LE; 1: BE
|
||||
|
||||
if (lastFlag == 0)
|
||||
{
|
||||
sctDescCfgPtr->u1.shaField.rcs = 1; // data is continuous
|
||||
sctDescCfgPtr->u1.shaField.outEn = 0; // not output
|
||||
}
|
||||
else
|
||||
{
|
||||
sctDescCfgPtr->u1.shaField.rcs = 0; // data has been the last sector
|
||||
sctDescCfgPtr->u1.shaField.outEn = 1; // open sha output value
|
||||
}
|
||||
|
||||
sctDescCfgPtr->u3.shaHeadLen.headLen = 0; // no head
|
||||
|
||||
sctCfgWord_t* sctCfgWord = (sctCfgWord_t*)AES_SHA_CH4_CFG_REG;
|
||||
chanCfgWord0_t cfgWord0;
|
||||
cfgWord0.val = 0;
|
||||
cfgWord0.fifoLen = 1; // here only 1 descriptor(sha)
|
||||
sctCfgWord->chanCfgWord0.val = cfgWord0.val;
|
||||
|
||||
ret = sctTrigger(sctDescCfgPtr);
|
||||
if (ret != SCTDRV_OK)
|
||||
{
|
||||
return SCTDRV_BUSY;
|
||||
}
|
||||
|
||||
ret = sctPollDone(50000);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,442 @@
|
||||
#include "usbd_clscdc.h"
|
||||
#include "usbd_clscdc_cust_tp.h"
|
||||
|
||||
//#include "func_dbg.h"
|
||||
#include "string.h"
|
||||
#include "usbd_macro_def.h"
|
||||
#include "usbd_func_cconf.h"
|
||||
#include "usbd_func_cc.h"
|
||||
#include "usbd_multi_usrcfg_common.h"
|
||||
|
||||
|
||||
const usbd_cdc_desc_custp1_st t_usbd_cdc_desc_custp1 = {
|
||||
.intf_ctrl_desc = {
|
||||
/*Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
INVALID_INTF_NUM, //VCOM_INTF_NUM_0, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
},
|
||||
|
||||
.cdc_diep_desc = {
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
INVALID_EP_NUM, //CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
||||
0x00 /* bInterval */
|
||||
},
|
||||
|
||||
.cdc_doep_desc = {
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
INVALID_EP_NUM, //CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
uint8_t vcom_func_custp1_desc_ass(usb_func_ccinst_st *p_func_ccinst)
|
||||
{
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
p_ccinst_cdc_setting->desc_assigned = 0;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
p_ccinst_cdc_setting->p_desc_src = (const uint8_t *)(&t_usbd_cdc_desc_custp1);
|
||||
p_ccinst_cdc_setting->desc_src_size = sizeof(t_usbd_cdc_desc_custp1);
|
||||
|
||||
p_ccinst_cdc_setting->desc_assigned = 1;
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp1_desc_parse(usb_func_ccinst_st *p_func_ccinst)
|
||||
{
|
||||
const uint8_t * p_desc_buf;
|
||||
uint16_t pos = 0;
|
||||
uint8_t ret = usbd_ret_no_err;
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
usb_endpoint_descriptor_st * p_endp_d;
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
if(p_ccinst_cdc_setting->desc_assigned!=1)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
p_desc_buf = p_ccinst_cdc_setting->p_desc_src;
|
||||
|
||||
p_ccinst_cdc_setting->desc_parsed = 0;
|
||||
|
||||
p_ccinst_cdc_setting->epctrl_valid = 0;
|
||||
p_ccinst_cdc_setting->epin_valid = 0;
|
||||
p_ccinst_cdc_setting->epout_valid = 0;
|
||||
|
||||
p_ccinst_cdc_setting->interface_cnt = 0;
|
||||
|
||||
while(pos < p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
if (p_desc_buf[pos] == 0)
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
if ((pos+ p_desc_buf[pos]) > p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (p_desc_buf[pos+1])
|
||||
{
|
||||
case USB_ENDPOINT_DESCRIPTOR_TYPE:
|
||||
if (p_desc_buf[pos] != STANDARD_ENDPOINT_DESC_SIZE)
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
p_endp_d = (usb_endpoint_descriptor_st *)(&(p_desc_buf[pos]));
|
||||
if (p_endp_d->bmAttributes == USBC_CTRL_EP_BULK)
|
||||
{
|
||||
//if (p_endp_d->bEndpointAddress &0x80)
|
||||
|
||||
if (p_endp_d == (&t_usbd_cdc_desc_custp1.cdc_diep_desc))
|
||||
{
|
||||
p_ccinst_cdc_setting->epin_valid = 1;
|
||||
p_ccinst_cdc_setting->p_epin_d = p_endp_d;
|
||||
}
|
||||
else if (p_endp_d == (&t_usbd_cdc_desc_custp1.cdc_doep_desc))
|
||||
{
|
||||
p_ccinst_cdc_setting->epout_valid = 1;
|
||||
p_ccinst_cdc_setting->p_epout_d = p_endp_d;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else if (p_endp_d->bmAttributes == USBC_CTRL_EP_INTR)
|
||||
{
|
||||
if (p_endp_d->bEndpointAddress &0x80)
|
||||
{
|
||||
p_ccinst_cdc_setting->epctrl_valid = 1;
|
||||
p_ccinst_cdc_setting->p_epctrl_d = p_endp_d;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case USB_INTERFACE_DESCRIPTOR_TYPE:
|
||||
if (p_desc_buf[pos] !=STANDARD_INTERFACE_DESC_SIZE)
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
p_ccinst_cdc_setting->interface_cnt++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ret!=usbd_ret_no_err)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos+= p_desc_buf[pos];
|
||||
}
|
||||
|
||||
if ((p_ccinst_cdc_setting->epctrl_valid ==1) ||
|
||||
(p_ccinst_cdc_setting->epin_valid ==0) ||
|
||||
(p_ccinst_cdc_setting->epout_valid==0)||
|
||||
(p_ccinst_cdc_setting->interface_cnt!=1) )
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
}
|
||||
if (ret == 0)
|
||||
{
|
||||
p_ccinst_cdc_setting->desc_parsed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp1_bind(usb_func_ccinst_st *p_func_ccinst,
|
||||
ccinst_bind_call_data_st *p_bind_call_data)
|
||||
{
|
||||
uint8_t ret = usbd_ret_no_err;
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((p_ccinst_cdc_setting->desc_assigned==0)
|
||||
|| (p_ccinst_cdc_setting->desc_parsed==0))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
p_ccinst_cdc_setting->ep_datain_num = p_bind_call_data->ep_datain_num;
|
||||
p_ccinst_cdc_setting->ep_dataout_num = p_bind_call_data->ep_dataout_num;
|
||||
|
||||
p_ccinst_cdc_setting->interface_cnt = p_bind_call_data->interface_cnt;
|
||||
|
||||
p_ccinst_cdc_setting->intf_base_idx = p_bind_call_data->intf_base_idx;
|
||||
p_ccinst_cdc_setting->intf_1st_idx = p_bind_call_data->intf_1st_idx;
|
||||
|
||||
p_ccinst_cdc_setting->intf_str_id = p_bind_call_data->intf_str_id;
|
||||
p_ccinst_cdc_setting->binded = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp1_get_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
|
||||
{
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
usbd_cdc_desc_custp1_st *p_usbd_desc_dst;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
if (p_ccinst_cdc_setting->binded == 0)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
p_usbd_desc_dst = (usbd_cdc_desc_custp1_st *)(p_desc_call_data->p_desc_buff_ptr);
|
||||
|
||||
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
|
||||
|
||||
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
|
||||
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
|
||||
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
|
||||
if (p_desc_call_data->b_intf_ctrl_desc_upd)
|
||||
{
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
|
||||
}
|
||||
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp1_get_othspd_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
|
||||
{
|
||||
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
usbd_cdc_desc_custp1_st *p_usbd_desc_dst;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
if (p_ccinst_cdc_setting->binded == 0)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
p_usbd_desc_dst = (usbd_cdc_desc_custp1_st*)(p_desc_call_data->p_desc_buff_ptr);
|
||||
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
|
||||
|
||||
|
||||
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
|
||||
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
|
||||
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_High = 0;
|
||||
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_Low = 0x40;
|
||||
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_High = 0;
|
||||
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_Low = 0x40;
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
|
||||
if (p_desc_call_data->b_intf_ctrl_desc_upd)
|
||||
{
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
|
||||
}
|
||||
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
|
||||
uint8_t vcom_func_custp1_init(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
|
||||
{
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp1_deinit(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
|
||||
{
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp1_unbind(usb_func_ccinst_st *p_func_ccinst)
|
||||
{
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_ccinst_cdc_setting->binded==0)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
p_ccinst_cdc_setting->binded = 0;
|
||||
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
#if (VCOM_CCINST_SUBTP1_2EP_CNT > 0)
|
||||
const ccinst_setting_base_st t_vcom_custp1_base_setting =
|
||||
{
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp1_2ep
|
||||
};
|
||||
|
||||
ccinst_cdc_setting_st t_vcom_custp1_setting_arr[VCOM_CCINST_SUBTP1_2EP_CNT] ={
|
||||
//[0]
|
||||
{
|
||||
.bs_set = t_vcom_custp1_base_setting,
|
||||
},
|
||||
|
||||
#if (VCOM_CCINST_SUBTP1_2EP_CNT >=2)
|
||||
//[1]
|
||||
|
||||
{
|
||||
.bs_set = t_vcom_custp1_base_setting,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_SUBTP1_2EP_CNT >= 3)
|
||||
//[2]
|
||||
{
|
||||
.bs_set = t_vcom_custp1_base_setting,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
usb_func_ccinst_st t_vcom_func_custp1_arr[VCOM_CCINST_SUBTP1_2EP_CNT] ={
|
||||
//[0]
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp1_setting_arr[0],
|
||||
|
||||
.func_desc_ass = vcom_func_custp1_desc_ass,
|
||||
.func_desc_parse = vcom_func_custp1_desc_parse,
|
||||
.func_bind = vcom_func_custp1_bind,
|
||||
.func_get_desc = vcom_func_custp1_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_custp1_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_custp1_init,
|
||||
.func_deinit = vcom_func_custp1_deinit,
|
||||
.func_unbind = vcom_func_custp1_unbind,
|
||||
},
|
||||
|
||||
#if (VCOM_CCINST_SUBTP1_2EP_CNT >=2)
|
||||
//[1]
|
||||
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp1_setting_arr[1],
|
||||
.func_desc_ass = vcom_func_custp1_desc_ass,
|
||||
.func_desc_parse = vcom_func_custp1_desc_parse,
|
||||
.func_bind = vcom_func_custp1_bind,
|
||||
.func_get_desc = vcom_func_custp1_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_custp1_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_custp1_init,
|
||||
.func_deinit = vcom_func_custp1_deinit,
|
||||
.func_unbind = vcom_func_custp1_unbind,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_SUBTP1_2EP_CNT >= 3)
|
||||
//[2]
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp1_setting_arr[2],
|
||||
|
||||
.func_desc_ass = vcom_func_custp1_desc_ass,
|
||||
.func_desc_parse = vcom_func_custp1_desc_parse,
|
||||
.func_bind = vcom_func_custp1_bind,
|
||||
.func_get_desc = vcom_func_custp1_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_custp1_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_custp1_init,
|
||||
.func_deinit = vcom_func_custp1_deinit,
|
||||
.func_unbind = vcom_func_custp1_unbind,
|
||||
},
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,501 @@
|
||||
#include "usbd_clscdc.h"
|
||||
#include "usbd_clscdc_cust_tp.h"
|
||||
|
||||
//#include "func_dbg.h"
|
||||
#include "string.h"
|
||||
#include "usbd_macro_def.h"
|
||||
#include "usbd_func_cconf.h"
|
||||
#include "usbd_func_cc.h"
|
||||
#include "usbd_multi_usrcfg_common.h"
|
||||
#define CC_CUSTP2_CMDEP_MPS 16
|
||||
|
||||
const usbd_cdc_desc_custp2_st t_usbd_cdc_desc_custp2 = {
|
||||
.intf_ctrl_desc = {
|
||||
/*Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
INVALID_INTF_NUM, //VCOM_INTF_NUM_0, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x03, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
},
|
||||
|
||||
.cdc_head_desc = {
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
},
|
||||
|
||||
.cdc_callmgr_desc = {
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
INVALID_INTF_NUM, /* bDataInterface: 1 */
|
||||
},
|
||||
|
||||
.cdc_acm_desc = {
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
},
|
||||
|
||||
.cdc_union_desc = {
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
INVALID_INTF_NUM,//VCOM_INTF_NUM_0, /* bMasterInterface: Communication class interface */
|
||||
INVALID_INTF_NUM,//VCOM_INTF_NUM_1, /* bSlaveInterface0: Data Class Interface */
|
||||
},
|
||||
|
||||
.cdc_cmd_ep_desc = {
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
INVALID_EP_NUM, //CDC_CMD_EP, /* bEndpointAddress */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
LOBYTE(CC_CUSTP2_CMDEP_MPS), /* wMaxPacketSize: */
|
||||
HIBYTE(CC_CUSTP2_CMDEP_MPS),
|
||||
#ifdef USE_USBC_CTRL_HS
|
||||
0x10, /* bInterval: */
|
||||
#else
|
||||
0xFF, /* bInterval: */
|
||||
#endif /* USE_USBC_CTRL_HS */
|
||||
},
|
||||
|
||||
|
||||
.cdc_diep_desc = {
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
INVALID_EP_NUM, //CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
||||
0x00 /* bInterval */
|
||||
},
|
||||
|
||||
.cdc_doep_desc = {
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
INVALID_EP_NUM, //CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
uint8_t vcom_func_custp2_desc_ass(usb_func_ccinst_st *p_func_ccinst)
|
||||
{
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
p_ccinst_cdc_setting->desc_assigned = 0;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
p_ccinst_cdc_setting->p_desc_src =(const uint8_t *)(&t_usbd_cdc_desc_custp2);
|
||||
p_ccinst_cdc_setting->desc_src_size = sizeof(t_usbd_cdc_desc_custp2);
|
||||
p_ccinst_cdc_setting->desc_assigned = 1;
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp2_desc_parse(usb_func_ccinst_st *p_func_ccinst)
|
||||
{
|
||||
const uint8_t * p_desc_buf;
|
||||
uint16_t pos = 0;
|
||||
uint8_t ret = usbd_ret_no_err;
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
usb_endpoint_descriptor_st * p_endp_d;
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
if(p_ccinst_cdc_setting->desc_assigned!=1)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
p_desc_buf = p_ccinst_cdc_setting->p_desc_src;
|
||||
|
||||
p_ccinst_cdc_setting->desc_parsed = 0;
|
||||
|
||||
p_ccinst_cdc_setting->epctrl_valid = 0;
|
||||
p_ccinst_cdc_setting->epin_valid = 0;
|
||||
p_ccinst_cdc_setting->epout_valid = 0;
|
||||
|
||||
p_ccinst_cdc_setting->interface_cnt = 0;
|
||||
|
||||
while(pos < p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
if (p_desc_buf[pos] == 0)
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
if ((pos+ p_desc_buf[pos]) > p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (p_desc_buf[pos+1])
|
||||
{
|
||||
case USB_ENDPOINT_DESCRIPTOR_TYPE:
|
||||
if (p_desc_buf[pos] != STANDARD_ENDPOINT_DESC_SIZE)
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
p_endp_d = (usb_endpoint_descriptor_st *)(&(p_desc_buf[pos]));
|
||||
if (p_endp_d->bmAttributes == USBC_CTRL_EP_BULK)
|
||||
{
|
||||
//if (p_endp_d->bEndpointAddress &0x80)
|
||||
if (p_endp_d == (&t_usbd_cdc_desc_custp2.cdc_diep_desc))
|
||||
{
|
||||
p_ccinst_cdc_setting->epin_valid = 1;
|
||||
p_ccinst_cdc_setting->p_epin_d = p_endp_d;
|
||||
}
|
||||
else if (p_endp_d == (&t_usbd_cdc_desc_custp2.cdc_doep_desc))
|
||||
{
|
||||
p_ccinst_cdc_setting->epout_valid = 1;
|
||||
p_ccinst_cdc_setting->p_epout_d = p_endp_d;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (p_endp_d->bmAttributes == USBC_CTRL_EP_INTR)
|
||||
{
|
||||
if (p_endp_d->bEndpointAddress &0x80)
|
||||
{
|
||||
p_ccinst_cdc_setting->epctrl_valid = 1;
|
||||
p_ccinst_cdc_setting->p_epctrl_d = p_endp_d;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case USB_INTERFACE_DESCRIPTOR_TYPE:
|
||||
if (p_desc_buf[pos] !=STANDARD_INTERFACE_DESC_SIZE)
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
|
||||
p_ccinst_cdc_setting->interface_cnt++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ret!=usbd_ret_no_err)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos+= p_desc_buf[pos];
|
||||
}
|
||||
|
||||
if ((p_ccinst_cdc_setting->epctrl_valid ==0) ||
|
||||
(p_ccinst_cdc_setting->epin_valid ==0) ||
|
||||
(p_ccinst_cdc_setting->epout_valid==0)||
|
||||
(p_ccinst_cdc_setting->interface_cnt!=1) )
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
}
|
||||
if (ret == 0)
|
||||
{
|
||||
p_ccinst_cdc_setting->desc_parsed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp2_bind(usb_func_ccinst_st *p_func_ccinst,
|
||||
ccinst_bind_call_data_st *p_bind_call_data)
|
||||
{
|
||||
uint8_t ret = usbd_ret_no_err;
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((p_ccinst_cdc_setting->desc_assigned==0)
|
||||
|| (p_ccinst_cdc_setting->desc_parsed==0))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
p_ccinst_cdc_setting->ep_ctrl_num = p_bind_call_data->ep_ctrl_num;
|
||||
p_ccinst_cdc_setting->ep_datain_num = p_bind_call_data->ep_datain_num;
|
||||
p_ccinst_cdc_setting->ep_dataout_num = p_bind_call_data->ep_dataout_num;
|
||||
|
||||
|
||||
p_ccinst_cdc_setting->intf_base_idx = p_bind_call_data->intf_base_idx;
|
||||
p_ccinst_cdc_setting->intf_1st_idx = p_bind_call_data->intf_1st_idx;
|
||||
p_ccinst_cdc_setting->intf_2nd_idx = p_bind_call_data->intf_2nd_idx;
|
||||
p_ccinst_cdc_setting->intf_str_id = p_bind_call_data->intf_str_id;
|
||||
p_ccinst_cdc_setting->binded = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp2_get_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
|
||||
{
|
||||
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
usbd_cdc_desc_custp2_st *p_usbd_desc_dst;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
if (p_ccinst_cdc_setting->binded == 0)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
p_usbd_desc_dst = (usbd_cdc_desc_custp2_st *)(p_desc_call_data->p_desc_buff_ptr);
|
||||
|
||||
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
|
||||
p_usbd_desc_dst->cdc_cmd_ep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_ctrl_num);
|
||||
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
|
||||
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
|
||||
p_usbd_desc_dst->cdc_union_desc.bMasterInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
p_usbd_desc_dst->cdc_union_desc.bSlaveInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
|
||||
if (p_desc_call_data->b_intf_ctrl_desc_upd)
|
||||
{
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
|
||||
}
|
||||
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp2_get_othspd_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
|
||||
{
|
||||
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
usbd_cdc_desc_custp2_st *p_usbd_desc_dst;
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
if (p_ccinst_cdc_setting->binded == 0)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
p_usbd_desc_dst = (usbd_cdc_desc_custp2_st*)(p_desc_call_data->p_desc_buff_ptr);
|
||||
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
|
||||
|
||||
|
||||
p_usbd_desc_dst->cdc_cmd_ep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_ctrl_num);
|
||||
p_usbd_desc_dst->cdc_cmd_ep_desc.bInterval = 0xff;
|
||||
|
||||
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
|
||||
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
|
||||
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_High = 0;
|
||||
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_Low = 0x40;
|
||||
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_High = 0;
|
||||
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_Low = 0x40;
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
p_usbd_desc_dst->cdc_union_desc.bMasterInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
p_usbd_desc_dst->cdc_union_desc.bSlaveInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
|
||||
|
||||
if (p_desc_call_data->b_intf_ctrl_desc_upd)
|
||||
{
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
|
||||
}
|
||||
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t vcom_func_custp2_init(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
|
||||
{
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp2_deinit(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
|
||||
{
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_custp2_unbind(usb_func_ccinst_st *p_func_ccinst)
|
||||
{
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_ccinst_cdc_setting->binded==0)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
p_ccinst_cdc_setting->binded = 0;
|
||||
|
||||
return usbd_ret_no_err;
|
||||
|
||||
}
|
||||
|
||||
#if (VCOM_CCINST_SUBTP2_3EP_CNT > 0)
|
||||
const ccinst_setting_base_st t_vcom_custp2_base_setting =
|
||||
{
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp2_3ep
|
||||
};
|
||||
|
||||
ccinst_cdc_setting_st t_vcom_custp2_setting_arr[VCOM_CCINST_SUBTP2_3EP_CNT] ={
|
||||
//[0]
|
||||
{
|
||||
.bs_set = t_vcom_custp2_base_setting,
|
||||
},
|
||||
|
||||
#if (VCOM_CCINST_SUBTP2_3EP_CNT >=2)
|
||||
//[1]
|
||||
{
|
||||
.bs_set = t_vcom_custp2_base_setting,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_SUBTP2_3EP_CNT >= 3)
|
||||
//[2]
|
||||
{
|
||||
.bs_set = t_vcom_custp2_base_setting,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
usb_func_ccinst_st t_vcom_func_custp2_arr[VCOM_CCINST_SUBTP2_3EP_CNT] ={
|
||||
//[0]
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp2_setting_arr[0],
|
||||
.func_desc_ass = vcom_func_custp2_desc_ass,
|
||||
.func_desc_parse = vcom_func_custp2_desc_parse,
|
||||
.func_bind = vcom_func_custp2_bind,
|
||||
.func_get_desc = vcom_func_custp2_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_custp2_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_custp2_init,
|
||||
.func_deinit = vcom_func_custp2_deinit,
|
||||
.func_unbind = vcom_func_custp2_unbind,
|
||||
},
|
||||
|
||||
#if (VCOM_CCINST_SUBTP2_3EP_CNT >=2)
|
||||
//[1]
|
||||
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp2_setting_arr[1],
|
||||
|
||||
.func_desc_ass = vcom_func_custp2_desc_ass,
|
||||
.func_desc_parse = vcom_func_custp2_desc_parse,
|
||||
.func_bind = vcom_func_custp2_bind,
|
||||
.func_get_desc = vcom_func_custp2_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_custp2_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_custp2_init,
|
||||
.func_deinit = vcom_func_custp2_deinit,
|
||||
.func_unbind = vcom_func_custp2_unbind,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_SUBTP2_3EP_CNT >= 3)
|
||||
//[2]
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp2_setting_arr[2],
|
||||
.func_desc_ass = vcom_func_custp2_desc_ass,
|
||||
.func_desc_parse = vcom_func_custp2_desc_parse,
|
||||
.func_bind = vcom_func_custp2_bind,
|
||||
.func_get_desc = vcom_func_custp2_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_custp2_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_custp2_init,
|
||||
.func_deinit = vcom_func_custp2_deinit,
|
||||
.func_unbind = vcom_func_custp2_unbind,
|
||||
},
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,603 @@
|
||||
#include "usbd_clscdc.h"
|
||||
#include "usbd_clscdc_cust_tp.h"
|
||||
|
||||
#include "string.h"
|
||||
#include "usbd_macro_def.h"
|
||||
#include "usbd_func_cconf.h"
|
||||
#include "usbd_func_cc.h"
|
||||
#include "usbd_multi_usrcfg_common.h"
|
||||
typedef struct tag_usbd_cdc_ccinst_desc_inhrnt usbd_cdc_desc_inhrnt_st;
|
||||
|
||||
#define CC_INHRNT_CMDEP_MPS 16
|
||||
|
||||
|
||||
#define CCINHRNT_SET_LAST_ERR(err_no) usbd_set_mod_last_err(usb_ccinst_inhrnt_mod, err_no)
|
||||
|
||||
|
||||
const usbd_cdc_desc_inhrnt_st t_usbd_cdc_desc_inhrnt = {
|
||||
.intf_asso_desc = {
|
||||
// IAD COM1
|
||||
0x08, // bLength: Interface Descriptor size
|
||||
0x0B, // bDescriptorType: IAD
|
||||
INVALID_INTF_NUM, //VCOM_INTF_NUM_0, bFirstInterface
|
||||
0x02, // bInterfaceCount
|
||||
0x02, // bFunctionClass: CDC
|
||||
0x02, // bFunctionSubClass
|
||||
0x01, // bFunctionProtocol
|
||||
0x02, // iFunction
|
||||
},
|
||||
|
||||
.intf_ctrl_desc = {
|
||||
/*Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
INVALID_INTF_NUM, //VCOM_INTF_NUM_0, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
},
|
||||
|
||||
.cdc_head_desc = {
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
},
|
||||
|
||||
.cdc_callmgr_desc = {
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
INVALID_INTF_NUM, /* bDataInterface: 1 */
|
||||
},
|
||||
|
||||
.cdc_acm_desc = {
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
},
|
||||
|
||||
.cdc_union_desc = {
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
INVALID_INTF_NUM,//VCOM_INTF_NUM_0, /* bMasterInterface: Communication class interface */
|
||||
INVALID_INTF_NUM,//VCOM_INTF_NUM_1, /* bSlaveInterface0: Data Class Interface */
|
||||
},
|
||||
|
||||
.cdc_cmd_ep_desc = {
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
INVALID_EP_NUM, //CDC_CMD_EP, /* bEndpointAddress */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
LOBYTE(CC_INHRNT_CMDEP_MPS), /* wMaxPacketSize: */
|
||||
HIBYTE(CC_INHRNT_CMDEP_MPS),
|
||||
#ifdef USE_USBC_CTRL_HS
|
||||
0x10, /* bInterval: */
|
||||
#else
|
||||
0xFF, /* bInterval: */
|
||||
#endif /* USE_USBC_CTRL_HS */
|
||||
},
|
||||
|
||||
.intf_data_desc = {
|
||||
/*Data class interface descriptor*/
|
||||
0x09, /* bLength: Endpoint Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
|
||||
INVALID_INTF_NUM, //VCOM_INTF_NUM_1, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
0x00, /* bInterfaceSubClass: */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00, /* iInterface: */
|
||||
},
|
||||
|
||||
|
||||
.cdc_diep_desc = {
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
INVALID_EP_NUM, //CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
||||
0x00 /* bInterval */
|
||||
},
|
||||
|
||||
.cdc_doep_desc = {
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
INVALID_EP_NUM, //CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
uint8_t vcom_func_inhrnt_desc_ass(usb_func_ccinst_st *p_func_ccinst)
|
||||
{
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
p_ccinst_cdc_setting->desc_assigned = 0;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
p_ccinst_cdc_setting->p_desc_src =(const uint8_t *)(&t_usbd_cdc_desc_inhrnt);
|
||||
p_ccinst_cdc_setting->desc_src_size = sizeof(t_usbd_cdc_desc_inhrnt);
|
||||
p_ccinst_cdc_setting->desc_assigned = 1;
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_inhrnt_desc_parse(usb_func_ccinst_st *p_func_ccinst)
|
||||
{
|
||||
const uint8_t * p_desc_buf;
|
||||
uint16_t pos = 0;
|
||||
uint8_t ret = usbd_ret_no_err;
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
usb_endpoint_descriptor_st * p_endp_d;
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
|
||||
{
|
||||
CCINHRNT_SET_LAST_ERR(desc_parse_err_tpinvalid);
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
if(p_ccinst_cdc_setting->desc_assigned!=1)
|
||||
{
|
||||
CCINHRNT_SET_LAST_ERR(desc_parse_err_ass0);
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
p_desc_buf = p_ccinst_cdc_setting->p_desc_src;
|
||||
|
||||
p_ccinst_cdc_setting->desc_parsed = 0;
|
||||
|
||||
p_ccinst_cdc_setting->epctrl_valid = 0;
|
||||
p_ccinst_cdc_setting->epin_valid = 0;
|
||||
p_ccinst_cdc_setting->epout_valid = 0;
|
||||
|
||||
p_ccinst_cdc_setting->interface_cnt = 0;
|
||||
|
||||
while(pos < p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
if (p_desc_buf[pos] == 0)
|
||||
{
|
||||
CCINHRNT_SET_LAST_ERR(desc_parse_err_len0);
|
||||
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
if ((pos+ p_desc_buf[pos]) > p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
CCINHRNT_SET_LAST_ERR(desc_parse_err_len_ovf);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (p_desc_buf[pos+1])
|
||||
{
|
||||
case USB_ENDPOINT_DESCRIPTOR_TYPE:
|
||||
if (p_desc_buf[pos] != STANDARD_ENDPOINT_DESC_SIZE)
|
||||
{
|
||||
CCINHRNT_SET_LAST_ERR(desc_parse_err_epdesclen);
|
||||
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
p_endp_d = (usb_endpoint_descriptor_st *)(&(p_desc_buf[pos]));
|
||||
if (p_endp_d->bmAttributes == USBC_CTRL_EP_BULK)
|
||||
{
|
||||
//if (p_endp_d->bEndpointAddress &0x80)
|
||||
if (p_endp_d == (&t_usbd_cdc_desc_inhrnt.cdc_diep_desc))
|
||||
{
|
||||
p_ccinst_cdc_setting->epin_valid = 1;
|
||||
p_ccinst_cdc_setting->p_epin_d = p_endp_d;
|
||||
}
|
||||
else if (p_endp_d == (&t_usbd_cdc_desc_inhrnt.cdc_doep_desc))
|
||||
{
|
||||
p_ccinst_cdc_setting->epout_valid = 1;
|
||||
p_ccinst_cdc_setting->p_epout_d = p_endp_d;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCINHRNT_SET_LAST_ERR(desc_parse_err_epdescptr_1);
|
||||
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (p_endp_d->bmAttributes == USBC_CTRL_EP_INTR)
|
||||
{
|
||||
if (p_endp_d == (&t_usbd_cdc_desc_inhrnt.cdc_cmd_ep_desc))
|
||||
|
||||
{
|
||||
p_ccinst_cdc_setting->epctrl_valid = 1;
|
||||
p_ccinst_cdc_setting->p_epctrl_d = p_endp_d;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
CCINHRNT_SET_LAST_ERR(desc_parse_err_epdescptr_2);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case USB_INTERFACE_DESCRIPTOR_TYPE:
|
||||
if (p_desc_buf[pos] !=STANDARD_INTERFACE_DESC_SIZE)
|
||||
{
|
||||
CCINHRNT_SET_LAST_ERR(desc_parse_err_intfdesclen);
|
||||
|
||||
ret = usbd_ret_fail;
|
||||
break;
|
||||
}
|
||||
|
||||
p_ccinst_cdc_setting->interface_cnt++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ret!=usbd_ret_no_err)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos+= p_desc_buf[pos];
|
||||
}
|
||||
|
||||
if (ret!=usbd_ret_no_err)
|
||||
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if ((p_ccinst_cdc_setting->epctrl_valid ==0) ||
|
||||
(p_ccinst_cdc_setting->epin_valid ==0) ||
|
||||
(p_ccinst_cdc_setting->epout_valid==0)||
|
||||
(p_ccinst_cdc_setting->interface_cnt!=2) )
|
||||
{
|
||||
CCINHRNT_SET_LAST_ERR(desc_parse_err_parserslt);
|
||||
|
||||
ret = usbd_ret_fail;
|
||||
}
|
||||
if (ret == 0)
|
||||
{
|
||||
p_ccinst_cdc_setting->desc_parsed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_inhrnt_bind(usb_func_ccinst_st *p_func_ccinst,
|
||||
ccinst_bind_call_data_st *p_bind_call_data)
|
||||
{
|
||||
uint8_t ret = usbd_ret_no_err;
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((p_ccinst_cdc_setting->desc_assigned==0)
|
||||
|| (p_ccinst_cdc_setting->desc_parsed==0))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
p_ccinst_cdc_setting->ep_ctrl_num = p_bind_call_data->ep_ctrl_num;
|
||||
p_ccinst_cdc_setting->ep_datain_num = p_bind_call_data->ep_datain_num;
|
||||
p_ccinst_cdc_setting->ep_dataout_num = p_bind_call_data->ep_dataout_num;
|
||||
|
||||
|
||||
p_ccinst_cdc_setting->intf_base_idx = p_bind_call_data->intf_base_idx;
|
||||
p_ccinst_cdc_setting->intf_1st_idx = p_bind_call_data->intf_1st_idx;
|
||||
p_ccinst_cdc_setting->intf_2nd_idx = p_bind_call_data->intf_2nd_idx;
|
||||
p_ccinst_cdc_setting->intf_str_id = p_bind_call_data->intf_str_id;
|
||||
|
||||
p_ccinst_cdc_setting->binded = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_inhrnt_get_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
|
||||
{
|
||||
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
usbd_cdc_desc_inhrnt_st *p_usbd_desc_dst;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
if (p_ccinst_cdc_setting->binded == 0)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
p_usbd_desc_dst = (usbd_cdc_desc_inhrnt_st *)(p_desc_call_data->p_desc_buff_ptr);
|
||||
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
|
||||
|
||||
|
||||
p_usbd_desc_dst->cdc_cmd_ep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_ctrl_num);
|
||||
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
|
||||
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
|
||||
|
||||
|
||||
p_usbd_desc_dst->cdc_callmgr_desc.bDataInterface = p_ccinst_cdc_setting->intf_2nd_idx;
|
||||
|
||||
p_usbd_desc_dst->intf_asso_desc.bFirstInterface = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
p_usbd_desc_dst->intf_asso_desc.bInterfaceCount = p_ccinst_cdc_setting->interface_cnt;
|
||||
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
p_usbd_desc_dst->cdc_union_desc.bMasterInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
p_usbd_desc_dst->cdc_union_desc.bSlaveInterface0 = p_ccinst_cdc_setting->intf_2nd_idx;
|
||||
|
||||
p_usbd_desc_dst->intf_data_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_2nd_idx;
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
|
||||
p_usbd_desc_dst->intf_asso_desc.iFunction = p_ccinst_cdc_setting->intf_str_id;
|
||||
|
||||
if (p_desc_call_data->b_intf_ctrl_desc_upd)
|
||||
{
|
||||
p_usbd_desc_dst->intf_asso_desc.bFunctionClass = p_desc_call_data->bInterfaceClass;
|
||||
p_usbd_desc_dst->intf_asso_desc.bFunctionSubClass = p_desc_call_data->bInterfaceSubClass;
|
||||
p_usbd_desc_dst->intf_asso_desc.bFunctionProtocol = p_desc_call_data->bInterfaceProtocol;
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
|
||||
}
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_inhrnt_get_othspd_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
|
||||
{
|
||||
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
usbd_cdc_desc_inhrnt_st *p_usbd_desc_dst;
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
if (p_ccinst_cdc_setting->binded == 0)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
|
||||
p_usbd_desc_dst = (usbd_cdc_desc_inhrnt_st*)(p_desc_call_data->p_desc_buff_ptr);
|
||||
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
|
||||
|
||||
|
||||
p_usbd_desc_dst->cdc_cmd_ep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_ctrl_num);
|
||||
p_usbd_desc_dst->cdc_cmd_ep_desc.bInterval = 0xff;
|
||||
|
||||
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
|
||||
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
|
||||
|
||||
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_High = 0;
|
||||
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_Low = 0x40;
|
||||
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_High = 0;
|
||||
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_Low = 0x40;
|
||||
|
||||
p_usbd_desc_dst->cdc_callmgr_desc.bDataInterface = p_ccinst_cdc_setting->intf_2nd_idx;
|
||||
|
||||
p_usbd_desc_dst->intf_asso_desc.bFirstInterface = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
p_usbd_desc_dst->intf_asso_desc.bInterfaceCount = p_ccinst_cdc_setting->interface_cnt;
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
p_usbd_desc_dst->cdc_union_desc.bMasterInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
|
||||
p_usbd_desc_dst->cdc_union_desc.bSlaveInterface0 = p_ccinst_cdc_setting->intf_2nd_idx;
|
||||
|
||||
p_usbd_desc_dst->intf_data_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_2nd_idx;
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
|
||||
p_usbd_desc_dst->intf_asso_desc.iFunction = p_ccinst_cdc_setting->intf_str_id;
|
||||
|
||||
if (p_desc_call_data->b_intf_ctrl_desc_upd)
|
||||
{
|
||||
p_usbd_desc_dst->intf_asso_desc.bFunctionClass = p_desc_call_data->bInterfaceClass;
|
||||
p_usbd_desc_dst->intf_asso_desc.bFunctionSubClass = p_desc_call_data->bInterfaceSubClass;
|
||||
p_usbd_desc_dst->intf_asso_desc.bFunctionProtocol = p_desc_call_data->bInterfaceProtocol;
|
||||
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
|
||||
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
|
||||
}
|
||||
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t vcom_func_inhrnt_init(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
|
||||
{
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_inhrnt_deinit(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
|
||||
{
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
uint8_t vcom_func_inhrnt_unbind(usb_func_ccinst_st *p_func_ccinst)
|
||||
{
|
||||
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
|
||||
|
||||
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
|
||||
#ifdef VCOM_CHK_CCINST_TYPE
|
||||
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
|
||||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_ccinst_cdc_setting->binded==0)
|
||||
{
|
||||
return usbd_ret_fail;
|
||||
}
|
||||
p_ccinst_cdc_setting->binded = 0;
|
||||
|
||||
|
||||
return usbd_ret_no_err;
|
||||
}
|
||||
|
||||
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT > 0)
|
||||
const ccinst_setting_base_st t_vcom_custp0_base_setting =
|
||||
{
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
};
|
||||
|
||||
ccinst_cdc_setting_st t_vcom_custp0_setting_arr[VCOM_CCINST_SUBTP0_INHERENT_CNT] ={
|
||||
//[0]
|
||||
{
|
||||
.bs_set = t_vcom_custp0_base_setting,
|
||||
},
|
||||
|
||||
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >=2)
|
||||
//[1]
|
||||
{
|
||||
.bs_set = t_vcom_custp0_base_setting,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >= 3)
|
||||
//[2]
|
||||
{
|
||||
.bs_set = t_vcom_custp0_base_setting,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >= 4)
|
||||
//[2]
|
||||
{
|
||||
.bs_set = t_vcom_custp0_base_setting,
|
||||
},
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
usb_func_ccinst_st t_vcom_func_custp0_inhrnt_arr[VCOM_CCINST_SUBTP0_INHERENT_CNT] ={
|
||||
//[0]
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp0_setting_arr[0],
|
||||
.func_desc_ass = vcom_func_inhrnt_desc_ass,
|
||||
.func_desc_parse = vcom_func_inhrnt_desc_parse,
|
||||
.func_bind = vcom_func_inhrnt_bind,
|
||||
.func_get_desc = vcom_func_inhrnt_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_inhrnt_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_inhrnt_init,
|
||||
.func_deinit = vcom_func_inhrnt_deinit,
|
||||
.func_unbind = vcom_func_inhrnt_unbind,
|
||||
},
|
||||
|
||||
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >=2)
|
||||
//[1]
|
||||
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp0_setting_arr[1],
|
||||
|
||||
.func_desc_ass = vcom_func_inhrnt_desc_ass,
|
||||
.func_desc_parse = vcom_func_inhrnt_desc_parse,
|
||||
.func_bind = vcom_func_inhrnt_bind,
|
||||
.func_get_desc = vcom_func_inhrnt_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_inhrnt_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_inhrnt_init,
|
||||
.func_deinit = vcom_func_inhrnt_deinit,
|
||||
.func_unbind = vcom_func_inhrnt_unbind,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >= 3)
|
||||
//[2]
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp0_setting_arr[2],
|
||||
.func_desc_ass = vcom_func_inhrnt_desc_ass,
|
||||
.func_desc_parse = vcom_func_inhrnt_desc_parse,
|
||||
.func_bind = vcom_func_inhrnt_bind,
|
||||
.func_get_desc = vcom_func_inhrnt_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_inhrnt_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_inhrnt_init,
|
||||
.func_deinit = vcom_func_inhrnt_deinit,
|
||||
.func_unbind = vcom_func_inhrnt_unbind,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >= 4)
|
||||
//[3]
|
||||
{
|
||||
.p_cc_setting = &t_vcom_custp0_setting_arr[3],
|
||||
.func_desc_ass = vcom_func_inhrnt_desc_ass,
|
||||
.func_desc_parse = vcom_func_inhrnt_desc_parse,
|
||||
.func_bind = vcom_func_inhrnt_bind,
|
||||
.func_get_desc = vcom_func_inhrnt_get_desc,
|
||||
.func_get_othspd_desc = vcom_func_inhrnt_get_othspd_desc,
|
||||
|
||||
.func_init = vcom_func_inhrnt_init,
|
||||
.func_deinit = vcom_func_inhrnt_deinit,
|
||||
.func_unbind = vcom_func_inhrnt_unbind,
|
||||
},
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
#include "bsp.h"
|
||||
//#include "bsp_custom.h"
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
#include "plat_config.h"
|
||||
#include DEBUG_LOG_HEADER_FILE
|
||||
#endif
|
||||
#include "string.h"
|
||||
|
||||
#include "rndis_protocol.h"
|
||||
#include "usbmst_external.h"
|
||||
|
||||
#define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset))
|
||||
#define CFGBUF ((rndis_config_parameter_t *) INFBUF)
|
||||
#define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset)
|
||||
#define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset)
|
||||
#define PARMVALUELENGTH CFGBUF->ParameterValueLength
|
||||
#define PARM_NAME_LENGTH 25 /* Maximum parameter name length */
|
||||
|
||||
#define MAC_OPT NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \
|
||||
NDIS_MAC_OPTION_RECEIVE_SERIALIZED | \
|
||||
NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | \
|
||||
NDIS_MAC_OPTION_NO_LOOPBACK
|
||||
|
||||
static const char *rndis_vendor = RNDIS_VENDOR;
|
||||
|
||||
|
||||
const uint32_t OIDSupportedList[] =
|
||||
{
|
||||
OID_GEN_SUPPORTED_LIST,
|
||||
OID_GEN_HARDWARE_STATUS,
|
||||
OID_GEN_MEDIA_SUPPORTED,
|
||||
OID_GEN_MEDIA_IN_USE,
|
||||
OID_GEN_MAXIMUM_FRAME_SIZE,
|
||||
OID_GEN_LINK_SPEED,
|
||||
OID_GEN_TRANSMIT_BLOCK_SIZE,
|
||||
OID_GEN_RECEIVE_BLOCK_SIZE,
|
||||
OID_GEN_VENDOR_ID,
|
||||
OID_GEN_VENDOR_DESCRIPTION,
|
||||
OID_GEN_VENDOR_DRIVER_VERSION,
|
||||
OID_GEN_CURRENT_PACKET_FILTER,
|
||||
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
||||
OID_GEN_PROTOCOL_OPTIONS,
|
||||
OID_GEN_MAC_OPTIONS,
|
||||
OID_GEN_MEDIA_CONNECT_STATUS,
|
||||
OID_GEN_MAXIMUM_SEND_PACKETS,
|
||||
OID_802_3_PERMANENT_ADDRESS,
|
||||
OID_802_3_CURRENT_ADDRESS,
|
||||
OID_802_3_MULTICAST_LIST,
|
||||
OID_802_3_MAXIMUM_LIST_SIZE,
|
||||
OID_802_3_MAC_OPTIONS
|
||||
};
|
||||
|
||||
#define OID_LIST_LENGTH (sizeof(OIDSupportedList) / sizeof(*OIDSupportedList))
|
||||
#define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32)
|
||||
|
||||
static const uint8_t station_hwaddr[6] = { RNDIS_HWADDR };
|
||||
static const uint8_t permanent_hwaddr[6] = { RNDIS_HWADDR };
|
||||
extern uint32_t connect_status;
|
||||
|
||||
//used for malloc buffer
|
||||
uint32_t RndisGetEncBufSize(void)
|
||||
{
|
||||
return ENC_BUF_SIZE;
|
||||
}
|
||||
|
||||
void FuncRndisInitNotify(void)
|
||||
{
|
||||
#if (!defined(USB_DRV_SMALL_IMAGE))
|
||||
usbDevNotifyRndisEvent(NOTIFY_MSG_INIT, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FuncRndisHaltNotify(void)
|
||||
{
|
||||
#if (!defined(USB_DRV_SMALL_IMAGE))
|
||||
usbDevNotifyRndisEvent(NOTIFY_MSG_HALT, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FuncRndisResetNotify(void)
|
||||
{
|
||||
#if (!defined(USB_DRV_SMALL_IMAGE))
|
||||
usbDevNotifyRndisEvent(NOTIFY_MSG_RESET, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void RdsProInitalMsgHdl(rndis_generic_msg_t *msgIn)
|
||||
{
|
||||
rndis_initialize_cmplt_t *m;
|
||||
m = ((rndis_initialize_cmplt_t *)msgIn);
|
||||
/* m->MessageID is same as before */
|
||||
m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
|
||||
m->MessageLength = sizeof(rndis_initialize_cmplt_t);
|
||||
m->MajorVersion = RNDIS_MAJOR_VERSION;
|
||||
m->MinorVersion = RNDIS_MINOR_VERSION;
|
||||
m->Status = RNDIS_STATUS_SUCCESS;
|
||||
m->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
|
||||
m->Medium = RNDIS_MEDIUM_802_3;
|
||||
m->MaxPacketsPerTransfer = RNDIS_MAX_PACK_PER_XFER;
|
||||
m->MaxTransferSize = RNDIS_RX_BUFFER_SIZE;
|
||||
m->PacketAlignmentFactor = 0;
|
||||
m->AfListOffset = 0;
|
||||
m->AfListSize = 0;
|
||||
}
|
||||
|
||||
void RdsProQueryCmplt(rndis_query_msg_t *m, int status, const void *data, int size)
|
||||
{
|
||||
rndis_query_cmplt_t *c = (rndis_query_cmplt_t *)m;
|
||||
|
||||
c->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
||||
c->MessageLength = sizeof(rndis_query_cmplt_t) + size;
|
||||
c->InformationBufferLength = size;
|
||||
c->InformationBufferOffset = 16;
|
||||
c->Status = status;
|
||||
memcpy(c + 1, data, size);
|
||||
}
|
||||
|
||||
void RdsProQueryCmplt32(rndis_query_msg_t *m, int status, uint32_t data)
|
||||
{
|
||||
rndis_query_cmplt_t *c = (rndis_query_cmplt_t *)m;
|
||||
|
||||
c->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
||||
c->MessageLength = sizeof(rndis_query_cmplt_t) + 4;
|
||||
c->InformationBufferLength = 4;
|
||||
c->InformationBufferOffset = 16;
|
||||
c->Status = status;
|
||||
*(uint32_t *)(c + 1) = data;
|
||||
}
|
||||
|
||||
void RdsProQueryHdl(rndis_query_msg_t *m, rndis_ctrl_data_st *p_ctrl_data)
|
||||
{
|
||||
switch (m->Oid)
|
||||
{
|
||||
case OID_GEN_SUPPORTED_LIST: RdsProQueryCmplt(m,RNDIS_STATUS_SUCCESS, OIDSupportedList, 4 * OID_LIST_LENGTH); return;
|
||||
case OID_GEN_VENDOR_DRIVER_VERSION: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0x00001000); return;
|
||||
case OID_802_3_CURRENT_ADDRESS: RdsProQueryCmplt(m,RNDIS_STATUS_SUCCESS, &station_hwaddr, 6); return;
|
||||
case OID_802_3_PERMANENT_ADDRESS: RdsProQueryCmplt(m,RNDIS_STATUS_SUCCESS, &permanent_hwaddr, 6); return;
|
||||
case OID_GEN_MEDIA_SUPPORTED: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return;
|
||||
case OID_GEN_MEDIA_IN_USE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return;
|
||||
case OID_GEN_PHYSICAL_MEDIUM: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return;
|
||||
case OID_GEN_HARDWARE_STATUS: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
|
||||
case OID_GEN_LINK_SPEED: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, RNDIS_LINK_SPEED / 100); return;
|
||||
case OID_GEN_VENDOR_ID: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0x00FFFFFF); return;
|
||||
case OID_GEN_VENDOR_DESCRIPTION: RdsProQueryCmplt(m,RNDIS_STATUS_SUCCESS, rndis_vendor, strlen(rndis_vendor) + 1); return;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->oid_packet_filter); return;
|
||||
case OID_GEN_MAXIMUM_FRAME_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, ETH_MAX_PACKET_SIZE - ETH_HEADER_SIZE); return;
|
||||
case OID_GEN_MAXIMUM_TOTAL_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, ETH_MAX_PACKET_SIZE); return;
|
||||
case OID_GEN_TRANSMIT_BLOCK_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, ETH_MAX_PACKET_SIZE); return;
|
||||
case OID_GEN_RECEIVE_BLOCK_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, ETH_MAX_PACKET_SIZE); return;
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, connect_status); return;
|
||||
case OID_GEN_RNDIS_CONFIG_PARAMETER: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
|
||||
case OID_802_3_MAXIMUM_LIST_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 1); return;
|
||||
case OID_802_3_MULTICAST_LIST: RdsProQueryCmplt32(m,RNDIS_STATUS_NOT_SUPPORTED, 0); return;
|
||||
case OID_802_3_MAC_OPTIONS: RdsProQueryCmplt32(m,RNDIS_STATUS_NOT_SUPPORTED, 0); return;
|
||||
case OID_GEN_MAC_OPTIONS: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
|
||||
case OID_802_3_RCV_ERROR_ALIGNMENT: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
|
||||
case OID_802_3_XMIT_ONE_COLLISION: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
|
||||
case OID_802_3_XMIT_MORE_COLLISIONS: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
|
||||
case OID_GEN_XMIT_OK: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->usb_eth_stat.txok); return;
|
||||
case OID_GEN_RCV_OK: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->usb_eth_stat.rxok); return;
|
||||
case OID_GEN_RCV_ERROR: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->usb_eth_stat.rxbad); return;
|
||||
case OID_GEN_XMIT_ERROR: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->usb_eth_stat.txbad); return;
|
||||
case OID_GEN_RCV_NO_BUFFER: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
|
||||
default: RdsProQueryCmplt(m,RNDIS_STATUS_FAILURE, NULL, 0); return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RdsProCfgParaHdl(const char *data, int keyoffset, int valoffset, int keylen, int vallen)
|
||||
{
|
||||
(void)data;
|
||||
(void)keyoffset;
|
||||
(void)valoffset;
|
||||
(void)keylen;
|
||||
(void)vallen;
|
||||
}
|
||||
|
||||
void RdsProPktFilter(uint32_t newfilter)
|
||||
{
|
||||
(void)newfilter;
|
||||
}
|
||||
|
||||
void RdsProSetMsgHdl(rndis_set_msg_t *msgIn, rndis_ctrl_data_st *p_ctrl_data)
|
||||
{
|
||||
rndis_set_cmplt_t *c;
|
||||
rndis_set_msg_t *m;
|
||||
rndis_Oid_t oid;
|
||||
|
||||
c = (rndis_set_cmplt_t *)msgIn;
|
||||
m = (rndis_set_msg_t *)msgIn;
|
||||
|
||||
oid = m->Oid;
|
||||
c->MessageType = REMOTE_NDIS_SET_CMPLT;
|
||||
c->MessageLength = sizeof(rndis_set_cmplt_t);
|
||||
c->Status = RNDIS_STATUS_SUCCESS;
|
||||
|
||||
switch (oid)
|
||||
{
|
||||
case OID_GEN_RNDIS_CONFIG_PARAMETER:
|
||||
{
|
||||
rndis_config_parameter_t *p;
|
||||
char *ptr = (char *)m;
|
||||
ptr += sizeof(rndis_generic_msg_t);
|
||||
ptr += m->InformationBufferOffset;
|
||||
p = (rndis_config_parameter_t *)ptr;
|
||||
RdsProCfgParaHdl(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength);
|
||||
}
|
||||
break;
|
||||
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
p_ctrl_data->oid_packet_filter = *INFBUF;
|
||||
if (p_ctrl_data->oid_packet_filter)
|
||||
{
|
||||
RdsProPktFilter(p_ctrl_data->oid_packet_filter);
|
||||
p_ctrl_data->rndis_state = rndis_data_initialized;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_ctrl_data->rndis_state = rndis_initialized;
|
||||
}
|
||||
break;
|
||||
|
||||
case OID_GEN_CURRENT_LOOKAHEAD:
|
||||
break;
|
||||
|
||||
case OID_GEN_PROTOCOL_OPTIONS:
|
||||
break;
|
||||
|
||||
case OID_802_3_MULTICAST_LIST:
|
||||
break;
|
||||
case OID_PNP_ADD_WAKE_UP_PATTERN:
|
||||
case OID_PNP_REMOVE_WAKE_UP_PATTERN:
|
||||
case OID_PNP_ENABLE_WAKE_UP:
|
||||
default:
|
||||
c->Status = RNDIS_STATUS_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void RdsProResetMsgHdl(rndis_reset_cmplt_t *m, rndis_ctrl_data_st *p_ctrl_data)
|
||||
{
|
||||
p_ctrl_data->rndis_state = rndis_uninitialized;
|
||||
m->MessageType = REMOTE_NDIS_RESET_CMPLT;
|
||||
m->MessageLength = sizeof(rndis_reset_cmplt_t);
|
||||
m->Status = RNDIS_STATUS_SUCCESS;
|
||||
m->AddressingReset = 1;
|
||||
}
|
||||
|
||||
void RdsProKeepAliveMsgHdl(rndis_keepalive_cmplt_t *m, uint32_t RequestId, rndis_ctrl_data_st *p_ctrl_data)
|
||||
{
|
||||
(void)p_ctrl_data;
|
||||
m->RequestId = RequestId;
|
||||
|
||||
m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
|
||||
m->MessageLength = sizeof(rndis_keepalive_cmplt_t);
|
||||
m->Status = RNDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,378 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "usb_portmon.h"
|
||||
#include "apmu_external.h"
|
||||
#include "plat_config.h"
|
||||
#include "string.h"
|
||||
#include "bsp_custom.h"
|
||||
#include "slpman.h"
|
||||
#include "usb_ext_inc.h"
|
||||
|
||||
#include DEBUG_LOG_HEADER_FILE
|
||||
typedef int (*pfn_PadWakeupHook)(uint32_t pad_num);
|
||||
|
||||
|
||||
osEventFlagsId_t vBusEvtFlags = NULL;
|
||||
#define USB_VBUS_EVT_FLAG 1
|
||||
//5 for module AirM2M E3 BOARD vbus pad
|
||||
//#define USB_WKUP_PAD_IDX 5
|
||||
//for module AirM2M E1 BOARD vbus pad
|
||||
uint8_t usb_wkup_pad_idx = 1;
|
||||
#define VBUS_FILTER_MAX_SAMPLE_CNT 10
|
||||
|
||||
extern uint8_t usbstack_clear_ctx_stat(void);
|
||||
extern uint8_t usbstack_ctx_stat_ison(void);
|
||||
extern uint8_t usbstack_ctx_stat_isoff(void);
|
||||
extern uint8_t usbstack_get_ctx_stat(void);
|
||||
extern void usbstack_set_ctx_vbus_mode(uint8_t vbus_mode_en, uint8_t vbus_pad_idx);
|
||||
extern void usbstack_top_var_clear(void);
|
||||
|
||||
extern int RegPadWakeupIntrHook(pfn_PadWakeupHook pfunc);
|
||||
|
||||
|
||||
|
||||
|
||||
extern void BSP_UsbDeInit(void);
|
||||
extern void BSP_UsbInit(void);
|
||||
int usb_portmon_intr_cb(void);
|
||||
int Pad1WakeupHook(void);
|
||||
int PadCmnWakeupHook(uint32_t pad_num);
|
||||
|
||||
void usb_portmon_padcfg(void)
|
||||
{
|
||||
APmuWakeupPadSettings_t wakeupPadSetting;
|
||||
wakeupPadSetting.negEdgeEn = true;
|
||||
wakeupPadSetting.posEdgeEn = true;
|
||||
wakeupPadSetting.pullDownEn = false;
|
||||
wakeupPadSetting.pullUpEn = false;
|
||||
apmuSetWakeupPadCfg(usb_wkup_pad_idx, true, &wakeupPadSetting);
|
||||
}
|
||||
|
||||
uint8_t usb_portmon_wkuppad_level(uint32_t idx);
|
||||
|
||||
uint8_t usb_portmon_vbuspad_level(void)
|
||||
{
|
||||
return usb_portmon_wkuppad_level(usb_wkup_pad_idx);
|
||||
}
|
||||
|
||||
|
||||
#define USB_PORTMON_WAIT_INIT_START 10
|
||||
#define USB_PORTMON_WAIT_FILTER 10
|
||||
#define USB_PORTMON_WAIT_ALWAYS 0xffffffff
|
||||
|
||||
typedef enum
|
||||
{
|
||||
usb_portmon_state_none= 0,
|
||||
usb_portmon_state_filter_reset = 1,
|
||||
usb_portmon_state_filter_sample = 2,
|
||||
usb_portmon_state_trigger = 3,
|
||||
usb_portmon_state_stable = 4,
|
||||
}usb_portmon_state_type;
|
||||
|
||||
uint32_t usb_portmon_stat = usb_portmon_state_none;
|
||||
|
||||
usb_portmon_state_type usb_portmon_getstat(void)
|
||||
{
|
||||
return usb_portmon_stat;
|
||||
}
|
||||
|
||||
void usb_portmon_setstat(usb_portmon_state_type stat)
|
||||
{
|
||||
usb_portmon_stat = stat;
|
||||
}
|
||||
|
||||
uint8_t vbus_val_last = 0;
|
||||
|
||||
int usb_portmon_init(void)
|
||||
{
|
||||
uint32_t ret;
|
||||
usbstack_clear_ctx_stat();
|
||||
vBusEvtFlags = osEventFlagsNew(NULL);
|
||||
if (vBusEvtFlags== NULL)
|
||||
{
|
||||
EC_ASSERT((0), 0, 0, 0);
|
||||
}
|
||||
|
||||
usb_wkup_pad_idx = BSP_UsbGetVBUSWkupPad();
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_init_1, P_WARNING, 1,"usb_wkup_pad_idx %d", usb_wkup_pad_idx);
|
||||
|
||||
if (usb_wkup_pad_idx>WAKEUP_PAD_5)
|
||||
{
|
||||
EC_ASSERT(0, usb_wkup_pad_idx, WAKEUP_PAD_5, 0);
|
||||
}
|
||||
|
||||
usbstack_top_var_clear();
|
||||
usbstack_set_ctx_vbus_mode(1,usb_wkup_pad_idx);
|
||||
|
||||
NVIC_DisableIRQ(PadWakeup0_IRQn+usb_wkup_pad_idx);
|
||||
NVIC_ClearPendingIRQ(PadWakeup0_IRQn+usb_wkup_pad_idx);
|
||||
|
||||
ret = RegPadWakeupIntrHook(PadCmnWakeupHook);
|
||||
EC_ASSERT((ret==0), 0, 0, 0);
|
||||
|
||||
|
||||
usb_portmon_stat = usb_portmon_state_filter_reset;
|
||||
usb_portmon_padcfg();
|
||||
NVIC_EnableIRQ(PadWakeup0_IRQn+usb_wkup_pad_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_portmon_deinit(void){
|
||||
NVIC_DisableIRQ(PadWakeup0_IRQn+usb_wkup_pad_idx);
|
||||
if (vBusEvtFlags !=NULL){
|
||||
osEventFlagsDelete(vBusEvtFlags);
|
||||
vBusEvtFlags = NULL;
|
||||
}
|
||||
usb_portmon_stat = usb_portmon_state_none;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t usbpm_vote_handle = 0xff;
|
||||
|
||||
void usb_portmon_task(void *arg)
|
||||
{
|
||||
uint32_t vbus_evtflag;
|
||||
uint32_t vbus_filter_sample_cnt = 0;
|
||||
uint8_t vbus_val_cur = 0;
|
||||
slpManApplyPlatVoteHandle("usbpm", &usbpm_vote_handle);
|
||||
slpManPlatVoteDisableSleep(usbpm_vote_handle, SLP_SLP2_STATE);
|
||||
|
||||
usb_portmon_init();
|
||||
|
||||
uint32_t usb_portmon_wait = USB_PORTMON_WAIT_ALWAYS;
|
||||
while(1)
|
||||
{
|
||||
switch (usb_portmon_getstat())
|
||||
{
|
||||
case usb_portmon_state_none:
|
||||
usb_portmon_setstat(usb_portmon_state_filter_reset);
|
||||
break;
|
||||
case usb_portmon_state_filter_reset:
|
||||
|
||||
usb_portmon_wait = USB_PORTMON_WAIT_INIT_START;
|
||||
vbus_evtflag = 0;
|
||||
vbus_evtflag = osEventFlagsWait (vBusEvtFlags, USB_VBUS_EVT_FLAG, osFlagsWaitAny, usb_portmon_wait);
|
||||
vbus_val_last = usb_portmon_vbuspad_level();
|
||||
|
||||
//reset vbus fileter sample cnt
|
||||
vbus_filter_sample_cnt = 0;
|
||||
if (vbus_evtflag&USB_VBUS_EVT_FLAG)
|
||||
{
|
||||
//filtered type 3, likely
|
||||
//detect evt in stable state, delay USB_PORTMON_WAIT_FILTER in filter state, detect evt again continuously in USB_PORTMON_WAIT_FILTER
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_1_1, P_WARNING, 2,"filter reset detect evt %x, vbus %d", vbus_evtflag, usb_portmon_vbuspad_level() );
|
||||
}
|
||||
else if (vbus_evtflag == osErrorTimeout)
|
||||
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_1_2, P_WARNING, 2,"filter reset (to) evt %x, vbus %d", vbus_evtflag, usb_portmon_vbuspad_level() );
|
||||
}
|
||||
usb_portmon_setstat(usb_portmon_state_filter_sample);
|
||||
break;
|
||||
case usb_portmon_state_filter_sample:
|
||||
usb_portmon_wait = USB_PORTMON_WAIT_FILTER;
|
||||
vbus_evtflag = 0;
|
||||
vbus_evtflag = osEventFlagsWait (vBusEvtFlags, USB_VBUS_EVT_FLAG, osFlagsWaitAny, usb_portmon_wait);
|
||||
if (vbus_evtflag&USB_VBUS_EVT_FLAG)
|
||||
{
|
||||
//filtered type 3, likely
|
||||
//detect evt in stable state, delay USB_PORTMON_WAIT_FILTER in filter state, detect evt again continuously in USB_PORTMON_WAIT_FILTER
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_1, P_WARNING, 2,"port filtered unstable evt %x, vbus %d", vbus_evtflag, usb_portmon_vbuspad_level() );
|
||||
usb_portmon_setstat(usb_portmon_state_filter_reset);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vbus_evtflag == osErrorTimeout)
|
||||
{
|
||||
vbus_val_cur = usb_portmon_vbuspad_level();
|
||||
|
||||
if (vbus_val_last!=vbus_val_cur)
|
||||
{
|
||||
//unlikely
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_2, P_WARNING, 2,"port vbus filter unstable level vbus last %d,vbus cur = %d", vbus_val_last, vbus_val_cur);
|
||||
usb_portmon_setstat(usb_portmon_state_filter_reset);
|
||||
|
||||
vbus_val_last = vbus_val_cur;
|
||||
break;
|
||||
}
|
||||
|
||||
//anyway update vbus_val_last
|
||||
vbus_val_last = vbus_val_cur;
|
||||
|
||||
//vbus_val_last==vbus_val_cur case
|
||||
//add vbus fileter sample cnt
|
||||
vbus_filter_sample_cnt++;
|
||||
if(vbus_filter_sample_cnt<VBUS_FILTER_MAX_SAMPLE_CNT)
|
||||
{
|
||||
//wait for more sample cnt
|
||||
break;
|
||||
}
|
||||
|
||||
if ((usbstack_ctx_stat_isoff()==1) && (vbus_val_cur ==0))
|
||||
{
|
||||
//filtered type 1, unlikely
|
||||
//detect evt in stable state, delay USB_PORTMON_WAIT_FILTER in filter state, but no pad val change
|
||||
//no trigger for vbus 0 and usb ctx stat is not on
|
||||
usb_portmon_setstat(usb_portmon_state_stable);
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_3, P_WARNING, 1,"port filtered type2(to) invalid vbus, evt %x, vbus 0 ", vbus_evtflag);
|
||||
}
|
||||
else if ((usbstack_ctx_stat_ison()==1) && (vbus_val_cur ==1))
|
||||
{
|
||||
//filtered type 2, unlikely
|
||||
//detect evt in stable state, delay USB_PORTMON_WAIT_FILTER in filter state, but no pad val change
|
||||
//no trigger for vbus 1 and usb ctx stat is on
|
||||
usb_portmon_setstat(usb_portmon_state_stable);
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_4, P_WARNING, 1,"port filtered type3(to) invalid vbus, evt %x ,vbus 1", vbus_evtflag);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if ((usbstack_ctx_stat_isoff()==0) &&(usbstack_ctx_stat_ison()==0))
|
||||
{
|
||||
//anyway pass to trigger state, then cause assert
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_5, P_WARNING, 2,"port vbus trigger warning, ctx stat not valid %x, vbus %d", usbstack_get_ctx_stat(), vbus_val_cur);
|
||||
}
|
||||
|
||||
//most likely
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_6, P_INFO, 2,"port vbus trigger, evt %x ,vbus %d", vbus_evtflag, vbus_val_cur);
|
||||
usb_portmon_setstat(usb_portmon_state_trigger);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case usb_portmon_state_trigger:
|
||||
//check the vbus if it is plug out
|
||||
|
||||
if (vbus_val_cur==0)
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_1, P_WARNING, 0,"BSP_UsbDeInit");
|
||||
BSP_UsbDeInit();
|
||||
if(usbstack_ctx_stat_isoff()==0)
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_2, P_ERROR, 0,"BSP_UsbDeInit, ctx stat not match");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//check the vbus if it is plug in
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_3, P_WARNING, 0,"BSP_UsbInit");
|
||||
|
||||
usblpw_clear_lpusbwkup_src();
|
||||
if (usblpw_retothwk_cur_stg_success()==0)
|
||||
{
|
||||
//all other not succ stag anyway set to terminate
|
||||
usblpw_retothwk_set_terminate_stage();
|
||||
}
|
||||
|
||||
BSP_UsbInit();
|
||||
if(usbstack_ctx_stat_ison()==0)
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_4, P_ERROR, 0,"BSP_UsbInit, ctx stat not match");
|
||||
}
|
||||
}
|
||||
vbus_val_last = usb_portmon_vbuspad_level();
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_5, P_WARNING, 2,"port vbus last %d,vbus cur = %d", vbus_val_last, vbus_val_cur);
|
||||
|
||||
usb_portmon_setstat(usb_portmon_state_stable);
|
||||
break;
|
||||
|
||||
case usb_portmon_state_stable:
|
||||
//vote enable sleep when stable state
|
||||
slpManPlatVoteEnableSleep(usbpm_vote_handle, SLP_SLP2_STATE);
|
||||
usb_portmon_wait = USB_PORTMON_WAIT_ALWAYS;
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_4_1, P_WARNING, 0,"port stable wait evt change");
|
||||
vbus_evtflag = 0;
|
||||
vbus_evtflag = osEventFlagsWait (vBusEvtFlags, USB_VBUS_EVT_FLAG, osFlagsWaitAny|osFlagsNoClear, usb_portmon_wait);
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_4_2, P_WARNING, 1,"port stable detect evt %x", vbus_evtflag);
|
||||
if (vbus_evtflag&USB_VBUS_EVT_FLAG)
|
||||
{
|
||||
usb_portmon_setstat(usb_portmon_state_filter_reset);
|
||||
}
|
||||
|
||||
//vote disable sleep when unstable state
|
||||
slpManPlatVoteDisableSleep(usbpm_vote_handle, SLP_SLP2_STATE);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int usb_portmon_intr_cb(void)
|
||||
{
|
||||
uint32_t wkup_val = usb_portmon_vbuspad_level();
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_intr_cb_1, P_INFO, 1,"wkup_val:0x%x", wkup_val);
|
||||
if (usb_portmon_getstat()>usb_portmon_state_none)
|
||||
{
|
||||
if (vBusEvtFlags)
|
||||
{
|
||||
osEventFlagsSet (vBusEvtFlags, USB_VBUS_EVT_FLAG);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Pad1WakeupHook(void)
|
||||
{
|
||||
return usb_portmon_intr_cb();
|
||||
}
|
||||
|
||||
int Pad5WakeupHook(void)
|
||||
{
|
||||
return usb_portmon_intr_cb();
|
||||
}
|
||||
|
||||
int PadCmnWakeupHook(uint32_t pad_num)
|
||||
{
|
||||
if (pad_num==usb_wkup_pad_idx)
|
||||
{
|
||||
switch (usb_wkup_pad_idx)
|
||||
{
|
||||
case 1:
|
||||
Pad1WakeupHook();
|
||||
break;
|
||||
case 5:
|
||||
Pad5WakeupHook();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (RTE_USB_EN == 1)
|
||||
#define USBPORTON_TASK_STACK_SIZE (1024)
|
||||
static uint8_t usb_portmon_task_stack[USBPORTON_TASK_STACK_SIZE];
|
||||
static StaticTask_t usb_portmon_task_tcb;
|
||||
|
||||
//share task stack_ptr
|
||||
uint8_t *usb_wkmon_portmon_share_stack_ptr(void)
|
||||
{
|
||||
return &(usb_portmon_task_stack[0]);
|
||||
}
|
||||
|
||||
uint32_t usb_wkmon_portmon_share_stack_size(void)
|
||||
{
|
||||
return USBPORTON_TASK_STACK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
void usb_portmon_task_init(void)
|
||||
{
|
||||
osThreadAttr_t task_attr;
|
||||
uint8_t * stack_ptr = usb_wkmon_portmon_share_stack_ptr();
|
||||
uint32_t stack_size = usb_wkmon_portmon_share_stack_size();
|
||||
|
||||
memset(&task_attr,0,sizeof(task_attr));
|
||||
memset(stack_ptr, 0xA5,stack_size);
|
||||
task_attr.name = "usbpm";
|
||||
task_attr.stack_mem = stack_ptr;
|
||||
task_attr.stack_size = stack_size;
|
||||
task_attr.priority = osPriorityNormal;
|
||||
task_attr.cb_mem = &usb_portmon_task_tcb;//task control block
|
||||
task_attr.cb_size = sizeof(StaticTask_t);//size of task control block
|
||||
|
||||
osThreadNew(usb_portmon_task, NULL, &task_attr);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,596 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "usb_wkmon.h"
|
||||
#include "apmu_external.h"
|
||||
#include "plat_config.h"
|
||||
#include "string.h"
|
||||
#include "bsp_custom.h"
|
||||
#include "slpman.h"
|
||||
#include DEBUG_LOG_HEADER_FILE
|
||||
#include "usb_ext_inc.h"
|
||||
#include "task.h"
|
||||
#include "usbd_errinfo.h"
|
||||
//#include "gpr.h"
|
||||
|
||||
#if (USB_WKMON_TASK_EXIST==1)
|
||||
typedef enum
|
||||
{
|
||||
usb_wkmon_state_uninit = 0,
|
||||
usb_wkmon_state_idle = 1,
|
||||
usb_wkmon_state_start,
|
||||
|
||||
usb_wkmon_state_detecting,
|
||||
usb_wkmon_state_actv,
|
||||
usb_wkmon_state_succ ,
|
||||
usb_wkmon_state_terminate,
|
||||
|
||||
}usb_wkmon_state_type;
|
||||
|
||||
uint32_t usb_wkmon_stat = usb_wkmon_state_uninit;
|
||||
|
||||
void usb_wkmon_setstat(usb_wkmon_state_type stat);
|
||||
|
||||
|
||||
osEventFlagsId_t LPUsbWkStatEvtFlags = NULL;
|
||||
osEventFlagsId_t LPUsbWkDetEvtFlags = NULL;
|
||||
|
||||
#define USB_RETWKUP_STAT_EVT_UPD_FLAG (1UL<0)
|
||||
#define USB_RETWKUP_STAT_EVT_START_FLAG (1UL<<1)
|
||||
#define USB_RETWKUP_STAT_EVT_RESET_FLAG (1UL<<2)
|
||||
|
||||
#define USB_RETWKUP_DEV_EVT_UPD_FLAG (1UL<0)
|
||||
#define USB_RETWKUP_DEV_EVT_TRIG_FLAG (1UL<<1)
|
||||
#define USB_RETWKUP_DEV_EVT_RESET_FLAG (1UL<<2)
|
||||
|
||||
typedef int (*pfn_LPUsbWkupHook)(void);
|
||||
extern int RegLPUSBWkupIntrHook(pfn_LPUsbWkupHook pfunc);
|
||||
|
||||
|
||||
int usb_wkmon_intr_cb(void);
|
||||
int USBMonLPWkupIRQHook(void);
|
||||
//#define TEST_LOW_USB_HCLK
|
||||
int usb_wkmon_pre_init(void)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
usb_wkmon_stat = usb_wkmon_state_uninit;
|
||||
|
||||
#ifdef TEST_LOW_USB_HCLK
|
||||
GPR_clockEnable(CLK_HF102M);
|
||||
GPR_setClockSrc(CLK_CC, CLK_CC_SEL_102M);
|
||||
#endif
|
||||
|
||||
LPUsbWkStatEvtFlags = osEventFlagsNew(NULL);
|
||||
if (LPUsbWkStatEvtFlags== NULL)
|
||||
{
|
||||
EC_ASSERT((0), 0, 0, 0);
|
||||
}
|
||||
|
||||
LPUsbWkDetEvtFlags = osEventFlagsNew(NULL);
|
||||
if (LPUsbWkDetEvtFlags== NULL)
|
||||
{
|
||||
EC_ASSERT((0), 0, 0, 0);
|
||||
}
|
||||
|
||||
if (NVIC_GetEnableIRQ(LpusbWakeup_IRQn))
|
||||
{
|
||||
//illegal LpusbWakeup_IRQn before start
|
||||
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
|
||||
}
|
||||
|
||||
ret = RegLPUSBWkupIntrHook(USBMonLPWkupIRQHook);
|
||||
EC_ASSERT((ret==0), 0, 0, 0);
|
||||
usb_wkmon_setstat(usb_wkmon_state_idle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int usb_wkmon_cmmon_clear(void){
|
||||
usblpw_wkmon_ll_enter_ctx_clear();
|
||||
usblpw_wkmon_lpusbwkup_flag_clear();
|
||||
|
||||
#ifdef TEST_LOW_USB_HCLK
|
||||
GPR_clockEnable(CLK_HF102M);
|
||||
|
||||
GPR_setClockSrc(CLK_CC, CLK_CC_SEL_102M);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_wkmon_deinit(void){
|
||||
if (LPUsbWkStatEvtFlags !=NULL){
|
||||
osEventFlagsDelete(LPUsbWkStatEvtFlags);
|
||||
LPUsbWkStatEvtFlags = NULL;
|
||||
}
|
||||
if (LPUsbWkDetEvtFlags !=NULL){
|
||||
osEventFlagsDelete(LPUsbWkDetEvtFlags);
|
||||
LPUsbWkDetEvtFlags = NULL;
|
||||
}
|
||||
|
||||
|
||||
usb_wkmon_setstat(usb_wkmon_state_uninit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_wkmon_hibslp2_stat_evt_start(void)
|
||||
{
|
||||
uint32_t stat_evtflag;
|
||||
uint32_t det_evtflag;
|
||||
if (LPUsbWkDetEvtFlags)
|
||||
{
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
|
||||
osEventFlagsClear(LPUsbWkDetEvtFlags, det_evtflag);
|
||||
|
||||
//any uncleared stat abort
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_UPD_FLAG;
|
||||
osEventFlagsSet (LPUsbWkDetEvtFlags, det_evtflag);
|
||||
}
|
||||
|
||||
if (LPUsbWkStatEvtFlags)
|
||||
{
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_wkmon_slp1_stat_evt_start(void)
|
||||
{
|
||||
uint32_t stat_evtflag;
|
||||
uint32_t det_evtflag;
|
||||
uint32_t irqflag;
|
||||
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_stat_evt_start_1, P_WARNING, 3,"usb_wkmon_stat %d, det evt 0x%x, stat evt 0x%x", usb_wkmon_stat, LPUsbWkDetEvtFlags, LPUsbWkStatEvtFlags);
|
||||
irqflag = SaveAndSetIRQMask();
|
||||
|
||||
switch (usb_wkmon_stat)
|
||||
{
|
||||
case usb_wkmon_state_idle:
|
||||
if (LPUsbWkDetEvtFlags)
|
||||
{
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
|
||||
osEventFlagsClear(LPUsbWkDetEvtFlags, det_evtflag);
|
||||
|
||||
//any uncleared stat abort
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_UPD_FLAG;
|
||||
osEventFlagsSet (LPUsbWkDetEvtFlags, det_evtflag);
|
||||
}
|
||||
|
||||
if (LPUsbWkStatEvtFlags)
|
||||
{
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
}
|
||||
break;
|
||||
|
||||
case usb_wkmon_state_start:
|
||||
//unlikely here, this stat is sleep disabled
|
||||
case usb_wkmon_state_actv:
|
||||
//unlikely , this stat is sleep disabled, deal as all reset
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_stat_evt_start_2, P_WARNING, 0,"usb_wkmon_stat unlikely");
|
||||
|
||||
case usb_wkmon_state_detecting:
|
||||
|
||||
//abort detecting and reset to none
|
||||
if (LPUsbWkDetEvtFlags)
|
||||
{
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
|
||||
osEventFlagsClear(LPUsbWkDetEvtFlags,det_evtflag);
|
||||
|
||||
//any uncleared stat abort
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG;
|
||||
osEventFlagsSet (LPUsbWkDetEvtFlags, det_evtflag);
|
||||
}
|
||||
|
||||
//start
|
||||
if (LPUsbWkStatEvtFlags)
|
||||
{
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
}
|
||||
|
||||
break;
|
||||
case usb_wkmon_state_succ:
|
||||
//start
|
||||
if (LPUsbWkStatEvtFlags)
|
||||
{
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG|USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usb_wkmon_stat);
|
||||
break;
|
||||
}
|
||||
RestoreIRQMask(irqflag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int usb_wkmon_slp1_nothwk_evt_reset(void)
|
||||
{
|
||||
uint32_t stat_evtflag;
|
||||
uint32_t det_evtflag;
|
||||
uint32_t irqflag;
|
||||
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_nothwk_evt_reset_1, P_WARNING, 3,"usb_wkmon_stat %d, det evt 0x%x, stat evt 0x%x", usb_wkmon_stat, LPUsbWkDetEvtFlags, LPUsbWkStatEvtFlags);
|
||||
irqflag = SaveAndSetIRQMask();
|
||||
|
||||
switch (usb_wkmon_stat)
|
||||
{
|
||||
case usb_wkmon_state_uninit:
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_stat_evt_start_uninit, P_WARNING, 0," ");
|
||||
break;
|
||||
case usb_wkmon_state_idle:
|
||||
if (LPUsbWkDetEvtFlags)
|
||||
{
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
|
||||
osEventFlagsClear(LPUsbWkDetEvtFlags, det_evtflag);
|
||||
}
|
||||
|
||||
if (LPUsbWkStatEvtFlags)
|
||||
{
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
}
|
||||
break;
|
||||
|
||||
case usb_wkmon_state_start:
|
||||
//unlikely here, this stat is sleep disabled
|
||||
case usb_wkmon_state_actv:
|
||||
//unlikely , this stat is sleep disabled, deal as all reset
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_stat_evt_start_2, P_WARNING, 0,"usb_wkmon_stat unlikely");
|
||||
|
||||
case usb_wkmon_state_detecting:
|
||||
|
||||
//abort detecting and reset to none
|
||||
if (LPUsbWkDetEvtFlags)
|
||||
{
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
|
||||
osEventFlagsClear(LPUsbWkDetEvtFlags,det_evtflag);
|
||||
|
||||
//any uncleared stat abort
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG;
|
||||
osEventFlagsSet (LPUsbWkDetEvtFlags, det_evtflag);
|
||||
}
|
||||
|
||||
//start
|
||||
if (LPUsbWkStatEvtFlags)
|
||||
{
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG;
|
||||
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
}
|
||||
|
||||
break;
|
||||
case usb_wkmon_state_succ:
|
||||
//start
|
||||
if (LPUsbWkStatEvtFlags)
|
||||
{
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG;
|
||||
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usb_wkmon_stat);
|
||||
break;
|
||||
}
|
||||
RestoreIRQMask(irqflag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
usb_wkmon_state_type usb_wkmon_getstat(void)
|
||||
{
|
||||
return usb_wkmon_stat;
|
||||
}
|
||||
|
||||
void usb_wkmon_setstat(usb_wkmon_state_type stat)
|
||||
{
|
||||
usb_wkmon_stat = stat;
|
||||
}
|
||||
|
||||
void BSP_UsbWkIRQLog(void);
|
||||
//uint8_t BSP_UsbRetOthWkLaterRestOnly(void);
|
||||
|
||||
|
||||
uint8_t usbwkm_vote_handle = 0xff;
|
||||
|
||||
//5ms
|
||||
//#define USBWKM_DET_WAIT_TIME 5
|
||||
uint8_t usblpw_rd_reg_retwkup_ctxstat(void);
|
||||
|
||||
void usb_wkmon_task(void *arg)
|
||||
{
|
||||
uint32_t stat_evtflag;
|
||||
uint32_t det_evtflag;
|
||||
|
||||
uint32_t stat_evt_retval;
|
||||
uint32_t det_evt_retval;
|
||||
|
||||
uint32_t irqflag;
|
||||
|
||||
uint8_t ret;
|
||||
uint8_t stage;
|
||||
usb_wkmon_setstat(usb_wkmon_state_idle);
|
||||
|
||||
slpManApplyPlatVoteHandle("usbwk", &usbwkm_vote_handle);
|
||||
//slpManPlatVoteDisableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
|
||||
while(1)
|
||||
{
|
||||
switch (usb_wkmon_getstat())
|
||||
{
|
||||
case usb_wkmon_state_idle:
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_START_FLAG | USB_RETWKUP_STAT_EVT_UPD_FLAG;
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_0, P_INFO, 0,"start");
|
||||
stat_evt_retval = osEventFlagsWait (LPUsbWkStatEvtFlags, stat_evtflag, osFlagsWaitAny, portMAX_DELAY);
|
||||
stage = usblpw_retothwk_get_cur_stg();
|
||||
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_1, P_INFO, 2,"stage 0x%x, stat_evt_retval:0x%x", stage, stat_evt_retval);
|
||||
|
||||
if (stat_evt_retval&USB_RETWKUP_STAT_EVT_START_FLAG)
|
||||
{
|
||||
if ((usblpw_retothwk_cur_stg_hibslp2_wkmon()==0) &&(usblpw_retothwk_cur_stg_slp1_wkmon()==0))
|
||||
{
|
||||
//only enabled from wkmon is legal
|
||||
//ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_2, P_WARNING, 1,"wkmon stage %d not match", stage);
|
||||
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
|
||||
break;
|
||||
//continue;
|
||||
}
|
||||
|
||||
slpManPlatVoteDisableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
|
||||
usb_wkmon_setstat(usb_wkmon_state_start);
|
||||
break;
|
||||
}
|
||||
else if (stat_evt_retval&0x80000000)
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_3, P_WARNING, 1,"stat_evt_retval err 0x%x", stat_evt_retval);
|
||||
}
|
||||
else
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_4, P_WARNING, 1,"stat_evt_retval no proc 0x%x", stat_evt_retval);
|
||||
}
|
||||
break;
|
||||
case usb_wkmon_state_start:
|
||||
if (NVIC_GetEnableIRQ(LpusbWakeup_IRQn))
|
||||
{
|
||||
//illegal LpusbWakeup_IRQn before start
|
||||
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
|
||||
break;
|
||||
}
|
||||
|
||||
irqflag = SaveAndSetIRQMask();
|
||||
//enable here after the wkup irq hook, otherwise the irq may not clear in irq hook
|
||||
usblpw_enable_lpusbwkup_src();
|
||||
usblpw_wkmon_lpusbwkup_flag_set();
|
||||
usb_wkmon_setstat(usb_wkmon_state_detecting);
|
||||
slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
|
||||
//because no usb drv is active here, so enable
|
||||
slpManDrvVoteSleep(SLP_VOTE_LPUSB, SLP_SLP1_STATE);
|
||||
RestoreIRQMask(irqflag);
|
||||
break;
|
||||
|
||||
case usb_wkmon_state_detecting:
|
||||
det_evt_retval = 0;
|
||||
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG | USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_0_0, P_INFO, 0,"usb_wkmon_state_detecting start");
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_0_1, P_INFO, 1,"ctx stat reg %d", usblpw_rd_reg_retwkup_ctxstat());
|
||||
|
||||
//may sleep here, current is enable sleep default
|
||||
det_evt_retval = osEventFlagsWait (LPUsbWkDetEvtFlags, det_evtflag, osFlagsWaitAny, portMAX_DELAY);
|
||||
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_1, P_INFO, 1,"det_evt_retval:0x%x", det_evt_retval);
|
||||
if (det_evt_retval&USB_RETWKUP_DEV_EVT_TRIG_FLAG)
|
||||
{
|
||||
//tirg stat, sleep is disabled by irq hook
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_2, P_WARNING, 0,"detect evt succ");
|
||||
ret = usblpw_retothwk_wkmon_idle_to_actv_proc();
|
||||
if (ret !=0)
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_3_1, P_WARNING, 0,"usblpw_retothwk_wkmon_idle_to_actv_proc fail");
|
||||
usb_wkmon_setstat(usb_wkmon_state_terminate);
|
||||
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
|
||||
//assert here
|
||||
break;
|
||||
}
|
||||
if (usblpw_retothwk_cur_proc_stat_gpwr_umatch())
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_3_2, P_WARNING, 0,"usblpw_retothwk_wkmon_idle_to_actv_proc more detecting");
|
||||
|
||||
irqflag = SaveAndSetIRQMask();
|
||||
//enable here after the wkup irq hook, otherwise the irq may not clear in irq hook
|
||||
usblpw_enable_lpusbwkup_src();
|
||||
usblpw_wkmon_lpusbwkup_flag_set();
|
||||
usb_wkmon_setstat(usb_wkmon_state_detecting);
|
||||
slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
|
||||
//because no usb drv is active here, so enable
|
||||
slpManDrvVoteSleep(SLP_VOTE_LPUSB, SLP_SLP1_STATE);
|
||||
RestoreIRQMask(irqflag);
|
||||
break;
|
||||
}
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_4, P_WARNING, 0,"usblpw_retothwk_wkmon_idle_to_actv_proc succ");
|
||||
|
||||
usb_wkmon_setstat(usb_wkmon_state_actv);
|
||||
}
|
||||
else if (det_evt_retval&USB_RETWKUP_DEV_EVT_RESET_FLAG)
|
||||
{
|
||||
//must be triggered by sleep1
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_5, P_WARNING, 0,"detecting reset event ");
|
||||
|
||||
//unlikely just wait for next trigger, restart
|
||||
usb_wkmon_setstat(usb_wkmon_state_idle);
|
||||
}
|
||||
else if (det_evt_retval == osErrorTimeout)
|
||||
|
||||
{
|
||||
//slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_6, P_WARNING, 0,"detect (to) ");
|
||||
usb_wkmon_setstat(usb_wkmon_state_detecting);
|
||||
}
|
||||
else
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_7, P_WARNING, 0,"unknown event ");
|
||||
|
||||
//unlikely just wait for next trigger, restart
|
||||
slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
|
||||
usb_wkmon_setstat(usb_wkmon_state_start);
|
||||
}
|
||||
break;
|
||||
|
||||
case usb_wkmon_state_actv:
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_2_0, P_WARNING, 0,"usblpw_retothwk_wkmon_actv_proc start");
|
||||
|
||||
ret = usblpw_retothwk_wkmon_actv_proc();
|
||||
if (ret != 0)
|
||||
{
|
||||
//terminate laterdet or assert
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_2_1, P_WARNING, 0,"usblpw_retothwk_wkmon_actv_proc fail");
|
||||
usb_wkmon_setstat(usb_wkmon_state_terminate);
|
||||
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
|
||||
break;
|
||||
}
|
||||
|
||||
if (usblpw_retothwk_cur_stg_success()==0)
|
||||
{
|
||||
usb_wkmon_setstat(usb_wkmon_state_terminate);
|
||||
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
|
||||
}
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_2_2, P_WARNING, 0,"usblpw_retothwk_wkmon_actv_proc succ");
|
||||
|
||||
usblpw_wkmon_lpusbwkup_flag_clear();
|
||||
usb_wkmon_setstat(usb_wkmon_state_succ);// try next loopo
|
||||
|
||||
break;
|
||||
case usb_wkmon_state_succ:
|
||||
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG;
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_0, P_INFO, 0,"start");
|
||||
|
||||
slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
|
||||
stat_evt_retval = osEventFlagsWait (LPUsbWkStatEvtFlags, stat_evtflag, osFlagsWaitAny, portMAX_DELAY);
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_1, P_INFO, 1,"stat_evt_retval:0x%x", stat_evt_retval);
|
||||
if (stat_evt_retval&USB_RETWKUP_STAT_EVT_RESET_FLAG)
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_2, P_WARNING, 0,"stat_evt_retval reset");
|
||||
usb_wkmon_setstat(usb_wkmon_state_idle);
|
||||
break;
|
||||
}
|
||||
else if (stat_evt_retval&0x80000000)
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_3, P_WARNING, 0,"stat_evt_retval err ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_4, P_WARNING, 0, "stat_evt_retval default proc as reset");
|
||||
usb_wkmon_setstat(usb_wkmon_state_idle);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usb_wkmon_getstat());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BSP_LPUsbWkIRQLog(void)
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_LPUsbWkIRQLog_1, P_VALUE, "othwkup stage %d, proc_stat %d", usblpw_get_retothwk_stage(), usblpw_get_retothwk_proc_stat());
|
||||
}
|
||||
|
||||
|
||||
int usb_wkmon_intr_cb(void)
|
||||
{
|
||||
if ((usblpw_retothwk_cur_stg_hibslp2_wkmon()) || (usblpw_retothwk_cur_stg_slp1_wkmon()))
|
||||
{
|
||||
if (usb_wkmon_getstat()==usb_wkmon_state_detecting)
|
||||
{
|
||||
//the legal wkmon stat is usb_wkmon_state_detecting for dev event
|
||||
osEventFlagsSet (LPUsbWkDetEvtFlags, USB_RETWKUP_DEV_EVT_TRIG_FLAG|USB_RETWKUP_DEV_EVT_UPD_FLAG);
|
||||
NVIC_DisableIRQ(LpusbWakeup_IRQn);
|
||||
slpManPlatVoteDisableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usb_wkmon_intr_cb_1_0, P_VALUE, "usb_wkmon_stat %d not match, no event sent", usb_wkmon_getstat());
|
||||
}
|
||||
|
||||
if (usblpw_wkmon_ll_enter_ctx_get())
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usb_wkmon_intr_cb_1_1, P_VALUE, "chk_abort_ll_inirq, wkmon_lpusbwkup_flag %x", usblpw_wkmon_lpusbwkup_flag_get());
|
||||
|
||||
usblpw_enter_wkmon_chk_abort_ll_inirq();
|
||||
}
|
||||
}
|
||||
else if (usblpw_retothwk_cur_stg_none()==0)
|
||||
{
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usb_wkmon_intr_cb_2, P_VALUE, "unlegal stag");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int USBMonLPWkupIRQHook(void)
|
||||
{
|
||||
BSP_LPUsbWkIRQLog();
|
||||
return usb_wkmon_intr_cb();
|
||||
}
|
||||
|
||||
#define USBWKM_TASK_STACK_SIZE (1024)
|
||||
//#define USB_WKMON_PRIVATE_STACK
|
||||
#ifdef USB_WKMON_PRIVATE_STACK
|
||||
static uint8_t usb_wkmon_task_stack[USBWKM_TASK_STACK_SIZE];
|
||||
static StaticTask_t usb_wkmon_task_tcb;
|
||||
|
||||
uint8_t *usb_wkmon_get_stack_ptr(void)
|
||||
{
|
||||
return &(usb_wkmon_task_stack[0]);
|
||||
}
|
||||
|
||||
uint32_t usb_wkmon_get_stack_size(void)
|
||||
{
|
||||
return USBWKM_TASK_STACK_SIZE;
|
||||
}
|
||||
#else
|
||||
static StaticTask_t usb_wkmon_task_tcb;
|
||||
|
||||
extern uint8_t *usb_wkmon_portmon_share_stack_ptr(void);
|
||||
extern uint32_t usb_wkmon_portmon_share_stack_size(void);
|
||||
|
||||
#endif
|
||||
void usb_wkmon_task_init(void)
|
||||
{
|
||||
osThreadAttr_t task_attr;
|
||||
uint8_t * stack_ptr = usb_wkmon_portmon_share_stack_ptr();
|
||||
uint32_t stack_size = usb_wkmon_portmon_share_stack_size();
|
||||
memset(&task_attr,0,sizeof(task_attr));
|
||||
memset(stack_ptr, 0xA5,stack_size);
|
||||
task_attr.name = "usbwkm";
|
||||
task_attr.stack_mem = stack_ptr;
|
||||
task_attr.stack_size = stack_size;
|
||||
task_attr.priority = osPriorityNormal;
|
||||
task_attr.cb_mem = &usb_wkmon_task_tcb;//task control block
|
||||
task_attr.cb_size = sizeof(StaticTask_t);//size of task control block
|
||||
|
||||
osThreadNew(usb_wkmon_task, NULL, &task_attr);
|
||||
}
|
||||
@@ -0,0 +1,993 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "plat_config.h"
|
||||
#include "string.h"
|
||||
#include "usbd_clscdc.h"
|
||||
#include "usbd_func_cc.h"
|
||||
#include "usbd_multi_usrcfg_common.h"
|
||||
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
#include "plat_config.h"
|
||||
|
||||
#include DEBUG_LOG_HEADER_FILE
|
||||
#endif
|
||||
#include "RTE_Device.h"
|
||||
|
||||
#define USBD_MULTIDEV_LOAD_FAIL 1
|
||||
|
||||
#define EP_REMAP_CUSTOM_CNT 13
|
||||
|
||||
#define CUST_DEF_TEST_TYPE1
|
||||
//#define CUST_DEF_TEST_TYPE3
|
||||
|
||||
//#define USBD_EMC_MAC_CONFIG
|
||||
#ifdef USBD_EMC_MAC_CONFIG
|
||||
|
||||
extern uint8_t *ecm_dev_local_string[1];
|
||||
void update_ecm_mac(void)
|
||||
{
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
ecm_dev_local_string[0] = (uint8_t*)"2089846a96ab";//update the ecm mac here
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT>0)
|
||||
extern usb_func_ccinst_st t_vcom_func_custp0_inhrnt_arr[VCOM_CCINST_SUBTP0_INHERENT_CNT];
|
||||
#endif
|
||||
|
||||
extern usb_func_ccinst_st t_vcom_func_custp1_arr[VCOM_CCINST_SUBTP1_2EP_CNT];
|
||||
extern usb_func_ccinst_st t_vcom_func_custp2_arr[VCOM_CCINST_SUBTP2_3EP_CNT];
|
||||
|
||||
typedef struct {
|
||||
uint8_t vcom_ccinst_subtp0_inhrnt_cnt;
|
||||
uint8_t vcom_ccinst_subtp1_2ep_cnt;
|
||||
uint8_t vcom_ccinst_subtp2_3ep_cnt;
|
||||
usb_func_ccinst_st *p_vcom_ccinst_subtp0_entry;
|
||||
usb_func_ccinst_st *p_vcom_ccinst_subtp1_entry;
|
||||
usb_func_ccinst_st *p_vcom_ccinst_subtp2_entry;
|
||||
|
||||
}usbd_multidev_ccinst_res_st;
|
||||
|
||||
usbd_multidev_ccinst_res_st t_usbd_multidev_ccinst_res =
|
||||
{
|
||||
.vcom_ccinst_subtp0_inhrnt_cnt = VCOM_CCINST_SUBTP0_INHERENT_CNT,
|
||||
.vcom_ccinst_subtp1_2ep_cnt = VCOM_CCINST_SUBTP1_2EP_CNT,
|
||||
.vcom_ccinst_subtp2_3ep_cnt = VCOM_CCINST_SUBTP2_3EP_CNT,
|
||||
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT>0)
|
||||
.p_vcom_ccinst_subtp0_entry = &(t_vcom_func_custp0_inhrnt_arr[0]),
|
||||
#endif
|
||||
#if (VCOM_CCINST_SUBTP1_2EP_CNT >0)
|
||||
.p_vcom_ccinst_subtp1_entry = &(t_vcom_func_custp1_arr[0]),
|
||||
#endif
|
||||
#if (VCOM_CCINST_SUBTP2_3EP_CNT >0)
|
||||
.p_vcom_ccinst_subtp2_entry = &(t_vcom_func_custp2_arr[0]),
|
||||
#endif
|
||||
};
|
||||
//#define CUST_DEF_TEST_TYPE2//change at/log order--ok
|
||||
//#define CUST_DEF_TEST_TYPE3//add a vcom---ok
|
||||
//#define CUST_DEF_TEST_TYPE4//remove a vcom---ok also need to modify dev create/destory
|
||||
//#define CUST_DEF_TEST_TYPE5//remove rndis--ok also need to modify dev create/destory
|
||||
//#define CUST_DEF_TEST_TYPE6//change ep--ok
|
||||
|
||||
|
||||
/*
|
||||
org: if0/1/2/3/4
|
||||
iep =2/4/6/8/10
|
||||
oep=1/2/3/4/5
|
||||
intep=1/2/3/4/5-also in-type
|
||||
|
||||
usr cfg:
|
||||
usb driver still use org epidx, map 2 usr defined ep in below table
|
||||
should make sure no same ep num in below table
|
||||
|
||||
e.g-1. if0 use iep=2 oep=1,intep=1, but user define iep=10, oep=5,intep still 1
|
||||
epin_remap_custom_tbl[2] =10
|
||||
epout_remap_custom_tbl[1]=5
|
||||
epin_remap_custom_tbl[10]=2 //not used but change to another val
|
||||
epout_remap_custom_tbl[5]=1//not used but change to another val
|
||||
|
||||
e.g-2. if0 use iep=2 oep=1,intep=1, if2 use iep=6 oep=3,intep=5. usr want switch if0/2 ep
|
||||
epin_remap_custom_tbl[2] =6
|
||||
epout_remap_custom_tbl[1]=3
|
||||
epin_remap_custom_tbl[6]=2
|
||||
epout_remap_custom_tbl[3]=1
|
||||
|
||||
|
||||
NOTE:
|
||||
1 currently, if enbale rndis, rndis should be at the first interface,
|
||||
if not,rndis enum will have some issue, mostly win host issue, need further debug
|
||||
|
||||
2 after add or remove some if, e.g. remmove PPP vcom or add a raw VCOM, user should also modify
|
||||
ccio dev create logic: not create corresponding dev if removed and create new dev if added.
|
||||
if still not clear ask EC for help
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef CUST_DEF_TEST_TYPE1
|
||||
|
||||
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
|
||||
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
#if ((defined LOW_SPEED_SERVICE_ONLY) || (defined LITE_FEATURE_MODE))
|
||||
|
||||
|
||||
#if (VCOM_CCINST_CASE_SEL==VCOM_CCINST_ORG_CASE)
|
||||
|
||||
static multidev_custom_info_st t_multidev_custom_info = {
|
||||
#ifdef __USER_CODE__
|
||||
.elem_cnt = 4,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"vcom3",
|
||||
multidev_tp_vcom_com,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[2] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
|
||||
.elem_arr[3] =
|
||||
{
|
||||
(const uint8_t*)"vcom2",
|
||||
multidev_tp_vcom_ppp,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
#else
|
||||
.elem_cnt = 2,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
#else
|
||||
|
||||
static multidev_custom_info_st t_multidev_custom_info = {
|
||||
.elem_cnt = 2,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp2_3ep,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp1_2ep,
|
||||
},
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if (VCOM_CCINST_CASE_SEL==VCOM_CCINST_ORG_CASE)
|
||||
static multidev_custom_info_st t_multidev_custom_info = {
|
||||
.elem_cnt = 5,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"rndis",
|
||||
multidev_tp_rndis,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"ecm",
|
||||
multidev_tp_ecm,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
|
||||
.elem_arr[2] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[3] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
|
||||
.elem_arr[4] =
|
||||
{
|
||||
(const uint8_t*)"vcom2",
|
||||
multidev_tp_vcom_ppp,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#if (VCOM_CCINST_CASE_SEL==VCOM_CCINST_CUST_CASE)
|
||||
|
||||
static multidev_custom_info_st t_multidev_custom_info = {
|
||||
.elem_cnt = 5,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"rndis",
|
||||
multidev_tp_rndis,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"ecm",
|
||||
multidev_tp_ecm,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
|
||||
.elem_arr[2] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp2_3ep,
|
||||
},
|
||||
.elem_arr[3] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp1_2ep,
|
||||
},
|
||||
|
||||
.elem_arr[4] =
|
||||
{
|
||||
(const uint8_t*)"vcom2",
|
||||
multidev_tp_vcom_ppp,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp2_3ep,
|
||||
},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CUST_DEF_TEST_TYPE2
|
||||
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
|
||||
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
static multidev_custom_info_st t_multidev_custom_info = {
|
||||
.elem_cnt = 5,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"rndis",
|
||||
multidev_tp_rndis,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"ecm",
|
||||
multidev_tp_ecm,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[2] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[3] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[4] =
|
||||
{
|
||||
(const uint8_t*)"vcom2",
|
||||
multidev_tp_vcom_ppp,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CUST_DEF_TEST_TYPE3
|
||||
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
|
||||
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
static multidev_custom_info_st t_multidev_custom_info = {
|
||||
.elem_cnt = 6,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"rndis",
|
||||
multidev_tp_rndis,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"ecm",
|
||||
multidev_tp_ecm,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[2] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[3] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[4] =
|
||||
{
|
||||
(const uint8_t*)"vcom2",
|
||||
multidev_tp_vcom_ppp,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[5] =
|
||||
{
|
||||
(const uint8_t*)"vcom3",
|
||||
multidev_tp_vcom_com,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CUST_DEF_TEST_TYPE4
|
||||
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
|
||||
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
static multidev_custom_info_st t_multidev_custom_info = {
|
||||
.elem_cnt = 4,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"rndis",
|
||||
multidev_tp_rndis,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"ecm",
|
||||
multidev_tp_ecm,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[2] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[3] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
|
||||
.elem_arr[4] =
|
||||
{
|
||||
NULL,
|
||||
multidev_tp_none,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef CUST_DEF_TEST_TYPE5
|
||||
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
|
||||
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,2,3,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
static multidev_custom_info_st t_multidev_custom_info = {
|
||||
.elem_cnt = 3,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[2] =
|
||||
{
|
||||
(const uint8_t*)"vcom2",
|
||||
multidev_tp_vcom_ppp,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[3] =
|
||||
{
|
||||
NULL,
|
||||
multidev_tp_none,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef CUST_DEF_TEST_TYPE6
|
||||
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 1,6,3,4,5,2,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
|
||||
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
|
||||
0, 3,2,1,4,5,6,7,8,9,10,11,12
|
||||
};
|
||||
|
||||
|
||||
static multidev_custom_info_st t_multidev_custom_info = {
|
||||
.elem_cnt = 5,
|
||||
.elem_arr[0] =
|
||||
{
|
||||
(const uint8_t*)"rndis",
|
||||
multidev_tp_rndis,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[1] =
|
||||
{
|
||||
(const uint8_t*)"ecm",
|
||||
multidev_tp_ecm,
|
||||
ccinst_setting_mainttp_none,
|
||||
ccinst_setting_subtp_none,
|
||||
},
|
||||
.elem_arr[2] =
|
||||
{
|
||||
(const uint8_t*)"vcom0",
|
||||
multidev_tp_vcom_at,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[3] =
|
||||
{
|
||||
(const uint8_t*)"vcom1",
|
||||
multidev_tp_vcom_log,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[4] =
|
||||
{
|
||||
(const uint8_t*)"vcom2",
|
||||
multidev_tp_vcom_ppp,
|
||||
ccinst_setting_cdc_vcom_maintp,
|
||||
ccinst_setting_vcom_subtp0_inhrnt,
|
||||
},
|
||||
.elem_arr[5] =
|
||||
{
|
||||
NULL,
|
||||
multidev_tp_none,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
extern uint32_t usbc_dev_int_handler (void);
|
||||
void USB_IRQ_Handler(void)
|
||||
{
|
||||
#if (RTE_USB_EN == 1)
|
||||
#if MEASURE_USB_INT_TIME
|
||||
extern void TMU_APTimeReadOpen(UINT32 *sysTime);
|
||||
uint32_t startTime, endTime;
|
||||
TMU_APTimeReadOpen(&startTime);
|
||||
#endif
|
||||
usbc_dev_int_handler();
|
||||
#if MEASURE_USB_INT_TIME
|
||||
TMU_APTimeReadOpen(&endTime);
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, USB_IRQ_Handler_0, P_VALUE, "USB IRQ Time=%d", (endTime-startTime)&0x1FFFFFFF);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uint8_t usbcustom_epin_id_map(uint8_t ep_idx)
|
||||
{
|
||||
if (ep_idx > EP_REMAP_CUSTOM_CNT)
|
||||
{
|
||||
return 0xff;
|
||||
}
|
||||
return epin_remap_custom_tbl[ep_idx];
|
||||
}
|
||||
|
||||
uint8_t usbcustom_epout_id_map(uint8_t ep_idx)
|
||||
{
|
||||
if (ep_idx > EP_REMAP_CUSTOM_CNT)
|
||||
{
|
||||
return 0xff;
|
||||
}
|
||||
return epout_remap_custom_tbl[ep_idx];
|
||||
}
|
||||
|
||||
uint8_t usbcustom_multidev_ccinfo_maprst(void)
|
||||
{
|
||||
uint8_t idx;
|
||||
usb_func_ccinst_st * p_ccinst;
|
||||
ccinst_cdc_setting_st *p_ccinst_cdc_set;
|
||||
|
||||
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp0_inhrnt_cnt; idx++)
|
||||
{
|
||||
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp0_entry;
|
||||
if (p_ccinst==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
|
||||
p_ccinst = p_ccinst+idx;
|
||||
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
|
||||
if (p_ccinst_cdc_set==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
p_ccinst_cdc_set->map_flag = 0;
|
||||
}
|
||||
|
||||
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp1_2ep_cnt;idx++)
|
||||
{
|
||||
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp1_entry;
|
||||
if (p_ccinst==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
|
||||
p_ccinst = p_ccinst+idx;
|
||||
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
|
||||
if(p_ccinst_cdc_set==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
p_ccinst_cdc_set->map_flag = 0;
|
||||
}
|
||||
|
||||
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp2_3ep_cnt;idx++)
|
||||
{
|
||||
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp2_entry;
|
||||
if (p_ccinst==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
p_ccinst = p_ccinst+idx;
|
||||
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
|
||||
if(p_ccinst_cdc_set==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
|
||||
p_ccinst_cdc_set->map_flag = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbcustom_multidev_ccinfo_map(usbcust_mdcd_ccinfo_st *p_mdcd_ccinfo)
|
||||
{
|
||||
uint8_t idx;
|
||||
usb_func_ccinst_st * p_ccinst;
|
||||
ccinst_cdc_setting_st *p_ccinst_cdc_set;
|
||||
uint8_t map_valid = 0;
|
||||
if(p_mdcd_ccinfo->setting_maintp == ccinst_setting_cdc_vcom_maintp)
|
||||
{
|
||||
if (p_mdcd_ccinfo->setting_subtp== ccinst_setting_vcom_subtp0_inhrnt)
|
||||
{
|
||||
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp0_inhrnt_cnt;idx++)
|
||||
{
|
||||
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp0_entry;
|
||||
if (p_ccinst==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
p_ccinst = p_ccinst+idx;
|
||||
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
|
||||
if (p_ccinst_cdc_set==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
if (p_ccinst_cdc_set->map_flag ==1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
p_ccinst_cdc_set->map_flag = 1;
|
||||
map_valid = 1;
|
||||
p_mdcd_ccinfo->p_func_ccinst = p_ccinst;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
else if (p_mdcd_ccinfo->setting_subtp== ccinst_setting_vcom_subtp1_2ep)
|
||||
{
|
||||
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp1_2ep_cnt;idx++)
|
||||
{
|
||||
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp1_entry;
|
||||
if (p_ccinst==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
|
||||
p_ccinst = p_ccinst+idx;
|
||||
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
|
||||
if (p_ccinst_cdc_set==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
if (p_ccinst_cdc_set->map_flag ==1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
p_ccinst_cdc_set->map_flag = 1;
|
||||
map_valid = 1;
|
||||
p_mdcd_ccinfo->p_func_ccinst = p_ccinst;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (p_mdcd_ccinfo->setting_subtp== ccinst_setting_vcom_subtp2_3ep)
|
||||
{
|
||||
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp2_3ep_cnt;idx++)
|
||||
{
|
||||
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp2_entry;
|
||||
if (p_ccinst==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
p_ccinst = p_ccinst+idx;
|
||||
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
|
||||
if (p_ccinst_cdc_set==NULL)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
if (p_ccinst_cdc_set->map_flag ==1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
p_ccinst_cdc_set->map_flag = 1;
|
||||
map_valid = 1;
|
||||
p_mdcd_ccinfo->p_func_ccinst = p_ccinst;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//other dev not support ccinst
|
||||
p_mdcd_ccinfo->p_func_ccinst = NULL;
|
||||
map_valid = 1;
|
||||
}
|
||||
|
||||
//load cnt is limited to MULTI_LOAD_CNT_MAX
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usbcustom_multidev_ccinfo_map_1, P_ERROR, 4, \
|
||||
"clstype %d, inst_id %d, maintp %d, subtp %d", \
|
||||
p_mdcd_ccinfo->cls_type, \
|
||||
p_mdcd_ccinfo->inst_id, \
|
||||
p_mdcd_ccinfo->setting_maintp, \
|
||||
p_mdcd_ccinfo->setting_subtp);
|
||||
#endif
|
||||
|
||||
if (map_valid==0)
|
||||
{
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usbcustom_multidev_ccinfo_map_2, P_ERROR, 4, \
|
||||
"clstype %d, inst_id %d, maintp %d, subtp %d", \
|
||||
p_mdcd_ccinfo->cls_type, \
|
||||
p_mdcd_ccinfo->inst_id, \
|
||||
p_mdcd_ccinfo->setting_maintp, \
|
||||
p_mdcd_ccinfo->setting_subtp);
|
||||
EC_ASSERT(0, p_mdcd_ccinfo->cls_type, p_mdcd_ccinfo->inst_id, \
|
||||
(p_mdcd_ccinfo->setting_maintp<<8) |p_mdcd_ccinfo->setting_subtp);
|
||||
#else
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t usbcustom_multidev_cfg_reset(void)
|
||||
{
|
||||
uint8_t loop_idx;
|
||||
uint32_t map_flag = 0;
|
||||
uint32_t cur_flag = 0;
|
||||
uint8_t ret;
|
||||
if (epout_remap_custom_tbl[0]!=0)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
for (loop_idx = 1; loop_idx < EP_REMAP_CUSTOM_CNT; loop_idx++)
|
||||
{
|
||||
if (epout_remap_custom_tbl[loop_idx] >= EP_REMAP_CUSTOM_CNT)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
cur_flag = (1UL<<epout_remap_custom_tbl[loop_idx]);
|
||||
if (cur_flag&map_flag)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
map_flag |= (1UL<<epout_remap_custom_tbl[loop_idx]);
|
||||
}
|
||||
ret = usbcustom_multidev_ccinfo_maprst();
|
||||
|
||||
if(ret)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
#ifdef USBD_EMC_MAC_CONFIG
|
||||
update_ecm_mac();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
multidev_custom_info_st* usbcustom_multidev_cfg_update(void)
|
||||
{
|
||||
return &t_multidev_custom_info;
|
||||
}
|
||||
|
||||
uint8_t usbcustom_multidev_cfg_end(multidev_load_info_st *p_multidev_load)
|
||||
{
|
||||
if ((p_multidev_load->load_cnt+ p_multidev_load->filter_cnt ) != t_multidev_custom_info.elem_cnt)
|
||||
{
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
|
||||
if (p_multidev_load->load_cnt > MULTI_DEV_LOADCNT_MAX)
|
||||
{
|
||||
//load cnt is limited to MULTI_LOAD_CNT_MAX
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
ECOMM_TRACE(UNILOG_PLA_DRIVER, usbcustom_multidev_cfg_end_1, P_ERROR, 1,"p_multidev_load->load_cnt %x", p_multidev_load->load_cnt);
|
||||
#endif
|
||||
return USBD_MULTIDEV_LOAD_FAIL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *usbcustom_multidev_strdesc(usbcust_mdcd_strdesc_st *p_mdcd_strdesc)
|
||||
{
|
||||
uint8_t* p_intf_str_desc = (uint8_t*)"default";
|
||||
switch(p_mdcd_strdesc->cls_type)
|
||||
{
|
||||
case multidev_tp_rndis:
|
||||
p_intf_str_desc = (uint8_t*)"rndis";
|
||||
break;
|
||||
case multidev_tp_ecm:
|
||||
p_intf_str_desc = (uint8_t*)"ecm";
|
||||
break;
|
||||
case multidev_tp_vcom_at:
|
||||
p_intf_str_desc = (uint8_t*)"at";
|
||||
break;
|
||||
case multidev_tp_vcom_log:
|
||||
p_intf_str_desc = (uint8_t*)"log";
|
||||
break;
|
||||
case multidev_tp_vcom_ppp:
|
||||
p_intf_str_desc = (uint8_t*)"ppp";
|
||||
break;
|
||||
case multidev_tp_vcom_com:
|
||||
p_intf_str_desc = (uint8_t*)"com";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidevstr_desc_1, P_DEBUG, \
|
||||
"cls_type %d, inst_id 0x%x, name %s, intf string %s", \
|
||||
p_mdcd_strdesc->cls_type, \
|
||||
p_mdcd_strdesc->inst_id, \
|
||||
p_mdcd_strdesc->p_func_name, \
|
||||
p_intf_str_desc);
|
||||
|
||||
#endif
|
||||
return p_intf_str_desc;
|
||||
}
|
||||
|
||||
uint8_t usbcustom_multidev_cmndesc(usbcust_mdcd_cmndesc_st *p_mdcd_cmndesc)
|
||||
{
|
||||
|
||||
usbcust_cmndesc_data_st *p_cmndesc_data= &(p_mdcd_cmndesc->t_cmndesc_data);
|
||||
|
||||
switch(p_mdcd_cmndesc->cls_type)
|
||||
{
|
||||
case multidev_tp_rndis:
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass = 0xE0;
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass = 0x01;
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol = 0x03;
|
||||
p_cmndesc_data->b_intf_ctrl_desc_upd = 1;
|
||||
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidev_cmndesc_1, P_DEBUG, \
|
||||
"name %s, cls = 0x%x, subcls 0x%x, protocol 0x%x", \
|
||||
p_mdcd_cmndesc->p_func_name, \
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass, \
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass, \
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol);
|
||||
#endif
|
||||
break;
|
||||
case multidev_tp_ecm:
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass = 0x02;
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass = 0x06;
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol = 0x00;
|
||||
p_cmndesc_data->b_intf_ctrl_desc_upd = 1;
|
||||
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidev_cmndesc_1, P_DEBUG, \
|
||||
"name %s, cls = 0x%x, subcls 0x%x, protocol 0x%x", \
|
||||
p_mdcd_cmndesc->p_func_name, \
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass, \
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass, \
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol);
|
||||
#endif
|
||||
break;
|
||||
case multidev_tp_vcom_at:
|
||||
case multidev_tp_vcom_log:
|
||||
case multidev_tp_vcom_ppp:
|
||||
case multidev_tp_vcom_com:
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass = 0x02;
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass = 0x02;
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol = 0x01;
|
||||
p_cmndesc_data->b_intf_ctrl_desc_upd = 1;
|
||||
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidev_cmndesc_1, P_DEBUG, \
|
||||
"name %s, cls = 0x%x, subcls 0x%x, protocol 0x%x", \
|
||||
p_mdcd_cmndesc->p_func_name, \
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass, \
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass, \
|
||||
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol);
|
||||
#endif
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbcustom_multidev_ctrl_proc(usbcust_md_ctrl_st* p_usbcust_md_ctrl)
|
||||
{
|
||||
// t_ctl_req.cmd Bit 31 : 0 host to dev, 1 dev to host
|
||||
|
||||
#ifndef USB_DRV_SMALL_IMAGE
|
||||
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidev_ctrl_proc_1, P_DEBUG, \
|
||||
"cls_type = %d, inst_id %d, name %s, req 0x%x", \
|
||||
p_usbcust_md_ctrl->cls_type, \
|
||||
p_usbcust_md_ctrl->inst_id, \
|
||||
p_usbcust_md_ctrl->p_func_name, \
|
||||
p_usbcust_md_ctrl->t_ctl_req.cmd);
|
||||
#if 0
|
||||
ECPLAT_DUMP(UNILOG_PLA_DRIVER, usbcustom_multidev_ctrl_proc_2, P_DEBUG, \
|
||||
"clsdev req data:", \
|
||||
p_usbcust_md_ctrl->t_ctl_req.len, \
|
||||
p_usbcust_md_ctrl->t_ctl_req.buf);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __USER_CODE__
|
||||
extern void usb_ctrl_pre_proc(usbcust_md_ctrl_st *);
|
||||
usb_ctrl_pre_proc(p_usbcust_md_ctrl);
|
||||
#endif
|
||||
p_usbcust_md_ctrl->t_ctl_req.cmd &= (~(0x1UL<<31));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\fn usblpw_innophy_enh_drv_strenth(void)
|
||||
\brief used by USB driver, called when USBC init.
|
||||
user could modify the para below for differnt use cases
|
||||
\note cfg usb phy para for none standard usb cable,e.g. fly wire in production line
|
||||
0x4d0b0030: Enables pre-emphasis----should keep default val set below
|
||||
0x4d0b0040: b[5:3] Tx HS pre_emphasize strength configure, 3b111 represents the
|
||||
strongest , 3b000 the weakest
|
||||
0x4d0b0064: b[6:3] Rx squelch trigger point configures
|
||||
0x4d0b0124: b[4:2] HS eye height tuning
|
||||
if any problem ,contact EC
|
||||
|
||||
*/
|
||||
void usblpw_innophy_enh_drv_strenth(void)
|
||||
{
|
||||
volatile uint32_t* addr = (volatile uint32_t*)0x4d0b0030;
|
||||
* addr = (* addr &~ (0x7<<0)) | (0x5<<0);
|
||||
|
||||
addr = (volatile uint32_t*)0x4d0b0040;
|
||||
* addr = (* addr &~ (0x7<<3)) | (0x4<<3);
|
||||
|
||||
addr = (volatile uint32_t*)0x4d0b0064;
|
||||
* addr = (* addr &~ (0xf<<3)) | (0x6<<3);
|
||||
|
||||
addr = (volatile uint32_t*)0x4d0b0124;
|
||||
* addr = (* addr &~ (0x7<<2)) | (0x5<<2);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
#include <stdio.h>
|
||||
#include "usbd_multi_clstype.h"
|
||||
|
||||
|
||||
#define USB_DEV_QUALIFIER_DESC_ARR_SIZE 0x0A
|
||||
|
||||
|
||||
#define DEF_LANGID_STR 0x409
|
||||
#define DEF_MANUFACT_STR "AirM2M";
|
||||
#define DEF_PRODUCT_HS_STR "AirM2M Compo";
|
||||
#define DEF_SER_NUM_HS_STR "000000000001"
|
||||
|
||||
#define DEF_CFG_HS_STR "Compo Config"
|
||||
#define DEF_INTF_HS_STR "Compo Interface"
|
||||
|
||||
|
||||
#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
|
||||
#define USB_STRING_DESCRIPTOR_TYPE 0x03
|
||||
#define USB_SIZ_STRING_LANGID 4
|
||||
#define USB_SIZ_DEVICE_DESC 0x12
|
||||
|
||||
#define LOBYTE(x) ((uint8_t)(x & 0x00FF))
|
||||
#define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8))
|
||||
|
||||
|
||||
#define USB_DESC_TYPE_DEVICE 1
|
||||
#define USB_DESC_TYPE_CONFIGURATION 2
|
||||
#define USB_DESC_TYPE_STRING 3
|
||||
#define USB_DESC_TYPE_INTERFACE 4
|
||||
#define USB_DESC_TYPE_ENDPOINT 5
|
||||
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
|
||||
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
|
||||
|
||||
|
||||
uint32_t udev_last_err = 0;
|
||||
|
||||
|
||||
|
||||
uint8_t usbd_dev_desc_arr[USB_SIZ_DEVICE_DESC] =
|
||||
{
|
||||
0x12, /* bLength */
|
||||
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
0x00,
|
||||
0x02, /* bcdUSB = 2.00 */
|
||||
0xEF, /* bDeviceClass: IAD */
|
||||
0x02, /* bDeviceSubClass */
|
||||
0x01, /* bDeviceProtocol */
|
||||
|
||||
0x40, /* bMaxPacketSize0 */
|
||||
|
||||
0xd1,
|
||||
0x19, /* idVendor = 0x19d1 */
|
||||
0x01,
|
||||
0x00, /* idProduct = 0x0001 */
|
||||
|
||||
0x00,
|
||||
0x02, /* bcdDevice = 2.00 */
|
||||
1, /* Index of string descriptor describing manufacturer */
|
||||
2, /* Index of string descriptor describing product */
|
||||
3, /* Index of string descriptor describing the device's serial number */
|
||||
0x01 /* bNumConfigurations */
|
||||
};
|
||||
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
uint8_t usbd_dev_qualifier_desc_arr[USB_DEV_QUALIFIER_DESC_ARR_SIZE] =
|
||||
{
|
||||
USB_DEV_QUALIFIER_DESC_ARR_SIZE,
|
||||
USB_DESC_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0xEF,
|
||||
0x02,
|
||||
0x01,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
};
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
uint8_t usbd_dev_langid_desc[USB_SIZ_STRING_LANGID] =
|
||||
{
|
||||
USB_SIZ_STRING_LANGID,
|
||||
USB_DESC_TYPE_STRING,
|
||||
LOBYTE(DEF_LANGID_STR),
|
||||
HIBYTE(DEF_LANGID_STR),
|
||||
};
|
||||
|
||||
uint8_t *usbcustom_product_str_desc(void)
|
||||
{
|
||||
return (uint8_t *)DEF_PRODUCT_HS_STR;
|
||||
}
|
||||
|
||||
uint8_t *usbcustom_manufacture_str_desc(void)
|
||||
{
|
||||
return (uint8_t *)DEF_MANUFACT_STR;
|
||||
}
|
||||
|
||||
uint8_t *usbcustom_ser_str_desc(void)
|
||||
{
|
||||
return (uint8_t *)DEF_SER_NUM_HS_STR;
|
||||
}
|
||||
|
||||
uint8_t *usbcustom_cfg_str_desc(void)
|
||||
{
|
||||
return (uint8_t *)DEF_CFG_HS_STR;
|
||||
}
|
||||
|
||||
uint8_t *usbcustom_intf_str_desc(void)
|
||||
{
|
||||
return (uint8_t *)DEF_INTF_HS_STR;
|
||||
}
|
||||
|
||||
uint8_t *usbcustom_qulifier_desc(void)
|
||||
{
|
||||
return usbd_dev_qualifier_desc_arr;
|
||||
}
|
||||
|
||||
uint8_t usbcustom_cfg_remote_wkup_bit(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t usbcustom_cfg_self_powered_bit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbcustom_cfg_max_power(void)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
void udev_notify_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void udev_notify_device_reset (uint8_t speed)
|
||||
{
|
||||
}
|
||||
|
||||
void udev_notify_device_config (void)
|
||||
{
|
||||
}
|
||||
|
||||
void udev_notify_device_suspend(void)
|
||||
{
|
||||
}
|
||||
|
||||
void udev_notify_device_resume(void)
|
||||
{
|
||||
}
|
||||
|
||||
void udev_notify_device_connect (void)
|
||||
{
|
||||
}
|
||||
|
||||
void udev_notify_device_disconnect (void)
|
||||
{
|
||||
}
|
||||
|
||||
void udev_set_last_err(uint32_t err_no)
|
||||
{
|
||||
udev_last_err = err_no;
|
||||
}
|
||||
|
||||
|
||||
uint32_t udev_get_last_err(void)
|
||||
{
|
||||
return udev_last_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
#include "string.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "hal_misc.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "usb_bl_api.h"
|
||||
|
||||
int vcomx_isconnect(uint8_t vcom_num);
|
||||
int vcomx_get_in_waiting(uint8_t vcom_num);
|
||||
int vcomx_poll_rx(uint8_t vcom_num, uint32_t timeout);
|
||||
int vcomx_recv(uint8_t vcom_num, uint8_t* buf, uint16_t len);
|
||||
int vcomx_get_out_avail(uint8_t vcom_num);
|
||||
int vcomx_poll_tx(uint8_t vcom_num, uint32_t timeout);
|
||||
int vcomx_send(uint8_t vcom_num, uint8_t* buf, uint16_t len);
|
||||
|
||||
|
||||
#ifdef VCOM_DBGEN
|
||||
void vcom_dbg_putchar(uint8_t ch);
|
||||
|
||||
void vcomdbg_hex(uint32_t hex)
|
||||
{
|
||||
uint16_t val;
|
||||
for (int32_t idx = 28; idx >=0; idx-=4)
|
||||
{
|
||||
val = ((hex>>idx)&0xf) + 0x30;
|
||||
if(val>=0x3a)
|
||||
{
|
||||
val = val + 0x27;
|
||||
}
|
||||
vcom_dbg_putchar(val);
|
||||
}
|
||||
}
|
||||
|
||||
void vcomdbg_str(uint8_t* str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
vcom_dbg_putchar(*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
void vcomdbg_str_and_hex(uint8_t* str, uint32_t hex)
|
||||
{
|
||||
vcomdbg_str(str);
|
||||
//vcomdbg_str((uint8_t*)"\r\n");
|
||||
vcomdbg_hex(hex);
|
||||
vcomdbg_str((uint8_t*)"\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void vcom_app_delay(uint32_t ticks)
|
||||
{
|
||||
volatile int us_cnt = 0;
|
||||
volatile int loop_in_us;
|
||||
//depend on code speed, add 6 for flash code at 50M, cpu 204m
|
||||
for (us_cnt = 0; us_cnt < ticks*1000; us_cnt+=6){
|
||||
loop_in_us = 0;
|
||||
while(loop_in_us++< 70);
|
||||
}
|
||||
}
|
||||
|
||||
int vcom_app_recv_proc(uint8_t vcom_num, uint8_t* rcvbuf_ptr, uint32_t size, uint8_t timeout)
|
||||
{
|
||||
int rxwait_cnt;
|
||||
int poll_stat;
|
||||
uint8_t recvd_size = 0;
|
||||
int byte_cnt = 0;
|
||||
uint32_t ticks_tmout = timeout; // 1tick for 1ms
|
||||
uint32_t ticks_elapsed = 0;
|
||||
uint32_t ticks_step = 1;
|
||||
|
||||
if (size ==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (vcomx_isconnect(vcom_num) <=0)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom[%d] not connected%x \r\n", vcom_num);
|
||||
return ERR_DEV_NO_CONNECT;
|
||||
}
|
||||
|
||||
//rxwait_cnt = p_serial_vcom->p_ops->get_in_waiting(p_serial_vcom);
|
||||
rxwait_cnt = vcomx_get_in_waiting(vcom_num);
|
||||
if (rxwait_cnt <0)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("get_in_waiting err %d \r\n", rxwait_cnt);
|
||||
return rxwait_cnt;
|
||||
}
|
||||
if (rxwait_cnt ==0)
|
||||
{
|
||||
if (ticks_elapsed >=ticks_tmout)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("recv timeout, recved bytes %d \r\n", recvd_size);
|
||||
return recvd_size;
|
||||
}
|
||||
|
||||
//poll_stat = p_serial_vcom->p_ops->poll_rx(p_serial_vcom, 0);
|
||||
poll_stat =vcomx_poll_rx(vcom_num, 0);
|
||||
if ((poll_stat <0) && (poll_stat!=ERR_DEV_RX_TIMOUT))
|
||||
{
|
||||
VCDBG_STR_AND_HEX("recv poll state break %d \r\n", poll_stat);
|
||||
return poll_stat;
|
||||
}
|
||||
vcom_app_delay(ticks_step);
|
||||
ticks_elapsed += ticks_step;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rxwait_cnt> size)
|
||||
{
|
||||
rxwait_cnt = size;
|
||||
}
|
||||
|
||||
//byte_cnt = p_serial_vcom->p_ops->recv(p_serial_vcom, rcvbuf_ptr, rxwait_cnt);
|
||||
byte_cnt = vcomx_recv(vcom_num, rcvbuf_ptr, rxwait_cnt);
|
||||
if (byte_cnt < 0)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("recv state break %d \r\n", byte_cnt);
|
||||
return byte_cnt;
|
||||
}
|
||||
|
||||
recvd_size += byte_cnt;
|
||||
if (recvd_size>=size)
|
||||
{
|
||||
return recvd_size;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vcom_app_send_proc(uint8_t vcom_num, uint8_t* sndbuf_ptr, uint32_t size, uint8_t timeout)
|
||||
{
|
||||
int txavail_cnt;
|
||||
int poll_stat;
|
||||
int byte_cnt;
|
||||
uint8_t sended_size = 0;
|
||||
uint32_t ticks_tmout = timeout; // 1tick for 1ms
|
||||
uint32_t ticks_elapsed = 0;
|
||||
uint32_t ticks_step = 1;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (vcomx_isconnect(vcom_num) <= 0)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom[%d] not connected \r\n", vcom_num);
|
||||
return ERR_DEV_NO_CONNECT;
|
||||
}
|
||||
|
||||
//txavail_cnt = p_serial_vcom->p_ops->get_out_avail(p_serial_vcom);
|
||||
txavail_cnt = vcomx_get_out_avail(vcom_num);
|
||||
if (txavail_cnt == 0)
|
||||
{
|
||||
if (ticks_elapsed >=ticks_tmout)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom[%d] \r\n", vcom_num);
|
||||
VCDBG_STR_AND_HEX("send timeout, sended bytes %x \r\n", sended_size);
|
||||
return sended_size;
|
||||
}
|
||||
//poll_stat = p_serial_vcom->p_ops->poll_tx(p_serial_vcom, 0);
|
||||
poll_stat = vcomx_poll_tx(vcom_num, 0);
|
||||
if ((poll_stat <0) && (poll_stat!=ERR_DEV_RX_TIMOUT))
|
||||
{
|
||||
VCDBG_STR_AND_HEX("send poll state break %d \r\n", poll_stat);
|
||||
return poll_stat;
|
||||
}
|
||||
|
||||
vcom_app_delay(ticks_step);
|
||||
ticks_elapsed += ticks_step;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (size < txavail_cnt)
|
||||
{
|
||||
txavail_cnt = size;
|
||||
}
|
||||
|
||||
//byte_cnt = p_serial_vcom->p_ops->send(p_serial_vcom, sndbuf_ptr, txavail_cnt);
|
||||
byte_cnt = vcomx_send(vcom_num, sndbuf_ptr, txavail_cnt);
|
||||
if (byte_cnt <0)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("send state break %d \r\n", byte_cnt);
|
||||
return byte_cnt;
|
||||
}
|
||||
|
||||
sended_size +=byte_cnt;
|
||||
if (sended_size>=size)
|
||||
{
|
||||
return sended_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,378 @@
|
||||
#include "ec618.h"
|
||||
#include "string.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "hal_misc.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "bl_bsp.h"
|
||||
#include "usb_bl_api.h"
|
||||
|
||||
int vcomx_isconnect(uint8_t vcom_num);
|
||||
int vcomx_get_in_waiting(uint8_t vcom_num);
|
||||
int vcomx_poll_rx(uint8_t vcom_num, uint32_t timeout);
|
||||
int vcomx_recv(uint8_t vcom_num, uint8_t* buf, uint16_t len);
|
||||
int vcomx_get_out_avail(uint8_t vcom_num);
|
||||
int vcomx_poll_tx(uint8_t vcom_num, uint32_t timeout);
|
||||
int vcomx_send(uint8_t vcom_num, uint8_t* buf, uint16_t len);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
vcom_step_idle = 0,
|
||||
vcom_step_recv ,
|
||||
vcom_step_send ,
|
||||
vcom_step_busy_sending ,
|
||||
|
||||
}vcom_app_step_type;
|
||||
|
||||
#define VCOM_STATE_IDLE 0
|
||||
#define VCOM_TEST_BUF_SIZE 0x400
|
||||
typedef struct
|
||||
{
|
||||
//uint8_t recv_en;
|
||||
//uint8_t send_en;
|
||||
vcom_app_step_type step;
|
||||
uint32_t received_len;
|
||||
uint32_t sended_len;
|
||||
uint8_t vcom_rcvbuff[VCOM_TEST_BUF_SIZE];
|
||||
uint8_t vcom_sndbuff[VCOM_TEST_BUF_SIZE];
|
||||
}vcom_app_ctx_st;
|
||||
|
||||
#define VCOM_NUM_MAX 3
|
||||
vcom_app_ctx_st vcom_app_ctx[VCOM_NUM_MAX];
|
||||
|
||||
void vcom_app_ctx_init(void)
|
||||
{
|
||||
memset(&vcom_app_ctx, 0, sizeof(vcom_app_ctx));
|
||||
}
|
||||
|
||||
int vcom_app_ctx_is_idlestep(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return -1;
|
||||
}
|
||||
if(vcom_app_ctx[vcom_num].step == vcom_step_idle)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t vcom_app_ctx_is_recvstep(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return 0;
|
||||
}
|
||||
if(vcom_app_ctx[vcom_num].step == vcom_step_recv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t vcom_app_ctx_is_sendstep(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return 0;
|
||||
}
|
||||
if(vcom_app_ctx[vcom_num].step == vcom_step_send)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t vcom_app_ctx_is_busysending(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return 0;
|
||||
}
|
||||
if(vcom_app_ctx[vcom_num].step == vcom_step_busy_sending)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vcom_app_ctx_set_step(uint8_t vcom_num, vcom_app_step_type step)
|
||||
{
|
||||
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return;
|
||||
}
|
||||
vcom_app_ctx[vcom_num].step = step;
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
int vcom_app_get_rcvbuff_size(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return -1;
|
||||
}
|
||||
return sizeof(vcom_app_ctx[vcom_num].vcom_rcvbuff);
|
||||
}
|
||||
|
||||
uint8_t* vcom_app_get_rcvbuff_ptr(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return NULL;
|
||||
}
|
||||
return &(vcom_app_ctx[vcom_num].vcom_rcvbuff[0]);
|
||||
}
|
||||
|
||||
int vcom_app_get_sndbuff_size(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return -1;
|
||||
}
|
||||
return sizeof(vcom_app_ctx[vcom_num].vcom_sndbuff);
|
||||
}
|
||||
|
||||
uint8_t* vcom_app_get_sndbuff_ptr(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return NULL;
|
||||
}
|
||||
return &(vcom_app_ctx[vcom_num].vcom_sndbuff[0]);
|
||||
}
|
||||
|
||||
int vcom_app_update_recved_size(uint8_t vcom_num, uint32_t size)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return -1;
|
||||
}
|
||||
vcom_app_ctx[vcom_num].received_len = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vcom_app_update_sended_size(uint8_t vcom_num, uint32_t size)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return -1;
|
||||
}
|
||||
vcom_app_ctx[vcom_num].sended_len = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vcom_app_get_recved_size(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return -1;
|
||||
}
|
||||
return vcom_app_ctx[vcom_num].received_len;
|
||||
}
|
||||
|
||||
int vcom_app_get_sended_size(uint8_t vcom_num)
|
||||
{
|
||||
if (vcom_num>=VCOM_NUM_MAX)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
|
||||
return -1;
|
||||
}
|
||||
return vcom_app_ctx[vcom_num].sended_len;
|
||||
}
|
||||
|
||||
int vcom_app_send_proc(uint8_t vcom_num, uint8_t* sndbuf_ptr, uint32_t size, uint8_t timeout);
|
||||
int vcom_app_recv_proc(uint8_t vcom_num, uint8_t* rcvbuf_ptr, uint32_t size, uint8_t timeout);
|
||||
void vcom_app_delay(uint32_t ticks);
|
||||
|
||||
void vcom_loopback_test(void *p)
|
||||
{
|
||||
int ret;
|
||||
int txavail_cnt;
|
||||
//#if DEVICE_VCOM_INSTANCE
|
||||
uint32_t sended_size;
|
||||
uint8_t * send_buf_ptr;
|
||||
uint8_t * recv_buf_ptr;
|
||||
|
||||
vcom_app_ctx_init();
|
||||
int vcom_num = 0;
|
||||
VCDBG_STR("uart_loopback_test start \r\n");
|
||||
|
||||
while(1)
|
||||
{
|
||||
vcom_app_delay(10);
|
||||
vcom_num = vcom_num+1;
|
||||
vcom_num = vcom_num%VCOM_NUM_MAX;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (vcomx_isconnect(vcom_num) ==0)
|
||||
{
|
||||
vcom_app_delay(1000);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vcom_app_ctx_is_idlestep(vcom_num)==1)
|
||||
{
|
||||
|
||||
if (vcomx_isconnect(vcom_num) ==0)
|
||||
{
|
||||
vcom_app_delay(20);
|
||||
break;
|
||||
}
|
||||
|
||||
vcom_app_ctx_set_step(vcom_num, vcom_step_recv);
|
||||
VCDBG_STR_AND_HEX("vcom(%d) [recv] \r\n", vcom_num);
|
||||
}
|
||||
|
||||
if (vcom_app_ctx_is_recvstep(vcom_num)==1)
|
||||
{
|
||||
ret= vcom_app_recv_proc(vcom_num,
|
||||
vcom_app_get_rcvbuff_ptr(vcom_num),
|
||||
vcom_app_get_rcvbuff_size(vcom_num), 1);
|
||||
if (ret <=0)
|
||||
{
|
||||
vcom_app_delay(1);
|
||||
break;
|
||||
}
|
||||
vcom_app_update_recved_size(vcom_num, ret);
|
||||
vcom_app_update_sended_size(vcom_num, 0);
|
||||
vcom_app_ctx_set_step(vcom_num, vcom_step_send);
|
||||
|
||||
VCDBG_STR_AND_HEX("vcom(%d) [recv] ->[send] \r\n", vcom_num);
|
||||
VCDBG_STR_AND_HEX("ret %d \r\n",ret);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (vcom_app_ctx_is_sendstep(vcom_num)==1)
|
||||
{
|
||||
if (vcom_app_get_recved_size(vcom_num) <0)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom(%d) [send] recved_size <0, ->[idle] \r\n", vcom_num);
|
||||
vcom_app_ctx_set_step(vcom_num, vcom_step_idle);
|
||||
vcom_app_update_recved_size(vcom_num, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
sended_size = vcom_app_get_sended_size(vcom_num);
|
||||
recv_buf_ptr= vcom_app_get_rcvbuff_ptr(vcom_num);
|
||||
send_buf_ptr = vcom_app_get_rcvbuff_ptr(vcom_num);
|
||||
if (sended_size >=vcom_app_get_recved_size(vcom_num))
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom(%d) [send] unneeded->[idle]", vcom_num);
|
||||
VCDBG_STR_AND_HEX("recved %d\r\n",
|
||||
vcom_app_get_recved_size(vcom_num));
|
||||
VCDBG_STR_AND_HEX("sended %d\r\n",
|
||||
vcom_app_get_sended_size(vcom_num));
|
||||
break;
|
||||
}
|
||||
|
||||
txavail_cnt = vcom_app_get_sndbuff_size(vcom_num);
|
||||
if ((txavail_cnt+sended_size) > vcom_app_get_recved_size(vcom_num))
|
||||
{
|
||||
txavail_cnt = vcom_app_get_recved_size(vcom_num) - sended_size;
|
||||
}
|
||||
memcpy(send_buf_ptr+sended_size, recv_buf_ptr+sended_size, txavail_cnt);
|
||||
|
||||
ret = vcom_app_send_proc(vcom_num, send_buf_ptr+sended_size, txavail_cnt, 1);
|
||||
if (ret <0)
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom(%d) [send] , ->[idle] \r\n", vcom_num);
|
||||
VCDBG_STR_AND_HEX("fail %08x %d\r\n",ret);
|
||||
vcom_app_ctx_set_step(vcom_num, vcom_step_idle);
|
||||
vcom_app_update_recved_size(vcom_num, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
sended_size+=ret;
|
||||
|
||||
|
||||
vcom_app_update_sended_size(vcom_num, ret);
|
||||
|
||||
if (sended_size >=vcom_app_get_recved_size(vcom_num))
|
||||
{
|
||||
VCDBG_STR_AND_HEX("vcom(%d) [send] ->[idle] finish \r\n", vcom_num);
|
||||
VCDBG_STR_AND_HEX("recved %d \r\n", vcom_app_get_recved_size(vcom_num));
|
||||
VCDBG_STR_AND_HEX("sended %d \r\n", vcom_app_get_sended_size(vcom_num));
|
||||
|
||||
vcom_app_ctx_set_step(vcom_num, vcom_step_idle);
|
||||
vcom_app_update_recved_size(vcom_num, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
vcom_app_ctx_set_step(vcom_num, vcom_step_busy_sending);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (vcom_app_ctx_is_busysending(vcom_num)==1)
|
||||
{
|
||||
vcom_app_delay(1);
|
||||
vcom_app_ctx_set_step(vcom_num, vcom_step_send);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VCDBG_STR("uart_loopback_test end \r\n");
|
||||
}
|
||||
|
||||
void vcom_urcprint_test(void)
|
||||
{
|
||||
uint8_t vcom_num = 0;
|
||||
int cnt = 0;
|
||||
while(cnt++<2000)
|
||||
{
|
||||
vcom_app_delay(10);
|
||||
vcom_num = vcom_num+1;
|
||||
vcom_num = vcom_num%VCOM_NUM_MAX;
|
||||
|
||||
SelNormalOrURCPrint(1);
|
||||
BSP_URCSetCfg(1, 115200, URCVCom0PrintType+vcom_num, vcom_num);
|
||||
printf("URC PRINT %d\r\n", vcom_num);
|
||||
|
||||
SelNormalOrURCPrint(0);
|
||||
printf("NO URC PRINT\r\n");
|
||||
|
||||
}
|
||||
}
|
||||
uint32_t BSP_UsbInit(void);
|
||||
void WDT_stop(void);
|
||||
void vcom_app_delay(uint32_t ticks);
|
||||
|
||||
void vcom_urc_test_entry(void)
|
||||
{
|
||||
WDT_stop();// stop watchdog for test
|
||||
extern uint8_t usbstack_clear_ctx_stat(void);
|
||||
extern void usbstack_set_ctx_vbus_mode(uint8_t vbus_mode_en, uint8_t vbus_pad_idx);
|
||||
|
||||
usbstack_clear_ctx_stat();
|
||||
usbstack_set_ctx_vbus_mode(0,0xf);
|
||||
BSP_UsbInit();
|
||||
|
||||
extern void vcom_urcprint_test(void);
|
||||
vcom_urcprint_test();
|
||||
|
||||
void vcom_loopback_test(void *p);
|
||||
vcom_loopback_test(NULL);
|
||||
while(1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
|
||||
* File name: wdt.c
|
||||
* Description: EC618 wdt driver source file
|
||||
* History: Rev1.0 2018-07-18
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "wdt.h"
|
||||
#include "clock.h"
|
||||
#include "slpman.h"
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
|
||||
/** \brief Internal used data structure */
|
||||
typedef struct _wdt_database
|
||||
{
|
||||
bool isInited; /**< whether wdt has been initialized */
|
||||
bool wdtStartStatus; /**< wdt enable status, used for low power restore */
|
||||
WdtConfig_t wdtConfig; /**< wdt configuration, used for low power restore */
|
||||
} WdtDatabase_t;
|
||||
|
||||
static WdtDatabase_t gWdtDataBase = {0};
|
||||
|
||||
/**
|
||||
\fn static void WDT_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
\brief Perform necessary preparations before sleep
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
*/
|
||||
static void WDT_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
if(gWdtDataBase.isInited == true)
|
||||
{
|
||||
gWdtDataBase.wdtStartStatus = WDT_getStartStatus();
|
||||
//disable clock
|
||||
CLOCK_clockDisable(PCLK_WDG);
|
||||
CLOCK_clockDisable(FCLK_WDG);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
\fn static void WDT_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
\brief Restore after exit from sleep
|
||||
\param[in] pdata pointer to user data, not used now
|
||||
\param[in] state low power state
|
||||
|
||||
*/
|
||||
static void WDT_exitLowPowerStateRestore(void* pdata, slpManLpState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case SLPMAN_SLEEP1_STATE:
|
||||
|
||||
if(gWdtDataBase.isInited == true)
|
||||
{
|
||||
//enable clock
|
||||
CLOCK_clockEnable(PCLK_WDG);
|
||||
CLOCK_clockEnable(FCLK_WDG);
|
||||
|
||||
WDT_unlock();
|
||||
WDT->CTRL = (WDT->CTRL &~ WDT_CTRL_MODE_Msk) | EIGEN_VAL2FLD(WDT_CTRL_MODE, gWdtDataBase.wdtConfig.mode);
|
||||
WDT_unlock();
|
||||
WDT->TOVR = gWdtDataBase.wdtConfig.timeoutValue;
|
||||
|
||||
if(gWdtDataBase.wdtStartStatus)
|
||||
WDT_start();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void WDT_unlock(void)
|
||||
{
|
||||
WDT->LOCK = 0xABABU;
|
||||
}
|
||||
|
||||
void WDT_kick(void)
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
WDT_unlock();
|
||||
WDT->CCR = WDT_CCR_CNT_CLR_Msk;
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
|
||||
void WDT_getDefaultConfig(WdtConfig_t *config)
|
||||
{
|
||||
ASSERT(config);
|
||||
|
||||
config->mode = WDT_INTERRUPT_ONLY_MODE;
|
||||
config->timeoutValue = 0xFFFFU;
|
||||
}
|
||||
|
||||
void WDT_init(const WdtConfig_t *config)
|
||||
{
|
||||
ASSERT(config);
|
||||
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
|
||||
if(gWdtDataBase.isInited == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_WDT_MODULE, WDT_enterLowPowerStatePrepare, NULL);
|
||||
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_WDT_MODULE, WDT_exitLowPowerStateRestore, NULL);
|
||||
|
||||
gWdtDataBase.isInited = true;
|
||||
gWdtDataBase.wdtConfig = *config;
|
||||
|
||||
#endif
|
||||
|
||||
//enable clock
|
||||
CLOCK_clockEnable(PCLK_WDG);
|
||||
CLOCK_clockEnable(FCLK_WDG);
|
||||
|
||||
|
||||
WDT_unlock();
|
||||
WDT->CTRL = (WDT->CTRL &~ WDT_CTRL_MODE_Msk) | EIGEN_VAL2FLD(WDT_CTRL_MODE, config->mode);
|
||||
WDT_unlock();
|
||||
WDT->TOVR = config->timeoutValue;
|
||||
}
|
||||
|
||||
void WDT_deInit(void)
|
||||
{
|
||||
#ifdef PM_FEATURE_ENABLE
|
||||
|
||||
if(gWdtDataBase.isInited == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_WDT_MODULE);
|
||||
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_WDT_MODULE);
|
||||
|
||||
gWdtDataBase.isInited = false;
|
||||
#endif
|
||||
|
||||
//disable clock
|
||||
CLOCK_clockDisable(PCLK_WDG);
|
||||
CLOCK_clockDisable(FCLK_WDG);
|
||||
|
||||
}
|
||||
|
||||
void WDT_start(void)
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
WDT_unlock();
|
||||
WDT->CTRL |= WDT_CTRL_ENABLE_Msk;
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
}
|
||||
|
||||
void WDT_stop(void)
|
||||
{
|
||||
uint32_t mask = SaveAndSetIRQMask();
|
||||
|
||||
WDT_unlock();
|
||||
WDT->CTRL &= ~WDT_CTRL_ENABLE_Msk;
|
||||
|
||||
RestoreIRQMask(mask);
|
||||
|
||||
}
|
||||
|
||||
uint32_t WDT_getInterruptFlags(void)
|
||||
{
|
||||
return WDT->STAT & WDT_STAT_ISTAT_Msk;
|
||||
}
|
||||
|
||||
void WDTclearInterruptFlags(uint32_t mask)
|
||||
{
|
||||
uint32_t msk = SaveAndSetIRQMask();
|
||||
|
||||
WDT_unlock();
|
||||
WDT->ICR = WDT_ICR_ICLR_Msk;
|
||||
|
||||
RestoreIRQMask(msk);
|
||||
}
|
||||
|
||||
WdtMode_e WDT_getMode(void)
|
||||
{
|
||||
return (WdtMode_e)EIGEN_FLD2VAL(WDT_CTRL_MODE, WDT->CTRL);
|
||||
}
|
||||
|
||||
bool WDT_getStartStatus(void)
|
||||
{
|
||||
return (bool)EIGEN_FLD2VAL(WDT_CTRL_ENABLE, WDT->CTRL);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
#include <stdbool.h>
|
||||
bool LPUSART_IsRxActive(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LPUSART_ClearStopFlag(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LPUSART_SetStopFlag(void)
|
||||
{
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2013 ARM Ltd
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the company may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This memcpy routine is optimised for Cortex-M3/M4 cores with/without
|
||||
unaligned access.
|
||||
|
||||
If compiled with GCC, this file should be enclosed within following
|
||||
pre-processing check:
|
||||
if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
|
||||
|
||||
Prototype: void *memcpy (void *dst, const void *src, size_t count);
|
||||
|
||||
The job will be done in 5 steps.
|
||||
Step 1: Align src/dest pointers, copy mis-aligned if fail to align both
|
||||
Step 2: Repeatedly copy big block size of __OPT_BIG_BLOCK_SIZE
|
||||
Step 3: Repeatedly copy big block size of __OPT_MID_BLOCK_SIZE
|
||||
Step 4: Copy word by word
|
||||
Step 5: Copy byte-to-byte
|
||||
|
||||
Tunable options:
|
||||
__OPT_BIG_BLOCK_SIZE: Size of big block in words. Default to 64.
|
||||
__OPT_MID_BLOCK_SIZE: Size of big block in words. Default to 16.
|
||||
*/
|
||||
#ifndef __OPT_BIG_BLOCK_SIZE
|
||||
#define __OPT_BIG_BLOCK_SIZE (4 * 16)
|
||||
#endif
|
||||
|
||||
#ifndef __OPT_MID_BLOCK_SIZE
|
||||
#define __OPT_MID_BLOCK_SIZE (4 * 4)
|
||||
#endif
|
||||
|
||||
#if __OPT_BIG_BLOCK_SIZE == 16
|
||||
#define BEGIN_UNROLL_BIG_BLOCK \
|
||||
.irp offset, 0,4,8,12
|
||||
#elif __OPT_BIG_BLOCK_SIZE == 32
|
||||
#define BEGIN_UNROLL_BIG_BLOCK \
|
||||
.irp offset, 0,4,8,12,16,20,24,28
|
||||
#elif __OPT_BIG_BLOCK_SIZE == 64
|
||||
#define BEGIN_UNROLL_BIG_BLOCK \
|
||||
.irp offset, 0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60
|
||||
#else
|
||||
#error "Illegal __OPT_BIG_BLOCK_SIZE"
|
||||
#endif
|
||||
|
||||
#if __OPT_MID_BLOCK_SIZE == 8
|
||||
#define BEGIN_UNROLL_MID_BLOCK \
|
||||
.irp offset, 0,4
|
||||
#elif __OPT_MID_BLOCK_SIZE == 16
|
||||
#define BEGIN_UNROLL_MID_BLOCK \
|
||||
.irp offset, 0,4,8,12
|
||||
#else
|
||||
#error "Illegal __OPT_MID_BLOCK_SIZE"
|
||||
#endif
|
||||
|
||||
#define END_UNROLL .endr
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
.align 2
|
||||
.global memcpy
|
||||
.thumb
|
||||
.thumb_func
|
||||
.type memcpy, %function
|
||||
memcpy:
|
||||
@ r0: dst
|
||||
@ r1: src
|
||||
@ r2: len
|
||||
#ifdef __ARM_FEATURE_UNALIGNED
|
||||
/* In case of UNALIGNED access supported, ip is not used in
|
||||
function body. */
|
||||
mov ip, r0
|
||||
#else
|
||||
push {r0}
|
||||
#endif
|
||||
orr r3, r1, r0
|
||||
ands r3, r3, #3
|
||||
bne .Lmisaligned_copy
|
||||
|
||||
.Lbig_block:
|
||||
subs r2, __OPT_BIG_BLOCK_SIZE
|
||||
blo .Lmid_block
|
||||
|
||||
/* Kernel loop for big block copy */
|
||||
.align 2
|
||||
.Lbig_block_loop:
|
||||
BEGIN_UNROLL_BIG_BLOCK
|
||||
#ifdef __ARM_ARCH_7EM__
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
END_UNROLL
|
||||
#else /* __ARM_ARCH_7M__ */
|
||||
ldr r3, [r1, \offset]
|
||||
str r3, [r0, \offset]
|
||||
END_UNROLL
|
||||
adds r0, __OPT_BIG_BLOCK_SIZE
|
||||
adds r1, __OPT_BIG_BLOCK_SIZE
|
||||
#endif
|
||||
subs r2, __OPT_BIG_BLOCK_SIZE
|
||||
bhs .Lbig_block_loop
|
||||
|
||||
.Lmid_block:
|
||||
adds r2, __OPT_BIG_BLOCK_SIZE - __OPT_MID_BLOCK_SIZE
|
||||
blo .Lcopy_word_by_word
|
||||
|
||||
/* Kernel loop for mid-block copy */
|
||||
.align 2
|
||||
.Lmid_block_loop:
|
||||
BEGIN_UNROLL_MID_BLOCK
|
||||
#ifdef __ARM_ARCH_7EM__
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
END_UNROLL
|
||||
#else /* __ARM_ARCH_7M__ */
|
||||
ldr r3, [r1, \offset]
|
||||
str r3, [r0, \offset]
|
||||
END_UNROLL
|
||||
adds r0, __OPT_MID_BLOCK_SIZE
|
||||
adds r1, __OPT_MID_BLOCK_SIZE
|
||||
#endif
|
||||
subs r2, __OPT_MID_BLOCK_SIZE
|
||||
bhs .Lmid_block_loop
|
||||
|
||||
.Lcopy_word_by_word:
|
||||
adds r2, __OPT_MID_BLOCK_SIZE - 4
|
||||
blo .Lcopy_less_than_4
|
||||
|
||||
/* Kernel loop for small block copy */
|
||||
.align 2
|
||||
.Lcopy_word_by_word_loop:
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
subs r2, #4
|
||||
bhs .Lcopy_word_by_word_loop
|
||||
|
||||
.Lcopy_less_than_4:
|
||||
adds r2, #4
|
||||
beq .Ldone
|
||||
|
||||
lsls r2, r2, #31
|
||||
itt ne
|
||||
ldrbne r3, [r1], #1
|
||||
strbne r3, [r0], #1
|
||||
|
||||
bcc .Ldone
|
||||
#ifdef __ARM_FEATURE_UNALIGNED
|
||||
ldrh r3, [r1]
|
||||
strh r3, [r0]
|
||||
#else
|
||||
ldrb r3, [r1]
|
||||
strb r3, [r0]
|
||||
ldrb r3, [r1, #1]
|
||||
strb r3, [r0, #1]
|
||||
#endif /* __ARM_FEATURE_UNALIGNED */
|
||||
|
||||
.Ldone:
|
||||
#ifdef __ARM_FEATURE_UNALIGNED
|
||||
mov r0, ip
|
||||
#else
|
||||
pop {r0}
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
.align 2
|
||||
.Lmisaligned_copy:
|
||||
#ifdef __ARM_FEATURE_UNALIGNED
|
||||
/* Define label DST_ALIGNED to BIG_BLOCK. It will go to aligned copy
|
||||
once destination is adjusted to aligned. */
|
||||
#define Ldst_aligned Lbig_block
|
||||
|
||||
/* Copy word by word using LDR when alignment can be done in hardware,
|
||||
i.e., SCTLR.A is set, supporting unaligned access in LDR and STR. */
|
||||
|
||||
cmp r2, #8
|
||||
blo .Lbyte_copy
|
||||
|
||||
/* if src is aligned, just go to the big block loop. */
|
||||
lsls r3, r1, #30
|
||||
beq .Ldst_aligned
|
||||
#else
|
||||
/* if len < 12, misalignment adjustment has more overhead than
|
||||
just byte-to-byte copy. Also, len must >=8 to guarantee code
|
||||
afterward work correctly. */
|
||||
cmp r2, #12
|
||||
blo .Lbyte_copy
|
||||
#endif /* __ARM_FEATURE_UNALIGNED */
|
||||
|
||||
/* Align dst only, not trying to align src. That is the because
|
||||
handling of aligned src and misaligned dst need more overhead than
|
||||
otherwise. By doing this the worst case is when initial src is aligned,
|
||||
additional up to 4 byte additional copy will executed, which is
|
||||
acceptable. */
|
||||
|
||||
ands r3, r0, #3
|
||||
beq .Ldst_aligned
|
||||
|
||||
rsb r3, #4
|
||||
subs r2, r3
|
||||
|
||||
lsls r3, r3, #31
|
||||
itt ne
|
||||
ldrbne r3, [r1], #1
|
||||
strbne r3, [r0], #1
|
||||
|
||||
bcc .Ldst_aligned
|
||||
|
||||
#ifdef __ARM_FEATURE_UNALIGNED
|
||||
ldrh r3, [r1], #2
|
||||
strh r3, [r0], #2
|
||||
b .Ldst_aligned
|
||||
#else
|
||||
ldrb r3, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
ldrb r3, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
/* Now that dst is aligned */
|
||||
.Ldst_aligned:
|
||||
/* if r1 is aligned now, it means r0/r1 has the same misalignment,
|
||||
and they are both aligned now. Go aligned copy. */
|
||||
ands r3, r1, #3
|
||||
beq .Lbig_block
|
||||
|
||||
/* dst is aligned, but src isn't. Misaligned copy. */
|
||||
|
||||
push {r4, r5}
|
||||
subs r2, #4
|
||||
|
||||
/* Backward r1 by misaligned bytes, to make r1 aligned.
|
||||
Since we need to restore r1 to unaligned address after the loop,
|
||||
we need keep the offset bytes to ip and sub it from r1 afterward. */
|
||||
subs r1, r3
|
||||
rsb ip, r3, #4
|
||||
|
||||
/* Pre-load on word */
|
||||
ldr r4, [r1], #4
|
||||
|
||||
cmp r3, #2
|
||||
beq .Lmisaligned_copy_2_2
|
||||
cmp r3, #3
|
||||
beq .Lmisaligned_copy_3_1
|
||||
|
||||
.macro mis_src_copy shift
|
||||
1:
|
||||
#ifdef __ARM_BIG_ENDIAN
|
||||
lsls r4, r4, \shift
|
||||
#else
|
||||
lsrs r4, r4, \shift
|
||||
#endif
|
||||
ldr r3, [r1], #4
|
||||
#ifdef __ARM_BIG_ENDIAN
|
||||
lsrs r5, r3, 32-\shift
|
||||
#else
|
||||
lsls r5, r3, 32-\shift
|
||||
#endif
|
||||
orr r4, r4, r5
|
||||
str r4, [r0], #4
|
||||
mov r4, r3
|
||||
subs r2, #4
|
||||
bhs 1b
|
||||
.endm
|
||||
|
||||
.Lmisaligned_copy_1_3:
|
||||
mis_src_copy shift=8
|
||||
b .Lsrc_misaligned_tail
|
||||
|
||||
.Lmisaligned_copy_3_1:
|
||||
mis_src_copy shift=24
|
||||
b .Lsrc_misaligned_tail
|
||||
|
||||
.Lmisaligned_copy_2_2:
|
||||
/* For 2_2 misalignment, ldr is still faster than 2 x ldrh. */
|
||||
mis_src_copy shift=16
|
||||
|
||||
.Lsrc_misaligned_tail:
|
||||
adds r2, #4
|
||||
subs r1, ip
|
||||
pop {r4, r5}
|
||||
|
||||
#endif /* __ARM_FEATURE_UNALIGNED */
|
||||
|
||||
.Lbyte_copy:
|
||||
subs r2, #4
|
||||
blo .Lcopy_less_than_4
|
||||
|
||||
.Lbyte_copy_loop:
|
||||
subs r2, #1
|
||||
ldrb r3, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
bhs .Lbyte_copy_loop
|
||||
|
||||
ldrb r3, [r1]
|
||||
strb r3, [r0]
|
||||
ldrb r3, [r1, #1]
|
||||
strb r3, [r0, #1]
|
||||
ldrb r3, [r1, #2]
|
||||
strb r3, [r0, #2]
|
||||
|
||||
#ifdef __ARM_FEATURE_UNALIGNED
|
||||
mov r0, ip
|
||||
#else
|
||||
pop {r0}
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
.size memcpy, .-memcpy
|
||||
Reference in New Issue
Block a user