From deb10f450ffee6fc2d012c34cd320deca1a160e9 Mon Sep 17 00:00:00 2001 From: cfif Date: Tue, 23 Sep 2025 13:35:15 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inc/fc7xxx_board_conf.h | 58 + Inc/fc7xxx_driver_adc.h | 422 +++++ Inc/fc7xxx_driver_aontimer.h | 140 ++ Inc/fc7xxx_driver_cmp.h | 295 +++ Inc/fc7xxx_driver_cmu.h | 197 ++ Inc/fc7xxx_driver_cordic.h | 150 ++ Inc/fc7xxx_driver_cpm.h | 106 ++ Inc/fc7xxx_driver_crc.h | 130 ++ Inc/fc7xxx_driver_csc.h | 594 ++++++ Inc/fc7xxx_driver_dma.h | 368 ++++ Inc/fc7xxx_driver_dsp.h | 45 + Inc/fc7xxx_driver_eim.h | 87 + Inc/fc7xxx_driver_erm.h | 107 ++ Inc/fc7xxx_driver_fciic.h | 209 +++ Inc/fc7xxx_driver_fcpit.h | 179 ++ Inc/fc7xxx_driver_fcsmu.h | 251 +++ Inc/fc7xxx_driver_fcspi.h | 620 +++++++ Inc/fc7xxx_driver_fcuart.h | 434 +++++ Inc/fc7xxx_driver_flash.h | 182 ++ Inc/fc7xxx_driver_flexcan.h | 461 +++++ Inc/fc7xxx_driver_fmc.h | 186 ++ Inc/fc7xxx_driver_fpu.h | 64 + Inc/fc7xxx_driver_freqm.h | 143 ++ Inc/fc7xxx_driver_ftu.h | 855 +++++++++ Inc/fc7xxx_driver_gpio.h | 145 ++ Inc/fc7xxx_driver_hsm.h | 3277 ++++++++++++++++++++++++++++++++++ Inc/fc7xxx_driver_intm.h | 137 ++ Inc/fc7xxx_driver_ism.h | 249 +++ Inc/fc7xxx_driver_lin.h | 427 +++++ Inc/fc7xxx_driver_lu.h | 138 ++ Inc/fc7xxx_driver_mam.h | 109 ++ Inc/fc7xxx_driver_mb.h | 201 +++ Inc/fc7xxx_driver_mpu.h | 242 +++ Inc/fc7xxx_driver_msc.h | 402 +++++ Inc/fc7xxx_driver_overlay.h | 172 ++ Inc/fc7xxx_driver_pcc.h | 157 ++ Inc/fc7xxx_driver_pmc.h | 181 ++ Inc/fc7xxx_driver_port.h | 239 +++ Inc/fc7xxx_driver_ptimer.h | 226 +++ Inc/fc7xxx_driver_rgm.h | 182 ++ Inc/fc7xxx_driver_rtc.h | 152 ++ Inc/fc7xxx_driver_scg.h | 459 +++++ Inc/fc7xxx_driver_scm.h | 232 +++ Inc/fc7xxx_driver_scst.h | 137 ++ Inc/fc7xxx_driver_sec.h | 371 ++++ Inc/fc7xxx_driver_sent.h | 498 ++++++ Inc/fc7xxx_driver_smc.h | 55 + Inc/fc7xxx_driver_stcu.h | 266 +++ Inc/fc7xxx_driver_systick.h | 28 + Inc/fc7xxx_driver_tmu.h | 156 ++ Inc/fc7xxx_driver_tpu.h | 176 ++ Inc/fc7xxx_driver_trgsel.h | 850 +++++++++ Inc/fc7xxx_driver_tstmp.h | 165 ++ Inc/fc7xxx_driver_wdog.h | 114 ++ Inc/fc7xxx_driver_wku.h | 60 + Src/fc7xxx_driver_adc.c | 791 ++++++++ Src/fc7xxx_driver_aontimer.c | 187 ++ Src/fc7xxx_driver_cmp.c | 324 ++++ Src/fc7xxx_driver_cmu.c | 386 ++++ Src/fc7xxx_driver_cordic.c | 280 +++ Src/fc7xxx_driver_cpm.c | 210 +++ Src/fc7xxx_driver_crc.c | 167 ++ Src/fc7xxx_driver_csc.c | 1698 ++++++++++++++++++ Src/fc7xxx_driver_dma.c | 795 +++++++++ Src/fc7xxx_driver_dsp.c | 38 + Src/fc7xxx_driver_eim.c | 217 +++ Src/fc7xxx_driver_erm.c | 175 ++ Src/fc7xxx_driver_fciic.c | 817 +++++++++ Src/fc7xxx_driver_fcpit.c | 524 ++++++ Src/fc7xxx_driver_fcsmu.c | 408 +++++ Src/fc7xxx_driver_fcspi.c | 3229 +++++++++++++++++++++++++++++++++ Src/fc7xxx_driver_fcuart.c | 1946 ++++++++++++++++++++ Src/fc7xxx_driver_flash.c | 998 +++++++++++ Src/fc7xxx_driver_flexcan.c | 2810 +++++++++++++++++++++++++++++ Src/fc7xxx_driver_fmc.c | 197 ++ Src/fc7xxx_driver_fpu.c | 51 + Src/fc7xxx_driver_freqm.c | 186 ++ Src/fc7xxx_driver_ftu.c | 1810 +++++++++++++++++++ Src/fc7xxx_driver_gpio.c | 175 ++ Src/fc7xxx_driver_hsm.c | 648 +++++++ Src/fc7xxx_driver_intm.c | 190 ++ Src/fc7xxx_driver_ism.c | 347 ++++ Src/fc7xxx_driver_lin.c | 1502 ++++++++++++++++ Src/fc7xxx_driver_lu.c | 184 ++ Src/fc7xxx_driver_mam.c | 259 +++ Src/fc7xxx_driver_mb.c | 456 +++++ Src/fc7xxx_driver_mpu.c | 128 ++ Src/fc7xxx_driver_msc.c | 569 ++++++ Src/fc7xxx_driver_overlay.c | 498 ++++++ Src/fc7xxx_driver_pcc.c | 421 +++++ Src/fc7xxx_driver_pmc.c | 175 ++ Src/fc7xxx_driver_port.c | 486 +++++ Src/fc7xxx_driver_ptimer.c | 326 ++++ Src/fc7xxx_driver_rgm.c | 312 ++++ Src/fc7xxx_driver_rtc.c | 365 ++++ Src/fc7xxx_driver_scg.c | 1941 ++++++++++++++++++++ Src/fc7xxx_driver_scm.c | 482 +++++ Src/fc7xxx_driver_scst.c | 230 +++ Src/fc7xxx_driver_sec.c | 424 +++++ Src/fc7xxx_driver_sent.c | 896 ++++++++++ Src/fc7xxx_driver_smc.c | 122 ++ Src/fc7xxx_driver_stcu.c | 202 +++ Src/fc7xxx_driver_systick.c | 60 + Src/fc7xxx_driver_tmu.c | 312 ++++ Src/fc7xxx_driver_tpu.c | 596 +++++++ Src/fc7xxx_driver_trgsel.c | 314 ++++ Src/fc7xxx_driver_tstmp.c | 420 +++++ Src/fc7xxx_driver_wdog.c | 131 ++ Src/fc7xxx_driver_wku.c | 97 + modular.json | 13 + 110 files changed, 48011 insertions(+) create mode 100644 Inc/fc7xxx_board_conf.h create mode 100644 Inc/fc7xxx_driver_adc.h create mode 100644 Inc/fc7xxx_driver_aontimer.h create mode 100644 Inc/fc7xxx_driver_cmp.h create mode 100644 Inc/fc7xxx_driver_cmu.h create mode 100644 Inc/fc7xxx_driver_cordic.h create mode 100644 Inc/fc7xxx_driver_cpm.h create mode 100644 Inc/fc7xxx_driver_crc.h create mode 100644 Inc/fc7xxx_driver_csc.h create mode 100644 Inc/fc7xxx_driver_dma.h create mode 100644 Inc/fc7xxx_driver_dsp.h create mode 100644 Inc/fc7xxx_driver_eim.h create mode 100644 Inc/fc7xxx_driver_erm.h create mode 100644 Inc/fc7xxx_driver_fciic.h create mode 100644 Inc/fc7xxx_driver_fcpit.h create mode 100644 Inc/fc7xxx_driver_fcsmu.h create mode 100644 Inc/fc7xxx_driver_fcspi.h create mode 100644 Inc/fc7xxx_driver_fcuart.h create mode 100644 Inc/fc7xxx_driver_flash.h create mode 100644 Inc/fc7xxx_driver_flexcan.h create mode 100644 Inc/fc7xxx_driver_fmc.h create mode 100644 Inc/fc7xxx_driver_fpu.h create mode 100644 Inc/fc7xxx_driver_freqm.h create mode 100644 Inc/fc7xxx_driver_ftu.h create mode 100644 Inc/fc7xxx_driver_gpio.h create mode 100644 Inc/fc7xxx_driver_hsm.h create mode 100644 Inc/fc7xxx_driver_intm.h create mode 100644 Inc/fc7xxx_driver_ism.h create mode 100644 Inc/fc7xxx_driver_lin.h create mode 100644 Inc/fc7xxx_driver_lu.h create mode 100644 Inc/fc7xxx_driver_mam.h create mode 100644 Inc/fc7xxx_driver_mb.h create mode 100644 Inc/fc7xxx_driver_mpu.h create mode 100644 Inc/fc7xxx_driver_msc.h create mode 100644 Inc/fc7xxx_driver_overlay.h create mode 100644 Inc/fc7xxx_driver_pcc.h create mode 100644 Inc/fc7xxx_driver_pmc.h create mode 100644 Inc/fc7xxx_driver_port.h create mode 100644 Inc/fc7xxx_driver_ptimer.h create mode 100644 Inc/fc7xxx_driver_rgm.h create mode 100644 Inc/fc7xxx_driver_rtc.h create mode 100644 Inc/fc7xxx_driver_scg.h create mode 100644 Inc/fc7xxx_driver_scm.h create mode 100644 Inc/fc7xxx_driver_scst.h create mode 100644 Inc/fc7xxx_driver_sec.h create mode 100644 Inc/fc7xxx_driver_sent.h create mode 100644 Inc/fc7xxx_driver_smc.h create mode 100644 Inc/fc7xxx_driver_stcu.h create mode 100644 Inc/fc7xxx_driver_systick.h create mode 100644 Inc/fc7xxx_driver_tmu.h create mode 100644 Inc/fc7xxx_driver_tpu.h create mode 100644 Inc/fc7xxx_driver_trgsel.h create mode 100644 Inc/fc7xxx_driver_tstmp.h create mode 100644 Inc/fc7xxx_driver_wdog.h create mode 100644 Inc/fc7xxx_driver_wku.h create mode 100644 Src/fc7xxx_driver_adc.c create mode 100644 Src/fc7xxx_driver_aontimer.c create mode 100644 Src/fc7xxx_driver_cmp.c create mode 100644 Src/fc7xxx_driver_cmu.c create mode 100644 Src/fc7xxx_driver_cordic.c create mode 100644 Src/fc7xxx_driver_cpm.c create mode 100644 Src/fc7xxx_driver_crc.c create mode 100644 Src/fc7xxx_driver_csc.c create mode 100644 Src/fc7xxx_driver_dma.c create mode 100644 Src/fc7xxx_driver_dsp.c create mode 100644 Src/fc7xxx_driver_eim.c create mode 100644 Src/fc7xxx_driver_erm.c create mode 100644 Src/fc7xxx_driver_fciic.c create mode 100644 Src/fc7xxx_driver_fcpit.c create mode 100644 Src/fc7xxx_driver_fcsmu.c create mode 100644 Src/fc7xxx_driver_fcspi.c create mode 100644 Src/fc7xxx_driver_fcuart.c create mode 100644 Src/fc7xxx_driver_flash.c create mode 100644 Src/fc7xxx_driver_flexcan.c create mode 100644 Src/fc7xxx_driver_fmc.c create mode 100644 Src/fc7xxx_driver_fpu.c create mode 100644 Src/fc7xxx_driver_freqm.c create mode 100644 Src/fc7xxx_driver_ftu.c create mode 100644 Src/fc7xxx_driver_gpio.c create mode 100644 Src/fc7xxx_driver_hsm.c create mode 100644 Src/fc7xxx_driver_intm.c create mode 100644 Src/fc7xxx_driver_ism.c create mode 100644 Src/fc7xxx_driver_lin.c create mode 100644 Src/fc7xxx_driver_lu.c create mode 100644 Src/fc7xxx_driver_mam.c create mode 100644 Src/fc7xxx_driver_mb.c create mode 100644 Src/fc7xxx_driver_mpu.c create mode 100644 Src/fc7xxx_driver_msc.c create mode 100644 Src/fc7xxx_driver_overlay.c create mode 100644 Src/fc7xxx_driver_pcc.c create mode 100644 Src/fc7xxx_driver_pmc.c create mode 100644 Src/fc7xxx_driver_port.c create mode 100644 Src/fc7xxx_driver_ptimer.c create mode 100644 Src/fc7xxx_driver_rgm.c create mode 100644 Src/fc7xxx_driver_rtc.c create mode 100644 Src/fc7xxx_driver_scg.c create mode 100644 Src/fc7xxx_driver_scm.c create mode 100644 Src/fc7xxx_driver_scst.c create mode 100644 Src/fc7xxx_driver_sec.c create mode 100644 Src/fc7xxx_driver_sent.c create mode 100644 Src/fc7xxx_driver_smc.c create mode 100644 Src/fc7xxx_driver_stcu.c create mode 100644 Src/fc7xxx_driver_systick.c create mode 100644 Src/fc7xxx_driver_tmu.c create mode 100644 Src/fc7xxx_driver_tpu.c create mode 100644 Src/fc7xxx_driver_trgsel.c create mode 100644 Src/fc7xxx_driver_tstmp.c create mode 100644 Src/fc7xxx_driver_wdog.c create mode 100644 Src/fc7xxx_driver_wku.c create mode 100644 modular.json diff --git a/Inc/fc7xxx_board_conf.h b/Inc/fc7xxx_board_conf.h new file mode 100644 index 0000000..5ce82ab --- /dev/null +++ b/Inc/fc7xxx_board_conf.h @@ -0,0 +1,58 @@ +/** + * @file fc7xxx_board_conf.h + * @author Flagchip032 + * @brief FC7xxx board configuration file + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-12 Flagchip032 N/A First version for FC7240 + ******************************************************************************** */ + +#ifndef _DRIVER_FC7XXX_BOARD_CONF_H_ +#define _DRIVER_FC7XXX_BOARD_CONF_H_ +#include "device_header.h" + +#if defined(__cplusplus) +extern "C" { +#endif +/** + * @addtogroup fc7xxx_board_conf + * @{ + */ + +/******************* Oscillator Values *******************/ +/** + * @brief Fast OSC frequency + */ +#ifndef FOSC_FREQUENCY +#define FOSC_FREQUENCY 24000000U +#endif + +/** + * @brief Slow OSC frequency + */ +#ifndef SOSC_FREQUENCY +#define SOSC_FREQUENCY 32768U +#endif + +/** + * @brief FTU input TCLK frequency + */ +#ifndef PCC_FTU_TCLK_FREQ +#define PCC_FTU_TCLK_FREQ 0U +#endif + + +/** @}*/ /* fc7xxx_board_conf */ +#if defined(__cplusplus) +} +#endif +#endif diff --git a/Inc/fc7xxx_driver_adc.h b/Inc/fc7xxx_driver_adc.h new file mode 100644 index 0000000..51b715f --- /dev/null +++ b/Inc/fc7xxx_driver_adc.h @@ -0,0 +1,422 @@ +/** + * @file fc7xxx_driver_adc.h + * @author Flagchip0126 + * @brief FC7xxx ADC driver type definition and API + * @version 0.1.0 + * @date 2024-01-15 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-15 Flagchip0126 N/A First version for FC7240 + ******************************************************************************** */ + +#ifndef _DRIVER_FC7XXX_DRIVER_ADC_H_ +#define _DRIVER_FC7XXX_DRIVER_ADC_H_ +#include "device_header.h" +#include "HwA_adc.h" +#include "fc7xxx_driver_dma.h" + +#if defined(__cplusplus) +extern "C" { +#endif +/** + * @addtogroup fc7xxx_driver_adc + * @{ + */ + +/** + * @name ADC0 Internal Channels + * @brief Available internal ADC channels for ADC Instance 0 + * + * @{ + */ +#define ADC0_CHANNEL_VBG_BUFFER ADC_CHANNEL_INTERNAL_0 +#define ADC0_CHANNEL_V25 ADC_CHANNEL_INTERNAL_1 +#define ADC0_CHANNEL_V11 ADC_CHANNEL_INTERNAL_2 +#define ADC0_CHANNEL_CMP0_DAC ADC_CHANNEL_INTERNAL_4 +#define ADC0_CHANNEL_TEMPSENSOR_OUT ADC_CHANNEL_INTERNAL_5 /* Must be in differential mode */ +/** @}*/ + +/** + * @name ADC1 Internal channels + * @brief Available internal ADC channels for ADC Instance 1 + * + * @{ + */ +#define ADC1_CHANNEL_V11_PD0 ADC_CHANNEL_INTERNAL_0 +#define ADC1_CHANNEL_VREFH ADC_CHANNEL_INTERNAL_1 +#define ADC1_CHANNEL_VDDA ADC_CHANNEL_INTERNAL_2 +#define ADC1_CHANNEL_V15 ADC_CHANNEL_INTERNAL_3 +#define ADC1_CHANNEL_CMP1_DAC ADC_CHANNEL_INTERNAL_4 +/** @}*/ + +/** + * @brief The ADC conversion complete callback function prototype + * + */ +typedef void (*ADC_ConvCompleteCallbackType)(const uint32_t *const pBuff); + +/** + * @brief The ADC overrun callback function prototype + * + */ +typedef void (*ADC_OverRunInterruptCallbackType)(void); + +/** + * @brief The ADC compare callback function prototype + * + */ +typedef void (*ADC_CompareInterruptCallbackType)(void); + +/** + * @brief The ADC end of sequence group callback function prototype + * + */ +typedef void (*ADC_EndOfSeqGroupInterruptCallbackType)(uint8_t u8SeqGroupIdx); + +/** + * @brief The instance index of the ADC peripheral + * + */ +typedef enum +{ + ADC_INSTANCE_0 = 0U, /*!< ADC instance 0 is selected */ + ADC_INSTANCE_1 = 1U, /*!< ADC instance 1 is selected */ +} ADC_InstanceType; + +/** + * @brief The channel selected for ADC conversion + * + */ +typedef enum +{ + ADC_CHANNEL_0 = 0U, + ADC_CHANNEL_1 = 1U, + ADC_CHANNEL_2 = 2U, + ADC_CHANNEL_3 = 3U, + ADC_CHANNEL_4 = 4U, + ADC_CHANNEL_5 = 5U, + ADC_CHANNEL_6 = 6U, + ADC_CHANNEL_7 = 7U, + ADC_CHANNEL_8 = 8U, + ADC_CHANNEL_9 = 9U, + ADC_CHANNEL_10 = 10U, + ADC_CHANNEL_11 = 11U, + ADC_CHANNEL_12 = 12U, + ADC_CHANNEL_13 = 13U, + ADC_CHANNEL_14 = 14U, + ADC_CHANNEL_15 = 15U, + ADC_CHANNEL_16 = 16U, + ADC_CHANNEL_17 = 17U, + ADC_CHANNEL_18 = 18U, + ADC_CHANNEL_19 = 19U, + ADC_CHANNEL_20 = 20U, + ADC_CHANNEL_21 = 21U, + ADC_CHANNEL_22 = 22U, + ADC_CHANNEL_23 = 23U, + ADC_CHANNEL_24 = 24U, + ADC_CHANNEL_25 = 25U, + ADC_CHANNEL_26 = 26U, + ADC_CHANNEL_27 = 27U, + ADC_CHANNEL_28 = 28U, + ADC_CHANNEL_29 = 29U, + ADC_CHANNEL_30 = 30U, + ADC_CHANNEL_31 = 31U, + ADC_CHANNEL_INTERNAL_0 = 32U, + ADC_CHANNEL_INTERNAL_1 = 33U, + ADC_CHANNEL_INTERNAL_2 = 34U, + ADC_CHANNEL_INTERNAL_3 = 35U, + ADC_CHANNEL_INTERNAL_4 = 36U, + ADC_CHANNEL_INTERNAL_5 = 37U +} ADC_ChannelType; + +/** + * @brief The channel selected for ADC conversion in differential mode + * + */ +typedef enum +{ + ADC_CHANNEL_0_4 = 0U, + ADC_CHANNEL_1_5 = 1U, + ADC_CHANNEL_2_6 = 2U, + ADC_CHANNEL_3_7 = 3U, + ADC_CHANNEL_TEMPSENSOR = 37U +} ADC_DifferentialChannelType; + +/** + * @brief The ADC sample time option for selection + * + */ +typedef enum +{ + ADC_SAMPLE_TIME_OPTION_0 = 0U, + ADC_SAMPLE_TIME_OPTION_1 = 1U, + ADC_SAMPLE_TIME_OPTION_2 = 2U, + ADC_SAMPLE_TIME_OPTION_3 = 3U +} ADC_SampleTimeOptionType; + +/** + * @brief The ADC SequenceGroup Index + * + */ +typedef enum +{ + ADC_SEQUENCE_GROUP_0 = 0U, + ADC_SEQUENCE_GROUP_1 = 1U, + ADC_SEQUENCE_GROUP_2 = 2U, + ADC_SEQUENCE_GROUP_3 = 3U +} ADC_SequenceGroupIndex; + +/** + * @brief ADC operation return values + * + */ +typedef enum +{ + ADC_STATUS_SUCCESS = 0x0U, /*!< The ADC operation is succeed */ + ADC_STATUS_ERROR = 0x1U, /*!< The ADC operation is failed */ + ADC_STATUS_TIMEOUT = 0x2U /*!< The ADC operation is failed because of time out */ +} ADC_StatusType; + +/** + * @brief Defines the converter configuration + * + * This structure is used to configure the ADC converter + * + * Implements : ADC_InitType + */ +typedef struct +{ + ADC_ResolutionType eResolution; /*!< ADC eResolution (8,10,12 bit) */ + ADC_AlignType eAlign; /*!< ADC alignment (left, right) */ + ADC_TrigModeType eTriggerMode; /*!< ADC trigger type (software, hardware) + - affects only the first control channel */ + bool bWaitEnable; /*!< Whether to enable ADC wait conversion mode */ + bool bSequenceGroupModeEnable; /*!< Whether to enable ADC sequence group mode, if true, ignore eSequenceMode*/ + bool bCalEnable; /*!< Whether to enable ADC calibration > */ + int32_t s32CalOffset; /*!< ADC calibration offset value > */ + int32_t s32CalGain; /*!< ADC calibration gain value > */ + ADC_TrgLatchUnitPri eTrgLatchUnitPri; /*!< Select priority of Trigger Latch Unit */ + ADC_ClockDivideType eClockDivider; /*!< ADC clock divider */ + ADC_SeqModeType eSequenceMode; /*!< ADC sequence mode (single, continuous, discontinuous) */ + bool bAutoDis; /*!< Whether to enable audo disable mode, only set this when adc in off state */ + ADC_OvrModeType eOverrunMode; /*!< Whether to preserve data when ADC overruns */ + ADC_RefType eVoltageRef; /*!< Voltage reference used (external, internal) */ + bool bHwAvgEnable; /*!< Enable averaging functionality */ + ADC_AverageType eHwAverage; /*!< Selection for number of samples used for averaging */ + uint8_t aSampleTimes[ADC_SAMPLE_TIME_OPTION_CNT]; /*!< ADC sample time options, range: 4 ~ 257 */ +} ADC_InitType; + +/** + * @brief The configuration option for the ADC channel + * + */ +typedef struct +{ + ADC_ChannelType eChannel; /*!< Selected ADC channel */ + ADC_SampleTimeOptionType eSampleTimeOption; /*!< The sample time selection for the channel */ + bool bDiff; /*!< Whether diff mode, if a channel do not support differential mode, ignore this */ +} ADC_ChannelCfgType; + +/** + * @brief The configuration option for the ADC sequence group + * + */ +typedef struct +{ + uint8_t u8Start; /*!< Sequence channel start */ + uint8_t u8Len; /*!< Sequence group length, is must be >= 0 */ +} ADC_SequenceGroupType; + + +/** + * @brief Defines the hardware compare configuration + * + * This structure is used to configure the hardware compare feature for the ADC + * + * Implements : ADC_CompareType + */ +typedef struct +{ + /* ADC_CMP_CTRL */ + bool bCmpEnable; /*!< Enable hardware compare */ + ADC_CmpChannelType eCmpSingleChn; /*!< 0: ADC compare on all channels; + 1: ADC compare on the selected channel */ + uint8_t u8CmpChnSel; /*!< Compare channel selection */ + + /* ADC_CMP_TR */ + uint16_t u16HighThres; /*!< Compare high threshold */ + uint16_t u16LowThres; /*!< Compare low threshold */ +} ADC_CompareType; + +/** + * @brief Defines the interrupt configuration + * + * This structure is used to configure the enabled interrupts and interrupt + * callbacks for ADC + * + */ +typedef struct +{ + /* ADC_INT_ENABLE */ + bool bConversionCompleteIntEn; /*!< Enable interrupt when conversion completed */ + bool bOverRunIntEn; /*!< Enable interrupt when overrun occured */ + bool bAnalogCmpIntEn; /*!< Enable interrupt when conversion result lays in the compare threshold */ + bool bEndOfSeqGroupIntEn; /*!< Enable interrupt when sequence group complete >*/ + uint32_t *pResultBuffer; /*!< When conversion complete interrupt is enabled, you shall provide the + result buffer to store the conversion results, this buffer only used for mode 0 ~ 3 */ + uint32_t *pSequenceGroupResultBuffer[ADC_SEQUENCE_GROUP_CNT]; /*!< When conversion complete interrupt is enabled, you shall provide the + result buffer to store the conversion results, these buffer only used for mode 4 */ + ADC_ConvCompleteCallbackType pConvCompleteNotify; /*!< Conversion complete interrupt callback */ + ADC_OverRunInterruptCallbackType pOverRunNotify; /*!< Overrun interrupt callback */ + ADC_CompareInterruptCallbackType pCompareNotify; /*!< Compare interrupt callback */ + ADC_EndOfSeqGroupInterruptCallbackType pEndOfSeqGroupNotify; /*!< End of Sequence End callback >*/ +} ADC_InterruptType; + +/** + * @brief Defines the DMA configuretion + * + * This structure is used to configure the DMA result transfer feature for ADC + * + */ +typedef struct +{ + bool bDmaEnable; /*!< Enable DMA for the ADC */ + ADC_SequenceGroupIndex eSeqGroupIndex; /*!< Only valid when SequenceGroupEn = true, otherwish ignore this */ + DMA_InstanceType eDmaInstance; /*!< The instance of DMA to use */ + DMA_ChannelType eDmaChannel; /*!< The DMA channel used to transfer the ADC conversion results */ + uint8_t u8ChannelPriority; /*!< The DMA channel priority, higher value means higher priority. + The priority for different channels must be unique. Default priority + value is same the channel number */ + uint32_t *pResultBuffer; /*!< Buffer to store the ADC conversion results */ + ADC_ConvCompleteCallbackType pConvCompleteNotify; /*!< DMA transfer complete callback */ +} ADC_DmaType; + +/** + * @brief Provide the default values of ADC_InitType + * + * @param pInitCfg the structure to initialize + */ +void ADC_InitStructure(ADC_InitType *const pInitCfg); + +/** + * @brief Initialize the ADC instance + * + * @param eInstance the ADC instance to init + * @param pInitCfg the configurations of the ADC instance + */ +void ADC_Init(const ADC_InstanceType eInstance, const ADC_InitType *const pInitCfg); + +/** + * @brief De-initialize the ADC instance + * + * Restore the ADC instance to its reset state + * + * @param eInstance the ADC instance to de-init + */ +void ADC_DeInit(const ADC_InstanceType eInstance); + +/** + * @brief Configure the ADC sample channels + * + * @param eInstance the ADC instance to use + * @param pChannels the channels to use + * @param u8ChnCnt the quantity of channels + */ +void ADC_InitChannel(const ADC_InstanceType eInstance, const ADC_ChannelCfgType aChannels[], + const uint8_t u8ChnCnt); + +/** + * @brief Configure the Sequence groups + * + * @param eInstance the ADC instance to use + * @param aSeqGroup the sequence groups to use + * @param u8SeqGroupCnt the quantity of sequence groups + */ +void ADC_InitSequenceGroup(const ADC_InstanceType eInstance, const ADC_SequenceGroupType aSeqGroup[], + const uint8_t u8SeqGroupCnt); + +/** + * @brief Configure the hardware compare feature of ADC + * + * @param eInstance the ADC instance to use + * @param pCmpCfg the compare paremeters + */ +void ADC_InitCompare(const ADC_InstanceType eInstance, const ADC_CompareType *const pCmpCfg); + +/** + * @brief Configure the interrupt of ADC + * + * @param eInstance the ADC instance to use + * @param pInterruptCfg the interrupt paremeters + */ +void ADC_InitInterrupt(const ADC_InstanceType eInstance, + const ADC_InterruptType *const pInterruptCfg); + +/** + * @brief Configure the DMA feature of ADC + * + * @param eInstance the ADC instance to use + * @param pAdcDmaCfg the DMA paremeters for the ADC instance + */ +void ADC_InitDmaChannel(const ADC_InstanceType eInstance, const ADC_DmaType *const pAdcDmaCfg); + +/** + * @brief Enable the ADC instance + * + * @param eInstance the ADC instance to enable + * @return ADC_StatusType whether ADC is enabled successfully + */ +ADC_StatusType ADC_Enable(const ADC_InstanceType eInstance); + +/** + * @brief Disable the ADC instance + * + * @param eInstance the ADC instance to disable + * @return ADC_StatusType whether ADC is disabled successfully + */ +ADC_StatusType ADC_Disable(const ADC_InstanceType eInstance); + +/** + * @brief Start the ADC conversion + * + * If the ADC sequence mode is single or continuous, and the trigger mode is ADC_TRIGMODE_SW, + * the adc conversion will start immediately. Otherwise, the ADC will wait for the trigger + * signal to start the conversion + * + * @param eInstance the ADC instance to start + */ +void ADC_Start(const ADC_InstanceType eInstance); + +/** + * @brief Stop the ADC conversion + * + * If the ADC sequence mode is single, it will stop the ongoing conversion. If no ongoing + * conversion, it will have no effect. If the ADC sequence mode is continuous or discontinuous, + * it will stop the ongoing conversion and meanwhile the further conversions. + * + * @param eInstance the ADC instance to stop + * @return ADC_StatusType whether ADC is stopped successfully + */ +ADC_StatusType ADC_Stop(const ADC_InstanceType eInstance); + +/** + * @brief Reset the ADC hardware + * + * @param eInstance the ADC instance to reset + */ +void ADC_Reset(const ADC_InstanceType eInstance); + +/** @}*/ + +/** @}*/ /* fc7xxx_driver_adc */ +#if defined(__cplusplus) +} +#endif +#endif diff --git a/Inc/fc7xxx_driver_aontimer.h b/Inc/fc7xxx_driver_aontimer.h new file mode 100644 index 0000000..56fc655 --- /dev/null +++ b/Inc/fc7xxx_driver_aontimer.h @@ -0,0 +1,140 @@ +/** + * @file fc7xxx_driver_aontimer.h + * @author Flagchip + * @brief FC7xxx aontimer driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-10 Flagchip0076 N/A First version for FC7240 +********************************************************************************/ + + +#ifndef DRIVER_INCLUDE_FC7XXX_DRIVER_AONTIMER_H_ +#define DRIVER_INCLUDE_FC7XXX_DRIVER_AONTIMER_H_ + +#include "HwA_aontimer.h" + +/** + * @addtogroup fc7xxx_driver_aontimer + * @{ + */ + +/** @brief Aontimer return type. */ +typedef enum +{ + AONTIMER_STATUS_SUCCESS = 0U, /**< Aontimer status is success.*/ + AONTIMER_STATUS_PARAM_INVALID = 1U, /**< Aontimer failed for param invalid.*/ + AONTIMER_STATUS_CLOCK_INVALID = 2U /**< Aontimer failed for colck invalid.*/ +} AONTIMER_StatusType; + +/** @brief Aontimer debug mode */ +typedef enum +{ + AONTIMER_DBG_COUNTER_STOP = 0x00U, /**< Aontimer is stop in debug mode.*/ + AONTIMER_DBG_COUNTER_RUNNING = 0x01U /**< Aontimer is running in debug mode.*/ +} AONTIMER_DebugType; + +/** @brief Aontimer mode. */ +typedef enum +{ + AONTIMER_COUNTER_MODE = 0, /**< In this mode ,the clock source is internal.*/ + AONTIMER_PULSE_MODE /**< In this mode ,the clock source is external(pin/trgsel).*/ +} AONTIMER_ModeType; + +/** @brief callback function type */ + +typedef void (*Aontimer_InterruptCallBackType)(void); + +typedef struct +{ + bool bIntEn; /**< whether to use interrupt */ + Aontimer_InterruptCallBackType pIsrNotify; /**< the notification function of interrupt */ +} AONTIMER_IntType; + +/** @brief Aontimer Initialization struct type */ +typedef struct +{ + AONTIMER_ModeType eMode; /**< enumeration of aontier mode */ + + AONTIMER_DebugType eDbgMode; /**< enumeration of aontier debug mode */ + + bool bBypassEn; /**< Whether to use prescaler in counter mode or use glitch filter in pulse mode, + if set input value is true ,then not use the prescaler or glitch filter.*/ + AONTIMER_PulseClkSrcType ePulseClkSrc; /**< clock source of pulse mode */ + AONTIMER_PulsePolarityType ePulsePol; /**< polarity of pulse mode */ + uint8_t u8PulseFilterWidth; /**< the width of glitch filter in pulse mode , the range of the input value is :1~15, + and the range of glitch filter is :2^1 ~ 2^15. */ + uint8_t u8Prescaler; /**< the width of prescaler in counter mode, the range of the input value is :0~15, + and the range of prescaler is :2^1 ~ 2^16. */ + AONTIMER_ClkSrcType eClkSrc; /**< clock source of counter mode */ + uint16_t u16StartValue; /**< start value of counter mode ,the range is : 0 ~ 65535 */ +} AONTIMER_InitType; + +/* global function */ +/** + * @brief Initialize aontimer instance + * + * @param pInitStruct Aontimer Initialize structure + */ +void AONTIMER_Init(const AONTIMER_InitType *const pInitStruct); + +/** + * @brief De-initialize aontimer instance + * + */ +void AONTIMER_Deinit(void); + +/** + * @brief Initialize aontimer interrupt functionality + * + * @param pIntStruct Aontimer interrupt structure + * @return Aontimer return type + * @note this function will disable timer + */ +AONTIMER_StatusType AONTIMER_InitInterrupt(const AONTIMER_IntType *const pIntStruct); + +/** + * @brief Enable AONTIMER interrupt + * @note this function will enable AONTIEMR timer. + */ +void AONTIMER_EnableInterrupt(void); + +/** + * @brief Disable AONTIMER interrupt + * @note this function will enable AONTIEMR timer. + * + */ +void AONTIMER_DisableInterrupt(void); + +/** + * @brief Start Aontimer + * + */ +void AONTIMER_StartTimer(void); + +/** + * @brief Stop Aontimer + * + */ +void AONTIMER_StopTimer(void); + +/** + * @brief Update value of aontimer counter + * + * @param u16StartValue input value, range : 0~65535 + */ +void AONTIMER_UpdateCounterValue(const uint16_t u16StartValue); + + +/** @}*/ /* fc7xxx_driver_aontimer */ + +#endif /* DRIVER_INCLUDE_FC7XXX_DRIVER_AONTIMER_H_ */ diff --git a/Inc/fc7xxx_driver_cmp.h b/Inc/fc7xxx_driver_cmp.h new file mode 100644 index 0000000..d41657c --- /dev/null +++ b/Inc/fc7xxx_driver_cmp.h @@ -0,0 +1,295 @@ +/** + * @file fc7xxx_driver_cmp.h + * @author Flagchip + * @brief FC7xxx CMP driver type definition and API + * @version 0.1.0 + * @date 2024-01-15 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-15 Flagchip0126 N/A First version for FC7240 +********************************************************************************/ +#ifndef _DRIVER_FC7XXX_DRIVER_CMP_H_ +#define _DRIVER_FC7XXX_DRIVER_CMP_H_ +#include "HwA_cmp.h" + + + +#if defined(__cplusplus) +extern "C" { +#endif + +/********* Local typedef ************/ + +/** + * @brief The CMP complete interrupt callback function prototype + * + */ +typedef void (*CMP_CompleteIntCallback)(void); + +/** + * @brief The instance index of the CMP Dac parts + */ +typedef struct +{ + bool bDacEn; /*!< CMP DAC enable/disable */ + uint8_t u8DacData; /*!< CMP DAC output voltage, output = Vin / 256 * (aDacData + 1) */ + CMP_DacEnableSrcType eDacEnsrc; /*!< CMP DAC enable selection(DCR,CCR0) */ + CMP_DacVinRefSelType eVinRefSel; /*!< CMP DAC high voltage reference (vrefh0,vrefh1) */ +} CMP_DacType; + +/** + * @brief The instance index of the CMP Mux parts + */ +typedef struct +{ + CMP_INSrcSelType eINPSel; /*!< CMP input positive select(DAC or analog mux) */ + CMP_INSrcSelType eINNSel; /*!< CMP input negative select(DAC or analog mux) */ + CMP_MuxSelType ePSelMux; /*!< CMP input positive mux select, this is ignored in channel scan mode */ + CMP_MuxSelType eNSelMux; /*!< CMP input negative mux select, this is ignored in channel scan mode */ + CMP_MuxSelType eChannelScanFixedChannel; /*!< CMP channel scan fixed channel select, this is ignored if DAC is enabled */ + CMP_PortSelType eChannelScanFixedPort; /*!< CMP channel scan fixed channel port select */ +} CMP_MuxType; + +/** + * @brief The instance index of the CMP Comparator parts + */ +typedef struct +{ + bool bStopModEn; /*!< CMP stop mode enable */ + bool bOutToPackagePinEn; /*!< CMP output to package pin enable */ + bool bWinSampleInvertEn; /*!< CMP window/sample signal invert enable */ + bool bEventCloseWinEn; /*!< CMP out event close window enable */ + bool bAnalogConfTransByp; /*!< CMP analog configuration transition bypass enable */ + uint16 u16AnalogConfTransBypCnt; /*!< Target count value for bypass function */ + uint8_t u8FilterPeriod; /*!< CMP set Filter Sample Period */ + CMP_ModSelType eModSel; /*!< CMP set function mode */ + CMP_InvertType eInvert; /*!< CMP output Invert or not(invert, non-invert) */ + CMP_OutSelectType eOutSelect; /*!< CMP output filter or not(CMPO = CMPOUT_FILTER/CMPOUT_WIN) */ + CMP_OutWinLevelType eOutWinLevel; /*!< CMP output when window close(hold, userdefine) */ + CMP_OutWinLevel_UserDefType eOutWin; /*!< CMP output under userdefine (0, 1) */ + CMP_EventType eEventSelect; /*!< CMP output event cause window close(rising edge, falling edge) */ + CMP_FilterCntType eFilterCnt; /*!< CMP filter count numbers(0,1,2,3,4) */ + CMP_SpeedModSelType eSpeedMod; /*!< CMP speed mode(low,high) */ + CMP_HystCtrlType eHystCrtl; /*!< CMP hysteresis internal control(0,1,2,3) */ +} CMP_ComparatorType; + +/** + * @brief Defines the comparator interrupt configuration + * + * @note This structure is used to configure CMP interrupt + * Implements : CMP_InterruptType + */ +typedef struct +{ + bool bRisingIntEn; /*!< Enable/disable rising interrupt */ + bool bFallingIntEn; /*!< Enable/disable falling interrupt */ + bool bChannelScanFlagIntEn; /*!< Enable/disable channel scan flag interrupt */ + CMP_CompleteIntCallback pInterrupterNotify; /*!< CMP complete interrupt callback */ +} CMP_InterruptType; + +/** + * @brief Defines the comparator dma configuration + * + * @note This structure is used to configure CMP dma + * Implements : CMP_DmaType + */ +typedef struct +{ + bool bRisingDmaEn; /*!< Enable/disable rising edge trigger dma */ + bool bFallingDmaEn; /*!< Enable/disable falling edge trigger dma */ +} CMP_DmaType; + +/** + * @brief Defines the comparator channel selected in channel scan mode + * + * @note This structure is used to configure a CMP channel that want to be enabled in channel scan sequence + * Implements : CMP_ChannelScanChannelCfgType + */ +typedef struct +{ + CMP_MuxSelType eChannel; /*!< Enabled channel */ + bool bPreSetState; /*!< Preset state for the given channel */ + bool bCurState; /*!< Current state for the given channel */ +} CMP_ChannelScanChannelCfgType; + +/** + * @brief Defines the comparator channel scan configuration + * + * @note This structure is used to configure CMP channel scan + * Implements : CMP_ChannelScanType + */ +typedef struct +{ + uint8_t u8ChannelScanInitModulus; /*! C/C++ Build -> Settings -> Tool Settings -> Target Processor -> Float ABI -> FP instructions(hard) -> FPU Type set to "fpv5-sp-d16" +2) configure FCIDE to enable FPU compiler support, "Properties" -> C/C++ Build -> Settings -> Tool Settings -> GNU Arm Cross C Compiler -> Preprocessor -> Defined symbols(-D) -> Add "__FPU_PRESENT=1" (without ") +3) and call FPU_Enable to enable FPU at the beginning of program. + +If want to use DSP, +1) configure FCIDE to enable FPU compiler support, Properties -> C/C++ Build -> Settings -> Tool Settings -> Target Processor -> Float ABI -> FP instructions(hard) +2) add MACRO "DRIVER_CM7_DSP_ENABLE" in FCIDE Properties -> C/C++ General -> Paths and Symbols -> Symbols -> GNU C and GNU C++ and Assembly +3) add Include Path to project Properties -> C/C++ General -> Paths and Symbols -> Includes -> GNU C and GNU C++ and Assembly: + ../../../../../Template/Device/CMSIS5_590/DSP/Include + ../../../../../Template/Device/CMSIS5_590/Core/Include + ../../../../../Template/Device/CMSIS5_590/DSP/PrivateInclude +4) and call FPU_Enable to enable FPU at the beginning of program. + @endverbatim + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-11 Flagchip054 N/A First version for FC7240 + ******************************************************************************** */ +#ifndef _DRIVER_FC4XXX_DRIVER_DSP_H_ +#define _DRIVER_FC4XXX_DRIVER_DSP_H_ + +#include "device_header.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* _DRIVER_FC4XXX_DRIVER_DSP_H_ */ diff --git a/Inc/fc7xxx_driver_eim.h b/Inc/fc7xxx_driver_eim.h new file mode 100644 index 0000000..2978ac6 --- /dev/null +++ b/Inc/fc7xxx_driver_eim.h @@ -0,0 +1,87 @@ +/** + * @file fc7xxx_driver_eim.h + * @author Flagchip + * @brief FC7xxx EIM driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- ------------------- +* 0.1.0 2024-01-14 qxw0100 N/A First version for FC7240 +********************************************************************************/ +#ifndef _DRIVER_FC7XXX_DRIVER_EIM_H_ +#define _DRIVER_FC7XXX_DRIVER_EIM_H_ + +#include "HwA_eim.h" +#include "device_header.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * @addtogroup fc4xxx_driver_eim + * @{ + */ + + +/** + * @brief Initialize EIM function + * + * @param pEimInitCfg Initialization structure of EIM + * @return return 0: initialize successful. 1: invalid parameter + */ +EIM_RetType EIM_Init(const EIM_InitType *pEimInitCfg); + +/** + * @brief Initialize EIM function + * + * @param eEimChannel channel want to set + * @param eDwpType Cpu to use + * @param bLockStatus Lock the cpu control settings + * @return Set operation success/failed + */ +EIM_RetType EIM_SetDwpMode(const EIM_ChannelType eEimChannel, const EIM_DWPType eDwpType, bool bLockStatus); + +/** + * @brief Deinin EIM function + * + */ +void Eim_Deinit(void); + +/** + * @brief Enable CPU lockstep monitor + * + * @param eEimCpuType EIM_CPU0_LOCKSTEP or EIM_CPU1_LOCKSTEP + * @param eMonitorType EIM_MONITOR0 or EIM_MONITOR1 + */ +void EIM_CpuLockStepMonitorSet_MonSet(const EIM_CPU_ChnType eEimCpuType,const EIM_MONType eMonitorType); + +/** + * @brief Clear CPU lockstep monitor + * + * @param eEimCpuType EIM_CPU0_LOCKSTEP or EIM_CPU1_LOCKSTEP + * @param eMonitorType EIM_MONITOR0 or EIM_MONITOR1 + */ +void EIM_CpuLockStepMonitorSet_MonClr(const EIM_CPU_ChnType eEimCpuType,const EIM_MONType eMonitorType); + +/** + * @brief Clean CPU lockstep monitor bit + * + * @param eEimCpuType EIM_CPU0_LOCKSTEP or EIM_CPU1_LOCKSTEP + * @param eMonitorType EIM_MONITOR0 or EIM_MONITOR1 + */ +void EIM_CpuLockStepMonitorClr(const EIM_CPU_ChnType eEimCpuType, const EIM_MONType eMonitorType); + +/** @} */ /* fc7xxx_driver_eim */ + +#if defined(__cplusplus) +} +#endif +#endif /* _DRIVER_FC4XXX_DRIVER_EIM_H_ */ diff --git a/Inc/fc7xxx_driver_erm.h b/Inc/fc7xxx_driver_erm.h new file mode 100644 index 0000000..2b74128 --- /dev/null +++ b/Inc/fc7xxx_driver_erm.h @@ -0,0 +1,107 @@ +/** + * @file fc7xxx_driver_erm.h + * @author Flagchip + * @brief FC7xxx ERM driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-14 qxw0100 N/A First version for FC7240 +********************************************************************************/ +#ifndef _DRIVER_FC7XXX_DRIVER_ERM_H_ +#define _DRIVER_FC7XXX_DRIVER_ERM_H_ + +#include "HwA_erm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* @addtogroup fc7xxx_driver_erm + * @{ + */ + +typedef enum +{ + ERM_STATUS_SUCCESS = 0U, /**< ERM status success */ + ERM_STATUS_PARAM_INVALID = 1U /**< ERM status parameter invalid */ +} ERM_RetType; + +/** @brief Erm interrupt notification type */ +typedef void (*ERM_InterruptCallBackType)(void); + +/** + * @brief Structure to configure ERM Init type + * + */ +typedef struct +{ + ERM_ChannelType eChannel; /*!< ERM enable memory No, No 0-31 */ + ERM_InterruptType eInt; /*!< ERM Interrupt type */ + uint8 u8ErmEnable; /*!< ERM enable Interrupt */ + ERM_InterruptCallBackType pIsrNotify; /**< Erm interrupt notification function pointer */ +} ERM_MemorytInitType; +/** + * @brief Initialize ERM function + * + * @param pErmInt_cfg Initialization structure of ERM + * @return return 0: initialize successful. 1: invalid parameter + */ + +ERM_RetType Erm_Init(const ERM_MemorytInitType *pErmInt_cfg); + +/** + * @brief De-initialize ERM function + * Restore the ERM instance to its reset state + */ +void Erm_DeInit(void); +/** + * @brief ERM Read EARn address. + * @param eChannel The channel type + * @return u32Address The error address + */ +//uint32_t ERM_ReadAddress(ERM_channelType eChannel); + +/** + * @brief ERM Clear SRn register. + * + * This function Clear ERM SR0 register. + */ +void ERM_ClearSRnRegister(void); + +/** + * @brief ERM read SRn register. + * + * This function Clear ERM SR0 register. + * @param u8Index the SRn channel + */ +uint32_t ERM_ReadSRnVal(uint8_t u8Index); + +/** + * @brief ERM clear CRn register. + * + * This function Clear ERM CRn register. + * @param u8Index of the CRn channel + */ +void ERM_ClearCRnVal(uint8_t u8Index); + +/** + * @brief ERM clear SRn register. + * + * This function Clear ERM SR0 register. + * @param u8Index the SRn channel + */ +uint32_t ERM_ClearSRnVal(uint8_t u8Index); +/** @} */ /* fc7xxx_driver_erm */ + +#if defined(__cplusplus) +} +#endif +#endif /* _DRIVER_FC4XXX_DRIVER_ERM_H_ */ diff --git a/Inc/fc7xxx_driver_fciic.h b/Inc/fc7xxx_driver_fciic.h new file mode 100644 index 0000000..6915170 --- /dev/null +++ b/Inc/fc7xxx_driver_fciic.h @@ -0,0 +1,209 @@ +/** + * @file fc7xxx_driver_fciic.h + * @author Flagchip + * @brief FC7xxx FCIIC driver type definition and API + * @version 0.2.0 + * @date 2022-12-05 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ + +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2022/12/31 qxw0052 N/A First version for FC7300 + * 0.2.0 2023/02/14 qxw0052 N/A Fix MISRA issues + *********************************************************************************/ + +#ifndef _DRIVER_FC7XXX_DRIVER_FCIIC_H_ +#define _DRIVER_FC7XXX_DRIVER_FCIIC_H_ + +#include "HwA_fciic.h" + +/** + * @addtogroup fc7xxx_driver_iic + * @{ + */ + +/** + * \brief IIC initial data define + * + */ +typedef struct +{ + uint32_t u32ClkSrcHz; /**< module clock hz */ + uint8_t bMasterMode; /**< bMasterMode=1 master mode */ + uint8_t u8SlaveAddr; /**< if bMasterMode=0, this is used, and address format is 7bits , not ended with R/W bit */ + uint8_t bTxFifoWMrk; /**< Tx FIFO Water Mark, FIFO always on, transmit FIFO is equal or less than TXWATER, set TDF */ + uint8_t bRxFifoWMrk; /**< Tx FIFO Water Mark, FIFO always on, receive FIFO is greater than RXWATER, set RDF */ + uint8_t bEnDma; /**< Enable DMA) */ + uint32_t u32Frequency; /**< normal frequency, only used in master mode */ + +} FCIIC_InitType; + + + +/** + * \brief IIC transmit data define + * + */ +typedef struct +{ + FCIIC_TX_CMDType eCmd; /**< command type */ + uint8_t u8Data; /**< 8bit data */ +} FCIIC_TxDataType; + + +/** + * \brief IIC receive data define + * + */ +typedef struct +{ + uint8_t u8Data; /**< 8bit data */ +} FCIIC_RxDataType; + + +/** Error call back function type */ +typedef void (*FCIIC_ErrorInterrupt_CallBackType)(uint8_t u8IicIndex, uint8_t bMaster, uint32_t u32Error); + +/** Receive call back function type */ +typedef void (*FCIIC_RxInterrupt_CallBackType)(uint8_t u8IicIndex, FCIIC_RxDataType *pRxCfg); + +/** + * \brief IIC interrupt callback setting + * + */ +typedef struct +{ + uint8_t bEnErrorInterrupt; /**< enable error interrupt */ + FCIIC_ErrorInterrupt_CallBackType pErrorNotify; /**< error interrupt callback function address */ + uint8_t bEnRxInterrupt; /**< enable receive interrupt */ + FCIIC_RxInterrupt_CallBackType pRxNotify; /**< receive interrupt callback function address */ + +} FCIIC_InterruptType; + + +/** + * \brief This Function is used to initial IIC instance + * + * \param u8IicIndex Iic Index, 0,1 + * \param pInitCfg is the structure address of IIC initial configuration parameters, and it contains IIC instance + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Init(uint8_t u8IicIndex, FCIIC_InitType *pInitCfg); + +/** + * \brief This Function is used to de-initial IIC instance + * + * \param u8IicIndex Iic Index, 0,1 + * \param pInitCfg is the structure address of IIC initial configuration parameters, bMaster should be set + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_DeInit(uint8_t u8IicIndex, FCIIC_InitType *pInitCfg); + +/** + * \brief This Function is used to configure IIC master interrupt + * + * \param u8IicIndex Iic Index, 0,1 + * \param pIntCfg contains IIC instance and interrupt callback functions + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Master_SetInterrupt(uint8_t u8IicIndex, FCIIC_InterruptType *pIntCfg); + +/** + * \brief This Function is used to transmit data in master mode + * + * \param u8IicIndex Iic Index, 0,1 + * \param pTxData contains IIC instance and buffer address + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Master_Transmit(uint8_t u8IicIndex, FCIIC_TxDataType *pTxData); + +/** + * \brief This Function is used to get master status + * + * \param u8IicIndex Iic Index, 0,1 + * \param eStatus is status type enumeration + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Master_GetStatus(uint8_t u8IicIndex, FCIIC_MasterStatusType eStatus); + +/** + * \brief This Function is used to receive data when polling (not used when rx interrupt enabled) in master mode + * + * \param u8IicIndex Iic Index, 0,1 + * \param pRxData contains IIC instance + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Master_Receive(uint8_t u8IicIndex, FCIIC_RxDataType *pRxData); + +/** + * \brief This Function is used to get master error value + * + * \param u8IicIndex Iic Index, 0,1 + * \return error value + */ +uint32_t FCIIC_Master_GetError(uint8_t u8IicIndex); + +/** + * \brief This Function is used to clear master error value + * + * \param u8IicIndex Iic Index, 0,1 + */ +void FCIIC_Master_ClrError(uint8_t u8IicIndex); + +/** + * \brief This Function is used to configure IIC slave interrupt + * + * \param u8IicIndex Iic Index, 0,1 + * \param pIntCfg contains IIC instance and interrupt callback functions + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Slave_SetInterrupt(uint8_t u8IicIndex, FCIIC_InterruptType *pIntCfg); + +/** + * \brief This Function is used to transmit data in slave mode + * + * \param u8IicIndex Iic Index, 0,1 + * \param pTxData contains IIC instance and buffer address + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Slave_Transmit(uint8_t u8IicIndex, FCIIC_TxDataType *pTxData); + +/** + * \brief This Function is used to receive data when polling (not used when rx interrupt enabled) in slave mode + * + * \param u8IicIndex Iic Index, 0,1 + * \param pRxData contains IIC instance and buffer address + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Slave_Receive(uint8_t u8IicIndex, FCIIC_RxDataType *pRxData); + +/** + * \brief This Function is used to get slave error value + * + * \param u8IicIndex Iic Index, 0,1 + * \return error value + */ +uint32_t FCIIC_Slave_GetError(uint8_t u8IicIndex); + +/** + * \brief This Function is used to clear slave error value + * + * \param u8IicIndex Iic Index, 0,1 + */ +void FCIIC_Slave_ClrError(uint8_t u8IicIndex); + + +#ifdef FCIIC_MASTER_STOP + uint8_t FCIIC_Master_Stop(uint8_t u8IicIndex); +#endif + + +/** @}*/ + +#endif diff --git a/Inc/fc7xxx_driver_fcpit.h b/Inc/fc7xxx_driver_fcpit.h new file mode 100644 index 0000000..6eb08e9 --- /dev/null +++ b/Inc/fc7xxx_driver_fcpit.h @@ -0,0 +1,179 @@ +/** + * @file fc7xxx_driver_fcpit.h + * @author Flagchip + * @brief FC7xxx FCPIT driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-10 Flagchip0076 N/A First version for FC7240 +********************************************************************************/ + +#ifndef _DRIVER_FC7XXX_DRIVER_FCPIT_H_ +#define _DRIVER_FC7XXX_DRIVER_FCPIT_H_ +#include "HwA_fcpit.h" + +/** + * @addtogroup fc7xxx_driver_fcpit + * @{ + */ + +/** @brief Fcpit return type. */ +typedef enum +{ + FCPIT_STATUS_SUCCESS = 0U, + FCPIT_STATUS_PARAM_INVALID = 1U, + FCPIT_STATUS_FUNCTION_ERROR = 2U +} FCPIT_StatusType; + +/** @brief Fcpit trigger source */ +typedef enum +{ + FCPIT_TRIGGER_INTERNAL_0 = 0, + FCPIT_TRIGGER_INTERNAL_1, + FCPIT_TRIGGER_INTERNAL_2, + FCPIT_TRIGGER_INTERNAL_3, + FCPIT_TRIGGER_EXTERNAL +} FCPIT_TriggerSelectType; + +/** @brief callback function type */ +typedef void (*FCPIT_InterruptCallBackType)(void); + +typedef struct +{ + FCPIT_ChannelType eFcpitChannel; /**< Fcpit channel number */ + FCPIT_TriggerSelectType eTriggerSel; /**< trigger source */ + bool bStartOnTrigger; /**< Fcpit timer start when triggered */ + bool bStopOnInterrupt; /**< Fcpit timer stop on interrupt */ + bool bReloadOnTrigger; /**< Fcpit timer reload when triggered */ +} FCPIT_TrggerType; + +/** @brief Fcpit interrupt structure */ +typedef struct +{ + FCPIT_ChannelType eFcpitChannel; /**< Fcpit channel number */ + bool bChannelIsrEn; /**< whether to use interrupt */ + FCPIT_InterruptCallBackType pIsrNotify; /**< interrupt notification function */ +} FCPIT_IntType; + +/** @brief Fcpit initialization type */ +typedef struct +{ + FCPIT_ChannelType eFcpitChannel; /**< Fcpit channel number */ + FCPIT_TimerModeType eMode; /**< Fcpit counter mode */ + bool bChainModeEn; /**< whether to use chain mode, if use this mode, channel must not be the channel 0 */ + uint32_t u32TimerValue; /**< timer compare value, the range of value is related to the counter mode */ + + bool bDebugEn; /**< whether to use debug mode ,if enable this mode, the counter will stop when debugging. */ + bool bLowPowerModeEn; /**< Configure the timer channels to continue running or stop when the device enters the LPM mode */ +} FCPIT_InitType; + +/** @brief FCPIT instance number */ +typedef enum +{ + FCPIT_0 = 0U, +} FCPIT_InstanceType; + + +/* global functions */ +/** + * @brief Initialize Fcpit instance. + * @param eFcpit instance + * @param pInitStruct Fcpit initialization structure + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_Init(const FCPIT_InstanceType eFcpit, const FCPIT_InitType *const pInitStruct); + +/** + * @brief Initialize Fcpit trigger configuration + * @param eFcpit instance + * @param pTrgStruct Fcpit trigger structure + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_InitTrigger(const FCPIT_InstanceType eFcpit, const FCPIT_TrggerType *const pTrgStruct); + +/** + * @brief De-initialize Fcpit instance. + * @param eFcpit instance + */ +FCPIT_StatusType FCPIT_Deinit(const FCPIT_InstanceType eFcpit); + +/** + * @brief Initialize Fcpit interrupt functionality + * @param eFcpit instance + * @param pTrgStruct Fcpit interrupt structure + * @return Fcpit return type + * @note this function will stop timer + */ +FCPIT_StatusType FCPIT_InitInterrupt(const FCPIT_InstanceType eFcpit, const FCPIT_IntType *const pIntStruct); + +/** + * @brief Enable Fcpit interrupt + * @param eFcpit instance + * @param pIntStruct Fcpit interrupt structure + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_EnableInterrupt(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel); + +/** + * @brief Disable Fcpit interrupt + * @param eFcpit instance + * @param eChannel Fcpit channel + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_DisableInterrupt(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel); + +/** + * @brief Fcpit start timer + * @param eFcpit instance + * @param eChannel Fcpit channel + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_Start(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel); + +/** + * @brief Fcpit stop + * @param eFcpit instance + * @param eChannel Fcpit channel + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_Stop(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel); + +/** + * @brief Update Fcpit channel value + * @param eFcpit instance + * @param eChannel Fcpit channel + * @param u32ChannelValue in/Out value + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_UpdateChannelValue(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel, const uint32_t u32ChannelValue); + +/** + * @brief read Fcpit channel time stamps. + * @param eFcpit instance + * @param eChannel Fcpit channel + * @param *u32timeStampValue channel value + * @return Fcpit return type + */ + +FCPIT_StatusType FCPIT_ReadTimstamp(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel,uint32_t *u32timeStampValue); + +/** + * @brief Immediately update Fcpit channel value + * @param eFcpit instance + * @param eChannel Fcpit channel + * @param u32ChannelValue in/Out value + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_ImmediateUpdateChannelValue(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel, const uint32_t u32ChannelValue); + +/** @}*/ /* fc7xxx_driver_fcpit */ +#endif diff --git a/Inc/fc7xxx_driver_fcsmu.h b/Inc/fc7xxx_driver_fcsmu.h new file mode 100644 index 0000000..1b3d75a --- /dev/null +++ b/Inc/fc7xxx_driver_fcsmu.h @@ -0,0 +1,251 @@ +/** + * @file fc7xxx_driver_fcsmu.h + * @author Flagchip + * @brief FC7xxx FCSMU driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-14 qxw0100 N/A First version for FC7240 + ******************************************************************************** */ +#ifndef _DRIVER_FC7XXX_DRIVER_FCSMU_H_ +#define _DRIVER_FC7XXX_DRIVER_FCSMU_H_ +#include "device_header.h" +#include "HwA_fcsmu.h" +/** + * @addtogroup fc7xxx_driver_fcsmu + * @{ +. */ + +typedef enum +{ + FCSMU_INSTANCE_0 = 0U, /*!< FCSMU instance 0 is selected. */ +} FCSMU_InstanceType; + +typedef enum +{ + FCSMU_STATUS_SUCCESS = 0U, /*!< FCSMU operation is succeed. */ + FCSMU_STATUS_ERROR = 1U /*!< FCSMU operation is failed. */ +} FCSMU_StatusType; + +typedef enum +{ + FCSMU_STATE_NORMAL = 0U, /*!< FCSMU state normal */ + FCSMU_STATE_CONGIG = 1U, /*!< FCSMU state config */ + FCSMU_STATE_WARN = 2U, /*!< FCSMU state warn */ + FCSMU_STATE_FAULT = 3U /*!< FCSMU state fault */ +} FCSMU_StateType; + +typedef enum +{ + FCSMU_OP_STATE_IDLE = 0U, /*!< FCSMU operation status idle */ + FCSMU_OP_STATE_BUSY = 1U, /*!< FCSMU operation status busy */ + FCSMU_OP_STATE_FAILED = 2U, /*!< FCSMU operation status failed */ + FCSMU_OP_STATE_SUCCESSFUL = 3U /*!< FCSMU operation status successful */ +} FCSMU_OperationStatusType; + +typedef enum +{ + FCSMU_CRC_SW_MODE = 0U, /*!< FCSMU crc software mode. */ + FCSMU_CRC_TRIGGER_MODE = 1U /*!< FCSMU crc trigger mode. */ +} FCSMU_CrcModeType; + +typedef enum +{ + FCSMU_SOUT_CTRL_BY_FSM = 0U, /*!< SOUT is controlled by the FSM. */ + FCSMU_SOUT_CTRL_KEEP_LOW = 1U, /*!< SOUT keeps low. */ + FCSMU_SOUT_CTRL_BY_FSM2 = 2U, /*!< SOUT is controlled by the FSM. */ + FCSMU_SOUT_CTRL_KEEP_HIGH_THEN_FSM = 3U /*!< SOUT keeps high until a fault occures on a channel, then controlled by FSM. */ +} FCSMU_SoutControlType; + +typedef enum +{ + FCSMU_SOUT_DEFAUT_POLARITY = 0U, /*!< Default polarity. */ + FCSMU_SOUT_SWITCH_POLARITY = 1U /*!< Switch polarity. */ +} FCSMU_SoutPolarityType; + +typedef enum +{ + FCSMU_SOUT_PROTOCOL_DUAL_RAIL = 0U, + FCSMU_SOUT_PROTOCOL_TIME_SWITCH = 1U, + FCSMU_SOUT_PROTOCOL_BISTABLE = 2U, + FCSMU_SOUT_PROTOCOL_FAULT_TOGGLE = 3U, + FCSMU_SOUT_PROTOCOL_TIME_DUAL_RAIL = 4U, + FCSMU_SOUT_PROTOCOL_DIAG0 = 5U, + FCSMU_SOUT_PROTOCOL_DIAG1 = 6U, + FCSMU_SOUT_PROTOCOL_DIAG2 = 7U, +} FCSMU_SoutProtocolType; + +typedef enum +{ + FCSMU_WARNING_IRQ = 0U, + FCSMU_FAULT_IRQ = 1U, + FCSMU_CFG_TIMEOUT = 2U +} FCSMU_IQRType; + +typedef enum +{ + FCSMU_FAULT_CHANNEL_NONE = 0x0U, + FCSMU_FAULT_CHANNEL_TEMP_ERROR = 0x1U, /*!< Event from temperature sensor. */ + FCSMU_FAULT_CHANNEL_PMC_ERROR = 0x2U, /*!< Voltage out of range indication from PMC. */ + FCSMU_FAULT_CHANNEL_NVR_ERROR = 0x4U, /*!< NVR load error/System abnormal alarm signal. */ + FCSMU_FAULT_CHANNEL_STCU_BIST_ERROR = 0x8U, /*!< STCU MBIST or LBIST fail. */ + FCSMU_FAULT_CHANNEL_STCU_LS0_ERROR = 0x10U, /*!< Lockstep compare fault. */ + FCSMU_FAULT_CHANNEL_SYSTEM_CPU0_ERROR = 0x40U, /*!< System RAM CPU0 access error. */ + FCSMU_FAULT_CHANNEL_SYSTEM_NON_CPU_ERROR = 0x200U, /*!< System RAM None CPU access error. */ + FCSMU_FAULT_CHANNEL_SCM_CPU0_ERROR = 0x400U, /*!< Matrix Access Monitor ECC check CPU0 error. */ + FCSMU_FAULT_CHANNEL_SCM_NON_CPU_ERROR = 0x2000U, /*!< Matrix Access Monitor ECC check non CPU error. */ + FCSMU_FAULT_CHANNEL_CPU0_ECC_ERROR = 0x4000U, /*!< Including ITCM/DTCM/ICACHE/DCACHE. */ + FCSMU_FAULT_CHANNEL_CMU4_FAIL_ERROR = 0x80000U, /*!< CMU4 failure interrupt. */ + FCSMU_FAULT_CHANNEL_CMU_FAIL_ERROR = 0x100000U, /*!< CMU1/2 failure interrupt. */ + FCSMU_FAULT_CHANNEL_FLASH_ECC_ERROR = 0x200000U, /*!< Flash ECC error. */ + FCSMU_FAULT_CHANNEL_SCG_PLL_FOSC_ERROR = 0x400000U, /*!< PLL/FOSC loss of clock. */ + FCSMU_FAULT_CHANNEL_DMA0_ERROR = 0x800000U, /*!< DM0 AHB Error/LS Error/CFG RAM Error. */ + FCSMU_FAULT_CHANNEL_INTM0_ERROR = 0x2000000U, /*!< Interrupt Monitor error. */ + FCSMU_FAULT_CHANNEL_FMC_ERROR = 0x10000000U, /*!< FMC ECC error. */ + FCSMU_FAULT_CHANNEL_SCG_SCM_CRC_ERROR = 0x20000000U, /*!< SCG and SCM etc. CRC check error. */ + FCSMU_FAULT_CHANNEL_MAM_WDG_ERROR = 0x80000000U, /*!< MAM master access time out error. */ +} FCSMU_ChannelAssignmentType; + +/** + * @brief FCSMU Channel ISR callback function prototype + * + */ +typedef void (*FCSMU_ISRCallbackType)(FCSMU_IQRType eIrqType, uint32_t u32IrqChannel); + +typedef struct +{ + bool bEnable; /*!< Enable or disable status output. */ + bool eFastMode; /*!< Enable or disable fast mode. */ + bool bDivex; /*!< SOUT Divider Extend Control. */ + FCSMU_SoutControlType eSoutCtrl; /*!< Configure Sout Control. */ + FCSMU_SoutPolarityType ePolarity; /*!< Status output polarity. */ + FCSMU_SoutProtocolType eProtocal; /*!< Status output protocal. */ + uint32_t u32Delaytimer; /*!< Configure the safe mode request delay in cycles of CLKSAFE. */ + uint32_t u32Divder; /*!< Configure the status output divider ratio. + bDevex = 0, SOUT_freq = CLKSAFE_freq/((SOUT_DIV+1)*2*256) + bDevex = 1, SOUT_freq = CLKSAFE_freq/((SOUT_DIV+1)*2*64) + */ + uint32_t u32SoutChannel; /*!< Configure the status output channel. */ +} FCSMU_StatusOutputConfigType; + +typedef struct +{ + uint32_t u32WarnTo; /*!< FCSMU warning timeoout value. */ + uint32_t u32WarnChannel; /*!< FCSMU warning channel. */ + uint32_t u32FaultChannel; /*!< FCSMU fault channel. */ + uint32_t u32WarnInterruptChannel; /*!< FCSMU warning interrupt channel. */ + uint32_t u32FaultInterruptChannel; /*!< FCSMU fault interrupt channel. */ + uint32_t u32FaultResetChannel; /*!< FCSMU fault reset channel. */ + uint32_t u32SoftwareClearedChannel; /*!< FCSMU fault is Cleard by software. */ + FCSMU_ISRCallbackType pISRCallback; /*!< ISR callback. */ +} FCSMU_InitCfgType; + +/** + * @brief Init the FCSMU. + * + * @param pInitConfig FCSMU initial configuration. + */ +FCSMU_StatusType FCSMU_init(const FCSMU_InitCfgType *pInitConfig); + +/** + * @brief Config the FCSMU status output. + * + * @param pInitConfig FCSMU status output configuration. + */ +FCSMU_StatusType FCSMU_ConfigStatusOutput(FCSMU_StatusOutputConfigType *pInitConfig); + +/** + * @brief Generate the CRC. + * + */ +void FCSMU_CrcGen(void); + +/** + * @brief Query CRC busy status. + * + * @return FCSMU_CrcModeType CRC status. + */ +bool FCSMU_IsCrcBusy(void); + +/** + * @brief Configure the FCSMU CRC. + * + * @param eMode Crc mode. + * @return FCSMU_StatusType Status of configuration. + */ +FCSMU_StatusType FCSMU_CrcConfig(FCSMU_CrcModeType eMode); + +/** + * @brief Clear the falut flag. + * + * @param u32FaultChannel Channel flag to be cleared. + * @return FCSMU_StatusType Status of clear. + */ +FCSMU_StatusType FCSMU_ClearFaultFlag(uint32_t u32FaultChannel); + +/** + * @brief Transform state from configuration to normal. + * + * @return FCSMU_StatusType Status of Transformation. + */ +FCSMU_StatusType FCSMU_TransStateCTN(void); + +/** + * @brief Transform state from normal to configuration. + * + * @return FCSMU_StatusType Status of Transformation. + */ +FCSMU_StatusType FCSMU_TransStateNTC(void); + +/** + * @brief Inject the fault tp fcsmu. + * + * @param u32ChannelIndex channel to be injected. + */ +void FCSMU_InjectionFault(uint32_t u32ChannelIndex); + +/** + * @brief Get the fault channels fcsmu. + * + * @return Fault channels. + */ +uint32_t FCSMU_GetFaultChannel(void); + +/** + * @brief Get the interrupt state of fcsmu. + * + * @return interrupt state. + */ +uint32_t FCSMU_GetIrqState(void); + +/** + * @brief Get the NTF flags of fcsmu. + * + * @return NTF flags. + */ +uint32_t FCSMU_GetNtfFlag(void); + +/** + * @brief Get the WTF flags of fcsmu. + * + * @return WTF flags. + */ +uint32_t FCSMU_GetWtfFlag(void); + +/** + * @brief Get the NTW flags of fcsmu. + * + * @return NTW flags. + */ +uint32_t FCSMU_GetNtwFlag(void); + +/** @}*/ /* fc7xxx_driver_fcsmu. */ +#endif diff --git a/Inc/fc7xxx_driver_fcspi.h b/Inc/fc7xxx_driver_fcspi.h new file mode 100644 index 0000000..d6c4513 --- /dev/null +++ b/Inc/fc7xxx_driver_fcspi.h @@ -0,0 +1,620 @@ +/** + * @file fc7xxx_driver_fcspi.h + * @author Flagchip + * @brief FC7xxx FCSPI driver type definition and API + * @version 0.1.0 + * @date 2024-1-12 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024/01/12 Flagchip071 N/A First version for FC7240 +********************************************************************************/ +#ifndef _DRIVER_FC7XXX_DRIVER_FCSPI_H_ +#define _DRIVER_FC7XXX_DRIVER_FCSPI_H_ + +#include "device_header.h" +#include "HwA_fcspi.h" +#include "fc7xxx_driver_dma.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * @addtogroup fc4xxx_driver_fcspi + * @{ + */ + +/** + * @brief Status returned by FCSpi APIs + * + */ +typedef enum { + FCSPI_STATUS_SUCCESS = 0, /*!< API execute successfully */ + FCSPI_STATUS_INSTANCE_ERROR, /*!< FCSpi instance index parameter error */ + FCSPI_STATUS_PARAM_ERR, /*!< parameter error */ + FCSPI_STATUS_ERROR, /*!< some error occur in API */ + FCSPI_STATUS_NO_DATA, /*!< user want to transfer nothing */ + FCSPI_STATUS_BUSY, /*!< FCSpi hardware is busy, not available */ + FCSPI_STATUS_SYNC_TIMEOUT, /*!< FCSpi synchronous transfer timeout */ + FCSPI_STATUS_TRANSFER_FAIL, /*!< FCSpi transfer fail */ + + FCSPI_STATUS_TRIGGER_OK, /*!< FCSpi user trigger successfully */ + FCSPI_STATUS_TRIGGER_ABORT_TX_FAIL, /*!< FCSpi user trigger fail due to send underrun */ + FCSPI_STATUS_TRIGGER_ABORT_RX_FAIL, /*!< FCSpi user trigger fail due to receive overflow */ + FCSPI_STATUS_TRIGGER_FINISH /*!< FCSpi user trigger finish, all data already send */ +} FCSPI_StatusType; + +/** + * @name Type definition for FCSpi master/slave mode + * + */ +/**@{*/ + +/** + * @brief FCSpi hardware instances + * + * FCSpi consist of multiple hardware instances, for example, FCSPI0, FCSPI1... + * Just as the enumeration type "FCSPI_InstanceType" definition shows. + * We use variables of this type to indicate which hardware instance to use. + */ +typedef enum { + FCSPI_0 = 0, + FCSPI_1 = 1, + FCSPI_2 = 2, + FCSPI_3 = 3, + FCSPI_4 = 4, + FCSPI_5 = 5, +} FCSPI_InstanceType; + + +/** + * @brief PCS(Peripheral Chip Select) pin select + * + * FCSPI has four PCS lines, in our driver code, + * we use FCSPI_PCS_0/FCSPI_PCS_1/FCSPI_PCS_2/FCSPI_PCS_3 to present them. + * Like the above, we use enumeration type "FCSPI_PCSType" to indicate + * which PCS to connect to the external device, + * "PCS" is short for Peripheral Chip Select, + * which usually use low level voltage to select the external chip to communicate. + */ +typedef enum { + FCSPI_PCS_0 = 0U, + FCSPI_PCS_1 = 1U, + FCSPI_PCS_2 = 2U, + FCSPI_PCS_3 = 3U +} FCSPI_PCSType; + +/** + * @brief Valid PCS pin voltage polarity + * + * The external device determines the voltage polarity (low or high) of PCS to enable it. + * So, FCSpi use enumeration type "FCSPI_PcsPolarityType" to indicate + * the polarity the PCS output when select the external device + */ +typedef enum { + FCSPI_PCS_POL_ACTIVE_HIGH = 1, /*!< pcs use high level to select external device */ + FCSPI_PCS_POL_ACTIVE_LOW = 0 /*!< pcs use low level to select external device */ +} FCSPI_PcsPolarityType; + +/** + * @brief SCK(serial clock) active phase + * + * Just as the SPI bus specification says, clock polarity (CPOL) and clock phase (CPHA) determine the sample point. + * FCSpi use enumeration type "FCSPI_SckPolarityType" to present CPOL configuration. + */ +typedef enum { + FCSPI_SCK_ACTIVE_HIGH = 0, /*!< sck is high level when active (idles low). */ + FCSPI_SCK_ACTIVE_LOW = 1 /*!< sck is low level when active (idles high). */ +} FCSPI_SckPolarityType; + +/** + * @brief SCK(serial clock) sample edge + * + * Just as the SPI bus specification says, + * clock polarity (CPOL) and clock phase (CPHA) determine the sample point. + * FCSpi use enumeration type "FCSPI_SckSamplePhaseType" to present CPHA configuration. + */ +typedef enum { + FCSPI_SCK_SAMPLE_FIRST_EDGE = 0, /*!< sample on first edge of sck active polarity, change on second */ + FCSPI_SCK_SAMPLE_SECOND_EDGE = 1 /*!< changed on first edge of sck active polarity, sample on second */ +} FCSPI_SckSamplePhaseType; + +/** + * @brief The order of rx/tx handles bit + * + * When send or receive data, the MOSI and MISO handle only one bit at a time, + * FCSpi map the bit data order according to the specific configuration. + * FCSpi driver provides the enumeration type "FCSPI_BitFirstOrderType" to indicate the order. + */ +typedef enum { + FCSPI_MSB_FIRST = 0, /*!< most significant bit first handle, from msb to lsb */ + FCSPI_LSB_FIRST = 1 /*!< least significant bit first handle, from lsb to msb */ +} FCSPI_BitFirstOrderType; + + +/** + * @brief Transfer method between memory and FCSpi's registers + * + * FCSpi support transferring data by ISR, DMA, or user poll. + * + * If use ISR method, in interrupt handler function, + * the driver will write data to register "FCSPI_TX_DATA" to push it into Tx FIFO + * and read the register "FCSPI_RX_DATA" to pop data from Rx FIFO. + * When finish, the hardware will create an interrupt to notify the end. + * + * If use DMA, the DMA channel and priority should also be configured. + * After configuring these, driver user doesn't need to take care of the detail of transferring. + * Just send data or send & receive at same time. When finish, the hardware will create an interrupt to notify the end. + * + * If use User Poll mode, driver user should call + * "FCSPI_SyncTransfer" API to move the data until it return error or finished. + * In this mode, the interrupt in driver is disabled. + */ +typedef enum { + FCSPI_TRANSFER_TRIGGER_SRC_ISR = 0, /*!< software(interrupt function) move data between register and memory, when finish, notified by interrupt */ + FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR, /*!< hardware(DMA) move data between register and memory, when finish, notified by interrupt */ + FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL /*!< NOT use ISR and DMA!!! driver user use API to move data between register and memory, notified by return value when finish */ +} FCSPI_TriggerSrcType; + + +/** + * @brief transfer stop callback function's prototype + * + * FCSpi use this type to define one function pointer variable, + * which is called when the transfer is aborted or finished. + */ +typedef void (*FCSPI_StopCbType)(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInIsr); + + +/** + * @brief Type return by semaphore callback function + * + * If want to use synchronous tranfer API, driver user need to provide semaphore callback, + * these callback function should return value of this enumeration defined. + */ +typedef enum { + FCSPI_SEMAPHORE_SUCCESS = 0, /*!< semaphore function execute successfully */ + FCSPI_SEMAPHORE_FAIL = 1, /*!< semaphore function execute fail */ + FCSPI_SEMAPHORE_TIMEOUT = 2 /*!< wait to get semaphore until reaching deadline */ +} FCSPI_SemaphoreStatType; + +/** + * @brief Callback function to reset semaphore + * + * After calling this function, the semaphore variable has a zero semaphore count. + * Then if try to take the semaphore, the take API will blocks. + * + * If the RTOS is FreeRTOS, the reference code as following. + * + * @code + * FCSPI_SemaphoreStatType SpiSemaphoreReset(FCSPI_InstanceType eInst) + * { + * while ( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) == pdTRUE ); + * return FCSPI_SEMAPHORE_SUCCESS; + * } + * @endcode + */ +typedef FCSPI_SemaphoreStatType (*FCSPI_SemaphoreResetCbType)(FCSPI_InstanceType eInst); + +/** + * @brief Callback function to obtain semaphore + * + * This function will only try to obtain the semaphore before the time expires. + * + * If the RTOS is FreeRTOS, the reference code as following. + * + * @code + * FCSPI_SemaphoreStatType SpiSemaphoreTake(FCSPI_InstanceType eInst, uint32_t u32Timeout) + * { + * if ( xSemaphoreTake( xSemaphore, ( TickType_t ) u32Timeout ) == pdTRUE ) + * return FCSPI_SEMAPHORE_SUCCESS; + * else + * return FCSPI_SEMAPHORE_TIMEOUT; + * } + * @endcode + */ +typedef FCSPI_SemaphoreStatType (*FCSPI_SemaphoreTakeCbType)(FCSPI_InstanceType eInst, uint32_t u32Timeout); + + +/** + * @brief Callback function to release semaphore + * + * This function will only release semaphore. + * + * If the RTOS is FreeRTOS, the reference code as following. + * + * @code + * static FCSPI_SemaphoreStatType SpiSemaphorePost(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInIsr) + * { + * FCSPI_SemaphoreStatType eRet = FCSPI_SEMAPHORE_SUCCESS; + * + * (void)eInst; + * if (FCSPI_TRUE == bIsInIsr) + * { + * BaseType_t tBase = pdFALSE; + * + * if ( xSemaphoreGiveFromISR( xSemaphore, &tBase ) == pdPASS ) + * { + * portYIELD_FROM_ISR(tBase); + * eRet = FCSPI_SEMAPHORE_SUCCESS; + * } + * else + * { + * eRet = FCSPI_SEMAPHORE_FAIL; + * } + * } + * else + * { + * if ( xSemaphoreGive( xSemaphore ) == pdPASS ) + * eRet = FCSPI_SEMAPHORE_SUCCESS; + * else + * eRet = FCSPI_SEMAPHORE_FAIL; + * } + * + * return eRet; + * } + * @endcode + */ +typedef FCSPI_SemaphoreStatType (*FCSPI_SemaphorePostCbType)(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInIsr); + + +/** + * @brief Asynchronous Transfer data buffer information + * + * @note @verbatim +if init frame bit count need N bytes to store, for example, 7bits need N=1 byte, 9bits need N=2bytes, 23bits need N=3bytes. +N = 1, one frame data stored in pSendBuffer using uint8_t, driver read data using step 1byte. +N = 2, one frame data stored in pSendBuffer using uint16_t, driver read data using step 2byte. +N = 3, one frame data stored in pSendBuffer using uint32_t, driver read data using step 4byte.The highest byte is dropped. +N > 3, byte count of frame data stored in the parameter pointer pSendBuffer aligned with 4bytes, + for example, one frame uses 5bytes, it will need two uint32_t, the highest 3bytes are dropped, + driver API user need declare as "uint32_t data[N]"; it use index 0 to 1, the next frame is 2 to 3. + @endverbatim + */ +typedef struct { + const uint8_t *pSendBuffer; /*!< The buffer containing data to be send, must keep valid before sending is terminated or finished, can be NULL */ + uint8_t *pReceiveBuffer; /*!< Optional, can be NULL. Buffer to store the data received.The data received is 1byte aligned, no dummy data insert. */ + uint16_t u16FrameCount; /*!< The frame count to be sent, the data stored in pSendBuffer is divided into many frames. */ +} FCSPI_AsyncDataInfType; + + +/** + * @brief Synchronous Transfer data buffer information + * + * @note @verbatim +if init frame bit count need N bytes to store, for example, 7bits need N=1 byte, 9bits need N=2bytes, 23bits need N=3bytes. +N = 1, one frame data stored in pSendBuffer using uint8_t, driver read data using step 1byte. +N = 2, one frame data stored in pSendBuffer using uint16_t, driver read data using step 2byte. +N = 3, one frame data stored in pSendBuffer using uint32_t, driver read data using step 4byte.The highest byte is dropped. +N > 3, byte count of frame data stored in the parameter pointer pSendBuffer aligned with 4bytes, + for example, one frame uses 5bytes, it will need two uint32_t, the highest 3bytes are dropped, + driver API user need declare as "uint32_t data[N]"; it use index 0 to 1, the next frame is 2 to 3. + @endverbatim + */ +typedef struct { + const uint8_t *pSendBuffer; /*!< The buffer containing data to be send, must keep valid before sending is terminated or finished, can be NULL */ + uint8_t *pReceiveBuffer; /*!< Optional, can be NULL. Buffer to store the data received.The data received is 1byte aligned, no dummy data insert. */ + uint16_t u16FrameCount; /*!< The frame count to be sent, the data stored in pSendBuffer is divided into many frames. */ + uint32_t u32Timeout; /*!< The timeout value, it will only be passed to the semaphore callback API configured by driver user */ +} FCSPI_SyncDataInfType; + +/** + * @brief tx/rx remain information + * + * + */ +typedef struct { + uint32_t u32ByteCountSendRemained; /*!< byte count remains to be sent */ + uint32_t u32ByteCountReceiveRemained; /*!< byte count remains to be get */ +} FCSPI_TransferRemainInfType; + + +/** + * @brief configuration when use DMA + * + * + */ +typedef struct { + DMA_InstanceType eDMAInstance; /*!< DMA Instance number, if DMA not used, this ignored */ + uint8_t u8RxDMAChannel; /*!< DMA channel number for Rx, if DMA not used, this ignored */ + uint8_t u8TxDMAChannel; /*!< DMA channel number for Tx, if DMA not used, this ignored */ + uint8_t u8RxDMAChannelPriority; /*!< DMA channel priority for Rx, should differ from others in project scope */ + uint8_t u8TxDMAChannelPriority; /*!< DMA channel priority for Tx, should differ from others in project scope */ +} FCSPI_TriggerDmaInfType; +/**@}*/ + + + +/** + * @name Type definition for FCSpi master mode + * + */ +/**@{*/ +/** + * @brief FCSpi Master mode configuration + * + * When One FCSpi instance used as master side, API "FCSPI_Master_Init" need this parameter to configure the driver. + * + */ +typedef struct { + uint32_t u32FCSpiSrcClk; /*!< fcspi hardware module source clock */ + + /* peripheral chip select configuration */ + FCSPI_PCSType ePcs; /*!< chip select pin */ + FCSPI_PcsPolarityType ePcsPolarity; /*!< chip select pin polarity */ + FCSPI_AtomicBoolType eIsPcsContinuous; /*!< keep PCS select enable until transfer finish */ + + /* about sample point, sample bit order */ + FCSPI_SckSamplePhaseType eSckSamplePhase; /*!< select which edge of active sck clock to capture data */ + FCSPI_SckPolarityType eSckPolarity; /*!< select output sclk clock polarity */ + FCSPI_BitFirstOrderType eBitFirstOrder; /*!< transmit LSB/MSB first */ + uint32_t u32BitCntPerSecond; /*!< baud rate in bits per second, actual baudrate is calculated in driver, it's the nearest value to this parameter */ + uint16_t u16BitCountPerFrame; /*!< bit count of one frame, should >= 8, we call the data after pcs select, before pcs become invalid, as a frame, */ + + FCSPI_TriggerSrcType eTransferTriggerSrc; /*!< type of transfer data between memory and data register of FCSPI */ + + /* if eTransferTriggerSrc is "FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR", these following fields should be set, or ingore */ + FCSPI_TriggerDmaInfType tTriggerDmaInf; /*!< if trigger src is DMA, this MUST configure */ + + /* if to be notified when transmittion successfully or aborted, need set these following fields */ + FCSPI_StopCbType pStopNotifyCb; /*!< transfer stop(transfer successfully or aborted) callback function, can be NULL */ + + /* if want to use semaphore to synchronous transfer, the following need to be set */ + FCSPI_SemaphoreResetCbType pSemaResetCb; /*!< function to reset the semaphore to init state */ + FCSPI_SemaphoreTakeCbType pSemaTakeCb; /*!< function pointer to get the semaphore */ + FCSPI_SemaphorePostCbType pSemaPostCb; /*!< function pointer to release the semaphore */ +} FCSPI_MasterCfgType; + +/** + * @brief parameters about the holding time (in us) between PCS and SCK + * + * Configure the duration (in us) of the clock voltage between PCS and SCK + */ +typedef struct { + uint32_t u32PCStoPCSHoldUs; /*!< Configures the delay cycles from the PCS negation to the next PCS assertion, in microsecond(us) */ + uint32_t u32SCKtoPCSHoldUs; /*!< Configure the delay cycles from the last SCK edge to the PCS negation, in microsecond(us) */ + uint32_t u32PCStoSCKHoldUs; /*!< Configure the delay cycles from the PCS assertion to the first SCK edge, in microsecond(us) */ +} FCSPI_MasterSckPcsHoldTimeType; + +/** + * @brief parameters about the holding time (in PCS/100) between PCS and SCK + * + * Configure the duration (in PCS/100) of the clock voltage between PCS and SCK + */ +typedef struct { + uint32_t u32PCStoPCSHoldPercentage; /*!< Configure the delay cycles from the PCS negation to the next PCS assertion, in PCS/100 */ + uint32_t u32SCKtoPCSHoldPercentage; /*!< Configure the delay cycles from the last SCK edge to the PCS negation, in PCS/100 */ + uint32_t u32PCStoSCKHoldPercentage; /*!< Configure the delay cycles from the PCS assertion to the first SCK edge, in PCS/100 */ +} FCSPI_MasterSckPcsHoldSckCycleType; + +/** + * @brief parameters about the PCS and its Polarity + * + * Configure the specific PCS to be used and its active polarity when FCSPI running as master side + */ +typedef struct { + FCSPI_PCSType ePcs; /*!< Which PCS pin to configure */ + FCSPI_PcsPolarityType ePolarity; /*!< Pin's active polarity */ +} FCSPI_MasterPcsConfType; +/**@}*/ + + +/** + * @name Type definition for FCSpi slave mode + * + */ +/**@{*/ +/** + * @brief FCSpi Slave mode configuration + * + * When One FCSpi instance used as slave side, API "FCSPI_Slave_Init" need this parameter to configure the driver. + */ +typedef struct { + FCSPI_BitFirstOrderType eBitFirstOrder; /*!< transmit LSB/MSB first */ + uint16_t u16BitCountPerFrame; /*!< bit count of one frame, should >= 8 */ + + FCSPI_PcsPolarityType ePcsPolarity; /*!< pcs polarity */ + FCSPI_PCSType ePcs; /*!< chip select pin */ + + + FCSPI_SckSamplePhaseType eSckSamplePhase; /*!< select which edge of active sck clock to capture data */ + FCSPI_SckPolarityType eSckPolarity; /*!< selects clock polarity */ + + + + FCSPI_TriggerSrcType eTransferTriggerSrc; /*!< type of transfer data between memory and data register of FCSPI */ + + /* if eTransferTriggerSrc is "FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR", these following fields should be set, or ingore */ + FCSPI_TriggerDmaInfType tTriggerDmaInf; /*!< if trigger src is DMA, this MUST configure */ + + /* if to be notified when transmittion stop(successfully, fail, aborted), need set these following fields */ + FCSPI_StopCbType pStopNotifyCb; /*!< transfer stop(successfully or fail, or aborted) callback function, can be NULL */ + + /* if want to use semaphore to synchronous transfer, the following need to be set */ + FCSPI_SemaphoreResetCbType pSemaResetCb; /*!< function to reset the semaphore to init state */ + FCSPI_SemaphoreTakeCbType pSemaTakeCb; /*!< function pointer to get the semaphore */ + FCSPI_SemaphorePostCbType pSemaPostCb; /*!< function pointer to release the semaphore */ +} FCSPI_SlaveCfgType; +/**@}*/ + +/** + * @name API declaration for FCSpi master mode + * + */ +/**@{*/ +/** + * @brief Init the FCSpi instance as spi master side + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Configuration of the FCSpi, MUST NOT NULL + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, some error occur. + */ +FCSPI_StatusType FCSPI_Master_Init(const FCSPI_InstanceType eInst, const FCSPI_MasterCfgType *pCfg); + +/** + * @brief Configure the holding time (in us) between PCS and SCK + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Configure the delay parameters between PCS and SCK, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, the hardware is busy now. + */ +FCSPI_StatusType FCSPI_Master_SetSckPcsHoldTime(const FCSPI_InstanceType eInst, const FCSPI_MasterSckPcsHoldTimeType *pCfg); + +/** + * @brief Configure the holding time (in SCK/100) between PCS and SCK + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Configure the delay parameters between PCS and SCK, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, the hardware is busy now. + */ +FCSPI_StatusType FCSPI_Master_SetSckPcsHoldSckPercentage(const FCSPI_InstanceType eInst, const FCSPI_MasterSckPcsHoldSckCycleType *pCfg); +/** + * @brief Select the PCS to use and configure + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Parameters about PCS configuration, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, the hardware is busy now. + */ +FCSPI_StatusType FCSPI_Master_SelectPcs(const FCSPI_InstanceType eInst, const FCSPI_MasterPcsConfType *pCfg); +/**@}*/ + +/** + * @name API declaration for FCSpi slave mode + * + */ +/**@{*/ +/** + * @brief Init the FCSpi instance as spi slave side + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Configuration of the FCSpi + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, some error occur. + */ +FCSPI_StatusType FCSPI_Slave_Init(const FCSPI_InstanceType eInst, const FCSPI_SlaveCfgType *pCfg); +/**@}*/ + +/** + * @name Type definition for FCSpi master/slave mode + * + */ +/**@{*/ +/** + * @brief Send and receive asynchronously + * 1) If the trigger source is driver user poll, this api not support this mode. + * 2) If the trigger source is interrupt or DMA, this api will start the transmission, then return immediately. + * After transmission stop, it will trigger an interrupt. + * During the transmission, the send data buffer and receive data buffer + * should keep valid until the transmission stop. + * @param eInst Which FCSpi Hardware instance + * @param pCfg the data information, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when start transfer successfully. Others, some error occur. + */ +FCSPI_StatusType FCSPI_AsyncTransfer(const FCSPI_InstanceType eInst, const FCSPI_AsyncDataInfType *pCfg); + +/** + * @brief Send and receive synchronously + * 1) If the semaphore callbacks are configured, + * and the driver is configured transmitting triggered by interrupt, or by DMA, + * the driver will use semaphore to wait the transmission stopped. + * In this case, the timeout value is passed to semaphore callback directly. + * 2) If the semaphore callbacks are not configured, + * this api will poll the status when triggered by interrupt or DMA, + * or poll to trigger the transmission when the mode is "FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL". + * In this case, the timeout value has different meaning for different trigger mode. + * Read the source code for detail. + * @param eInst Which FCSpi Hardware instance + * @param pCfg the data information, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when transfer successfully. Others, some error occur. + */ +FCSPI_StatusType FCSPI_SyncTransfer(const FCSPI_InstanceType eInst, const FCSPI_SyncDataInfType *pCfg); + +/** + * @brief If it's in transfer, get its stat, or get the last transfer's stat. + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg the transfer information, can be null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when the last transfer is finish successfully. Others, busy or error occur. + */ +FCSPI_StatusType FCSPI_GetLatestTransferStat(const FCSPI_InstanceType eInst, FCSPI_TransferRemainInfType *pCfg); + +/** + * @brief Abort current transfer if exist, or just recovery the hardware. + * + * @param eInst Which FCSpi Hardware instance + */ +void FCSPI_AbortTransfer(const FCSPI_InstanceType eInst); + +/** + * @brief Deinit the FCSpi + * + * @param eInst Which FCSpi Hardware instance + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when deinit the FCSpi successfully. Others, the hardware is busy now. + */ +FCSPI_StatusType FCSPI_Deinit(const FCSPI_InstanceType eInst); + +/** + * @brief Select the trigger source(DMA with interrupt / interrupt / user poll) + * + * @param eInst Which FCSpi Hardware instance + * @param eSrc three source, 1) DMA move data between memory and registers, notified when finish by interrupt; 2) purely by interrupt; 3) purely by user poll. + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when successfully. Others, error. + */ +FCSPI_StatusType FCSPI_SelectTriggerSrc(FCSPI_InstanceType eInst, FCSPI_TriggerSrcType eSrc); + +/** + * @brief fcspi 0 interrupt handler + * + * @note This function should be called as/in FCSPI 0 interrupt handler + */ +void FCSPI0_IRQHandler(void); + +/** + * @brief fcspi 1 interrupt handler + * + * @note This function should be called as/in FCSPI 1 interrupt handler + */ +void FCSPI1_IRQHandler(void); + +/** + * @brief fcspi 2 interrupt handler + * + * @note This function should be called as/in FCSPI 2 interrupt handler + */ +void FCSPI2_IRQHandler(void); + +/** + * @brief fcspi 3 interrupt handler + * + * @note This function should be called as/in FCSPI 3 interrupt handler + */ +void FCSPI3_IRQHandler(void); + +/** + * @brief fcspi 4 interrupt handler + * + * @note This function should be called as/in FCSPI 4 interrupt handler + */ +void FCSPI4_IRQHandler(void); + +/** + * @brief fcspi 5 interrupt handler + * + * @note This function should be called as/in FCSPI 5 interrupt handler + */ +void FCSPI5_IRQHandler(void); + +/**@}*/ + +/** @}*/ /* fc7xxx_driver_fcspi */ + +#if defined(__cplusplus) +} +#endif +#endif /* _DRIVER_FC7XXX_DRIVER_FCSPI_H_ */ diff --git a/Inc/fc7xxx_driver_fcuart.h b/Inc/fc7xxx_driver_fcuart.h new file mode 100644 index 0000000..b7f4201 --- /dev/null +++ b/Inc/fc7xxx_driver_fcuart.h @@ -0,0 +1,434 @@ +/** + * @file fc7xxx_driver_fcuart.h + * @author Flagchip + * @brief FC7xxx FCUart driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ + +/******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-10 Flagchip0122 N/A FC7xxx internal release version + ********************************************************************************/ + + +#ifndef _DRIVER_FC7XXX_DRIVER_FCUART_H_ +#define _DRIVER_FC7XXX_DRIVER_FCUART_H_ + + +#include "HwA_fcuart.h" + +/** + * @addtogroup fc7xxx_driver_fcuart + * @{ + */ + +/********* Macro ************/ +#define FCUART_FIFO_DEPTH 16U + +#define ESCAPE_CHARACTER (char)0x5c +#define ENTER (uint8_t)0x0d +#define NEW_LINE (uint8_t)0x0a +#define SPACE (uint8_t)0x20 +#define FLOAT_ZERO 0.00000001 + + +/********* Local typedef ************/ +/** + * @brief FCUART error status + * + */ +typedef enum +{ + FCUART_ERROR_OK = 0x00U, /**< FCUART_ERROR_OK means no error */ + FCUART_ERROR_INVALID_VERSION = 0x01U, /**< FCUART_ERROR_INVALID_VERSION means version is not same */ + FCUART_ERROR_FAILED = 0x02U, /**< FCUART_ERROR_FAILED means operation is failed */ + FCUART_ERROR_INVALID_PARAM = 0x04U, /**< FCUART_ERROR_INVALID_PARAM means parameters are invalid */ + FCUART_ERROR_INVALID_SIZE = 0x08U, /**< FCUART_ERROR_INVALID_SIZE means size is invalid */ + FCUART_ERROR_INVALID_SEQUENCE = 0x10U, /**< FCUART_ERROR_INVALID_SEQUENCE means sequence is error */ + FCUART_ERROR_TIMEOUT = 0x20U, /**< FCUART_ERROR_TIMEOUT means operation is timeout */ +}FCUART_ErrorTypeEnum; + +/** + * @brief UART fifo receive idle character number + */ +typedef enum +{ + FCUART_FIFO_RX_IDLE_DISABLE = 0U, + FCUART_FIFO_RX_IDLE_CHARACTER_1, + FCUART_FIFO_RX_IDLE_CHARACTER_2, + FCUART_FIFO_RX_IDLE_CHARACTER_4, + FCUART_FIFO_RX_IDLE_CHARACTER_8, + FCUART_FIFO_RX_IDLE_CHARACTER_16, + FCUART_FIFO_RX_IDLE_CHARACTER_32, + FCUART_FIFO_RX_IDLE_CHARACTER_64 +} FCUART_Fifo_RxIdleCharNumType; + + +/** + * @brief UART CTRL register interrupt + * + */ +typedef enum +{ + FCUART_INT_CTRL_ORIE = FCUART_CTRL_ORIE_MASK, + FCUART_INT_CTRL_NEIE = FCUART_CTRL_NEIE_MASK, + FCUART_INT_CTRL_FEIE = FCUART_CTRL_FEIE_MASK, + FCUART_INT_CTRL_PEIE = FCUART_CTRL_PEIE_MASK, + FCUART_INT_CTRL_TIE = FCUART_CTRL_TIE_MASK, + FCUART_INT_CTRL_TCIE = FCUART_CTRL_TCIE_MASK, + FCUART_INT_CTRL_RIE = FCUART_CTRL_RIE_MASK, + FCUART_INT_CTRL_IIE = FCUART_CTRL_IIE_MASK, + FCUART_INT_CTRL_TE = FCUART_CTRL_TE_MASK, + FCUART_INT_CTRL_RE = FCUART_CTRL_RE_MASK, + FCUART_INT_CTRL_M0IE = FCUART_CTRL_M0IE_MASK, + FCUART_INT_CTRL_M1IE = FCUART_CTRL_M1IE_MASK +} FCUART_InterruptSel; + +/** + * @brief UART error status type + * + */ +typedef enum +{ + FCUART_ERROR_NONE = 0x0000U, /**< FCUART_ERROR_NONE No Error, */ + FCUART_ERROR_RORF = 0x0001U, /**< FCUART_ERROR_RORF Receiver Overrun Flag, */ + FCUART_ERROR_NF = 0x0002U, /**< FCUART_ERROR_NF Noise Flag, */ + FCUART_ERROR_FEF = 0x0004U, /**< FCUART_ERROR_FEF Frame Error Flag, */ + FCUART_ERROR_PEF = 0x0008U, /**< FCUART_ERROR_PEF Parity Error Flag, */ + FCUART_ERROR_RPEF = 0x0010U, /**< FCUART_ERROR_RPEF Receive Data Parity Error Flag, */ + FCUART_ERROR_TPEF = 0x0020U /**< FCUART_ERROR_TPEF Transmit Data Parity Error Flag, */ +}FCUART_ErrorStatusType; + +/** + * @brief UART idle character number + */ +typedef enum +{ + FCUART_IDLE_CHARCTER_1 = 0U, + FCUART_IDLE_CHARCTER_2, + FCUART_IDLE_CHARCTER_4, + FCUART_IDLE_CHARCTER_8, + FCUART_IDLE_CHARCTER_16, + FCUART_IDLE_CHARCTER_32, + FCUART_IDLE_CHARCTER_64, + FCUART_IDLE_CHARCTER_128 +} FCUART_IdleCharNumType; + +/** + * @brief UART idle type + */ +typedef enum +{ + FCUART_START_AFTER_STARTBIT = 0U, + FCUART_START_AFTER_STOPBIT +} FCUART_IdleStartType; + +/** + * @brief UART initial data define + * + */ +typedef struct +{ + uint32_t u32ClkSrcHz; /**< module clock hz */ + FCUART_BitModeType eBitMode; /**< 8bits or 9bits */ + bool bParityEnable; /**< Parity Enable=1 */ + FCUART_ParityType eParityType; /**< parity type */ + FCUART_StopBitNumType eStopBit; /**< stop bit num; */ + bool bEnTxFifo; /**< Enable Tx FIFO, 16 data words depth */ + uint8_t u8TxFifoWaterMark; /**< Tx FIFO,When FIFO/buffer number equal or less than this + an interrupt or a DMA request will be generated */ + bool bEnRxFifo; /**< Enable Rx FIFO, 16 data words depth */ + uint8_t u8RxFifoWaterMark; /**< Rx FIFO, When FIFO/buffer number greater than this + an interrupt or a DMA request will be generated */ + FCUART_Fifo_RxIdleCharNumType eFifoRxIdleCharNum; /**< Fifo Rx idle character number */ + bool bEnTxEmptyDma; /**< Enable transmit DMA */ + bool bEnRxFullDma; /**< Enable receiver full DMA */ + bool bEnRxIdleDma; /**< Enable Rx Idle DMA */ + FCUART_IdleCharNumType eIdleCharNum; /**< Idle character number */ + FCUART_IdleStartType eIdleStart; /**< Idle character start type */ + uint32_t u32Baudrate; /**< normal baud-rate */ + uint32_t u32TransmitTimeout; /**< transmit timeout tick, default 3000U */ +} FCUART_InitType; + +/** + * @brief UART transmit and receive data define + * + */ +typedef struct +{ + uint8_t* pDatas; /**< Data buffer point, Must be initial with a array address */ + uint32_t u32DataLen; /**< data length */ +}FCUART_DataType; + +/** Error call back function type, errors are combine with FCUART_ErrorStatusType */ +typedef void (*FCUART_ErrorInterrupt_CallBackType)(uint8_t u8UartIndex, uint32_t u32Error); + +/** Transmit/Receive call back function type */ +typedef void (*FCUART_TxRxInterrupt_CallBackType)(uint8_t u8UartIndex, FCUART_DataType *pTxRxCfg); + +/** Idle call back function type */ +typedef void (*FCUART_IdleInterrupt_CallBackType)(uint8_t u8UartIndex); + +/** + * @brief UART callback functions data define + * + */ +typedef struct +{ + bool bEnErrorInterrupt; /**< enable error interrupt */ + FCUART_ErrorInterrupt_CallBackType pErrorNotify; /**< error interrupt callback function address */ + bool bEnRxInterrupt; /**< enable receive interrupt */ + FCUART_DataType *pRxBuf; /**< receive interrupt message buffer */ + FCUART_TxRxInterrupt_CallBackType pRxNotify; /**< receive interrupt callback function address */ + bool bEnTxInterrupt; /**< enable receive interrupt */ + FCUART_DataType *pTxBuf; /**< transfer interrupt message buffer */ + FCUART_TxRxInterrupt_CallBackType pTxEmptyNotify; /**< transfer empty interrupt callback function address */ + FCUART_TxRxInterrupt_CallBackType pTxCompleteNotify; /**< transfer complete interrupt callback function address */ + bool bEnIdleInterrupt; /**< enable idle interrupt */ + FCUART_IdleInterrupt_CallBackType pIdleNotify; /**< idle interrupt callback function address */ +} FCUART_InterruptType; + +/** + * @brief UART WakeUp functions data define + * + */ +typedef struct +{ + bool bEnWakeup; /**< enable wake-up */ + uint32_t u32WakeUpData; /**< wake-up data */ + +} FCUART_WakeupType; + + + +/** Errortype Define as uint8 */ +typedef uint8_t FCUART_ErrorType; + +/* ################################################################################## */ +/* ########################### Global Prototype Functions ########################### */ + + +/** + * @brief Initial UART variables Memory + * + */ +void FCUART_InitMemory(uint8_t u8UartIndex); + +/** + * @brief This Function is used to initial UART instance + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pInitCfg contains clock, baud-rate, Bit Mode, parity and so on. + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Init(uint8_t u8UartIndex, FCUART_InitType *pInitCfg); + +/** + * @brief This Function is used to de-initial UART instance + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_DeInit(uint8_t u8UartIndex); + +/** + * @brief This Function is used to set UART interrupt + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pInterruptCfg contains callback functions + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_SetInterrupt(uint8_t u8UartIndex, FCUART_InterruptType *pInterruptCfg); + +/** + * @brief This Function is used to set UART WakeUp + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pWakeupCfg contains UART wake-up parameters + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_SetWakeup(uint8_t u8UartIndex, FCUART_WakeupType *pWakeupCfg); + +/** + * @brief This Function is used to start receiving + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_StartReceive(uint8_t u8UartIndex); + +/** + * @brief This Function is used to stop receiving + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_StopReceive(uint8_t u8UartIndex); + +/** + * @brief This Function is used to start transmit + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_StartTransmit(uint8_t u8UartIndex); + +/** + * @brief This Function is used to stop transmitting + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_StopTransmit(uint8_t u8UartIndex); + +/** + * @brief This Function is used to transmit UART data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pUartData contains UART data and length + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Transmit(uint8_t u8UartIndex, FCUART_DataType *pUartData); + + +/** + * @brief This Function is used to print ASCII char from UART + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param fmt is char format + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Printf(uint8_t u8UartIndex, char* fmt,...); + +/** + * @brief Get Stat Flag + * + * @param u8UartIndex UART instance + * @param eStatusType stat type + * @return FCUART STAT status flag + */ +uint32_t FCUART_GetStatus(uint8_t u8UartIndex, FCUART_StatType eStatusType); + +/** + * @brief This Function is used to receive data when polling (not used when rx interrupt enabled) + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pRxMsg is data buffer address, and pDatas need to be initialed with external buffer + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Receive_Polling(uint8_t u8UartIndex, FCUART_DataType *pRxMsg); + + +/** + * @brief This Function is used to get error when polling (not used when error interrupt enabled) + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pErrorValue is error value + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Error_Polling(uint8_t u8UartIndex, uint32_t *pErrorValue); + +/** + * @brief This Function is used to enable fcuart loop mode + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param bStatus enable/disable status of loop mode + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_SetLoopMode(uint8_t u8UartIndex, bool bStatus); + +/** + * @brief This Function is used to deal with FCUART TxRx interrupt + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * + */ +void FCUARTN_RxTx_IRQHandler(uint8_t u8UartIndex); + +/** + * @brief This Function is used to send 9 bits data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param u16Data data to send + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_SendData_9Bits(uint8_t u8UartIndex, uint16_t u16Data); + +/** + * @brief This Function is used to Get 9 bits data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pData pointer to data + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_GetData_9Bits(uint8_t u8UartIndex, uint16_t *pData); + +/** + * @brief This Function is used to send 10 bits data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param u16Data data to send + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_SendData_10Bits(uint8_t u8UartIndex, uint16_t u16Data); + +/** + * @brief This Function is used to Get 10 bits data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pData pointer to data + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_GetData_10Bits(uint8_t u8UartIndex, uint16_t *pData); + +/** + * @brief This Function is used to set bit mode,parity and stop bit + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pData pointer to data + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_SetBitModeAndParity( uint8_t u8UartIndex, + FCUART_BitModeType eBitMode, + FCUART_StopBitNumType eStopBit, + FCUART_ParityType eParityType, + bool bParityEnable + ); + +/** + * @brief This Function is used to Get current interrupt mode + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param u32Data Interrupt type to get + * @return true/false + * + */ +bool FCUART_GetInterruptMode(uint8_t u8UartIndex, uint32_t u32Data); + +/** + * @brief This Function is used to assign data to send through interrupt + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pData data pointer + * @param u32Length data length to send + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_AssignTxInterruptData(uint8_t u8UartIndex, uint8_t * pData, uint32_t u32Length); + +/** @}*/ + +#endif diff --git a/Inc/fc7xxx_driver_flash.h b/Inc/fc7xxx_driver_flash.h new file mode 100644 index 0000000..dcbf5ee --- /dev/null +++ b/Inc/fc7xxx_driver_flash.h @@ -0,0 +1,182 @@ +/** + * @file fc7xxx_driver_flash.c + * @author Flagchip + * @brief FC7xxx Flash driver type definition and API + * @version 0.1.0 + * @date 2024-01-11 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-11 Flagchip054 N/A First version for FC7200 + ******************************************************************************** */ +#ifndef _DRIVER_FC7XXX_DRIVER_FLASH_H_ +#define _DRIVER_FC7XXX_DRIVER_FLASH_H_ + +#include "device_header.h" + + +/** + * @addtogroup fc7xxx_driver_flash + * @{ + */ +/*********************************************************************************************************************** + * DEFINES + **********************************************************************************************************************/ + +/* ------------------------- PFlash ------------------------ */ +/** PFlash start address */ +#define PFLASH_ADDR_START 0x01000000U + +#define PFLASH_ADDR_END 0x011FFFFFU + +#define PFLASH_SIZE 0x00200000U /* 256KB */ + +#define PFLASH_BANK_SIZE 0x00100000U + +#define PFLASH_LAST256K_OFFSET 0xC0000UL + +/** Program minimum size */ +#define PFLASH_PROGRAM_PAGE_MIN_SIZE 0x08U /* 8 bytes */ +/** Program maximum */ +#define PFLASH_PROGRAM_PAGE_MAX_SIZE 0x80U /* 128 bytes */ + +/** Erase size */ +#define PFLASH_ERASE_SECTOR_SIZE 0x800U /* 2 KBytes */ + +/** Erase value of flash memory */ +#define PFLASH_ERASED_VALUE 0xFFU + +/** 4 PFlash Banks, every bank is 2MB */ +#define PFLASH_BANK_NUM 0x02U + + +/* ------------------------- DFlash ------------------------ */ + +/** DFlash total size */ +#define DFLASH_SIZE 0x00040000U /* 256KB */ +/** DFlash start address */ +#define DFLASH_ADDR_START 0x04000000U +/** DFlash end address */ +#define DFLASH_ADDR_END 0x0401FFFFU + +/** Program minimum size */ +#define DFLASH_PROGRAM_PAGE_MIN_SIZE 0x08U /* 16 bytes */ +/** Program maximum */ +#define DFLASH_PROGRAM_PAGE_MAX_SIZE 0x80U /* 128 bytes */ + +/** Erase size */ +#define DFLASH_ERASE_SECTOR_SIZE 0x800U /* 8 KBytes */ + +/** Erase value of flash memory */ +#define DFLASH_ERASED_VALUE 0xFFU + +/** 1 DFlash Banks, every bank is 2MB */ +#define DFLASH_BANK_NUM 0x01U + +/** DFlash Bank 0 size */ +#define DFLASH_BANK0_SIZE 0x00040000U + + + +#define FLASH_256KB_SIZE 0x00040000U + + +/** ########################################## Error Code ################################################ */ + + +/** + * \brief FLASH API error status + * + */ +typedef enum +{ + FLASH_ERROR_OK = 0x00U,/**< FLASH_ERROR_OK means no error */ + FLASH_ERROR_NO_INIT, /**< FLASH_ERROR_NO_INIT means rom code api address is not initialed */ + FLASH_ERROR_INVALID_VERSION, /**< FLASH_ERROR_INVALID_VERSION means rom code api version is not same */ + FLASH_ERROR_FAILED, /**< FLASH_ERROR_FAILED means operation is failed */ + FLASH_ERROR_INVALID_PARAM, /**< FLASH_ERROR_INVALID_PARAM means parameters are invalid */ + FLASH_ERROR_INVALID_ADDR, /**< FLASH_ERROR_INVALID_ADDR means address is invalid */ + FLASH_ERROR_INVALID_SIZE, /**< FLASH_ERROR_INVALID_SIZE means size is invalid */ + FLASH_ERROR_INVALID_SEQUENCE, /**< FLASH_ERROR_INVALID_SEQUENCE means sequence is error */ + FLASH_ERROR_TIMEOUT, /**< FLASH_ERROR_TIMEOUT means operation is timeout */ + FLASH_ERROR_END = 0xFFFFFFFFU /**< FLASH_ERROR_END make aligned 32bits */ +}FLASH_StatusType; + +typedef enum +{ + FLASH_BLOCK_SELECT0 =0x000u, + FLASH_BLOCK_SELECT1 =0x001u, + FLASH_DATA_BLOCK_SELECT0 =0x002u +}FLASH_API_BLOCK_SELECT_TYPE; + +/** ########################################## Type define ################################################ */ + + +/** + * \brief Flash driver parameter define + * + */ +typedef struct +{ + uint32_t u32Address; /**< Logical target address */ + uint32_t u32Length; /**< Length in logical sectors or bytes */ + uint8_t *pData; /**< Pointer to data buffer (read only) */ + uint8_t (*wdTriggerFct)(void); /**< Pointer to watchdog handling function */ + uint32_t u32ErrorAddress; /**< Error address */ + +} FLASH_DRIVER_ParamType; + +/** + * \brief Initial Flash api address + * + */ +void FLASHDRIVER_Init(void); + +/** + * \brief flash driver erase block function + * + * \param blk_sel c + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_FlashEraseBlock ( FLASH_API_BLOCK_SELECT_TYPE blk_sel ); + +/** + * \brief Pflash driver erase function, called after FLASHDRIVER_ArrayCopyToRam + * + * \param pFlashParam contains flash erase function parameter, address is align to 0x400, and length is align to 0x400 + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_PFlashEraseSector ( FLASH_DRIVER_ParamType * pFlashParam ); + +/** + * \brief Pflash driver write function, called after FLASHDRIVER_ArrayCopyToRam + * + * \param pFlashParam contains flash write function parameter, address is align to 0x08, and length is align to 0x08 + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_PFlashWrite ( FLASH_DRIVER_ParamType * pFlashParam ); + +/** + * \brief DFlash Driver Function for Erasing + * + * \param pFlashParam flash driver erase parameter + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_DFlashEraseSector(FLASH_DRIVER_ParamType *pFlashParam); + +/** + * \brief DFlash Driver Function for Writing + * + * \param pFlashParam flash driver write parameter + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_DFlashWrite(FLASH_DRIVER_ParamType *pFlashParam); + + +#endif /* end of DRIVER_FLASH_H_ */ diff --git a/Inc/fc7xxx_driver_flexcan.h b/Inc/fc7xxx_driver_flexcan.h new file mode 100644 index 0000000..48c746a --- /dev/null +++ b/Inc/fc7xxx_driver_flexcan.h @@ -0,0 +1,461 @@ +/** + * @file fc7xxx_driver_flexcan.h + * @author Flagchip + * @brief FC7xxx CAN driver type definition and API + * @version 0.1.0 + * @date 2022-02-20 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ + +/* ******************************************************************************** + * Revision History: + * + * Version Date Author Descriptions + * --------- ---------- ------------ --------------- + * 0.1.0 2024-1-13 Flagchip0112 First version for FC7240 + ******************************************************************************** */ + +#ifndef _DRIVER_FC4XXX_DRIVER_FLEXCAN_H_ +#define _DRIVER_FC4XXX_DRIVER_FLEXCAN_H_ + +#include "HwA_flexcan.h" + + +/* ################################################################################## */ +/* ####################################### Macro #################################### */ + +#define FLEXCAN_CHECK_PARAMETERS STD_ON + + +/* ################################################################################## */ +/* ################################### Type define ################################## */ + +/** + * @addtogroup fc7xxx_driver_can + * @{ + */ + + + + + +/** + * @brief FLEXCAN ID Type + * + */ +typedef enum +{ + FLEXCAN_ID_STD = 0x00U, /**< FLEXCAN_ID_STD standard id */ + FLEXCAN_ID_EXT = 0x01U /**< FLEXCAN_ID_EXT extended id */ +} FLEXCAN_IdType; + +/** + * @brief FLEXCAN Data Frame Type + * + */ +typedef enum +{ + FLEXCAN_FRAME_DATA = 0x00U, /**< FLEXCAN_FRAME_DATA data frame */ + FLEXCAN_FRAME_REMOTE = 0x01U /**< FLEXCAN_FRAME_REMOTE remote frame */ +} FLEXCAN_DataType; + + +/** + * @brief FLEXCAN baud-rate clock source + * + */ +typedef enum +{ + FLEXCAN_BAUDCLK_HZ_8M = 8000000U, /**< FLEXCAN_BAUDCLK_HZ_8M 8MHz clock source */ + FLEXCAN_BAUDCLK_HZ_12M = 12000000U, /**< FLEXCAN_BAUDCLK_HZ_12M 12MHz clock source */ + FLEXCAN_BAUDCLK_HZ_16M = 16000000U, /**< FLEXCAN_BAUDCLK_HZ_16M 16MHz clock source */ + FLEXCAN_BAUDCLK_HZ_24M = 24000000U, /**< FLEXCAN_BAUDCLK_HZ_24M 24MHz clock source */ + FLEXCAN_BAUDCLK_HZ_48M = 48000000U, /**< FLEXCAN_BAUDCLK_HZ_48M 48MHz clock source */ + FLEXCAN_BAUDCLK_HZ_96M = 96000000U, /**< FLEXCAN_BAUDCLK_HZ_96M 96MHz clock source */ + FLEXCAN_BAUDCLK_HZ_120M = 120000000U,/**< FLEXCAN_BAUDCLK_HZ_120M 120MHz clock source */ + FLEXCAN_BAUDCLK_HZ_150M = 150000000U /**< FLEXCAN_BAUDCLK_HZ_150M 150MHz clock source */ +} FLEXCAN_BaudClkType; + + + +/** + * @brief FLEXCAN baud-rate source + * + */ +typedef enum +{ + FLEXCAN_BAUD_100K = 100000U, /**< FLEXCAN_BAUD_100K normal bit 100Kbps */ + FLEXCAN_BAUD_125K = 125000U, /**< FLEXCAN_BAUD_100K normal bit 125Kbps */ + FLEXCAN_BAUD_250K = 250000U, /**< FLEXCAN_BAUD_250K normal bit 250Kbps */ + FLEXCAN_BAUD_500K = 500000U, /**< FLEXCAN_BAUD_500K normal bit 500Kbps */ + FLEXCAN_BAUD_800K = 800000U, /**< FLEXCAN_BAUD_500K normal bit 800Kbps */ + FLEXCAN_BAUD_1M = 1000000U,/**< FLEXCAN_BAUD_1M normal bit 1Mbps */ + FLEXCAN_BAUD_2M = 2000000U,/**< FLEXCAN_BAUD_2M normal bit 2Mbps */ + FLEXCAN_BAUD_3M = 3000000U,/**< FLEXCAN_BAUD_3M normal bit 3Mbps */ + FLEXCAN_BAUD_4M = 4000000U,/**< FLEXCAN_BAUD_4M normal bit 4Mbps */ + FLEXCAN_BAUD_5M = 5000000U,/**< FLEXCAN_BAUD_5M normal bit 5Mbps */ + FLEXCAN_BAUD_6M = 6000000U,/**< FLEXCAN_BAUD_6M normal bit 6Mbps */ + FLEXCAN_BAUD_8M = 8000000U /**< FLEXCAN_BAUD_8M normal bit 8Mbps */ +} FLEXCAN_BaudType; + +/** + * @brief FLEXCAN data length type + * + */ +typedef enum +{ + FLEXCAN_DATAWIDTH_8 = 8U, /**< FLEXCAN_DATALEN_8 8 bytes data width */ + FLEXCAN_DATAWIDTH_16 = 16U,/**< FLEXCAN_DATALEN_16 16 bytes data width */ + FLEXCAN_DATAWIDTH_32 = 32U,/**< FLEXCAN_DATALEN_32 32 bytes data width */ + FLEXCAN_DATAWIDTH_64 = 64U /**< FLEXCAN_DATALEN_64 64 bytes data width */ + +} FLEXCAN_DataWidthType; + +/** + * @brief FLEXCAN data length type + * + */ +typedef enum +{ + FLEXCAN_DIR_DISABLE = 0U, /**< FLEXCAN_DATALEN_8 8 bytes data width */ + FLEXCAN_DIR_ENABLE_WITHOUT_TRIG = 1U, /**< FLEXCAN_DATALEN_8 8 bytes data width */ + FLEXCAN_DIR_ENABLE_WITH_TRIG = 3U /**< FLEXCAN_DATALEN_8 8 bytes data width */ +} FLEXCAN_DirectType; + +/** + * @brief FLEXCAN init structure definition + */ +typedef struct +{ + FLEXCAN_ClockSrcType eClkSrcSel; /**< Clock Source Select */ + FLEXCAN_BaudClkType eClkSrcHz; /**< clock hz for baud-rate */ + uint8_t bListenOnly; + uint8_t bEnFd; /**< enable FLEXCAN fd */ + uint8_t bEnBrs; /**< data bit baud-rate used */ + uint8_t bEnRxFifo; /**< Rx FIFO */ + uint8_t bEnDma; /**< The DMA feature FLEXCAN only be used in Rx FIFO */ + uint8_t u8EnhancedFifoDmaWM; /**< The DMA watermark only work in CANFD FIFO mode, range 1- 12 */ + FLEXCAN_BaudType eBaudrate; /**< normal baud-rate */ + FLEXCAN_BaudType eDataBaud; /**< data baud-rate */ + FLEXCAN_DataWidthType eMbDataWidth; /**< when bEnFd=0, only FLEXCAN be set 8; when bEnFd=1, FLEXCAN be set as 8/16/32/64 */ + FLEXCAN_DirectType eDirect; /** C/C++ Build -> Settings -> Tool Settings -> Target Processor -> Float ABI -> FP instructions(hard) -> FPU Type set to "fpv5-sp-d16" +2) configure FCIDE to enable FPU compiler support, "Properties" -> C/C++ Build -> Settings -> Tool Settings -> GNU Arm Cross C Compiler -> Preprocessor -> Defined symbols(-D) -> Add "__FPU_PRESENT=1" (without ") +3) and call FPU_Enable to enable FPU at the beginning of program. + +If want to use DSP, +1) configure FCIDE to enable FPU compiler support, Properties -> C/C++ Build -> Settings -> Tool Settings -> Target Processor -> Float ABI -> FP instructions(hard) +2) add MACRO "DRIVER_CM7_DSP_ENABLE" in FCIDE Properties -> C/C++ General -> Paths and Symbols -> Symbols -> GNU C and GNU C++ and Assembly +3) add Include Path to project Properties -> C/C++ General -> Paths and Symbols -> Includes -> GNU C and GNU C++ and Assembly: + ../../../../../../Template/Device/CMSIS5_590/DSP/Include + ../../../../../../Template/Device/CMSIS5_590/Core/Include + ../../../../../../Template/Device/CMSIS5_590/DSP/PrivateInclude +4) and call FPU_Enable to enable FPU at the beginning of program. + @endverbatim + */ +void FPU_Enable(void); + +/** + * @brief Disable the FPU hardware. + * + */ +void FPU_Disable(void); + +/** @} */ /* fc7xxx_driver_fpu */ +#if defined(__cplusplus) +} +#endif +#endif /* _DRIVER_FC4XXX_DRIVER_FPU_H_ */ diff --git a/Inc/fc7xxx_driver_freqm.h b/Inc/fc7xxx_driver_freqm.h new file mode 100644 index 0000000..14a6d02 --- /dev/null +++ b/Inc/fc7xxx_driver_freqm.h @@ -0,0 +1,143 @@ +/** + * @file fc7xxx_driver_freqm.h + * @author Flagchip + * @brief FC7xxx FREQM driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-14 qxw0100 N/A First version for FC7240 +********************************************************************************/ + +#ifndef _DRIVER_FC4XXX_DRIVER_FREQM_H_ +#define _DRIVER_FC4XXX_DRIVER_FREQM_H_ + +#include "HwA_freqm.h" +#include "stddef.h" +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * @brief FREQM operation return values + * + */ +typedef enum +{ + FREQM_STATUS_SUCCESS = 0U, /*!< The FREQM operation is succeed */ + FREQM_STATUS_PARAM_INVALID, /*!< The FREQM operation is failed because of parameter error */ + FREQM_STATUS_TIMEOUT, /*!< The FREQM operation is failed because of time out */ +} FREQM_StatusType; + +/** + * @brief The FREQM measure counter start interrupt callback function prototype + * + */ +typedef void (*FREQM_MesCntStartCallBackType)(void); + +/** + * @brief The FREQM measure counter stop interrupt callback function prototype + * + */ +typedef void (*FREQM_MesCntStopCallBackType)(void); + +/** + * @brief The FREQM reference counter stop interrupt callback function prototype + * + */ +typedef void (*FREQM_RefCntStopCallBackType)(void); +/** + * @brief The FREQM fault interrupt callback function prototype + * + */ +typedef void (*FREQM_FaultCallBackType)(void); + + +/** + * @brief The configuration option for the FREQM interrupt + * + */ +typedef struct +{ + bool bIntEnable; /*!< interrupt enable mask */ + FREQM_MesCntStartCallBackType pMesCntStartCallback; /*!< Measure Counter Start interrupt callback */ + FREQM_MesCntStopCallBackType pMesCntStopCallback; /*!< Measure Counter Stop interrupt callback */ + FREQM_RefCntStopCallBackType pRefCntStopCallback; /*!< Reference Counter Stop interrupt callback */ + FREQM_FaultCallBackType pFaultCallback; /*!< Fault interrupt callback */ +} FREQM_InterruptType; + +/** + * @brief The basic configuration option for the FREQM peripheral + * + */ +typedef struct +{ + uint32_t u32MesLen; + uint32_t u32RefTo; + FREQM_MesClkSelType eClkSel; /*!< Ftu clock source */ + uint8_t u8PredivVal; /*!< Frequency of the Reload Opportunities. Range is 0-31, */ +} FREQM_InitType; + + +/** + * @brief Initialize FREQM configuration + * + * @param pInitStruct the basic configurations of the FREQM + * @return FREQM_StatusType whether the operation is successfully + */ +FREQM_StatusType FREQM_Init(const FREQM_InitType *const pInitStruct); + +/** + * @brief De-initialize the FREQM + * + * @param eInstance the selected FREQM + * @return FREQM_StatusType whether the operation is successfully + */ +FREQM_StatusType FREQM_DeInit(void); + +/** + * @brief Start the FREQM + * + * @return FREQM_StatusType whether the operation is successfully + */ +FREQM_StatusType FREQM_ClearStatus(void); + +/** + * @brief Start the reference/measure counter + * + */ +void FREQM_StartMeasureCnt(void); + +/** + * @brief Get saved reference counter value + * + * @return uint32_t saved reference counter value + */ +uint32_t FREQM_GetRefCntSave(void); + +/** + * @brief Interrupt IRQ handle of FREQM + * + */ +void FREQM_IRQHandler(void); +/** + * @brief FREQM initialize interrupt function + * + * @param pIntStruct FREQM interrupt structure + * @return FREQM_StatusType whether the operation is successfully + */ +FREQM_StatusType FREQM_InterruptInit(const FREQM_InterruptType *const pIntrStruct); + +/** @}*/ /* fc7xxx_driver_freqm */ +#if defined(__cplusplus) +} +#endif +#endif diff --git a/Inc/fc7xxx_driver_ftu.h b/Inc/fc7xxx_driver_ftu.h new file mode 100644 index 0000000..120ac10 --- /dev/null +++ b/Inc/fc7xxx_driver_ftu.h @@ -0,0 +1,855 @@ +/** + * @file fc7xxx_driver_ftu.h + * @author Flagchip070 + * @brief FC7xxx FTU driver type definition and API + * @version 0.1.0 + * @date 2022-11-15 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2022-11-15 Flagchip070 N/A First version for FC7300 +********************************************************************************/ + +#ifndef _DRIVER_FC4XXX_DRIVER_FTU_H_ +#define _DRIVER_FC4XXX_DRIVER_FTU_H_ +#include "HwA_ftu.h" +#include "stddef.h" +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * @addtogroup fc7xxx_driver_ftu + * @{ + */ + +/** + * @name FTU Channel Bit Flag + * @brief Bit of channel indicate channel number + * + * @{ + */ +#define BIT_FTU_CHANNEL_0 0x01U +#define BIT_FTU_CHANNEL_1 0x02U +#define BIT_FTU_CHANNEL_2 0x04U +#define BIT_FTU_CHANNEL_3 0x08U +#define BIT_FTU_CHANNEL_4 0x10U +#define BIT_FTU_CHANNEL_5 0x20U +#define BIT_FTU_CHANNEL_6 0x40U +#define BIT_FTU_CHANNEL_7 0x80U +/** @}*/ + +/** + * @name FTU Fault Bit Flag + * @brief Bit of fault flag + * + * @{ + */ +#define FTU_FAULT_INPUT_0 0x01U +#define FTU_FAULT_INPUT_1 0x02U +/** @}*/ + +/** + * @brief Max number of Ftu fault + * + */ +#define FTU_FAULT_COUNT 2u + +/** + * @brief Max number of Ftu input count + * + */ +#define FTU_INPUT_FILTER_COUNT 4u +/** + * @brief FTU operation return values + * + */ +typedef enum +{ + FTU_STATUS_SUCCESS = 0U, /*!< The FTU operation is success */ + FTU_STATUS_PARAM_INVALID, /*!< The FTU operation is failed because of parameter error */ + FTU_STATUS_NO_CLOCK_SOURCE, /*!< The FTU operation is failed because of instance clock source is not set */ +} FTU_StatusType; + +/** + * @brief The FTU overflow and reload point callback function prototype + * + */ +typedef void (*FTU_InterruptCallBackType)(void); + +/** + * @brief The FTU fault callback function prototype + * + */ +typedef void (*FTU_FaultCallBackType)(uint32_t); + +/** + * @brief The FTU channel callback function prototype + * + */ +typedef void (*FTU_ChannelCallBackType)(uint32_t, uint32_t); + +/** + * @brief The instance index of the FTU peripheral + * + */ +typedef enum +{ + FTU_INSTANCE_0 = 0U, + FTU_INSTANCE_1, + FTU_INSTANCE_2, + FTU_INSTANCE_3, + FTU_INSTANCE_4, + FTU_INSTANCE_5, + FTU_INSTANCE_6, + FTU_INSTANCE_7, +} FTU_InstanceType; + +/** + * @brief The channel index of the FTU peripheral + * + */ +typedef enum +{ + FTU_CHANNEL_0 = 0U, + FTU_CHANNEL_1, + FTU_CHANNEL_2, + FTU_CHANNEL_3, + FTU_CHANNEL_4, + FTU_CHANNEL_5, + FTU_CHANNEL_6, + FTU_CHANNEL_7 +} FTU_ChannelType; + +/** + * @brief The clock source of FTU peripheral + * + */ +typedef enum +{ + FTU_NO_CLK = 0U, /*!< No clock selected */ + FTU_INTERNAL_CLK = 1U, /*!< FTU input clock */ + FTU_EXTERNAL_CLK0 = 3U, /*!< External pin 0 input clock */ + FTU_EXTERNAL_CLK1 = 4U, /*!< External pin 1 input clock */ + FTU_EXTERNAL_CLK2 = 5U /*!< External pin 2 input clock */ +} FTU_ClkSrcType; + +/** + * @brief The channel operation of output compare mode + * + */ +typedef enum +{ + FTU_OUTPUT_TOGGLE_PIN = 0U, /*!< Toggle Output on match */ + FTU_OUTPUT_CLEAR_PIN, /*!< Clear Output on match */ + FTU_OUTPUT_SET_PIN /*!< Set Output on match */ +} FTU_OutputComparePinModeType; + +/** + * @brief The initial level of the output compare channel + * + */ +typedef enum +{ + FTU_OUTPUT_CMP_INIT_LOW = 0U, /*!< The initial level is low */ + FTU_OUTPUT_CMP_INIT_HIGH, /*!< The initial level is high */ +} FTU_OutputCompareInitLevelType; + +/** + * @brief The channel operation of PWM mode + * + */ +typedef enum +{ + FTU_PWM_HIGH_TRUE_PULSE = 0U, /*!< High-true pulses in PWM */ + FTU_PWM_LOW_TRUE_PULSE, /*!< Low-true pulses in PWM */ +} FTU_PwmPinModeType; + +/** + * @brief PWM Aligned Mode + * + */ +typedef enum +{ + FTU_EDGE_ALIGNED_PWM = 0u, /*!< Edge-Aligned PWM */ + FTU_CENTER_ALIGNED_PWM /*!< Center-Aligned PWM */ +}FTU_PwmAlignedType; + +/** + * @brief The measurement is single or continuous + * + */ +typedef enum +{ + FTU_MEASURE_SINGLE_MODE = 0u, /*!< Single mode */ + FTU_MEASURE_CONTINUOUS_MODE /*!< Continuous mode */ +} FTU_MeasureContModeType; + +/** + * @brief Timing of start measurement + * + */ +typedef enum +{ + FTU_MEASURE_START_AFTER_EDGE = 0u, /*!< The channel starts measuring after the first edge is detected */ + FTU_MEASURE_START_IMMEDIATELY /*!< The measurement starts immediately after activating the channel */ +}FTU_MeasureStartModeType; + +/** + * @brief The reload point flag of FTU peripheral + * + */ +typedef enum +{ + FTU_RELOAD_POINT_CNTMAX = 1u, /*!< Maximum Loading Point */ + FTU_RELOAD_POINT_CNTMIN = (1u << 1), /*!< Minimum Loading Point */ + FTU_RELOAD_POINT_CHANNEL_0 = (1u << 2), /*!< Channel 0 match is included as a reload opportunity */ + FTU_RELOAD_POINT_CHANNEL_1 = (1u << 3), /*!< Channel 1 match is included as a reload opportunity */ + FTU_RELOAD_POINT_CHANNEL_2 = (1u << 4), /*!< Channel 2 match is included as a reload opportunity */ + FTU_RELOAD_POINT_CHANNEL_3 = (1u << 5), /*!< Channel 3 match is included as a reload opportunity */ + FTU_RELOAD_POINT_CHANNEL_4 = (1u << 6), /*!< Channel 4 match is included as a reload opportunity */ + FTU_RELOAD_POINT_CHANNEL_5 = (1u << 7), /*!< Channel 5 match is included as a reload opportunity */ + FTU_RELOAD_POINT_CHANNEL_6 = (1u << 8), /*!< Channel 6 match is included as a reload opportunity */ + FTU_RELOAD_POINT_CHANNEL_7 = (1u << 9), /*!< Channel 7 match is included as a reload opportunity */ +} FTU_ReloadPointCfgType; + +/** + * @brief The synchronization flag of FTU peripheral + * + */ +typedef enum +{ + FTU_SYNC_FLAG_FTUEN = 1u, /*!< FTU Enable */ + FTU_SYNC_FLAG_LDOK = (1u << 1), /*!< Load Enable */ + FTU_SYNC_FLAG_CNTINC = (1u << 2), /*!< CNTIN Register Synchronization */ + FTU_SYNC_FLAG_PWMSYNC = (1u << 3), /*!< Synchronization Mode: Selects which triggers can be used + by MOD, CV, OUTMASK, and FTU counter synchronization. */ + FTU_SYNC_FLAG_REINIT = (1u << 4), /*!< FTU Counter re-initialization by Synchronization */ + FTU_SYNC_FLAG_SYNCHOM = (1u << 5), /*!< Selects when the OUTMASK register is updated with the + value of its buffer */ + FTU_SYNC_FLAG_SYNCEN01 = (1u << 6), /*!< synchronization of registers C(0)V and C(1)V. */ + FTU_SYNC_FLAG_SYNCEN23 = (1u << 7), /*!< synchronization of registers C(2)V and C(3)V. */ + FTU_SYNC_FLAG_SYNCEN45 = (1u << 8), /*!< synchronization of registers C(4)V and C(5)V. */ + FTU_SYNC_FLAG_SYNCEN67 = (1u << 9), /*!< synchronization of registers C(6)V and C(7)V. */ + FTU_SYNC_FLAG_HW_TRIG0 = (1u << 10), /*!< hardware trigger 0 to the synchronization */ + FTU_SYNC_FLAG_HW_TRIG1 = (1u << 11), /*!< hardware trigger 1 to the synchronization */ + FTU_SYNC_FLAG_HW_TRIG2 = (1u << 12), /*!< hardware trigger 2 to the synchronization */ +} FTU_SyncFlagType; + +/** + * @brief The interrupt enable/disable mask of FTU peripheral + * + */ +typedef enum +{ + FTU_INTR_MASK_CHANNEL_0 = 1u, /*!< interrupt mask of channel 0 */ + FTU_INTR_MASK_CHANNEL_1 = (1u << 1), /*!< interrupt mask of channel 1 */ + FTU_INTR_MASK_CHANNEL_2 = (1u << 2), /*!< interrupt mask of channel 2 */ + FTU_INTR_MASK_CHANNEL_3 = (1u << 3), /*!< interrupt mask of channel 3 */ + FTU_INTR_MASK_CHANNEL_4 = (1u << 4), /*!< interrupt mask of channel 4 */ + FTU_INTR_MASK_CHANNEL_5 = (1u << 5), /*!< interrupt mask of channel 5 */ + FTU_INTR_MASK_CHANNEL_6 = (1u << 6), /*!< interrupt mask of channel 6 */ + FTU_INTR_MASK_CHANNEL_7 = (1u << 7), /*!< interrupt mask of channel 7 */ + FTU_INTR_MASK_OVERFLOW = (1u << 8), /*!< interrupt mask of overflow */ + FTU_INTR_MASK_FAULT = (1u << 9), /*!< interrupt mask of fault */ + FTU_INTR_MASK_RELOAD_POINT = (1u << 10), /*!< interrupt mask of reload point */ +} FTU_IntrMaskType; + +/** + * @brief The fault control enable/disable mask for channels + * + */ +typedef enum +{ + FTU_FAULT_FOR_CHANNEL01 = 1u, /*!< fault control for channel 0 and channel 1 */ + FTU_FAULT_FOR_CHANNEL23 = (1u << 1), /*!< fault control for channel 2 and channel 3 */ + FTU_FAULT_FOR_CHANNEL45 = (1u << 2), /*!< fault control for channel 4 and channel 5 */ + FTU_FAULT_FOR_CHANNEL67 = (1u << 3), /*!< fault control for channel 6 and channel 7 */ +} FTU_FaultChannelEnableType; + +/** + * @brief the fault input polarity + * + */ +typedef enum +{ + FTU_FAULT_POL_ACTIVE_HIGH = 0u, /*!< The fault input polarity is active high. + 1 at the fault input indicates a fault */ + FTU_FAULT_POL_ACTIVE_LOW = 1u, /*!< The fault input polarity is active low. + 0 at the fault input indicates a fault */ +}FTU_FaultPolActiveType; + +/** + * @brief the output trigger mask + * + */ +typedef enum +{ + FTU_TRIG_OUTPUT_MASK_CHANNEL_0_MATCH = 1u, /*!< Enables/Disables the channel 0 match trigger */ + FTU_TRIG_OUTPUT_MASK_CHANNEL_1_MATCH = (1u << 1), /*!< Enables/Disables the channel 1 match trigger */ + FTU_TRIG_OUTPUT_MASK_CHANNEL_2_MATCH = (1u << 2), /*!< Enables/Disables the channel 2 match trigger */ + FTU_TRIG_OUTPUT_MASK_CHANNEL_3_MATCH = (1u << 3), /*!< Enables/Disables the channel 3 match trigger */ + FTU_TRIG_OUTPUT_MASK_CHANNEL_4_MATCH = (1u << 4), /*!< Enables/Disables the channel 4 match trigger */ + FTU_TRIG_OUTPUT_MASK_CHANNEL_5_MATCH = (1u << 5), /*!< Enables/Disables the channel 5 match trigger */ + FTU_TRIG_OUTPUT_MASK_CHANNEL_6_MATCH = (1u << 6), /*!< Enables/Disables the channel 6 match trigger */ + FTU_TRIG_OUTPUT_MASK_CHANNEL_7_MATCH = (1u << 7), /*!< Enables/Disables the channel 7 match trigger */ + FTU_TRIG_OUTPUT_MASK_ALL_CHANNEL_MATCH = (0xFFu), /*!< Enables/Disables all channel match trigger */ + FTU_TRIG_OUTPUT_MASK_RELOAD = (1u << 8), /*!< Enables/Disables reload trigger */ +}FTU_TriggerOutputMaskType; + +/** @brief Ftu input capture mode */ +typedef enum +{ + FTU_INPUT_RISING_EDGE = 0U, /*!< capture on rising edge only */ + FTU_INPUT_FALLING_EDGE, /*!< capture on falling edge only */ + FTU_INPUT_BOTH_EDGE /*!< capture on rising or falling edge */ +} FTU_InputCapturePinModeType; + +/** @brief Ftu Global Time Base instance start mask */ +typedef enum +{ + FTU_GTB_INSTANCE_START_FTU0 = 1u, /*!< FTU0 GTB start */ + FTU_GTB_INSTANCE_START_FTU1 = (1u << 1), /*!< FTU1 GTB start */ + FTU_GTB_INSTANCE_START_FTU2 = (1u << 2), /*!< FTU2 GTB start */ + FTU_GTB_INSTANCE_START_FTU3 = (1u << 3), /*!< FTU3 GTB start */ + FTU_GTB_INSTANCE_START_FTU4 = (1u << 4), /*!< FTU4 GTB start */ + FTU_GTB_INSTANCE_START_FTU5 = (1u << 5), /*!< FTU5 GTB start */ + FTU_GTB_INSTANCE_START_FTU6 = (1u << 6), /*!< FTU6 GTB start */ + FTU_GTB_INSTANCE_START_FTU7 = (1u << 7), /*!< FTU7 GTB start */ +} FTU_GlobalTimeBaseStartInstanceType; + +/** @brief Ftu Global Time Base start mask */ +typedef enum +{ + FTU_GTB_START_AT_ONCE = 1u, /*!< GTB start at once */ + FTU_GTB_START_AT_TSTMP1_MOD0 = (1u << 1), /*!< GTB start at modulate timer 0 of TSTMP1 */ + FTU_GTB_START_AT_TSTMP1_MOD1 = (1u << 2), /*!< GTB start at modulate timer 1 of TSTMP1 */ + FTU_GTB_START_AT_TSTMP1_MOD2 = (1u << 3), /*!< GTB start at modulate timer 2 of TSTMP1 */ + FTU_GTB_START_AT_TSTMP1_MOD3 = (1u << 4), /*!< GTB start at modulate timer 3 of TSTMP1 */ +} FTU_GlobalTimeBaseStartType; + +/** @brief FTU signal measurement mode type */ +typedef enum +{ + FTU_SIGNAL_MEASURE_HIGH_TIME = 0u, /*!< Measurement high time */ + FTU_SIGNAL_MEASURE_LOW_TIME = 1u, /*!< Measurement low time */ + FTU_SIGNAL_MEASURE_PERIOD_RISING_EDGE = 2u, /*!< Measurement period of rising edge */ + FTU_SIGNAL_MEASURE_PERIOD_FALLING_EDGE = 3u /*!< Measurement period of falling edge */ +} FTU_SignalMeasureModeType; + +/** @brief FTU signal measurement configuration type */ +typedef struct +{ + uint8_t u8Channel; /*!< selected FTU channel */ + FTU_SignalMeasureModeType eMeasureMode; /*!< signal measurement mode type */ + FTU_MeasureContModeType eContinuouslyMode; /*!< The measurement is single or continuous */ + FTU_MeasureStartModeType eStartMode; /*!< Timing of start measurement */ +} FTU_SignalMeasureType; + +/** @brief FTU signal measurement result time */ +typedef struct +{ + uint32_t u32StartTime; /*!< start time of measured signal */ + uint32_t u32EndTime; /*!< end time of measured signal */ +} FTU_SignalMeasureValueType; + +/** @brief Expect edge number result time */ +typedef struct +{ + uint32_t u32FirstEdgeTime; /*!< first edge time of measured signal */ + uint32_t u32LastEdgeTime; /*!< last edge time of measured signal */ +} FTU_ExpectEdgeNumberResultType; + +/** @brief FTU edge number measurement configuration type */ +typedef struct +{ + uint8_t u8Channel; /*!< selected FTU channel */ + FTU_InputCapturePinModeType eEdgeMode; /*!< input capture mode */ + FTU_MeasureContModeType eContinuouslyMode; /*!< The measurement is single or continuous */ + uint32_t u32StartWindow; /*!< start-point window */ + uint32_t u32EndWindow; /*!< end-point window */ +} FTU_EdgeNumberMeasureType; + +/** @brief FTU expect edge number measurement configuration type */ +typedef struct +{ + uint8_t u8Channel; /*!< selected FTU channel */ + FTU_InputCapturePinModeType eEdgeMode; /*!< input capture mode */ + uint8_t u8ExpectEdgeNumber; /*!< Expected number of edges */ + FTU_MeasureContModeType eContinuouslyMode; /*!< The measurement is single or continuous */ +} FTU_ExpectEdgeNumberMeasureType; + +/** + * @brief The configuration option for the FTU interrupt + * + */ +typedef struct +{ + uint32_t u32InterruptMask; /*!< interrupt enable mask */ + FTU_ChannelCallBackType pChannelCallback; /*!< channel interrupt callback */ + FTU_FaultCallBackType pFaultCallback; /*!< fault interrupt callback */ + FTU_InterruptCallBackType pOverflowCallback; /*!< overflow interrupt callback */ + FTU_InterruptCallBackType pReloadPointCallback; /*!< reload point interrupt callback */ +} FTU_InterruptType; + +/** + * @brief The configuration for the Pwm channel + * + */ +typedef struct +{ + uint8_t u8Channel; /*!< selected FTU channel */ + FTU_PwmPinModeType ePinMode; /*!< pwm mode */ + uint32_t u32PwmDuty; /*!< pwm duty (timer ticks) */ + uint32_t u32PhaseShift; /*!< pwm phase shift (timer ticks)*/ + bool bLinkMode; /*!< pwm channel link mode enable, channel num must be even,and the linked channel is current_channel+1*/ + bool bLinkChannelComplement; /*!< pwm link channel output complement */ + bool bDeadtimeEnable; /*!< Deadtime Enable */ + uint32_t u32ChannelDeadtime; /*!< The separated deadtime (source clock ticks) */ +} FTU_PwmChannelType; + +/** + * @brief The configuration option for the Pwm Mode + * + */ +typedef struct +{ + uint32_t u32PwmPeriod; /*!< pwm period (timer ticks) */ + uint32_t u32PublicDeadtime; /*!< pwm deadtime (source clock ticks) */ + FTU_PwmAlignedType eAlignedMode; /*!< pwm Aligned Mode */ + uint32_t u32ChannelCount; /*!< channel count of the Ftu instance */ + FTU_PwmChannelType *pPwmChannels; /*!< point to the pwm channel */ +} FTU_PwmModeType; + +/** + * @brief The configuration option for the output compare mode + * + */ +typedef struct +{ + uint8_t u8Channel; /*!< selected FTU channel */ + FTU_OutputComparePinModeType eOutputMode; /*!< ouput compare mode */ + uint32_t u32CompareValue; /*!< output compare value (timer ticks) */ + FTU_OutputCompareInitLevelType eInitLevel; /*!< the initial level of the channel */ +} FTU_OutputCompareModeType; + +/** + * @brief The configuration option for the time counter mode + * + */ +typedef struct +{ + uint32_t u32CounterValue; /*!< counter overflow value (timer ticks) */ + uint32_t u32InitialValue; /*!< counter initial value (timer ticks) */ +} FTU_CounterModeType; + +/** + * @brief The basic configuration option for the FTU peripheral + * + */ +typedef struct +{ + FTU_PrescalerType ePrescaler; /*!< Ftu prescaler */ + FTU_ClkSrcType eClkSrc; /*!< Ftu clock source */ + FTU_FilterPrescalerType eFliterPrescaler; /*!< Select the prescaler of the FTU filter */ + uint32_t u32OverflowValue; /*!< Ftu modulo value */ + uint16_t u16ReloadPoints; /*!< Ftu Synchronization points to update the buffered registers.Multiple + update modes can be used by providing an OR'ed list of options + available in enumeration ::FTU_ReloadPointCfgType. */ + uint8_t u8ReloadFreq; /*!< Frequency of the Reload Opportunities. Range is 0-31, */ + uint16_t u16SyncFlag; /*!< Ftu Synchronization flags to config the Synchronization and update of + the buffered registers. Multiple update modes can be used by + providing an OR'ed list of options available in + enumeration ::FTU_SyncFlagType. */ + FTU_TrigModeType eHwTrigMode; /*!< hardware trigger mode */ + FTU_DebugModeType eDbgMode; /*!< Ftu debug mode */ + FTU_UpDownDisableType eUpDownDisable; /*!< Disable channel match trigger/interrupt when count-up/down in CPWM/QUAD mode */ + bool bGtbEnable; /*!< Global Time Base Enable */ +} FTU_CommonType; + +/** + * @brief The configuration option for initializing FTU fault + * + */ +typedef struct +{ + FTU_FaultModeType eFaultMode; /*!< fault control mode */ + uint8_t u8FilterValue; /*!< selects the filter value for the fault inputs */ + uint8_t u8FaultChannelEnable; /*!< fault control for channel */ + uint8_t u8FaultDisableDelay0; /*!< Fault Disable Channel Output Delay Value 0 (timer ticks) */ + uint8_t u8FaultDisableDelay1; /*!< Fault Disable Channel Output Delay Value 1 (timer ticks) */ +} FTU_FaultInitType; + +/** + * @brief The configuration option for enabling a FTU fault + * + */ +typedef struct +{ + uint8_t u8FaultIndex; /*!< fault index */ + FTU_FaultPolActiveType eFaultPol; /*!< the fault input active polarity */ + bool bFaultFilterEnable; /*!< whether to enable fault input glitch filter*/ +} FTU_FaultControlType; + +/** + * @brief The configuration option for a input capture channel + * + */ +typedef struct +{ + uint8_t u8Channel; /*!< selected FTU channel */ + FTU_InputCapturePinModeType eInputMode; /*!< input capture mode */ + uint8_t u8FilterValue; /*!< selects the filter value for the channel input */ +} FTU_InputChannelType; + +/** + * @brief The configuration option for the quadrature decoder mode + * + */ +typedef struct +{ + FTU_QuadratureModeType eQuadMode; /*!< selects the encoding mode used in the Quadrature Decoder mode */ + FTU_QuadratureDirectionType eQuadDirection; /*!< indicates the counting direction */ + FTU_TimerOverflowDirectionType eOveflowDirection; /*!< Indicates if the TOF bit was set on the top or the bottom of counting */ + uint8_t u8PhaFilterVal; /*!< The filter value for the phase A input */ + uint8_t u8PhbFilterVal; /*!< The filter value for the phase B input */ + bool bPhaInverted; /*!< whether to inverted polarity of phase A input */ + bool bPhbInverted; /*!< whether to inverted polarity of phase B input */ + uint16_t u16TopValue; /*!< the top value of counting */ + uint16_t u16BottomValue; /*!< the bottom value of counting */ +} FTU_QuadratureInitType; + +/** + * @brief Initialize FTU basic configuration + * + * @param eInstance the selected FTU instance + * @param pCommonStruct the basic configurations of the FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_CommonInit(const FTU_InstanceType eInstance, const FTU_CommonType *const pCommonStruct); + +/** + * @brief Fills in the FTU configuration structure with the default settings. + * + * @param pCommonStruct Pointer to the user configuration structure + */ +void FTU_GetDefaultInitCfg(FTU_CommonType *pCommonStruct); + +/** + * @brief Configure FTU to counter mode + * + * @param eInstance the selected FTU instance + * @param pCounterStruct the configurations of the counter mode + * @return FTU_StatusType whether the operation is successfully + * @note This function will stop timer + */ +FTU_StatusType FTU_CounterModeInit(const FTU_InstanceType eInstance, + const FTU_CounterModeType *const pCounterStruct); + + +/** + * @brief Configure FTU to output compare mode + * + * @param eInstance the selected FTU instance + * @param pOutputModeStruct the configurations of the output compare mode + * @return FTU_StatusType whether the operation is successfully + * @note This function will stop timer + */ +FTU_StatusType FTU_OutputCompareModeInit(const FTU_InstanceType eInstance, + const FTU_OutputCompareModeType *const pOutputModeStruct); + +/** + * @brief Configure Configure FTU to PWM mode + * + * @param eInstance the selected FTU instance + * @param pPwmModeStruct the configurations of the PWM mode + * @return FTU_StatusType whether the operation is successfully + * @note This function will stop timer + */ +FTU_StatusType FTU_PwmModeInit(const FTU_InstanceType eInstance, const FTU_PwmModeType *const pPwmModeStruct); + +/** + * @brief Update the duty cycle of the FTU instance + * + * @param eInstance the selected FTU instance + * @param u8Channel the selected FTU channel + * @param u32Duty duty cycle of the PWM mode + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_PwmUpdateDuty(const FTU_InstanceType eInstance, uint8_t u8Channel, uint32_t u32Duty); + +/** + * @brief Ftu initialize interrupt function + * + * @param eInstance the selected FTU instance + * @param pIntStruct the configurations of the interrupt + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_InterruptInit(const FTU_InstanceType eInstance, const FTU_InterruptType *const pIntStruct); + +/** + * @brief Enable FTU interrupt + * + * @param eInstance the selected FTU instance + * @param u32InterruptMask interrupt enable mask + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EnableInterrupt(const FTU_InstanceType eInstance, uint32_t u32InterruptMask); + +/** + * @brief Enable FTU interrupt + * + * @param eInstance the selected FTU instance + * @param u32InterruptMask interrupt disable mask + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DisableInterrupt(const FTU_InstanceType eInstance, uint32_t u32InterruptMask); +/** + * @brief Start the FTU instance + * + * @param eInstance the selected FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_StartTimer(const FTU_InstanceType eInstance); +/** + * @brief Stop the FTU global time base + * + * @param u32InstanceMask The selected FTU, each bit represents an instance + */ +void FTU_StopGlobalTimeBase(uint32_t u32InstanceMask); +/** + * @brief Start the FTU global time base + * + * @param u32InstanceMask The selected FTU, each bit represents an instance + * @param u32StartMask Start time, refer to FTU_GlobalTimeBaseStartType + */ +void FTU_StartGlobalTimeBase(uint32_t u32InstanceMask, uint32_t u32StartMask); +/** + * @brief Stop the FTU instance + * + * @param eInstance the selected FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_StopTimer(const FTU_InstanceType eInstance); + +/** + * @brief De-initialize the FTU instance + * + * @param eInstance the selected FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DeInit(const FTU_InstanceType eInstance); + +/** + * @brief initialize fault input of the selected Ftu instance + * + * @param eInstance the selected FTU instance + * @param pFaultInit the fault configurations of the FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_FaultInit(const FTU_InstanceType eInstance, const FTU_FaultInitType *const pFaultInit); + +/** + * @brief Enable a fault input + * + * @param eInstance the selected FTU instance + * @param pFaultCtrl configurations of the fault input + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_FaultEnable(const FTU_InstanceType eInstance, const FTU_FaultControlType *const pFaultCtrl); + +/** + * @brief Select fault disable channel output delay value + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number, range is 0-7. + * @param eDelaySelection Fault disable channel output delay value selection. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_FaultSelectDelayValue(const FTU_InstanceType eInstance, uint8_t u8Channel, FTU_FaultDisableDelayType eDelaySelection); +/** + * @brief Get Edge number counter + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number. + * @return uint8_t Edge number counter + */ +uint8_t FTU_GetEdgeNumberCount(const FTU_InstanceType eInstance, uint8_t u8Channel); +/** + * @brief Initialize a Edge Number Measurement channel + * + * @param eInstance the selected FTU instance + * @param pEdgeNumMeasure measurement configuration. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EdgeNumberMeasureChannelInit(const FTU_InstanceType eInstance, FTU_EdgeNumberMeasureType *pEdgeNumMeasure); +/** + * @brief Initialize a signal measure channel + * + * @param eInstance the selected FTU instance + * @param pMeasure measurement configuration. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_SignalMeasureChannelInit(const FTU_InstanceType eInstance, FTU_SignalMeasureType *pMeasure); +/** + * @brief Re-start measurement when in single mode + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number, range is 0-7. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_SignalMeasureChannelSingle(const FTU_InstanceType eInstance, uint8_t u8Channel); +/** + * @brief Get the measurement result of the channel + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number, range is 0-7. + * @param pResult point to the result buffer. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_GetSignaMeasureResult(const FTU_InstanceType eInstance, uint8_t u8Channel, FTU_SignalMeasureValueType *pResult); +/** + * @brief Disable a fault input + * + * @param eInstance the selected FTU instance + * @param u32FaultIndex index of the fault input + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_FaultDisable(const FTU_InstanceType eInstance, uint32_t u32FaultIndex); + +/** + * @brief Clear the fault flag of the FTU instance + * + * @param eInstance the selected FTU instance + * @param u32FaultFlag flag to clear + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_ClearFault(const FTU_InstanceType eInstance, uint32_t u32FaultFlag); + +/** + * @brief Get the fault flag of the FTU instance + * + * @param eInstance the selected FTU instance + * @return uint32_t the fault flag of the selected Ftu instance + */ +uint32_t FTU_GetFaultFlag(const FTU_InstanceType eInstance); + +/** + * @brief initialize a input capture channel of the selected Ftu instance + * + * @param eInstance the selected FTU instance + * @param pInputChannel configurations of the input capture channel + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_InputCaptureChannelInit(const FTU_InstanceType eInstance, + const FTU_InputChannelType *const pInputChannel); +/** + * @brief enable the synchronization of the selected FTU + * + * @param eInstance the selected FTU instance + * @param u16ReloadPoints The synchronization flag + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EnableSync(const FTU_InstanceType eInstance, uint16_t u16SyncFlag); +/** + * @brief disable the synchronization of the selected FTU + * + * @param eInstance the selected FTU instance + * @param u16SyncFlag The synchronization flag + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DisableSync(const FTU_InstanceType eInstance, uint16_t u16SyncFlag); +/** + * @brief Enable the output trigger of the selected FTU instance + * + * @param eInstance the selected FTU instance + * @param u32TriggerOutputMask the output trigger mask + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EnableTriggerOutput(const FTU_InstanceType eInstance, uint32_t u32TriggerOutputMask); +/** + * @brief Disable the output trigger of the selected FTU instance + * + * @param eInstance the selected FTU instance + * @param u32TriggerOutputMask the output trigger mask + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DisableTriggerOutput(const FTU_InstanceType eInstance, uint32_t u32TriggerOutputMask); +/** + * @brief initialize the quadrature decoder mode + * + * @param eInstance the selected FTU instance + * @param pQuadInit configurations of the quadrature decoder + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_QuadratureModeInit(const FTU_InstanceType eInstance, + const FTU_QuadratureInitType *const pQuadInit); +/** + * @brief Enable the reload points of the selected FTU instance + * + * @param eInstance the selected FTU instance + * @param u16ReloadPoints The reload points flag + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EnableReloadPoints(const FTU_InstanceType eInstance, uint16_t u16ReloadPoints); +/** + * @brief Disable the reload points of the selected FTU instance + * + * @param eInstance the selected FTU instance + * @param u16ReloadPoints The reload points flag + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DisableReloadPoints(const FTU_InstanceType eInstance, uint16_t u16ReloadPoints); + +/** + * @brief Enable ftu channel DMA + * + * @param eInstance the selected FTU instance + * @param u32DmaMask The dma channel mask. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EnableChannelDma(const FTU_InstanceType eInstance, uint32_t u32DmaMask); +/** + * @brief Get the expect edge number result of the channel + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number, range is 0-7. + * @param pResult point to the result buffer. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_GetExpectEdgeNumberResult(const FTU_InstanceType eInstance, uint8_t u8Channel, FTU_ExpectEdgeNumberResultType *pResult); +/** + * @brief Initialize a Expect Edge Number Measurement channel + * + * @param eInstance the selected FTU instance + * @param pExpectEdgeNumMeasure measurement configuration. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_ExpectEdgeNumberMeasureChannelInit(const FTU_InstanceType eInstance, FTU_ExpectEdgeNumberMeasureType *pExpectEdgeNumMeasure); +/** + * @brief Get the measurement result of the channel + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number, range is 0-7. + * @param pResult point to the result buffer. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_GetSignalMeasureResult(const FTU_InstanceType eInstance, uint8_t u8Channel, FTU_SignalMeasureValueType *pResult); +/** + * @brief Interrupt IRQ handle of FTU instance + * + * @param eInstance the selected FTU instance + */ +void FTUn_IRQHandler(const FTU_InstanceType eInstance); +/** @}*/ /* fc7xxx_driver_ftu */ +#if defined(__cplusplus) +} +#endif +#endif diff --git a/Inc/fc7xxx_driver_gpio.h b/Inc/fc7xxx_driver_gpio.h new file mode 100644 index 0000000..9e92846 --- /dev/null +++ b/Inc/fc7xxx_driver_gpio.h @@ -0,0 +1,145 @@ +/** + * @file fc7xxx_driver_gpio.h + * @author Flagchip + * @brief FC7xxx GPIO driver type definition and API + * @version 0.1.0 + * @date 2023-2-14 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2022/12/31 Flagchip071 N/A First version for FC7240 +********************************************************************************/ +#ifndef DRIVER_GPIO_H_ +#define DRIVER_GPIO_H_ +#include "HwA_gpio.h" + +/** + * @addtogroup fc7xxx_driver_port + * @{ + */ + +/********* global define ************/ + +#define GPIO_MAX_PORT_PINS 32 + +#define GPIO_PIN_0 ((uint32_t)0x00000001) /**< GPIO Pin 0 select */ +#define GPIO_PIN_1 ((uint32_t)0x00000002) /**< GPIO Pin 1 select */ +#define GPIO_PIN_2 ((uint32_t)0x00000004) /**< GPIO Pin 2 select */ +#define GPIO_PIN_3 ((uint32_t)0x00000008) /**< GPIO Pin 3 select */ +#define GPIO_PIN_4 ((uint32_t)0x00000010) /**< GPIO Pin 4 select */ +#define GPIO_PIN_5 ((uint32_t)0x00000020) /**< GPIO Pin 5 select */ +#define GPIO_PIN_6 ((uint32_t)0x00000040) /**< GPIO Pin 6 select */ +#define GPIO_PIN_7 ((uint32_t)0x00000080) /**< GPIO Pin 7 select */ +#define GPIO_PIN_8 ((uint32_t)0x00000100) /**< GPIO Pin 8 select */ +#define GPIO_PIN_9 ((uint32_t)0x00000200) /**< GPIO Pin 9 select */ +#define GPIO_PIN_10 ((uint32_t)0x00000400) /**< GPIO Pin 10 select */ +#define GPIO_PIN_11 ((uint32_t)0x00000800) /**< GPIO Pin 11 select */ +#define GPIO_PIN_12 ((uint32_t)0x00001000) /**< GPIO Pin 12 select */ +#define GPIO_PIN_13 ((uint32_t)0x00002000) /**< GPIO Pin 13 select */ +#define GPIO_PIN_14 ((uint32_t)0x00004000) /**< GPIO Pin 14 select */ +#define GPIO_PIN_15 ((uint32_t)0x00008000) /**< GPIO Pin 15 select */ +#define GPIO_PIN_16 ((uint32_t)0x00010000) /**< GPIO Pin 16 select */ +#define GPIO_PIN_17 ((uint32_t)0x00020000) /**< GPIO Pin 17 select */ +#define GPIO_PIN_18 ((uint32_t)0x00040000) /**< GPIO Pin 18 select */ +#define GPIO_PIN_19 ((uint32_t)0x00080000) /**< GPIO Pin 19 select */ +#define GPIO_PIN_20 ((uint32_t)0x00100000) /**< GPIO Pin 20 select */ +#define GPIO_PIN_21 ((uint32_t)0x00200000) /**< GPIO Pin 21 select */ +#define GPIO_PIN_22 ((uint32_t)0x00400000) /**< GPIO Pin 22 select */ +#define GPIO_PIN_23 ((uint32_t)0x00800000) /**< GPIO Pin 23 select */ +#define GPIO_PIN_24 ((uint32_t)0x01000000) /**< GPIO Pin 24 select */ +#define GPIO_PIN_25 ((uint32_t)0x02000000) /**< GPIO Pin 25 select */ +#define GPIO_PIN_26 ((uint32_t)0x04000000) /**< GPIO Pin 26 select */ +#define GPIO_PIN_27 ((uint32_t)0x08000000) /**< GPIO Pin 27 select */ +#define GPIO_PIN_28 ((uint32_t)0x10000000) /**< GPIO Pin 28 select */ +#define GPIO_PIN_29 ((uint32_t)0x20000000) /**< GPIO Pin 29 select */ +#define GPIO_PIN_30 ((uint32_t)0x40000000) /**< GPIO Pin 30 select */ +#define GPIO_PIN_31 ((uint32_t)0x80000000) /**< GPIO Pin 31 select */ + +/************************************global typedef ***************************************/ + +/** @brief GPIO return structure */ +typedef enum +{ + GPIO_STATUS_SUCCESS = 0U, + GPIO_STATUS_PARAM_INVALID = 1U +} GPIO_StatusType; + +/** @brief GPIO instance number */ +typedef enum +{ + GPIO_A = 0U, + GPIO_B, + GPIO_C, + GPIO_D, + GPIO_E +} GPIO_InstanceType; + +/** @brief GPIO direction */ +typedef enum +{ + GPIO_OUT = 0U, /* GPIO pin directon is output */ + GPIO_IN = 1U, /* GPIO pin directon is input */ + GPIO_ZERO = 2U /* GPIO pin directon is input disable */ +} GPIO_PinDirectionType; + +typedef struct +{ + uint32_t u32GpioPins; + GPIO_PinDirectionType ePinDirection; + GPIO_PinLevelType ePinLevel; +}GPIO_InitType; + +/************************************global typedef ***************************************/ + +/** + * @brief Initialize GPIO. + * + * @param eGpio GPIO instance + * @param pInitStruct Initialization structure of GPIO. + */ +GPIO_StatusType GPIO_InitPins(const GPIO_InstanceType eGpio, const GPIO_InitType *const pInitStruct); + +/** + * @brief Initialize GPIO. + * + * @param eGpio GPIO instance + * @param u32Pins The bit of u32Pins indicate the pin number of this GPIO. + */ +GPIO_StatusType GPIO_Deinit(const GPIO_InstanceType eGpio, const uint32_t u32Pins); + +/** + * @brief Read level of input port pins. + * + * @param ePort Port instance for GPIO functionality + * @param u32Pins The bit of u32Pins indicate the pin number of this Port. + * @return Pins level + */ +uint32_t GPIO_ReadPins(const GPIO_InstanceType ePort, const uint32_t u32Pins); + +/** + * @brief Write gpio level to u32Pins. + * + * @param ePort Port instance for GPIO functionality + * @param u32Pins The bit of u32Pins indicate the pin number of this Port. + * @param eOutput Output level enumeration + * @return Port return type. + */ +GPIO_StatusType GPIO_WritePins(const GPIO_InstanceType ePort, const uint32_t u32Pins, const GPIO_PinLevelType eOutput); + +/** + * @brief Toggle gpio api + * + * @param ePort ePort Port instance for GPIO functionality + * @param u32Pins The bit of u32Pins indicate the pin number of this Port. + * @return Port return type. + */ +GPIO_StatusType GPIO_Toggle(const GPIO_InstanceType ePort, const uint32_t u32Pins); + + +#endif /* end of DRIVER_GPIO_H_ */ diff --git a/Inc/fc7xxx_driver_hsm.h b/Inc/fc7xxx_driver_hsm.h new file mode 100644 index 0000000..249d1dd --- /dev/null +++ b/Inc/fc7xxx_driver_hsm.h @@ -0,0 +1,3277 @@ +/** + * @file fc7xxx_driver_hsm.h + * @author Flagchip0103 + * @brief FC7xxx HSM driver type definition and API + * @version 0.1.0 + * @date 2023-12-20 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2023-12-20 Flagchip0103 N/A First version for FC7240 + ******************************************************************************** */ + +#ifndef DRIVER_HSM_H_ +#define DRIVER_HSM_H_ + +#include "device_header.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * @addtogroup fc7xxx_driver_hsm + * @{ + */ + + +/** + * @brief Status returned by HSM SDK CM7 side APIs + * + */ +typedef enum +{ + HSM_STATUS_SUCCESS = 0U, /*!< return this when HSM API execute successfully */ + HSM_STATUS_PARAM_ERR, /*!< return this when parameter error */ + HSM_STATUS_AGAIN, /*!< return this when need more API call to continue process */ + HSM_STATUS_FINISH, /*!< return this when the process is finish */ +} HSM_StatusType; + + +/** + * @name definitions for HSM_MailboxApiRetType + * + */ +/**@{*/ +/** + * @brief success status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_SUCCESS (0u) + +/** + * @brief error status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_ERROR (1u) + +/** + * @brief failure status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_FAIL (2u) + +/** + * @brief verify pass status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_PASS (3u) + +/** + * @brief function not support status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_NOT_SUPPORT (4u) + +/** + * @brief hardware error status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_HW_ERROR (5u) + +/** + * @brief have no permission status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_NO_PRIVILEGES (6u) + +/** + * @brief parameters error status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_PARAMETER_ERROR (7u) + +/** + * @brief authority error status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_AUTHORITY_ERROR (8u) + +/** + * @brief hardware busy status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_BUSY (9u) + +/** + * @brief flash ecc error status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_ECC_ERR (10u) + +/** + * @brief time expire error status (HSM_MailboxApiRetType) returned by HSM subsystem APIs + * + */ +#define MAILBOXAPI_RET_TIMEOUIT (11u) + +/** + * @brief status type definition returned by HSM subsystem APIs + * + */ +typedef uint32_t HSM_MailboxApiRetType; +/**@}*/ + + +/** + * @brief HSM 4bytes unit data format for HSM_DataFormatType + * for example, if data is 0x000102030405060708090a0b0c0d0e0f, use this format, should be divided as following. + * 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f + */ +#define HSM_DATA_FORMAT_4B 0u + +/** + * @brief HSM 1byte unit data format for HSM_DataFormatType + * for example, if data is 0x000102030405060708090a0b0c0d0e0f, use this format, should be divided as following. + * 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + */ +#define HSM_DATA_FORMAT_1B 1u + +/** + * @brief HSM data format + * refer to HSM_DATA_FORMAT_4B, HSM_DATA_FORMAT_1B + */ +typedef uint32_t HSM_DataFormatType; + + +/** + * @name Type definition for HSM Isr/Poll mode + * + */ +/**@{*/ + +typedef struct +{ + uint32_t u32Cmd; /*!< current command id to HSM core via mailbox */ + uint32_t u32Addr; /*!< current parameter address to HSM core via mailbox */ +} HSM_CmdType; + + +/** + * @name definitions for HSM_BoolType + * + */ +/**@{*/ +/** + * @brief Boolean false value definition for type HSM_BoolType used by HSM + * + */ +#define HSM_FALSE (0u) + +/** + * @brief Boolean true value definition for type HSM_BoolType used by HSM + * + */ +#define HSM_TRUE (1u) + +/** + * @brief Boolean type for HSM + * + */ +typedef uint32_t HSM_BoolType; +/**@}*/ + + +/* ------------------------------------------------------------------------------- */ +/** + * @brief the true random count return by the API + * + */ +#define HSM_TRNG_RAND_U32_CNT (16u) +/* ------------------------------------------------------------------------------- */ +/** + * @brief the true random source_0 definition for type HSMCom_TrueRandType.u32RandSrcType + * + */ +#define HSM_TRNG_SRC_0 (0u) +/* ------------------------------------------------------------------------------- */ +/** + * @brief the true random source_1 definition for type HSMCom_TrueRandType.u32RandSrcType + * + */ +#define HSM_TRNG_SRC_1 (1u) +/* ------------------------------------------------------------------------------- */ +/** + * @brief the true XOR random source_1 definition for type HSMCom_TrueRandType.u32RandSrcType + * + */ +#define HSM_TRNG_SRC_XOR (2u) +/* ------------------------------------------------------------------------------- */ +/** + * @brief the true any random source_1 definition for type HSMCom_TrueRandType.u32RandSrcType + * + */ +#define HSM_TRNG_SRC_ANY (3u) +/* ------------------------------------------------------------------------------- */ +/** + * @brief the pseudorandom source definition for type HSMCom_TrueRandType.u32RandSrcType + * + */ +#define HSM_DRNG_SRC (4u) +typedef uint32_t HSM_RndSrcType; +/** + * @brief the true random information passed to HSM core by mailbox + * + */ +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t (*aRandom)[HSM_TRNG_RAND_U32_CNT]; /*!< the buffer address, HSM core will write random data to this buffer */ + HSM_RndSrcType u32RandSrc; /*!< which random source will be selected */ +} HSMCom_TrueRandType; + +/* ------------------------------------------------------------------------------- */ + + +/** + * @name definitions for HSM_HashAlgType + * + */ +/**@{*/ +/** + * @brief MD5 algorithm value for type "HSM_HashAlgType" + * + */ +#define HSM_HASH_MD5 (0U) + +/** + * @brief SHA160 algorithm value for type "HSM_HashAlgType" + * + */ +#define HSM_HASH_SHA160 (1U) + +/** + * @brief SHA224 algorithm value for type "HSM_HashAlgType" + * + */ +#define HSM_HASH_SHA224 (2U) + +/** + * @brief SHA256 algorithm value for type "HSM_HashAlgType" + * + */ +#define HSM_HASH_SHA256 (3U) + +/** + * @brief SHA384 algorithm value for type "HSM_HashAlgType" + * + */ +#define HSM_HASH_SHA384 (4U) + +/** + * @brief SHA512 algorithm value for type "HSM_HashAlgType" + * + */ +#define HSM_HASH_SHA512 (5U) + +/** + * @brief SHA512_224 algorithm value for type "HSM_HashAlgType" + * + */ +#define HSM_HASH_SHA512_224 (6U) + +/** + * @brief SHA512_256 algorithm value for type "HSM_HashAlgType" + * + */ +#define HSM_HASH_SHA512_256 (7U) + +/** + * @brief SM3 algorithm value for type "HSM_HashAlgType" + * + */ +#define HSM_HASH_SM3 (8U) + +/** + * @brief type definition for HASH algorithm + * refer to HSM_HASH_MD5,HSM_HASH_SHA160,HSM_HASH_SHA224,HSM_HASH_SHA256,HSM_HASH_SHA384,HSM_HASH_SHA512,HSM_HASH_SHA512_224,HSM_HASH_SHA512_256,HSM_HASH_SM3 + */ +typedef uint32_t HSM_HashAlgType; +/**@}*/ + + +/** + * @name definitions for HSM_ShaAlgType + * + */ +/**@{*/ +/** + * @brief SHA160 algorithm value for type "HSM_ShaAlgType" + * @note it's the so-called SHA1 + */ +#define HSM_SHA_160 (1U) + +/** + * @brief SHA224 algorithm value for type "HSM_ShaAlgType" + * @note it's the so-called SHA2-224 + */ +#define HSM_SHA_224 (2U) + +/** + * @brief SHA256 algorithm value for type "HSM_ShaAlgType" + * @note it's the so-called SHA2-256 + */ +#define HSM_SHA_256 (3U) + +/** + * @brief SHA384 algorithm value for type "HSM_ShaAlgType" + * @note it's the so-called SHA2-384 + */ +#define HSM_SHA_384 (4U) + +/** + * @brief SHA512 algorithm value for type "HSM_ShaAlgType" + * @note it's the so-called SHA2-512 + */ +#define HSM_SHA_512 (5U) + +/** + * @brief SHA512/224 algorithm value for type "HSM_ShaAlgType" + * @note it's the so-called SHA2-512/224 + */ +#define HSM_SHA_512_224 (6U) + +/** + * @brief SHA512/256 algorithm value for type "HSM_ShaAlgType" + * @note it's the so-called SHA2-512/256 + */ +#define HSM_SHA_512_256 (7U) + +/** + * @brief type definition for SHA algorithm + * refer to HSM_SHA_160,HSM_SHA_224,HSM_SHA_256,HSM_SHA_384,HSM_SHA_512,HSM_SHA_512_224,HSM_SHA_512_256 + */ +typedef uint32_t HSM_ShaAlgType; +/**@}*/ + + +/** + * @name definitions for HSM_HfamMacType + * + */ +/**@{*/ +/** + * @brief SMAC mode value for type "HSM_HfamMacType" + * + */ +#define HSM_HFAM_MAC_SMAC (0U) + +/** + * @brief HMAC mode value for type "HSM_HfamMacType" + * + */ +#define HSM_HFAM_MAC_HMAC (1U) + +/** + * @brief SM3/MD5/SHA can generate MAC, use this to select the type of MAC + * SMAC refer to HSM_HFAM_MAC_SMAC + * HMAC refer to HSM_HFAM_MAC_HMAC + */ +typedef uint32_t HSM_HfamMacType; +/**@}*/ + + +/** + * @brief SHA/MD5/SM3 context information used by driver when call specific API + * + */ +typedef struct +{ + HSM_BoolType bGenerateMacEn; /*!< whether generate MAC */ + HSM_HfamMacType eMacType; /*!< if enable generating MAC, this should configure */ + uint32_t *pKeyData; /*!< key to generate MAC, if enable generating MAC, this should configure */ + uint32_t u32KeyByteCnt; /*!< the byte count of key data */ + uint32_t u32GenerateMacByteCnt; /*!< the byte count of MAC data output */ + + uint32_t u32InputDataByteCnt; /*!< the byte count of input data */ + const uint32_t *pInputData; /*!< point to the input data */ +} HSM_SmsCfgType; /* sms is short for sha/md5/sm3 */ + +/** + * @brief SHA context information used by driver when call specific API + * + */ +typedef HSM_SmsCfgType HSM_ShaCtxType; + +/** + * @brief type definition for driver to store information + * + */ +typedef struct +{ + uint32_t aResult[0x10]; /*!< store the sha result, max size 0x10 is for SHA512 */ + uint32_t u32ResultU32Cnt; /*!< store the result uint32_t count, it's set by driver */ +} HSM_ShaResultBufType; + +/** + * @brief SHA information used by driver when call specific API + * + */ +typedef struct +{ + HSM_ShaAlgType eAlg; /*!< select sha algorithm type */ + HSM_ShaCtxType tCfg; /*!< sha algorithm parameter set by user */ + HSM_ShaResultBufType *pResult; /*!< point to the memory that HSM core to write result */ +} HSM_ShaType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + HSM_ShaType tCfg; /*!< sha algorithm parameter set by user */ +} HSMCom_ShaType; + +/** + * @brief SHA information used by driver when call specific API + * + */ +typedef struct +{ + HSM_ShaAlgType eAlg; /*!< select sha algorithm type */ + HSM_ShaCtxType tCfg; /*!< sha algorithm parameter set by user */ + uint8_t *pResult; /*!< point to the memory that HSM core to write result */ + HSM_DataFormatType eInputFmt; /*!< input data organized format,uint8_t array or uint32_t array */ + HSM_DataFormatType eOutputFmt; /*!< output data organized format,uint8_t array or uint32_t array */ +} HSM_Sha2Type; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout Millisecond count, max 916000ms, if set to 0, means 1000ms */ + HSM_Sha2Type tCfg; /*!< sha algorithm parameter set by user */ +} HSMCom_Sha2Type; + +typedef struct +{ + HSM_ShaAlgType eAlg; /*!< select sha algorithm type */ + HSM_ShaCtxType tCfg; /*!< sha algorithm parameter set by user */ + uint32_t (*pResult)[18]; /*!< point to the memory that HSM core to write result */ +} HSM_ScatterHashType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout Millisecond count, max 916000ms, if set to 0, means 1000ms */ + HSM_ScatterHashType tCfg; /*!< sha algorithm parameter set by user */ +} HSMCom_ScatterHashType; +/* ------------------------------------------------------------------------------- */ +typedef struct { + uint32_t u32KeyType; + uint32_t u32KeySel; + uint32_t *pKeyData; +} HSM_AesmKeyCfgType; + +typedef struct { + HSM_AesmKeyCfgType *pKeyCfg; + uint32_t u32KeyCfgEn; + uint32_t u32AesMode; + uint32_t u32AesAs; + uint32_t u32AesEncDecrypt; + uint32_t u32EngSel; + uint32_t u32AhbEn; + uint32_t u32IcvEn; + uint32_t u32DataLen; + uint32_t u32IcvLen; + uint32_t u32AadLen; + uint32_t *pInput; + uint32_t *pOutput; + uint32_t *pIvData; + uint32_t u32DbgWait; + uint32_t u32IvLen; +} HSM_AesmHwEntryCfgType; + +typedef struct { + HSM_AesmHwEntryCfgType tCfg; + HSM_AesmKeyCfgType tKeyCfg; + uint32_t (*pCtx)[16]; +} HSM_AesmRawApiType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout Millisecond count, max 916000ms, if set to 0, means 1000ms */ + uint32_t u32UserKeyId; + HSM_AesmRawApiType tCfg; /*!< algorithm parameter set by user */ +} HSMCom_AesmRawApiType; + +/* ------------------------------------------------------------------------------- */ +typedef struct { + uint32_t u32Flags; + uint32_t *pKeyData; + uint32_t *pMacOut; + uint32_t u32MacOutBufSz; + uint32_t *aData[8]; + uint32_t aDataSize[8]; +} HSM_ScatterMacType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout Millisecond count, max 916000ms, if set to 0, means 1000ms */ + uint32_t u32UserKeyId; + HSM_ScatterMacType tCfg; /*!< algorithm parameter set by user */ +} HSMCom_ScatterMacType; + + +/* ------------------------------------------------------------------------------- */ +/** + * @name definitions for HSM_DrvEccCurvePrmIndexType + * + */ +/**@{*/ +/** + * @brief ECC curve NIST SECP224R1 value for type "HSM_DrvEccCurvePrmIndexType" + * + */ +#define HSM_DRV_ECC_CURVE_PRM_IDX_SECP224R1 (0U) + +/** + * @brief ECC curve NIST SECP256R1 value for type "HSM_DrvEccCurvePrmIndexType" + * + */ +#define HSM_DRV_ECC_CURVE_PRM_IDX_SECP256R1 (1U) + +/** + * @brief ECC curve NIST SECP384R1 value for type "HSM_DrvEccCurvePrmIndexType" + * + */ +#define HSM_DRV_ECC_CURVE_PRM_IDX_SECP384R1 (2U) + +/** + * @brief ECC curve NIST SECP521R1 value for type "HSM_DrvEccCurvePrmIndexType" + * + */ +#define HSM_DRV_ECC_CURVE_PRM_IDX_SECP521R1 (3U) + +/** + * @brief ECC curve NIST SECP224R1_FIX value for type "HSM_DrvEccCurvePrmIndexType" + * + */ +#define HSM_DRV_ECC_CURVE_PRM_IDX_SECP224R1_FIX (4U) + + +/** + * @brief max count of ECC curve supported for type "HSM_DrvEccCurvePrmIndexType" + * + */ +#define HSM_DRV_ECC_CURVE_PRM_IDX_MAX (5U) + +/** + * @brief type definition for ECC curve data that defined by NIST + * + */ +typedef uint32_t HSM_DrvEccCurvePrmIndexType; +/**@}*/ + +/** + * @brief ECC curve information used by driver when call specific API + * + */ +typedef struct +{ + const uint32_t *pP; /*!< ecc curve modulus */ + const uint32_t *pN; /*!< ecc curve order; size; the count of all possible EC points */ + const uint32_t *pA; /*!< the constant "a" in y^2 = x^3 + a*x + b (mod p) */ + const uint32_t *pB; /*!< the constant "b" in y^2 = x^3 + a*x + b (mod p) */ + const uint32_t *pGx; /*!< x of the curve generator point G {x, y} */ + const uint32_t *pGy; /*!< y of the curve generator point G {x, y} */ +} HSM_DrvEccCurveParamType; + +/** + * @brief ECC sign information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t u32ByteCount; /*!< all the data size, it should contains all N data */ + HSM_DrvEccCurveParamType tCurve; /*!< ecc curve parameters */ + const uint32_t *pPrivateKey; /*!< private key */ + const uint32_t *pHashData; /*!< hash of the data to verify */ + + /* the following the sign output */ + uint32_t *pR; /*!< driver internal use this buffer to store the sign result R of the data to sign */ + uint32_t *pS; /*!< driver internal use this buffer to store the sign result S of the data to sign */ +} HSM_EccSignType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_PrivateKey; /*!< 0 means use key from HSM internal key space, otherwise would load key with KEYID from key space */ + uint32_t u32BitCnt; /*!< ECC parameter N bit count */ + HSM_DrvEccCurvePrmIndexType u32EccCurve; /*!< select hsm rom internal ecc curve parameters, if use user's self curve, set it to HSM_DRV_ECC_CURVE_PRM_IDX_MAX */ + HSM_EccSignType tCfg; /*!< ecc sign parameters */ +} HSMCom_EccSignType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief ECC verify information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t u32DataByteCnt; /*!< the byte count of all ecc curve parameter */ + HSM_DrvEccCurveParamType tCurve; /*!< ecc curve parameters */ + const uint32_t *pkG_x; /*!< public key axis x */ + const uint32_t *pkG_y; /*!< public key axis y */ + const uint32_t *pHashData; /*!< hash of the data to verify */ + const uint32_t *pR; /*!< the sign result R of the data to verify */ + const uint32_t *pS; /*!< the sign result S of the data to verify */ +} HSM_EccVerifyType; +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_PublicKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + uint32_t u32BitCnt; /*!< ECC parameter N bit count */ + HSM_DrvEccCurvePrmIndexType u32EccCurve; /*!< select hsm rom internal ecc curve parameters, if use user's self curve, set it to HSM_DRV_ECC_CURVE_PRM_IDX_MAX */ + HSM_EccVerifyType tCfg; /*!< ecc verify parameters */ +} HSMCom_EccVerifyType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief SM2 key pair generation information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t (*pPrivateKey)[8]; /*!< private key */ + uint32_t (*pPublicKey_X)[8]; /*!< the public key X */ + uint32_t (*pPublicKey_Y)[8]; /*!< the public key Y */ +} HSM_Sm2GenKeyPairType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + HSM_Sm2GenKeyPairType tCfg; /*!< sm2 generate key pair parameters */ +} HSMCom_Sm2GenKeyPairType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief SM2 encrypt information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t u32SM2InputByteCnt; /*!< the length should be <= 32bytes */ + uint32_t *pSM2OutputByteCnt; /*!< driver internal will set output byte count in the memory this pointer point to */ + uint32_t *pInputData; /*!< length should be more than u32SM2InputByteCnt, and must be 4bytes align */ + uint32_t (*pPublicKey_x)[8]; /*!< public key axis x data */ + uint32_t (*pPublicKey_y)[8]; /*!< public key axis y data */ + uint32_t *pOutputData; /*!< length should be more than u32SM2InputByteCnt+97, and must be 4bytes align */ +} HSM_Sm2EncryptType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_PublicKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_Sm2EncryptType tCfg; /*!< sm2 encrypt parameters */ +} HSMCom_Sm2EncryptType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief SM2 decrypt information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t u32SM2InputByteCnt; /*!< the length should be <= 129bytes */ + uint32_t *pSM2OutputByteCnt; /*!< driver internal will set output byte count in the memory this pointer point to */ + uint32_t *pInputData; /*!< length should be more than u32SM2InputByteCnt, and must be 4bytes align */ + uint32_t (*pPrivateKey)[8]; /*!< private key */ + uint32_t *pOutputData; /*!< length should be more than u32SM2InputByteCnt-97, and must be 4bytes align */ +} HSM_Sm2DecryptType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_PrivateKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_Sm2DecryptType tCfg; +} HSMCom_Sm2DecryptType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief SM2 sign information used by driver when call specific API + * + */ +typedef struct +{ + HSM_BoolType bUseDefaultID; /*!< TRUE means use default ID. FALSE means use specific ID with "pInputData_ID" and "u32SM2InputIDByteCnt" params. */ + HSM_BoolType bHashInput; /*!< TRUE means process hash message. FALSE means process raw M message */ + uint32_t u32SM2InputMByteCnt; /*!< the length should be <= 32bytes */ + uint32_t u32SM2InputIDByteCnt; /*!< the length should be <= 32bytes note: If "bUseDefaultID" is FALSE, would use this specific ID length with byte unit. */ + uint32_t *pInputData_ID; /*!< note: If "bUseDefaultID" is FALSE, would use this specific ID. length should be more than u32SM2InputIDByteCnt, and must be 4bytes align */ + uint32_t *pInputData_MOrHash; /*!< length should be more than u32SM2InputMOrHashByteCnt, and must be 4bytes align */ + uint32_t (*pPrivateKey)[8]; /*!< private key */ + uint32_t (*pPublicKey_X)[8]; /*!< If bHashInput is false, the pointer must be not NULL */ + uint32_t (*pPublicKey_Y)[8]; /*!< If bHashInput is false, the pointer must be not NULL */ + uint32_t (*pOutputData_R)[8]; /*!< sign result R */ + uint32_t (*pOutputData_S)[8]; /*!< sign result S */ +} HSM_Sm2SignType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_PublicKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + uint32_t u32UserKeyID_PrivateKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_Sm2SignType tCfg; +} HSMCom_Sm2SignType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief SM2 verify information used by driver when call specific API + * + */ +typedef struct +{ + HSM_BoolType bUseDefaultID; /*!< TRUE means use default ID. FALSE means use specific ID with "pInputData_ID" and "u32SM2InputIDByteCnt" params. */ + HSM_BoolType bHashInput; /*!< TRUE means process hash message. FALSE means process raw M message */ + uint32_t u32SM2InputMByteCnt; /*!< the length should be <= 32bytes */ + uint32_t u32SM2InputIDByteCnt; /*!< the length should be <= 32bytes note: If "bUseDefaultID" is FALSE, would use this specific ID length with byte unit. */ + uint32_t *pInputData_MOrHash; /*!< length should be more than u32SM2InputMOrHashByteCnt, and must be 4bytes align */ + uint32_t *pInputData_ID; /*!< note: If "bUseDefaultID" is FALSE, would use this specific ID. length should be more than u32SM2InputIDByteCnt, and must be 4bytes align */ + uint32_t (*pInputData_R)[8]; /*!< the sign result R */ + uint32_t (*pInputData_S)[8]; /*!< the sign result S */ + uint32_t (*pPublicKey_X)[8]; /*!< the public key X */ + uint32_t (*pPublicKey_Y)[8]; /*!< the public key Y */ +} HSM_Sm2VerifyType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_PublicKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_Sm2VerifyType tCfg; /*!< sm2 verify parameters */ +} HSMCom_Sm2VerifyType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief SM2 ZA generation information used by driver when call specific API + * + */ +typedef struct +{ + HSM_BoolType bUseDefaultID; /*!< TRUE means use default ID. FALSE means use specific ID with "pInputData_ID" and "u32SM2InputIDByteCnt" params. */ + uint32_t u32SM2InputIDByteCnt;/*!< the length should be <= 32bytes note: If "bUseDefaultID" is FALSE, would use this specific ID length with byte unit.*/ + uint32_t (*pPublicKey_X)[8]; + uint32_t (*pPublicKey_Y)[8]; + uint32_t *pInputData_ID; /*!< note: If "bUseDefaultID" is FALSE, would use this specific ID. length should be more than u32SM2InputIDByteCnt, and must be 4bytes align */ + uint32_t (*pOutputData_Za)[8]; /*!< Length is 32bytes, SM3 always output 256bit */ +} HSM_Sm2GenZaType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_PublicKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_Sm2GenZaType tCfg; +} HSMCom_Sm2GenZaType; +/* ------------------------------------------------------------------------------- */ +/** + * @brief SM2 HASH generation information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t u32InputDataByteCnt; /*!< input data byte count */ + uint32_t *pInputData_ZaAndM; /*!< note: it should be ZA||M, the length should be more than u32InputDataByteCnt, and must be 4bytes align */ + uint32_t (*pOutputData_Hash)[8]; /*!< Length is 32bytes, SM3 always output 256bit */ +} HSM_Sm2GenHashType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + HSM_Sm2GenHashType tCfg; +} HSMCom_Sm2GenHashType; +/* ------------------------------------------------------------------------------- */ +/** + * @name definitions for HSM_Sm4KeyType + * + */ +/**@{*/ +/** + * @brief vendor key value for type "HSM_Sm4KeyType" + * + * HSM hardware support accessing the SM4 key stored in nvr flash directly, + * chip user should program the key in flash already. + * This way don't need software read data and write it to some place, + * hardware will read the data itself automatically. + */ +#define HSM_SM4_KEY_CHIP_VENDOR_IFR (0U) /* key has existed in Flash IFR, it provided by chip, not changeable */ + +/** + * @brief driver user's new key value for type "HSM_Sm4KeyType" + * + * HSM use the key passed by driver API user. + */ +#define HSM_SM4_KEY_NEW (1U) /* user should provide the new key */ +typedef uint32_t HSM_Sm4KeyType; +/**@}*/ + +/** + * @name definitions for HSM_Sm4EnDecryptAlgType + * + */ +/**@{*/ +/** + * @brief SM4 CTR mode value for type "HSM_Sm4EnDecryptAlgType" + * + */ +#define HSM_SM4_CTR (0U) + +/** + * @brief SM4 CBC mode value for type "HSM_Sm4EnDecryptAlgType" + * + */ +#define HSM_SM4_CBC (1U) + +/** + * @brief SM4 ECB mode value for type "HSM_Sm4EnDecryptAlgType" + * + */ +#define HSM_SM4_ECB (2U) + +/** + * @brief SM4 CFB mode value for type "HSM_Sm4EnDecryptAlgType" + * + */ +#define HSM_SM4_CFB (3U) + +/** + * @brief SM4 OFB mode value for type "HSM_Sm4EnDecryptAlgType" + * + */ +#define HSM_SM4_OFB (4U) + +/** + * @brief type definition for SM4 encrypt/decrypt mode + * + * HSM support CTR/CBC/ECB/CFB/OFB mode, driver api use this to select the encrypt/decrypt mode. + */ +typedef uint32_t HSM_Sm4EnDecryptAlgType; +/**@}*/ + +/** + * @brief SM4 encrypt/decrypt information used by driver when call specific API + * + */ +typedef struct +{ + HSM_Sm4KeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + const uint32_t (*pKeyAddr)[4]; /*!< when eUseKeyType is HSM_SM4_KEY_NEW, this MUST configure */ + HSM_Sm4EnDecryptAlgType eSm4Alg; /*!< SM4 encrypt/decrypt mode */ + + const uint32_t *pDataInput; /*!< address should align with 4bytes */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t *pDataOutput; /*!< address should align with 4bytes */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + + uint32_t (*pIvData)[4]; /*!< 128bit(16Bytes) iv(initialization vector) data array, ECB not need configure this */ +} HSM_Sm4EnDecryptType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_Sm4EnDecryptType tCfg; +} HSMCom_Sm4EnDecryptType; + +typedef HSMCom_Sm4EnDecryptType HSMCom_Sm4DecryptType; + +typedef HSMCom_Sm4EnDecryptType HSMCom_Sm4EncryptType; + +typedef struct { + HSMCom_Sm4EncryptType *pParam; + uint32_t u32Remain; +} HSMWrap_Sm4EncryptType; +/* ------------------------------------------------------------------------------- */ +/** + * @brief ECC encrypt information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t u32ByteCount; /*!< all the data size, it should contains all N data */ + + const uint32_t *pCoeffi_A; /*!< the constant "a" in y^2 = x^3 + a*x + b (mod p), all data 8 bytes aligned */ + const uint32_t *pCoeffi_B; /*!< the constant "b" in y^2 = x^3 + a*x + b (mod p) */ + const uint32_t *pP; /*!< ecc curve modulus */ + const uint32_t *pN; /*!< ecc curve order; size; the count of all possible EC points */ + const uint32_t *pOtherSidePublicKey_x; /*!< decrypt side's public key axis x data */ + const uint32_t *pOtherSidePublicKey_y; /*!< decrypt side's public key axis y data */ + const uint32_t *pPrivateKey; /*!< encrypt side private key */ + const uint32_t *pPlainData; /*!< data to be encrypted, its byte count should be same as u32ByteCount */ + + uint32_t *pEncryedData; /*!< driver internal write the result to this buffer */ +} HSM_EccEasyEncryType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_PrivateKey;/*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + uint32_t u32UserKeyID_PublicKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + uint32_t u32BitCnt; + HSM_DrvEccCurvePrmIndexType u32EccCurve; + HSM_EccEasyEncryType tCfg; +} HSMCom_EccEasyEncryType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief ECC decrypt information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t u32ByteCount; /*!< all the data size, it should contains all N data */ + const uint32_t *pCoeffi_A; /*!< the constant "a" in y^2 = x^3 + a*x + b (mod p), all data 8 bytes aligned */ + const uint32_t *pCoeffi_B; /*!< the constant "b" in y^2 = x^3 + a*x + b (mod p) */ + const uint32_t *pP; /*!< ecc curve modulus */ + const uint32_t *pN; /*!< ecc curve order; size; the count of all possible EC points */ + const uint32_t *pOtherSidePublicKey_x; /*!< encrypt side's public key axis x data */ + const uint32_t *pOtherSidePublicKey_y; /*!< encrypt side's public key axis y data */ + const uint32_t *pPrivateKey; /*!< decrypt side private key */ + const uint32_t *pEncryedData; /*!< data to be decrypted, its byte count should be same as u32ByteCount */ + uint32_t *pPlainData; /*!< driver internal write the result to this buffer */ +} HSM_EccEasyDecryType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_PrivateKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + uint32_t u32UserKeyID_PublicKey; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + uint32_t u32BitCnt; + HSM_DrvEccCurvePrmIndexType u32EccCurve; + HSM_EccEasyDecryType tCfg; +} HSMCom_EccEasyDecryType; +/* ------------------------------------------------------------------------------- */ +/** + * @brief ECC generate key pair information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t u32ByteCount; /*!< all the data size, it should contains all N data */ + HSM_DrvEccCurveParamType tEccParam; + uint32_t *pPrivateKey; /*!< decrypt side private key */ + uint32_t *pPublicKey_x; /*!< encrypt side's public key axis x data */ + uint32_t *pPublicKey_y; /*!< encrypt side's public key axis y data */ +} HSM_EccKeyPairGenType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32Bitcnt; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_DrvEccCurvePrmIndexType u32EccCurve; + HSM_EccKeyPairGenType tCfg; +} HSMCom_EccKeyPairGenType; +/* ------------------------------------------------------------------------------- */ + + +#define HSM_ECC_CALC_PADD 0xFC73F800 +#define HSM_ECC_CALC_PDBL 0xFC73F801 +#define HSM_ECC_CALC_PMUL 0xFC73F802 +#define HSM_ECC_CALC_PCHK 0xFC73F803 + +/** + * @brief ECC point calclulate used by driver when call specific API + * + */ +typedef struct +{ + uint32_t u32ByteCount; /*!< all the data size, it should contains all N data */ + const uint32_t *pCoeffi_A; /*!< address should align with 4bytes, the constant "a" in y^2 = x^3 + a*x + b (mod p), all data 8 bytes aligned */ + const uint32_t *pCoeffi_B; /*!< address should align with 4bytes, the constant "b" in y^2 = x^3 + a*x + b (mod p) */ + const uint32_t *pP; /*!< address should align with 4bytes, ecc curve modulus */ + const uint32_t *pN; /*!< address should align with 4bytes, ecc curve order; size; the count of all possible EC points */ + const uint32_t *pP1x; /*!< address should align with 4bytes, encrypt side's public key axis x data */ + const uint32_t *pP1y; /*!< address should align with 4bytes, encrypt side's public key axis y data */ + const uint32_t *pE; /*!< address should align with 4bytes, decrypt side private key */ + const uint32_t *pP2x; /*!< address should align with 4bytes, data to be decrypted, its byte count should be same as u32ByteCount */ + uint32_t *pResultx; /*!< address should align with 4bytes, driver internal write the result to this buffer */ + uint32_t u32CalcType; + const uint32_t *pP2y; + uint32_t *pResulty; +} HSM_EccCalcType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout Millisecond count, max 916000ms, if set to 0, means 1000ms */ + uint32_t u32UserKeyID_E; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + uint32_t u32UserKeyID_P1; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + uint32_t u32BitCnt; /*!< ecc encrypt data bit count */ + HSM_DrvEccCurvePrmIndexType u32EccCurve; /*!< ecc curve */ + HSM_EccCalcType tCfg; /*!< ecc decrypt parameters */ +} HSMCom_EccCalcType; +/* ------------------------------------------------------------------------------- */ + +#define HSM_COM_REQUEST_AUTH_DATA_U32_CNT 8 +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t (*pData)[HSM_COM_REQUEST_AUTH_DATA_U32_CNT]; +} HSMCom_RequestAuthType; +/* ------------------------------------------------------------------------------- */ +#define AUTH_CHECK_DATA_BYTE_CNT 32 +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + const uint32_t *pkG_x; + const uint32_t *pkG_y; + const uint32_t *pR; + const uint32_t *pS; + //For user code verify function + const uint32_t *pData; + uint32_t u32DataLength; +} HSMCom_LifeCycleChangeType; +/* ------------------------------------------------------------------------------- */ +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32MailboxChannel; +} HSMCom_CancelJobType; +/* ------------------------------------------------------------------------------- */ +/** + * @name definitions for HSMCom_FirmwareLoadStatus + * + */ +/**@{*/ +/** + * @brief no firmware detected in flash status + * + */ +#define HSMCOM_FIRMWARE_LOAD_NONE (0u) + +/** + * @brief status value represents firmware is loading now + * + */ +#define HSMCOM_FIRMWARE_LOADING (1u) + +/** + * @brief status value represents firmware waiting user to trigger load in CM7 side + * + */ +#define HSMCOM_FIRMWARE_NEED_USER_LOAD (2u) + +/** + * @brief status value represents firmware is loaded successfully + * + */ +#define HSMCOM_FIRMWARE_LOAD_OK (3u) + +/** + * @brief status value represents firmware load fail + * + */ +#define HSMCOM_FIRMWARE_LOAD_FAIL (4u) + +typedef uint32_t HSMCom_FirmwareLoadStatus; +/**@}*/ + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32Rng0CtrlAndNotFlag; // conf val, only ft mode, other mode REPO_COMMIT_ID + uint32_t u32Rng0CtrlOrFlag; // conf val,only ft mode, other mode REPO_BUILD_DATA + uint32_t u32FirmVersion; /*!< firmware version */ + uint32_t u32Rng1CtrlOrFlag; /*< FIX to 0x4d6f0000 */ + uint32_t u32BusClk; /*!< the hsm bus clock */ + uint32_t u32EntropyDelay0; + uint32_t u32FreqMax0; + uint32_t u32EntropyDelay1; + uint32_t u32FreqMax1; + HSMCom_FirmwareLoadStatus u32FirmwareLoadStatus; /*!< the status of loading firmware, IF >= 4 FAIL */ +} HSMCom_SelfTestType; +/* ------------------------------------------------------------------------------- */ + +#define HSMCOM_NVR_OTP_START_ADDR 0x04400400 +#define HSMCOM_NVR_OTP_END_ADDR 0x04401fff + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32Addr; // 0x04400400 - 0x04401fff, 16bytes align + uint32_t aData[4]; +} HSMCom_NvrOtpType; +/* ------------------------------------------------------------------------------- */ +/** + * @name definitions for KeyManager_BoolType + * + */ +/**@{*/ +#define KEYMANAGER_FALSE (0u) +#define KEYMANAGER_TRUE (1u) +typedef uint32_t KeyManager_BoolType; +/**@}*/ + +/** + * @name definitions for KEYMANAGER_KeyExportType + * + */ +/**@{*/ +#define KEYMANAGER_KEY_EXPORT_FORBIRD (0u) +#define KEYMANAGER_KEY_EXPORT_PLAIN (1u) +#define KEYMANAGER_KEY_EXPORT_CIPHER (2u) +#define KEYMANAGER_KEY_EXPORT_MAX (3u) +typedef uint32_t KEYMANAGER_KeyExportType; +/**@}*/ + +/** + * @name definitions for KeyManager_UserKeyEnDecryType + * + */ +/**@{*/ +#define KEYMANAGER_ENDECRY_NONE (0u)/* For plain key, no need to encrypt or decrypt. */ +#define KEYMANAGER_ENDECRY_AES256 (1u) +#define KEYMANAGER_ENDECRY_SM4 (2u) +#define KEYMANAGER_ENDECRY_MAX (3u) +typedef uint32_t KeyManager_UserKeyEnDecryType; +/**@}*/ + +/** + * @name definitions for KeyManager_UserKeyTypeType + * + */ +/**@{*/ +#define KEYMANAGER_USER_KEY_TYPE_NONE (0u)//not configure the key type, HSM shall not check if the key type is matched with de/encrypt ALG. +#define KEYMANAGER_USER_KEY_TYPE_AES (1u) +#define KEYMANAGER_USER_KEY_TYPE_SM4 (2u) +#define KEYMANAGER_USER_KEY_TYPE_ECC_PRIVATE (3u) +#define KEYMANAGER_USER_KEY_TYPE_ECC_PUBLIC (4u) +#define KEYMANAGER_USER_KEY_TYPE_SM2_PRIVATE (5u) +#define KEYMANAGER_USER_KEY_TYPE_SM2_PUBLIC (6u) +#define KEYMANAGER_USER_KEY_TYPE_RSA_E (7u) +#define KEYMANAGER_USER_KEY_TYPE_RSA_N (8u) +#define KEYMANAGER_USER_KEY_TYPE_XMAC (9u) +#define KEYMANAGER_USER_KEY_TYPE_CMAC (10u) +#define KEYMANAGER_USER_KEY_TYPE_CCM (11u) +#define KEYMANAGER_USER_KEY_TYPE_GCM (12u) +typedef uint32_t KeyManager_UserKeyTypeType; +/**@}*/ + +/** + * @name definitions for KEYMANAGER_EnDecryAlgType + * + */ +/**@{*/ + +#define KEYMANAGER_ENDECRY_ALG_CTR (0u) +#define KEYMANAGER_ENDECRY_ALG_CBC (1u) +#define KEYMANAGER_ENDECRY_ALG_ECB (2u) +#define KEYMANAGER_ENDECRY_ALG_CFB (3u) +#define KEYMANAGER_ENDECRY_ALG_OFB (4u) +#define KEYMANAGER_ENDECRY_ALG_MAX (5u) + +typedef uint32_t KEYMANAGER_EnDecryAlgType; +/**@}*/ + +typedef struct +{ + uint32_t *pDataAddr; + uint32_t *pDataLength; + uint32_t u32KeyID; + KeyManager_UserKeyEnDecryType eEncryType; //indicate if the key exported is need to be encrypted + //if the key exported need to be encrypted, below Param need to configure + uint32_t u32EncryKeyID; //0 means use USRK as encrykey, otherwise load decrykey with KEYID from hsm key space + KEYMANAGER_EnDecryAlgType eAlgType; + uint32_t (*pIV)[4]; + uint32_t *pCiperKeyLength; +} KeyManager_ExportUserKeyType; + +typedef struct +{ + KeyManager_BoolType bStoreInFlash; //true means store the key in flash, false means store the key in ram + KEYMANAGER_KeyExportType eExportType; + uint32_t *pDataAddr; //the address of key imported + uint32_t u32DataLength; // the length of key imported + uint32_t *pKeyID; + KeyManager_UserKeyEnDecryType eDecryType; //indicate if the key imported is plain + //if the key imported is encrypted, below Param need to configure + uint32_t u32DecryKeyID; //0 means use USRK as decrykey, otherwise load decrykey with KEYID from hsm key space + KeyManager_UserKeyTypeType eUserKeyType; + KEYMANAGER_EnDecryAlgType eAlgType; + uint32_t (*pIV)[4]; +} KeyManager_ImportUserKeyType; + +#define KEYMANAGER_GEN_KEYPAIR_SM2 (0u) +#define KEYMANAGER_GEN_KEYPAIR_ECC (1u) +#define KEYMANAGER_GEN_KEYPAIR_MAX (2u) +typedef uint32_t KeyManager_GeNKeyPairType; + +typedef struct +{ + KeyManager_GeNKeyPairType eKeyPairType; + KEYMANAGER_KeyExportType eExportType; + KeyManager_BoolType bStoreInFlash; + uint32_t *pPrivateKeyID; + uint32_t *pPublicKeyID; +} KeyManager_GenAsymmetricUserKeyType; + +typedef struct +{ + KEYMANAGER_KeyExportType eExportType; + KeyManager_BoolType bStoreInFlash; + uint32_t u32KeyLength; + uint32_t *pKeyID; +} KeyManager_GenSymmetricUserKeyType; + +typedef struct +{ + union{ + KeyManager_GenAsymmetricUserKeyType tGenKeyPairCfg; + KeyManager_GenSymmetricUserKeyType tGenKeyCfg; + }; + HSM_DrvEccCurveParamType tEccParam; //only for generate ECC key pair + uint32_t u32EccBitLength; //only for generate ECC key pair + HSM_BoolType bGenSymmetricKey; + HSM_DrvEccCurvePrmIndexType u32EccCurve; +} HSMCom_GenUserKeyType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + union + { + uint32_t u32RevokeUserKeyID;/* For revoke UserKey function*/ + KeyManager_ImportUserKeyType tImportUserKeyCfg;/* For import User Key function*/ + KeyManager_ExportUserKeyType tExportUserKeyCfg;/* For export user key function */ + HSMCom_GenUserKeyType tGenUserKeyCfg;/* For generate key pair function */ + }; +} HSMCom_UserKeyManageType; +/* ------------------------------------------------------------------------------- */ +typedef struct +{ + //For Key Flash Space + KeyManager_BoolType bCriticalError; + KeyManager_BoolType bKMLackKeyHeadSpace; + KeyManager_BoolType bKMLackKeyDataSpace; + uint32_t u32KeyHeadRestSpace; //The unit is number + uint32_t u32KeyDataRestSpace; //The unit is page + uint32_t u32InvalidKeyCounter; + //For Key ram space + uint32_t u32KeyRamSpaceUsed; +} KeyManager_SpaceStatusType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + KeyManager_SpaceStatusType *pKMSpaceStatus; +} HSMCom_KeySpaceStatusType; +/* ------------------------------------------------------------------------------- */ + +/** + * @name definitions for HSM_AesKeyType + * + */ +/**@{*/ + +/** + * @brief vendor key value for type "HSM_AesKeyType" + * + * HSM hardware support accessing the aes key stored in nvr flash directly, + * chip user should program the key in flash already. + * This way don't need software read data and write it to some place, + * hardware will read the data itself automatically. + */ +#define HSM_AES_KEY_CHIP_VENDOR_IFR (0U) /* key has existed in Flash IFR, it provided by chip hardware, not changeable */ + +/** + * @brief driver user's new key value for type "HSM_AesKeyType" + * + * HSM use the key passed by driver API user. + */ +#define HSM_AES_KEY_NEW (1U) /* user should provide the new key */ + +/** + * @brief type definition for the key source + * + * key from the nvr refer to HSM_AES_KEY_CHIP_VENDOR_IFR + * key from driver user's parameters refer to HSM_AES_KEY_NEW + */ +typedef uint32_t HSM_AesKeyType; +/**@}*/ + +/** + * @name definitions for HSM_AesKeyBitCntType + * + */ +/**@{*/ + +/** + * @brief AES128 key type value for type "HSM_AesKeyBitCntType" + * + */ +#define HSM_AES_KEY128 (0U) + +/** + * @brief AES192 key type value for type "HSM_AesKeyBitCntType" + * + */ +#define HSM_AES_KEY192 (1U) + +/** + * @brief AES256 key type value for type "HSM_AesKeyBitCntType" + * + */ +#define HSM_AES_KEY256 (2U) + +/** + * @brief type definition for AES key + * + * HSM support AES128/192/256, driver api use this to select the algorithm. + */ +typedef uint32_t HSM_AesKeyBitCntType; +/**@}*/ + + +/** + * @brief key information used by AES when use one key in software + * + */ +typedef struct +{ + HSM_AesKeyBitCntType eKeyType; /*!< the key bit count, which determine the AES algorithm type */ + const uint32_t *pKeyAddr; /*!< the key data pointer, the address should 4bytes align, the buffer array should declared by uint32_t */ +} HSM_AesNewKeyInfType; + +/** + * @brief key information used by AES when use one key in nvr flash + * + */ +typedef struct +{ + HSM_AesKeyBitCntType eKeyType; /*!< the key bit count, which determine the AES algorithm type */ +} HSM_AesVendorKeyInfType; + +/** + * @name definitions for HSM_AesEnDecryptAlgType + * + */ +/**@{*/ + +/** + * @brief AES CTR mode value for type "HSM_AesEnDecryptAlgType" + * + */ +#define HSM_AES_CTR (0U) + +/** + * @brief AES CBC mode value for type "HSM_AesEnDecryptAlgType" + * + */ +#define HSM_AES_CBC (1U) + +/** + * @brief AES ECB mode value for type "HSM_AesEnDecryptAlgType" + * + */ +#define HSM_AES_ECB (2U) + +/** + * @brief AES CFB mode value for type "HSM_AesEnDecryptAlgType" + * + */ +#define HSM_AES_CFB (3U) + +/** + * @brief AES OFB mode value for type "HSM_AesEnDecryptAlgType" + * + */ +#define HSM_AES_OFB (4U) + +/** + * @brief type definition for AES encrypt/decrypt mode + * + * HSM support CTR/CBC/ECB/CFB/OFB mode, driver api use this to select the encrypt/decrypt mode. + */ +typedef uint32_t HSM_AesEnDecryptAlgType; +/**@}*/ + +/** + * @brief AES encrypt/decrypt information used by driver when call specific API + * + */ +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + HSM_AesEnDecryptAlgType eAesAlg; /*!< encrypt/decrypt mode */ + + const uint32_t *pDataInput; /*!< address should align with 4bytes */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t *pDataOutput; /*!< address should align with 4bytes */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + + uint32_t (*pIvData)[4]; /*!< 128bit(16Bytes) iv(initialization vector) data array, ECB not need configure this */ + +} HSM_AesEnDecryptType; + +/** + * @brief Flexiable AES zero padding type for type "HSM_FlexAesPadType" + * if input data is not aligned with 16bytes, this configuration will make append byte data 0 to keep 16bytes align. + */ +#define HSM_FLEXAES_PAD_ZERO 0u + +/** + * @brief Flexiable AES PKCS7 padding type for type "HSM_FlexAesPadType" + * if input data is not aligned with 16bytes, this configuration will make append bytes by PKCS7 method to keep 16bytes align. + */ +#define HSM_FLEXAES_PAD_PKCS7 1u + +/** + * @brief Flexiable AES padding type definition + * if use zero padding, refer to HSM_FLEXAES_PAD_ZERO, after decrypt, user should remove the zero manually + * if use PKCS7 padding, refer to HSM_FLEXAES_PAD_PKCS7 + */ +typedef uint32_t HSM_FlexAesPadType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief AES hardware backend for AES for type "HSM_AesBackendType" + * + */ +#define HSM_AES_BACKEND_AES 0u + +/** + * @brief SM4 hardware backend for AES for type "HSM_AesBackendType" + * + */ +#define HSM_AES_BACKEND_SM4 1u + +/** + * @brief type definition for GCM's hardware backend + * AES backend refer to HSM_AES_BACKEND_AES + * SM4 backend refer to HSM_GCM_BACKEND_SM4 + */ +typedef uint32_t HSM_AesBackendType; + +/** + * @brief Flex AES encrypt/decrypt information used by driver when call specific API + * + */ +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + HSM_AesEnDecryptAlgType eAesAlg; /*!< encrypt/decrypt mode */ + + const uint32_t *pDataInput; /*!< address should align with 4bytes */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t *pDataOutput; /*!< address should align with 4bytes */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + + uint32_t (*pIvData)[4]; /*!< address should align with 4bytes, 128bit(16Bytes) iv(initialization vector) data array, ECB not need configure this */ + + uint32_t *pGenerateOutByteCnt; /*!< point to the uint32_t variable to store the result byte count, can't be NULL */ + + HSM_FlexAesPadType epad; + HSM_DataFormatType eInputFmt; + HSM_DataFormatType eOutputFmt; + HSM_AesBackendType eBackend; +} HSM_FlexAesEnDecryptType; + +/** + * @brief AES decrypt information used by driver when call specific API + * + */ +typedef HSM_AesEnDecryptType HSM_AesEncryptType; +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_AesEncryptType tCfg; /*!< aes parameters */ +} HSMCom_AesEncryptType; +/* ------------------------------------------------------------------------------- */ +/** + * @brief AES encrypt information used by driver when call specific API + * + */ +typedef HSM_AesEnDecryptType HSM_AesDecryptType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_AesDecryptType tCfg; /*!< AES decrypt parameters */ +} HSMCom_AesDecryptType; +/* ------------------------------------------------------------------------------- */ + +/** + * @brief Flex AES decrypt information used by driver when call specific API + * + */ +typedef HSM_FlexAesEnDecryptType HSM_FlexAesEncryptType; +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout Millisecond count, max 916000ms, if set to 0, means 1000ms */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_FlexAesEncryptType tCfg; /*!< aes parameters */ +} HSMCom_FlexAesEncryptType; +/* ------------------------------------------------------------------------------- */ +/** + * @brief AES encrypt information used by driver when call specific API + * + */ +typedef HSM_FlexAesEnDecryptType HSM_FlexAesDecryptType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout Millisecond count, max 916000ms, if set to 0, means 1000ms */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_FlexAesDecryptType tCfg; /*!< AES decrypt parameters */ +} HSMCom_FlexAesDecryptType; +/* ------------------------------------------------------------------------------- */ + +/** + * @brief CMAC/XMAC information used by driver when call specific API + * + */ + +#define HSM_XCMAC_BACKEND_AES 0u +#define HSM_XCMAC_BACKEND_SM4 1u + +typedef uint32_t HSM_XCMAC_BackendType; + +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< fix to HSM_AES_KEY_NEW */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t u32GenMacByteCnt; /*!< XCMAC API generate MAC data, it's "u32GenMacByteCnt" size ICV data */ + HSM_BoolType bCheckMacEn; /*!< if enable this check, user should place the data after the input data, hsm will check the generated data and it, if fail, hsm generate a interrupt, and if user get hw status, will get a error status */ + const uint32_t *pDataInput; /*!< address should align with 4bytes */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t *pDataOutput; /*!< address should align with 4bytes */ + uint32_t u32OutputMemSize; /*!< 4bytes align, the output data buffer "pDataOutput" size, should >= "u32GenMacByteCnt" */ +} HSM_XCMacType; + +/** + * @brief CMAC information used by driver when call specific API + * + */ +typedef HSM_XCMacType HSM_CMacType; + + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_CMacType tCfg; /*!< CMAC parameters */ +} HSMCom_CMacType; + +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< fix to HSM_AES_KEY_NEW */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t u32GenMacByteCnt; /*!< XCMAC API generate MAC data, it's "u32GenMacByteCnt" size ICV data */ + HSM_BoolType bCheckMacEn; /*!< if enable this check, user should place the data after the input data, hsm will check the generated data and it, if fail, hsm generate a interrupt, and if user get hw status, will get a error status */ + const uint32_t *pDataInput; /*!< address should align with 4bytes */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t *pDataOutput; /*!< address should align with 4bytes */ + uint32_t u32OutputMemSize; /*!< 4bytes align, the output data buffer "pDataOutput" size, should >= "u32GenMacByteCnt" */ + + HSM_XCMAC_BackendType eBackend; + HSM_DataFormatType eInputFmt; + HSM_DataFormatType eOutputFmt; +} HSM_XCMacExType; + +typedef HSM_XCMacExType HSM_CMacExType; +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_CMacExType tCfg; /*!< CMAC parameters */ +} HSMCom_CMacExType; + + +/* ------------------------------------------------------------------------------- */ +/** + * @brief XMAC information used by driver when call specific API + * + */ +typedef HSM_XCMacType HSM_XMacType; +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_XMacType tCfg; /*!< XMAC parameter */ +} HSMCom_XMacType; + +typedef HSM_XCMacExType HSM_XMacExType; +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_XMacExType tCfg; /*!< XMAC parameter */ +} HSMCom_XMacExType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief AES hardware backend for CCM for type "HSM_CcmBackendType" + * + */ +#define HSM_CCM_BACKEND_AES 0u + +/** + * @brief SM4 hardware backend for CCM for type "HSM_CcmBackendType" + * + */ +#define HSM_CCM_BACKEND_SM4 1u + +/** + * @brief type definition for CCM's hardware backend + * AES backend refer to HSM_CCM_BACKEND_AES + * SM4 backend refer to HSM_CCM_BACKEND_SM4 + */ +typedef uint32_t HSM_CcmBackendType; + + +/** + * @brief CCM Encrypt information used by driver when call specific API + * + */ +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t *pAllData; /*!< address should align with 4bytes, place AAD data(16bytes align) first, then input data */ + uint32_t u32AadByteCnt; /*!< the byte count contain the 2bytes in the head, it's the valid data size, not after aligned, 128bit(16Bytes) align, if not, only the aligned data treat as AAD, the left AAD bytes will be treated as input data */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align, ONLY represent data */ + uint32_t u32GenMacByteCnt; /*!< output mac size */ + uint32_t *pDataOutput; /*!< address should align with 4bytes */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + uint32_t (*pIvData)[8]; /*!< iv data, consist of 16bytes B0 data, and 16bytes CTR, MUST configure */ + uint32_t (*pMacOut)[4]; /*!< HSM generated MAC data */ + uint32_t (*pEmacOut)[4]; /*!< HSM generated encrypted MAC data */ +} HSM_CcmEncryptType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_CcmEncryptType tCfg; /*!< CCM encrypt parameters */ +} HSMCom_CcmEncryptType; + +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t *pAllData; /*!< address should align with 4bytes, place AAD data(16bytes align) first, then input data */ + uint32_t u32AadByteCnt; /*!< the byte count contain the 2bytes in the head, it's the valid data size, not after aligned, 128bit(16Bytes) align, if not, only the aligned data treat as AAD, the left AAD bytes will be treated as input data */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align, ONLY represent data */ + uint32_t u32GenMacByteCnt; /*!< output mac size */ + uint32_t *pDataOutput; /*!< address should align with 4bytes */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + uint32_t (*pIvData)[8]; /*!< iv data, consist of 16bytes B0 data, and 16bytes CTR, MUST configure */ + uint32_t (*pMacOut)[4]; /*!< HSM generated MAC data */ + uint32_t (*pEmacOut)[4]; /*!< HSM generated encrypted MAC data */ + HSM_CcmBackendType eBackend; +} HSM_CcmEncryptExType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_CcmEncryptExType tCfg; /*!< CCM encrypt parameters */ +} HSMCom_CcmEncryptExType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief CCM Decrypt information used by driver when call specific API + * + */ +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t *pAllData; /*!< address should align with 4bytes, place AAD data(if exist, 16bytes align) first, then input data, then MAC data(if exist) */ + uint32_t u32AadByteCnt; /*!< 128bit(16Bytes) align, if not, only the aligned data treat as AAD, the left AAD bytes will be treated as input data */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + HSM_BoolType bCheckMacEn; /*!< check the MAC data in input or not */ + uint32_t u32MacByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t *pDataOutput; /*!< point to the buffer that store the result */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + uint32_t (*pIvData)[8]; /*!< iv data, consist of 16bytes B0 data, and 16bytes CTR, MUST configure */ +} HSM_CcmDecryptType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_CcmDecryptType tCfg; /*!< CCM decrypt parameter */ +} HSMCom_CcmDecryptType; + +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t *pAllData; /*!< address should align with 4bytes, place AAD data(if exist, 16bytes align) first, then input data, then MAC data(if exist) */ + uint32_t u32AadByteCnt; /*!< 128bit(16Bytes) align, if not, only the aligned data treat as AAD, the left AAD bytes will be treated as input data */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + HSM_BoolType bCheckMacEn; /*!< check the MAC data in input or not */ + uint32_t u32MacByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t *pDataOutput; /*!< point to the buffer that store the result */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + uint32_t (*pIvData)[8]; /*!< iv data, consist of 16bytes B0 data, and 16bytes CTR, MUST configure */ + HSM_CcmBackendType eBackend; +} HSM_CcmDecryptExType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_CcmDecryptExType tCfg; /*!< CCM decrypt parameter */ +} HSMCom_CcmDecryptExType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief AES hardware backend for GCM for type "HSM_GcmBackendType" + * + */ +#define HSM_GCM_BACKEND_AES 0u + +/** + * @brief SM4 hardware backend for GCM for type "HSM_GcmBackendType" + * + */ +#define HSM_GCM_BACKEND_SM4 1u + +/** + * @brief type definition for GCM's hardware backend + * AES backend refer to HSM_GCM_BACKEND_AES + * SM4 backend refer to HSM_GCM_BACKEND_SM4 + */ +typedef uint32_t HSM_GcmBackendType; + +/** + * @brief GCM Encrypt information used by driver when call specific API + * + */ +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t *pAllData; /*!< address should align with 4bytes, place IV data first, then AAD data(16bytes align), then input data */ + uint32_t u32IvDataByteCnt; /*!< 64bit(8Bytes) align, if not, only the aligned data treat as IV, the left IV bytes will be treated as AAD data */ + uint32_t u32AadByteCnt; /*!< 64bit(8Bytes) align, if not, only the aligned data treat as AAD, the left AAD bytes will be treated as input data */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t u32GenMacByteCnt; /*!< set the MAC result byte count */ + uint32_t *pDataOutput; /*!< address should align with 4bytes */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + uint32_t (*pMacOut)[4]; /*!< buffer address, this buffer store the result */ +} HSM_GcmEncryptType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_GcmEncryptType tCfg; /*!< GCM parameters */ +} HSMCom_GcmEncryptType; + +/** + * @brief GCM Encrypt information used by driver when call specific API + * + */ +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t *pAllData; /*!< address should align with 4bytes, place IV data first, then AAD data(16bytes align), then input data */ + uint32_t u32IvDataByteCnt; /*!< 64bit(8Bytes) align, if not, only the aligned data treat as IV, the left IV bytes will be treated as AAD data */ + uint32_t u32AadByteCnt; /*!< 64bit(8Bytes) align, if not, only the aligned data treat as AAD, the left AAD bytes will be treated as input data */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t u32GenMacByteCnt; /*!< set the MAC result byte count */ + uint32_t *pDataOutput; /*!< address should align with 4bytes */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + uint32_t (*pMacOut)[4]; /*!< buffer address, this buffer store the result */ + HSM_GcmBackendType eBackend; +} HSM_GcmEncryptExType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_GcmEncryptExType tCfg; /*!< GCM parameters */ +} HSMCom_GcmEncryptExType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief GCM Decrypt information used by driver when call specific API + * + */ +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t *pAllData; /*!< address should align with 4bytes, place IV data first, then AAD data(if exist, 16bytes align), then input data, then MAC data(if exist) */ + uint32_t u32IvDataByteCnt; /*!< 64bit(8Bytes) align, if not, only the aligned data treat as IV, the left IV bytes will be treated as AAD data */ + uint32_t u32AadByteCnt; /*!< 64bit(8Bytes) align, if not, only the aligned data treat as AAD, the left AAD bytes will be treated as input data */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + HSM_BoolType bCheckMacEn; /*!< check the MAC data in input or not */ + uint32_t u32MacByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t *pDataOutput; /*!< point to the buffer that store the result */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ +} HSM_GcmDecryptType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_GcmDecryptType tCfg; /*!< GCM decrypt parameter */ +} HSMCom_GcmDecryptType; + +/** + * @brief GCM Decrypt information used by driver when call specific API + * + */ +typedef struct +{ + HSM_AesKeyType eUseKeyType; /*!< the key source:vendor key programmed in nvr flash or new key in software */ + HSM_AesNewKeyInfType tNewKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_NEW, this MUST configure */ + HSM_AesVendorKeyInfType tVendorKeyInf; /*!< when eUseKeyType is HSM_AES_KEY_CHIP_VENDOR_IFR, this MUST configure */ + uint32_t *pAllData; /*!< address should align with 4bytes, place IV data first, then AAD data(if exist, 16bytes align), then input data, then MAC data(if exist) */ + uint32_t u32IvDataByteCnt; /*!< 64bit(8Bytes) align, if not, only the aligned data treat as IV, the left IV bytes will be treated as AAD data */ + uint32_t u32AadByteCnt; /*!< 64bit(8Bytes) align, if not, only the aligned data treat as AAD, the left AAD bytes will be treated as input data */ + uint32_t u32InputByteCnt; /*!< 128bit(16Bytes) align */ + HSM_BoolType bCheckMacEn; /*!< check the MAC data in input or not */ + uint32_t u32MacByteCnt; /*!< 128bit(16Bytes) align */ + uint32_t *pDataOutput; /*!< point to the buffer that store the result */ + uint32_t u32OutputMemSize; /*!< the output data buffer "pDataOutput" size, should >= "u32InputByteCnt" */ + HSM_GcmBackendType eBackend; +} HSM_GcmDecryptExType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID; /*!< 0 means don't use key from HSM internal key space, otherwise would load key with KEYID from HSM */ + HSM_GcmDecryptExType tCfg; /*!< GCM decrypt parameter */ +} HSMCom_GcmDecryptExType; + +/* ------------------------------------------------------------------------------- */ +/** + * @brief MD5 context information used by driver when call specific API + * + */ +typedef HSM_SmsCfgType HSM_Md5CtxType; +/** + * @brief MD5 information used by driver when call specific API + * + */ +typedef struct +{ + HSM_Md5CtxType tCfg; /*!< MD5 algorithm parameter set by user */ + uint32_t (*pRet)[4]; /*!< point to the memory that driver to store result */ + HSM_DataFormatType eIntputFmt; + HSM_DataFormatType eOutputFmt; +} HSM_Md5Type; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + HSM_Md5Type tCfg; +} HSMCom_Md5Type; +/* ------------------------------------------------------------------------------- */ +/** + * @brief SM3 context information used by driver when call specific API + * + */ +typedef HSM_SmsCfgType HSM_Sm3CtxType; +/** + * @brief SM3 information used by driver when call specific API + * + */ +typedef struct +{ + HSM_Sm3CtxType tCfg; /*!< sm3 algorithm parameter set by user */ + uint32_t (*pRet)[8]; /*!< point to the memory that driver to store result */ + HSM_DataFormatType eIntputFmt; + HSM_DataFormatType eOutputFmt; +} HSM_Sm3Type; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + HSM_Sm3Type tCfg; +} HSMCom_Sm3Type; + +/* ------------------------------------------------------------------------------- */ +#define HSMCOM_MONOTOIC_COUNTER_FLEX_REG_CNT 8 +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32MonotonicIndex; // 0-13 + uint32_t u32CurrentValue; + uint32_t (*u32ExtraValue)[HSMCOM_MONOTOIC_COUNTER_FLEX_REG_CNT - 1]; + uint32_t (*u32ExtraAdd)[HSMCOM_MONOTOIC_COUNTER_FLEX_REG_CNT]; +} HSMCom_MonCountType; +/* ------------------------------------------------------------------------------- */ +/** + * @brief RSA information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t *pInputData; /*!< input data, if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32InputDataByteCount; /*!< the byte count of input data */ + uint32_t *pKey_E; /*!< input key E data for "A = (input data)^E mod N", if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32Key_E_ByteCount; /*!< the byte count of key E */ + uint32_t *pKey_N; /*!< input key N data for "A = (input data)^E mod N", if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32Key_N_ByteCount; /*!< hw will get the actual key data bit count according to the non-zero bit count, it means key not generate by multiply 2 */ + uint32_t *pResult; /*!< output buffer, the buffer size should >= "u32Key_N_ByteCount" */ + uint32_t u32ResultBufByteCnt; /*!< the result buffer size */ +} HSM_RsaType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout tick count, tick refer to the HSM bus clock */ + uint32_t u32UserKeyID_KEY_E; //0 means don't load key from HSM, otherwise would load key with KEYID from HSM + uint32_t u32UserKeyID_KEY_N; //0 means don't load key from HSM, otherwise would load key with KEYID from HSM + uint32_t u32RsaBitCnt; + HSM_RsaType tCfg; +} HSMCom_RsaType; +/* ------------------------------------------------------------------------------- */ +#define HSM_BIGNUMBER_CALC_A_ADD_B 0xFC730002 +#define HSM_BIGNUMBER_CALC_A_SUB_B 0xFC730003 +#define HSM_BIGNUMBER_CALC_B_SUB_A 0xFC730004 +#define HSM_BIGNUMBER_CALC_A_MUL_B 0xFC730005 +#define HSM_BIGNUMBER_CALC_A_EXP_E 0xFC730006 +#define HSM_BIGNUMBER_CALC_A_RED_N 0xFC730007 +#define HSM_BIGNUMBER_CALC_A_INV 0xFC730008 + +/** + * @brief RSA information used by driver when call specific API + * + */ +typedef struct +{ + uint32_t *pA; /*!< address is 4bytes aligned, input data, if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32AByteCount; /*!< the byte count of input data */ + uint32_t *pE; /*!< address is 4bytes aligned, input key E data for "A = (input data)^E mod N", if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32EByteCount; /*!< the byte count of key E */ + uint32_t *pN; /*!< address is 4bytes aligned, input key N data for "A = (input data)^E mod N", if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32NByteCount; /*!< hw will get the actual key data bit count according to the non-zero bit count, it means key not generate by multiply 2 */ + uint32_t *pResult; /*!< address is 4bytes aligned, output buffer, the buffer size should >= "u32Key_N_ByteCount" */ + uint32_t u32ResultBufByteCnt; /*!< the result buffer size */ + uint32_t u32CalcType; + uint32_t *pB; + uint32_t u32BByteCount; +} HSM_BigNumberCalcType; + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout Millisecond count, max 916000ms, if set to 0, means 1000ms */ + uint32_t u32UserKeyID_KEY_E; /*!< means don't load key from HSM, otherwise would load key with KEYID from HSM */ + uint32_t u32UserKeyID_KEY_N; /*!< means don't load key from HSM, otherwise would load key with KEYID from HSM */ + uint32_t u32BitCnt; /*!< the bit count of numbers used of N */ + HSM_BigNumberCalcType tCfg; /*!< RSA parameters */ +} HSMCom_BigNumberCalcType; +/* ------------------------------------------------------------------------------- */ + + +typedef struct +{ + HSM_MailboxApiRetType u32HSMStatusRet; /*!< HSM core write return status value in this */ + uint32_t u32Timeout; /*!< current command timeout Millisecond count, max 916000ms, if set to 0, means 1000ms */ +} HSMCom_LoadFirmwareType; + +/* ------------------------------------------------------------------------------- */ + +typedef HSMCom_LoadFirmwareType HSMCom_BasicType; + +/* #define AUTH_CHECK_DATA_BYTE_CNT 32 */ + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + const uint32_t *pkG_x; /*!< address should align with 4bytes */ + const uint32_t *pkG_y; /*!< address should align with 4bytes */ + const uint32_t *pR; /*!< address should align with 4bytes */ + const uint32_t *pS; /*!< address should align with 4bytes */ + //For user code verify function + const uint32_t *pData; /*!< address should align with 4bytes */ + uint32_t u32DataLength; +} HSMCom_AuthCheckType; + +typedef struct { + HSM_BoolType bStoreInFlash; + HSM_BoolType bUseDefaultID; //TRUE means use default ID. FALSE means use specific ID with "pInputData_ID" and "u32SM2InputIDByteCnt" params. + uint32_t u32SM2InputIDByteCnt;//the length should be <= 32bytes note: If "bUseDefaultID" is FALSE, would use this specific ID length with byte unit. + uint32_t *pInputData_ID; //note: If "bUseDefaultID" is FALSE, would use this specific ID. length should be more than u32SM2InputIDByteCnt, and must be 4bytes align + uint32_t (*pRaPublicKey_X)[8]; + uint32_t (*pRaPublicKey_Y)[8]; + uint32_t (*pPaPublicKey_X)[8]; + uint32_t (*pPaPublicKey_Y)[8]; + uint32_t (*pPublicKey_X)[8]; + uint32_t (*pPublicKey_Y)[8]; + uint32_t (*PrivateKey)[8]; + uint32_t (*pRbPublicKey_X)[8]; + uint32_t (*pRbPublicKey_Y)[8]; + uint32_t *pOutputKeyID; +}HSM_SmDHType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + HSM_SmDHType tCfg; +} HSMCom_SmDHType; + +typedef struct { + uint32_t u32ByteCount; /*!< all the data size, it should contains all N data */ + HSM_DrvEccCurveParamType tCurve; + const uint32_t *pASidePublicKey_x; /*!< A side's public key axis x data */ + const uint32_t *pASidePublicKey_y; /*!< A side's public key axis y data */ + const uint32_t *pBSidePrivateKey; /*!< B side private key */ + /* Below is output data */ + uint32_t *pBSidePublicKey_x; /*!< B side's public key axis x data */ + uint32_t *pBSidePublicKey_y; /*!< B side's public key axis y data */ + uint32_t *pSharedPublicKey_x; + uint32_t *pSharedPublicKey_y; +}HSM_ECDHType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_BSidePrivateKey; //0 means don't load key from HSM, otherwise would load key with KEYID from HSM + uint32_t u32UserKeyID_BSidePublicKey; //0 means don't load key from HSM, otherwise would load key with KEYID from HSM + uint32_t u32BitCnt; + HSM_DrvEccCurvePrmIndexType u32EccCurve; + HSM_ECDHType tCfg; +} HSMCom_ECDHType; + +typedef struct { + uint32_t *pInputKey_a; /*!< input private key b data, if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32Key_a_ByteCount; /*!< the byte count of key b */ + uint32_t *pInputKey_B; /*!< input public key A data, if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32Key_B_ByteCount; /*!< the byte count of key A */ + uint32_t *pPublicParam_g; /*!< Param g data for "A = g^a mod p", if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32PublicParam_g_ByteCount; /*!< the byte count of param g */ + uint32_t *pPublicParam_p; /*!< Param p data for "A = g^a mod p", if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t u32PublicParam_p_ByteCount; /*!< the byte count of param p */ + uint32_t *pOutputKey_A; /*!< output public key B data, if not 64bytes align, the last uint64_t's high byte left to patch 0 to align */ + uint32_t *pOutputKey_S; +} HSM_RsaDHType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_a; //0 means don't load key from HSM, otherwise would load key with KEYID from HSM + uint32_t u32UserKeyID_B; //0 means don't load key from HSM, otherwise would load key with KEYID from HSM + HSM_RsaDHType tCfg; +} HSMCom_RsaDHType; + +typedef struct { + HSM_HashAlgType eHashAlg; + uint32_t u32Counter; + uint32_t u32dkLen; + uint32_t u32PasswordByteLength; + const uint32_t *pPassword; + uint32_t u32SaltByteLength; + const uint32_t *pSalt; + uint32_t *pKdfOutput; +} HSM_PBKDF2Type; + +/** + * @brief RSA SSA input data is the raw message for HSM_RsaSsaInputType + * + */ +#define HSM_RSA_SSA_INPUT_RAW_MESSAGE 0u + +/** + * @brief RSA SSA input data is the hash value of raw message for HSM_RsaSsaInputType + * + */ +#define HSM_RSA_SSA_INPUT_HASH_DATA 1u + +/** + * @brief type definition for rsa ssa input data type + * refer to HSM_RSA_SSA_INPUT_RAW_MESSAGE, HSM_RSA_SSA_INPUT_HASH_DATA + */ +typedef uint32_t HSM_RsaSsaInputType; + + +/** + * @brief RSA PSS signature information used by driver when call specific API + * + */ +typedef struct { + HSM_BoolType bUsePseudoRand; + HSM_HashAlgType eMgfHashType; + HSM_DataFormatType eInputFmt; /*!< input data organized format, uint8_t array, or uint32_t array */ + HSM_DataFormatType eOutputFmt; /*!< output data organized format, uint8_t array, or uint32_t array */ + uint32_t u32EmBitCnt; /* RFC8017 require set it to (N's bit count - 1).the em data bit count, it MUST < N's bit count */ + HSM_HashAlgType eHashType; /*!< the hash type used by signature */ + HSM_RsaSsaInputType eInputType; /*!< input data type, may raw input message, or the hash data of raw message */ + const uint8_t *pInputData; /*!< input data */ + uint32_t u32InputDataByteCount; /*!< the byte count of input data */ + const uint8_t *pPrivateKey; /*!< private key, input key E data for "A = (input data)^E mod N" */ + uint32_t u32PrivateKeyByteCnt; /*!< the byte count of key E */ + HSM_BoolType bUseInputSaltData; /*!< use input salt data or not, , suggest set to HSM_FALSE to use internal random data */ + const uint8_t *pSalt; /*!< input salt data, , suggest set to NULL. if use hsm internal random data, just set it to NULL */ + uint32_t u32SaltByteCount; /*!< the byte count of salt data, it must > 0, suggest use hash length, for example, if eHashType is HSM_SHA_256, set this to 256/8=32bytes */ + const uint8_t *pKeyN; /*!< input key N data for "A = (input data)^E mod N" */ + uint32_t u32KeyNByteCount; /*!< key N's data byte count */ + uint8_t *pResult; /*!< output buffer, the buffer size should >= "u32KeyNByteCount" */ + uint32_t u32ResultBufByteCnt; /*!< the result buffer size */ + uint32_t *pResultByteCnt; /*!< the result data byte count */ +} HSM_RsaSsaPssSignType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_KEY_E; + uint32_t u32UserKeyID_KEY_N; + uint32_t u32RsaBitCnt; + HSM_RsaSsaPssSignType tCfg; +}HSMCom_RsaSsaPssSignType; + +/** + * @brief RSA PSS signature verify information used by driver when call specific API + * + */ +typedef struct { + uint32_t u32EmBitCnt; /* RFC8017 require set it to (N's bit count - 1). the em data bit count, it MUST < N's bit count, should keep same with the signature generate configuration */ + HSM_HashAlgType eMgfHashType; + HSM_HashAlgType eHashType; /*!< the hash type used by signature */ + uint32_t u32SaltByteCount; /*!< the byte count of salt data, it must > 0, suggest use hash length, for example, if eHashType is HSM_SHA_256, set this to 256/8=32bytes */ + HSM_DataFormatType eInputDataFmt; /*!< input data(raw message or hash data) organized format, uint8_t array, or uint32_t array */ + HSM_RsaSsaInputType eInputType; /*!< input data type, may raw input message, or the hash data of raw message */ + const uint8_t *pInputData; /*!< input data */ + uint32_t u32InputDataByteCount; /*!< the byte count of input data, when the eInputType is HSM_RSA_SSA_INPUT_RAW_MESSAGE */ + HSM_DataFormatType eSignDataFmt; /*!< Signature/Public key/N input data organized format, uint8_t array, or uint32_t array */ + const uint8_t *pSignData; /*!< input signature data */ + uint32_t u32SignDataByteCount; /*!< the byte count of signature data, it must > 0 */ + HSM_DataFormatType ePublicKeyDataFmt; + const uint8_t *pPublicKey; /*!< public key, input key E data for "A = (input data)^E mod N" */ + uint32_t u32PublicKeyByteCnt; /*!< the byte count of key E */ + HSM_DataFormatType eKeyNDataFmt; + const uint8_t *pKeyN; /*!< input key N data for "A = (input data)^E mod N" */ + uint32_t u32KeyNByteCount; /*!< key N data byte count */ +} HSM_RsaSsaPssVerifyType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_KEY_E; + uint32_t u32UserKeyID_KEY_N; + uint32_t u32RsaBitCnt; + HSM_RsaSsaPssVerifyType tCfg; +}HSMCom_RsaSsaPssVerifyType; + +/** + * @brief RSA PKCS1 V1.5 signature information used by driver when call specific API + * + */ +typedef struct { + HSM_DataFormatType eInputFmt; /*!< input data organized format, uint8_t array, or uint32_t array */ + HSM_DataFormatType eOutputFmt; /*!< output data organized format, uint8_t array, or uint32_t array */ + uint32_t u32EmByteCnt; /* RFC8017 require set it to N'byte count, equal to u32KeyNByteCount. the em data byte count, itx8 MUST < N's bit count, should keep same with the signature generate configuration */ + HSM_HashAlgType eHashType; /*!< the hash type used by signature */ + const uint8_t *pInputData; /*!< input data */ + uint32_t u32InputDataByteCount; /*!< the byte count of input data */ + const uint8_t *pPrivateKey; /*!< private key, input key E data for "A = (input data)^E mod N" */ + uint32_t u32PrivateKeyByteCnt; /*!< the byte count of key E */ + HSM_BoolType bUseInputDer; /*!< set to HSM_TRUE when RFC8017 not support some hash algorithm, for example SM3 Hash type, DER encoding of the DigestInfo value, if use hsm internal data, just set it to HSM_FALSE */ + const uint8_t *pDer; /*!< when bUseInputDer is HSM_TRUE, this field point to the DER encoding of the DigestInfo value, others, ignore */ + uint32_t u32DerByteCount; /*!< when bUseInputDer is HSM_TRUE, this field represent the byte count of DER data, if bUseInputDer is HSM_FALSE, ignore this field */ + const uint8_t *pKeyN; /*!< input key N data for "A = (input data)^E mod N" */ + uint32_t u32KeyNByteCount; /*!< key N's data byte count */ + uint8_t *pResult; /*!< output buffer, the buffer size should >= "u32KeyNByteCount" */ + uint32_t u32ResultBufByteCnt; /*!< the result buffer size */ + uint32_t *pResultByteCnt; /*!< the result data byte count */ +} HSM_RsaSsaPkcs1V15SignType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_KEY_E; + uint32_t u32UserKeyID_KEY_N; + uint32_t u32RsaBitCnt; + HSM_RsaSsaPkcs1V15SignType tCfg; +}HSMCom_RsaSsaPkcs1V15SignType; + +/** + * @brief RSA PKCS1 V1.5 signature verify information used by driver when call specific API + * + */ +typedef struct { + HSM_DataFormatType eInputFmt; /*!< input data organized format, uint8_t array, or uint32_t array */ + uint32_t u32EmByteCnt; /* RFC8017 require set it to N'byte count, equal to u32KeyNByteCount. the em data byte count, itx8 MUST < N's bit count, should keep same with the signature generate configuration */ + HSM_HashAlgType eHashType; /*!< the hash type used by signature */ + const uint8_t *pInputData; /*!< input data */ + uint32_t u32InputDataByteCount; /*!< the byte count of input data */ + const uint8_t *pSignData; /*!< input signature data */ + uint32_t u32SignDataByteCount; /*!< the byte count of signature data, it must > 0 */ + const uint8_t *pPublicKey; /*!< public key, input key E data for "A = (input data)^E mod N" */ + uint32_t u32PublicKeyByteCnt; /*!< the byte count of key E */ + HSM_BoolType bUseInputDer; /*!< set to HSM_TRUE when RFC8017 not support some hash algorithm, for example SM3 Hash type, DER encoding of the DigestInfo value, if use hsm internal data, just set it to HSM_FALSE */ + const uint8_t *pDer; /*!< when bUseInputDer is HSM_TRUE, this field point to the DER encoding of the DigestInfo value, others, ignore */ + uint32_t u32DerByteCount; /*!< when bUseInputDer is HSM_TRUE, this field represent the byte count of DER data, if bUseInputDer is HSM_FALSE, ignore this field */ + const uint8_t *pKeyN; /*!< input key N data for "A = (input data)^E mod N" */ + uint32_t u32KeyNByteCount; /*!< key N's data byte count */ +} HSM_RsaSsaPkcs1V15VerifyType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_KEY_E; + uint32_t u32UserKeyID_KEY_N; + uint32_t u32RsaBitCnt; + HSM_RsaSsaPkcs1V15VerifyType tCfg; +}HSMCom_RsaSsaPkcs1V15VerifyType; + +typedef struct { + + HSM_BoolType bUsePseudoRand; + const uint8_t *pInputData; /*!< input data */ + uint32_t u32InputDataByteCount; + HSM_DataFormatType eInputDataFmt; + const uint8_t *pKeyE; + uint32_t u32KeyEByteCount; + HSM_DataFormatType eKeyEFmt; + const uint8_t *pKeyN; + uint32_t u32KeyNByteCount; + HSM_DataFormatType eKeyNFmt; + uint8_t *pResult; + uint32_t u32ResultBufByteCnt; + HSM_DataFormatType eOutputFmt; + uint32_t *pResultByteCnt; +} HSM_RsaEsPkcs1V15EnDecryptType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_KEY_E; + uint32_t u32UserKeyID_KEY_N; + uint32_t u32RsaBitCnt; + HSM_RsaEsPkcs1V15EnDecryptType tCfg; +}HSMCom_RsaEsPkcs1V15EnDecryptType; + +typedef HSMCom_RsaEsPkcs1V15EnDecryptType HSMCom_RsaEsPkcs1V15EncryptType; + +typedef HSMCom_RsaEsPkcs1V15EnDecryptType HSMCom_RsaEsPkcs1V15DecryptType; + +typedef struct { + HSM_BoolType bUsePseudoRand; + HSM_HashAlgType eHashType; /*!< the hash type used by signature */ + HSM_HashAlgType eMgfHashType; + const uint8_t *pLabel; /*!< input data */ + uint32_t u32LabelByteCount; + HSM_DataFormatType eLabelFmt; + const uint8_t *pInputData; /*!< input data */ + uint32_t u32InputDataByteCount; + HSM_DataFormatType eInputDataFmt; + const uint8_t *pKeyE; + uint32_t u32KeyEByteCount; + HSM_DataFormatType eKeyEFmt; + const uint8_t *pKeyN; + uint32_t u32KeyNByteCount; + HSM_DataFormatType eKeyNFmt; + uint8_t *pResult; + uint32_t u32ResultBufByteCnt; + HSM_DataFormatType eOutputFmt; + uint32_t *pResultByteCnt; +} HSM_RsaEsOaepEnDecryptType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_KEY_E; + uint32_t u32UserKeyID_KEY_N; + uint32_t u32RsaBitCnt; + HSM_RsaEsOaepEnDecryptType tCfg; +}HSMCom_RsaEsOaepEnDecryptType; + + +typedef HSMCom_RsaEsOaepEnDecryptType HSMCom_RsaEsOaepEncryptType; + +typedef HSMCom_RsaEsOaepEnDecryptType HSMCom_RsaEsOaepDecryptType; + + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_Password; //0 means don't load key from HSM, otherwise would load key with KEYID from HSM + HSM_PBKDF2Type tCfg; +} HSMCom_Pbkdf2Type; + +typedef struct { + uint32_t u32Counter; + uint32_t u32dkLen; + uint32_t u32PasswordByteLength; + const uint32_t *pPassword; + uint32_t u32SaltByteLength; + const uint32_t *pSalt; + uint32_t *pKdfOutput; +} HSM_GMPBKDFType; + +typedef struct { + uint32_t u32HSMStatusRet; + uint32_t u32Timeout; + uint32_t u32UserKeyID_Password; //0 means don't load key from HSM, otherwise would load key with KEYID from HSM + HSM_GMPBKDFType tCfg; +} HSMCom_GMpbkdfType; +/* ------------------------------------------------------------------------------- */ + +/**@}*/ + + +/** + * @name API declaration for HSM + * + */ +/**@{*/ + +/** + * @brief Get the true random data + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pRandom the array address to store the result + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_TrueRandGetSrc0(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg); + + +/** + * @brief Get the true random data + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pRandom the array address to store the result + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_TrueRandGetSrc1(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg); + + +/** + * @brief Get the true random data + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pRandom the array address to store the result + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_TrueRandGetSrcXor(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg); + + +/** + * @brief Get the true random data + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pRandom the array address to store the result + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_TrueRandGet(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg); + + +/** + * @brief Get the pseudo random data + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pRandom the array address to store the result + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_PseudoRandGet(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg); + + +/** + * @brief SHA + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SHA parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sha(HSM_CmdType *pCmd, const HSMCom_ShaType *pCfg); + + +/** + * @brief SHAEx + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SHA parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_ShaEx(HSM_CmdType *pCmd, const HSMCom_Sha2Type *pCfg); + + +/** + * @brief Md5Ex + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MD5 parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Md5Ex(HSM_CmdType *pCmd, const HSMCom_Md5Type *pCfg); + + +/** + * @brief Sm3Ex + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM3 parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm3Ex(HSM_CmdType *pCmd, const HSMCom_Sm3Type *pCfg); + + +/** + * @brief HashEx Init + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg HashEx parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_HashInitEx(HSM_CmdType *pCmd, const HSMCom_ShaType *pCfg); + + +/** + * @brief HashEx Update + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg HashEx parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_HashUpdateEx(HSM_CmdType *pCmd, const HSMCom_ShaType *pCfg); + + +/** + * @brief HashEx Finally + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg HashEx parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_HashFinallyEx(HSM_CmdType *pCmd, const HSMCom_ShaType *pCfg); + + +/** + * @brief Scatter Hash Init + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg scatter hash parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_ScatterHashInit(HSM_CmdType *pCmd, const HSMCom_ScatterHashType *pCfg); + + +/** + * @brief Scatter Hash Update + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg scatter hash parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_ScatterHashUpdate(HSM_CmdType *pCmd, const HSMCom_ScatterHashType *pCfg); + + +/** + * @brief Scatter Hash Finally + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg scatter hash parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_ScatterHashFinally(HSM_CmdType *pCmd, const HSMCom_ScatterHashType *pCfg); + +/** + * @brief ECC Sign + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg ECC sign parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_EccSign(HSM_CmdType *pCmd, const HSMCom_EccSignType *pCfg); + + +/** + * @brief EccPointCalc + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg EccPointCalc parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_EccPointCalc(HSM_CmdType *pCmd, const HSMCom_EccCalcType *pCfg); + + +/** + * @brief ECC Verify + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg ECC verify parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_EccVerify(HSM_CmdType *pCmd, const HSMCom_EccVerifyType *pCfg); + + +/** + * @brief ECC key pair generate + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg ECC key pair parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_EccGenKeyPair(HSM_CmdType *pCmd, const HSMCom_EccKeyPairGenType *pCfg); + + +/** + * @brief SM2 key pair generate + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM2 key pair parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm2GenKeyPair(HSM_CmdType *pCmd, const HSMCom_Sm2GenKeyPairType *pCfg); + + +/** + * @brief SM2 encrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM2 encrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm2Encry(HSM_CmdType *pCmd, const HSMCom_Sm2EncryptType *pCfg); + + +/** + * @brief SM2 decrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM2 decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm2Decry(HSM_CmdType *pCmd, const HSMCom_Sm2DecryptType *pCfg); + + +/** + * @brief SM2 sign + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM2 sign parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm2Sign(HSM_CmdType *pCmd, const HSMCom_Sm2SignType *pCfg); + + +/** + * @brief SM2 verify + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM2 verify parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm2Verify(HSM_CmdType *pCmd, const HSMCom_Sm2VerifyType *pCfg); + + +/** + * @brief SM2 ZA + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM2 ZA parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm2GenZa(HSM_CmdType *pCmd, const HSMCom_Sm2GenZaType *pCfg); + + +/** + * @brief SM2 Hash generate + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM2 HASH parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm2GenHash(HSM_CmdType *pCmd, const HSMCom_Sm2GenHashType *pCfg); + + +/** + * @brief SM4 encrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM4 encrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm4Encrypt(HSM_CmdType *pCmd, const HSMCom_Sm4EncryptType *pCfg); + + +/** + * @brief SM4 decrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM4 decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm4Decrypt(HSM_CmdType *pCmd, const HSMCom_Sm4DecryptType *pCfg); + + +/** + * @brief ECC easy encrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg ECC encrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_EccEasyEncry(HSM_CmdType *pCmd, const HSMCom_EccEasyEncryType *pCfg); + + +/** + * @brief ECC easy decrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg ECC decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_EccEasyDecry(HSM_CmdType *pCmd, const HSMCom_EccEasyDecryType *pCfg); + + +/** + * @brief RequestAuthorization + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg ECC decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RequestAuthorization(HSM_CmdType *pCmd, const HSMCom_RequestAuthType *pCfg); + + +/** + * @brief TakeEffect + * + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_TakeEffect(HSM_CmdType *pCmd); + + +/** + * @brief OemDevEnter + * + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_OemDevEnter(HSM_CmdType *pCmd); + + +/** + * @brief HSM_OemPdtEnter + * + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_OemPdtEnter(HSM_CmdType *pCmd); + +/** + * @brief HSM_InFieldEnter + * + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_InFieldEnter(HSM_CmdType *pCmd); + + +/** + * @brief CancelJob + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_CancelJob(HSM_CmdType *pCmd, const HSMCom_CancelJobType *pCfg); + + +/** + * @brief SelfTest + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg self test parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_SelfTest(HSM_CmdType *pCmd, const HSMCom_SelfTestType *pCfg); + + +/** + * @brief NvrOtpProgram + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_NvrOtpProgram(HSM_CmdType *pCmd, const HSMCom_NvrOtpType *pCfg); + + +/** + * @brief NvrOtpRead + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_NvrOtpRead(HSM_CmdType *pCmd, const HSMCom_NvrOtpType *pCfg); + + +/** + * @brief Revoke UserKey + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg UserKeyManage parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_UserKeyRevoke(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg); + + +/** + * @brief Revoke Umrk0 + * + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RevokeUmrk0(HSM_CmdType *pCmd); + + +/** + * @brief Revoke Umrk1 + * + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RevokeUmrk1(HSM_CmdType *pCmd); + + +/** + * @brief Revoke Umrk2 + * + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RevokeUmrk2(HSM_CmdType *pCmd); + + +/** + * @brief Revoke Umrk3 + * + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RevokeUmrk3(HSM_CmdType *pCmd); + + +/** + * @brief UserKeyImport + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_UserKeyImport(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg); + + +/** + * @brief UserKeyExport + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_UserKeyExport(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg); + + +/** + * @brief Generate User Key + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_UserKeyGen(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg); + + +/** + * @brief Generate Usrk + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_GenUsrk(HSM_CmdType *pCmd,const HSMCom_RsaType *pCfg); + + +/** + * @brief Erase Key in Flash + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_EraseKeyFlash(HSM_CmdType *pCmd, HSMCom_BasicType *pCfg); + + +/** + * @brief Enable Ram Key Copy + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_EnableKeyRamCopy(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg); + + +/** + * @brief Disable Ram Key Copy + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_DisableKeyRamCopy(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg); + + +/** + * @brief GetKeySpaceStatus + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg ECC decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_GetKeySpaceStatus(HSM_CmdType *pCmd, const HSMCom_KeySpaceStatusType *pCfg); + + +/** + * @brief TidyUpKeySpace + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg ECC decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_TidyUpKeySpace(HSM_CmdType *pCmd, const HSMCom_KeySpaceStatusType *pCfg); + + +/** + * @brief AES encrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg AES encrypt parameters. + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_AesEncrypt(HSM_CmdType *pCmd, const HSMCom_AesEncryptType *pCfg); + + +/** + * @brief AES decrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg AES decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. Others, some error occur. + */ +HSM_StatusType HSM_AesDecrypt(HSM_CmdType *pCmd, const HSMCom_AesDecryptType *pCfg); + + +/** + * @brief AES FlexEncrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg AES encrypt parameters. + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Aes_FlexEncrypt(HSM_CmdType *pCmd, const HSMCom_FlexAesEncryptType *pCfg); + + +/** + * @brief AES FlexDecrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg AES decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. Others, some error occur. + */ +HSM_StatusType HSM_Aes_FlexDecrypt(HSM_CmdType *pCmd, const HSMCom_FlexAesDecryptType *pCfg); + + +/** + * @brief CMAC + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg CMAC parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_CMac(HSM_CmdType *pCmd, const HSMCom_CMacType *pCfg); + + +/** + * @brief CmacAesm + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_CmacAesm(HSM_CmdType *pCmd, const HSMCom_AesmRawApiType *pCfg); + + +/** + * @brief CmacEx + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg CMAC parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_CmacEx(HSM_CmdType *pCmd, const HSMCom_CMacExType *pCfg); + + +/** + * @brief Scatter Cmac + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg CMAC parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_CmacScatter(HSM_CmdType *pCmd, const HSMCom_ScatterMacType *pCfg); + + +/** + * @brief XMAC + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg XMAC parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_XMac(HSM_CmdType *pCmd, const HSMCom_XMacType *pCfg); + + +/** + * @brief XMacEx + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg XMAC parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_XMacEx(HSM_CmdType *pCmd, const HSMCom_XMacExType *pCfg); + + +/** + * @brief CCM encrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg CCM encrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_CcmEncry(HSM_CmdType *pCmd, const HSMCom_CcmEncryptType *pCfg); + + +/** + * @brief CCM decrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg CCM decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_CcmDecry(HSM_CmdType *pCmd, const HSMCom_CcmDecryptType *pCfg); + + +/** + * @brief CcmEncryEx + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg Ccm encrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_CcmEncryEx(HSM_CmdType *pCmd, const HSMCom_CcmEncryptExType *pCfg); + + +/** + * @brief CcmDecryEx + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg Ccm decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_CcmDecryEx(HSM_CmdType *pCmd, const HSMCom_CcmDecryptExType *pCfg); + + +/** + * @brief GCM encrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg GCM encrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_GcmEncry(HSM_CmdType *pCmd, const HSMCom_GcmEncryptType *pCfg); + + +/** + * @brief GCM decrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg GCM decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_GcmDecry(HSM_CmdType *pCmd, const HSMCom_GcmDecryptType *pCfg); + + + +/** + * @brief GcmEncryEx + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg Gcm encrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_GcmEncryEx(HSM_CmdType *pCmd, const HSMCom_GcmEncryptExType *pCfg); + + +/** + * @brief GcmDecryEx + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg Gcm decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_GcmDecryEx(HSM_CmdType *pCmd, const HSMCom_GcmDecryptExType *pCfg); + +/** + * @brief MD5 + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MD5 parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Md5(HSM_CmdType *pCmd, const HSMCom_Md5Type *pCfg); + + +/** + * @brief SM3 + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg SM3 parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_Sm3(HSM_CmdType *pCmd, const HSMCom_Sm3Type *pCfg); + + +/** + * @brief Increase Monotonic Counter + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MonotonicCounter parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_MonotonicCounterIncrease(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg); + + +/** + * @brief Read Monotonic Counter + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MonotonicCounter parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_MonotonicCounterRead(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg); + + +/** + * @brief Set Monotonic Counter Value + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MonotonicCounter parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_MonotonicCounterSetValue(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg); + + +/** + * @brief Read All Flex Counters + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MonotonicCounter parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_MonotonicReadAllFlexCounters(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg); + + +/** + * @brief Set Single Config + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MonotonicCounter parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_MonotonicCounterSetSingleCfg(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg); + + +/** + * @brief Get Single Config + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MonotonicCounter parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_MonotonicCounterGetSingleCfg(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg); + + +/** + * @brief Increase Monotonic Counter 2 + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MonotonicCounter parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_MonotonicIncreaseCounter2(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg); + + +/** + * @brief Read Monotonic Counter 2 + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MonotonicCounter parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_MonotonicReadCounter2(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg); + + +/** + * @brief Increase Monotonic Counter when equal + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg MonotonicCounter parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY When driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_MonotonicIncCountWhenEqu(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg); + + +/** + * @brief LoadFirmware + * + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. Others, some error occur. + */ +HSM_StatusType HSM_LoadFirmware(HSM_CmdType *pCmd); + + +/** + * @brief RSA + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg RSA parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. Others, some error occur. + */ +HSM_StatusType HSM_Rsa(HSM_CmdType *pCmd, const HSMCom_RsaType *pCfg); + + +/** + * @brief RSA PSS Sign + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg RSA Sign parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RSA_SSA_PSS_Sign(HSM_CmdType *pCmd, const HSMCom_RsaSsaPssSignType *pCfg); + + +/** + * @brief RSA PSS Verify + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg RSA Verify parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RSA_SSA_PSS_Verify(HSM_CmdType *pCmd, const HSMCom_RsaSsaPssVerifyType *pCfg); + + +/** + * @brief RSA ES_PKCS1V15 Encrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg RSA encrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RSA_SSA_ES_PKCS1V15_Encrypt(HSM_CmdType *pCmd, const HSMCom_RsaEsPkcs1V15EncryptType *pCfg); + + +/** + * @brief RSA ES_PKCS1V15 Decrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg RSA decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RSA_SSA_ES_PKCS1V15_Decrypt(HSM_CmdType *pCmd, const HSMCom_RsaEsPkcs1V15DecryptType *pCfg); + + +/** + * @brief RSA ES_PKCS1V15 Verify + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg RSA Verify parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RSA_SSA_ES_PKCS1V15_Verify(HSM_CmdType *pCmd, const HSMCom_RsaSsaPkcs1V15VerifyType *pCfg); + + +/** + * @brief RSA ES PKCS1V15 Sign + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg RSA Verify parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RSA_SSA_ES_PKCS1V15_Sign(HSM_CmdType *pCmd, const HSMCom_RsaSsaPkcs1V15SignType *pCfg); + + +/** + * @brief RSA ES OAEP Encrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg RSA encrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RSA_SSA_ES_OAEP_Encrypt(HSM_CmdType *pCmd, const HSMCom_RsaEsOaepEncryptType *pCfg); + + +/** + * @brief RSA ES OAEP Decrypt + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg RSA decrypt parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_RSA_SSA_ES_OAEP_Decrypt(HSM_CmdType *pCmd, const HSMCom_RsaEsOaepDecryptType *pCfg); + + +/** + * @brief BigNumberCalc + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_BigNumberCalc(HSM_CmdType *pCmd, const HSMCom_BigNumberCalcType *pCfg); + + +/** + * @brief SMDH + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_SMDH(HSM_CmdType *pCmd, HSMCom_SmDHType *pCfg); + + +/** + * @brief ECDH + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_ECDH(HSM_CmdType *pCmd, HSMCom_ECDHType *pCfg); + + +/** + * @brief DH + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_DH(HSM_CmdType *pCmd, HSMCom_RsaDHType *pCfg); + + +/** + * @brief PBKDF2 + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_PBKDF2(HSM_CmdType *pCmd, HSMCom_Pbkdf2Type *pCfg); + + +/** + * @brief GMPBKDF + * @param pCmd point to the struct variable used to configure the mailbox information send to HSM core + * @param pCfg parameters for trigger the process + * @return HSM_StatusType HSM_STATUS_SUCCESS when succeed. HSM_STATUS_BUSY when driver is busy. Others, some error occur. + */ +HSM_StatusType HSM_GMPBKDF(HSM_CmdType *pCmd, HSMCom_GMpbkdfType *pCfg); + + +/**@}*/ + +/** @}*/ /* fc7xxx_driver_hsm */ + +#if defined(__cplusplus) +} +#endif + +#endif /* end of DRIVER_HSM_H_ */ diff --git a/Inc/fc7xxx_driver_intm.h b/Inc/fc7xxx_driver_intm.h new file mode 100644 index 0000000..b5280e4 --- /dev/null +++ b/Inc/fc7xxx_driver_intm.h @@ -0,0 +1,137 @@ +/** + * @file fc7xxx_driver_intm.h + * @author Flagchip + * @brief FC7240 INTM driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-10 Flagchip084 N/A FC7240 release version + ******************************************************************************** */ + +#ifndef _DRIVER_INTM_H_ +#define _DRIVER_INTM_H_ + +#include "HwA_intm.h" + +typedef enum +{ + INTM_INSTANCE_0 = 0U, + INTM_INSTANCE_MAX = 1u +} INTM_InstanceType; + +typedef enum +{ + INTM_IRQ_MONITOR_0 = 0U, + INTM_IRQ_MONITOR_1 = 1U, + INTM_IRQ_MONITOR_MAX = 2U +} INTM_IrqMonitorType; + +typedef enum +{ + INTM_RETURN_OK = 0x00U, /*!< The INTM operation is succeeded */ + INTM_RETURN_E_NOT_OK = 0x01U, /*!< The INTM operation is failed */ + INTM_RETURN_E_ALREADY_INIT = 0x02U, /*!< The INTM has been initialized. */ + INTM_RETURN_E_UNINIT = 0x03U, /*!< The INTM is not initialized */ + INTM_RETURN_E_PARAM = 0x04U /*!< The INTM parameter is incorrect or out of range. */ +} INTM_ReturnType; + +typedef enum +{ + INTM_INTERRUPT_MODE_ACTIVE = 0x00U, /*!< INTM is configured as active mode */ + INTM_INTERRUPT_MODE_INACTIVE /*!< INTM is configured as inactive mode */ +} INTM_InterruptModeType; + +/** + * @brief INTM Channel ISR callback function prototype + * + */ +typedef void (*INTM_ISRCallbackType)(void); + +typedef struct +{ + INTM_InterruptModeType eMode; /*!< INTM active mode */ + bool bEnReset; /*!< Enable Reset */ + bool bEnInterrupt; /*!< Enable Interrupt */ + uint32_t u32SrcDelayCnt; /*!< Enable Interrupt */ + uint16_t u16IrqNumber; /*!< Monitored interrupt number */ + INTM_ISRCallbackType pIntmIsrCallback; /*!< INTM interrupt callback. */ +} INTM_InitType; + +/** + * @brief Init the INTM. + * @param eInstance INTM instance. + * @param eIrqMonitorIndex Monitor index. + * @param pInitCfg Init Configuration. + * @return INTM_ReturnType INTM Status. + */ +INTM_ReturnType INTM_Init(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex, INTM_InitType *pInitCfg); + +/** + * @brief Enable INTM. + * + * @param eInstance INTM instance. + * @param bEnable Enable INTM. + * @return INTM_ReturnType INTM Status. + */ +INTM_ReturnType INTM_enable(INTM_InstanceType eInstance, bool bEnable); + +/** + * @brief Start INTM inactive mode. + * @param eInstance INTM instance. + * @param eIrqMonitorIndex Monitor index. + * @return INTM_ReturnType INTM Status. + */ +INTM_ReturnType INTM_StartInactiveMode(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex); + +/** + * @brief + * @param eInstance INTM instance. + * @param eIrqMonitorIndex Monitor index. + * @return INTM_ReturnType INTM Status. + */ +INTM_ReturnType INTM_StopInactiveMode(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex); + +/** + * @brief Write the interrupt acknowledge. + * + * @param eInstance INTM instance. + * @param u16IrqNumber Interrupt nunmber. + * @return INTM_ReturnType INTM Status. + */ +INTM_ReturnType INTM_SetAcknowledge(INTM_InstanceType eInstance, uint16_t u16IrqNumber); + +/** + * @brief Return counter value. + * + * @param eInstance INTM instance. + * @param eIrqMonitorIndex Monitor index. + * @return Counter value. + */ +uint32_t INTM_GetCounterValue(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex); + +/** + * @brief Clear the interrupt flag. + * + * @param eInstance INTM instance. + * @param eIrqMonitorIndex Monitor index. + */ +INTM_ReturnType INTM_ClearIntFlag(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex); + +/** + * @brief Get the timeout flag. Return true if INTM_TMR value has exceeded the INTM_LATR value. + * + * @param eInstance INTM instance. + * @param eIrqMonitorIndex Monitor index. + * @return Timeout flag. + */ +bool INTM_GetTimeoutStatus(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex); + +#endif /* end of _DRIVER_INTM_H_ */ diff --git a/Inc/fc7xxx_driver_ism.h b/Inc/fc7xxx_driver_ism.h new file mode 100644 index 0000000..4867328 --- /dev/null +++ b/Inc/fc7xxx_driver_ism.h @@ -0,0 +1,249 @@ +/** + * @file fc7xxx_driver_ism.h + * @author Flagchip084 + * @brief FC7xxx ISM driver type definition and API + * @version 0.2.0 + * @date 2023-02-13 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2022-11-18 Flagchip084 N/A First version for FC7xxx + * 0.2.0 2023-02-13 Flagchip084 N/A FC7xxx release version + ******************************************************************************** */ + +#ifndef _DRIVER_FC7XXX_DRIVER_ISM_H_ +#define _DRIVER_FC7XXX_DRIVER_ISM_H_ +#include "device_header.h" +#include "HwA_ism.h" +/** + * @addtogroup fc7xxx_driver_ism + * @{ + */ + +#define ISM_ECM_CHANNEL(x) (1<<(x)) +#define ISM_LAM_CHANNEL(x) (1<<(x)) +#define ISM_FPC_CHANNEL(x) (1<<(x)) + +typedef enum +{ + ISM_INSTANCE_0 = 0U, /*!< ISM instance 0 is selected. */ +} ISM_InstanceType; + +typedef enum +{ + FPC_RISING_GLITCH_DETECTED = 0x01U, /*!< PFC Rising Glitch Detected. */ + FPC_FALLING_GLITCH_DETECTED = 0x02U /*!< PFC Falling Glitch Detected. */ +} FPC_GlitchDetectType; + +/** + * @brief ISM Channel ISR callback function prototype + * + */ +typedef void (*ISM_EventISRCallbackType)(const uint16_t u16LamStatus, const uint8_t u8EcmStatus); + +/** + * @brief FPC Channel Glitch dectection ISR callback function prototype + * + */ +typedef void (*FPC_ISRCallbackType)(const uint32_t u32Status); + +/** + * @brief LAM Channel Overflow ISR callback function prototype + * + */ +typedef void (*LAM_ISRCallbackType)(void); + +typedef struct +{ + + bool bIntEnable; + ISM_EventISRCallbackType pEventIsrCallback; +} ISM_InitCfgType; + +typedef struct +{ + bool bGlitchIntEnable; + ISM_FPC_EdgeDetectModeType eFallingDetectMode; + ISM_FPC_EdgeDelayModeType eFallingDelayNode; + ISM_FPC_EdgeDetectModeType eRisingDetectMode; + ISM_FPC_EdgeDelayModeType eRisingDelayNode; + uint16_t u32ThresholdValue; + FPC_ISRCallbackType pFpcIsrCallback; +} ISM_FpcCfgType; + +typedef struct +{ + bool bOvflIntEnable; + uint8_t u8SrcSel; + uint8_t u8MonSel; + ISM_LAM_InvertEventWindowType eInvWin; + ISM_LAM_EventWindowEdgeType eWinEdgSel; + ISM_LAM_EventWindowSelectType eEvtWinSel; + ISM_LAM_RunModeSelectType eRunMode; + ISM_LAM_MonitorSourceType eMonSrcSel; + ISM_LAM_InvertMonitorType eInvMon; + ISM_LAM_InvertReferenceType eInvRef; + uint32_t u32EvtCntThreshold; + LAM_ISRCallbackType pLamOverFlowIsrCallback; +} ISM_LamCfgType; + +/** + * @brief Init the ISM. + * + * @param pInitConfig ISMInstance initial configuration. + */ +void ISM_Init(const ISM_InitCfgType *pInitConfig); + +/** + * @brief Get the channels mask of ECM that has event happened. + * + * @return Channels mask. + */ +uint8_t ISM_GetEcmEventHappenedChannels(void); + +/** + * @brief Get the channels mask of LAM that has event happened. + * + * @return Channels mask. + */ +uint16_t ISM_GetLamEventHappenedChannels(void); + +/** + * @brief Clear the channels status of ECM that has event happened. + * + * @param u8Channels Channels mask. + */ +void ISM_ClearEcmEventHappenedChannels(uint8_t u8Channels); + +/** + * @brief Clear the channels status of LAM that has event happened. + * + * @param u16Channels Channels mask. + */ +void ISM_ClearLamEventHappenedChannels(uint16_t u16Channels); + +/** + * @brief Enable or disable ISM. + * + * @param bEnable Enable value. + */ +void ISM_Enable(bool bEnable); + +/** + * @brief Enable or disable ISM interrupt. + * + * @param bEnable Enable value. + */ +void ISM_InterruptEnable(bool bEnable); + +/** + * @brief ENable LAM overflow interrupt. + * + * @param u8LamIndex LAM index. + * @param bEnable Enable value. + */ +void ISM_LamOverflowInterruptEnable(uint8_t u8LamIndex, bool bEnable); + +/** + * @brief Enable LAM Channel. + * + * @param u8LamIndex LAM index. + * @param bEnable Enable value. + */ +void ISM_LamEnable(uint8_t u8LamIndex, bool bEnable); + +/** + * @brief Config the LAM channel. + * + * @param u8LamIndex LAM index. + * @param pConfig LAM configuration. + */ +void ISM_LamConfig(uint8_t u8LamIndex, const ISM_LamCfgType *pConfig); + +/** + * @brief Enable FPC glitch interrupt. + * + * @param u8FpcIndex FPC index. + * @param bEnable Enable value. + */ +void ISM_FpcGlitchInterruptEnable(uint8_t u8FpcIndex, bool bEnable); + +/** + * @brief Enable FPC channel. + * + * @param u8FpcIndex FPC index. + * @param bEnable Enable value. + */ +void ISM_FpcEnable(uint8_t u8FpcIndex, bool bEnable); + +/** + * @brief Config the FPC channel. + * + * @param u8FpcIndex FPC index. + * @param pConfig FPC configuration. + */ +void ISM_FpcConfig(uint8_t u8FpcIndex, const ISM_FpcCfgType *pConfig); + +/** + * @brief Enable ECM system event + * + * @param u32Channels Channel masks. + * @param bEnable Enable value. + */ +void ISM_EnableEcmSystemEvent(uint32_t u32Channels, bool bEnable); + +/** + * @brief Enable LAM system event + * + * @param u32Channels Channel masks. + * @param bEnable Enable value. + */ +void ISM_EnableLamSystemEvent(uint32_t u32Channels, bool bEnable); + +/** + * @brief Enable LAM system event + * + * @param u32LamIndex Lam channel index. + * @param u32EcmIndex Ecm channel index. + * @param u8EventCount Threshold of the ECM channel counter value. + */ +void ISM_EcmEventConfig(uint8_t u32LamIndex, uint8_t u32EcmIndex, uint8_t u8EventCount); + +/** + * @brief Clears the value of the LAM counter. + * + * @param u32LamIndex Lam channel index. + */ +void ISM_ClearLamStatusCounter(uint8_t u8LamIndex); + +/** + * @brief Gets the value of the LAM counter when a LAM event is triggered. + * + * @param u32LamIndex Lam channel index. + * @return Counter value. + */ +uint32_t ISM_GetLamStatusCounter(uint8_t u8LamIndex); + +/** + * @brief Clears LAM Timer Overflow Flag. + * + * @param u32LamIndex Lam channel index. + */ +void ISM_ClearLamStatusOvfl(uint8_t u8LamIndex); + +/** + * @brief Gets LAM Timer Overflow Flag. + * + * @param u32LamIndex Lam channel index. + * @return Overflow flag. + */ +bool ISM_GetLamStatusOvfl(uint8_t u8LamIndex); + +/** @}*/ /* fc7xxx_driver_ism. */ +#endif diff --git a/Inc/fc7xxx_driver_lin.h b/Inc/fc7xxx_driver_lin.h new file mode 100644 index 0000000..107ba23 --- /dev/null +++ b/Inc/fc7xxx_driver_lin.h @@ -0,0 +1,427 @@ +/** + * @file fc7xxx_driver_lin.h + * @author Flagchip0122 + * @brief FC7xxx LIN driver type definition and API + * @version 0.1.0 + * @date 2023-12-26 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2023-12-26 Flagchip0122 N/A First version for FC7xxx + ******************************************************************************** */ + +#ifndef _DRIVER_FC4XXX_DRIVER_LIN_H_ +#define _DRIVER_FC4XXX_DRIVER_LIN_H_ + +#include "HwA_fcuart.h" +#include "device_header.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * @addtogroup fc4xxx_driver_lin + * @{ + */ + +/** + * @brief LIN status type use in API. + */ +typedef enum +{ + LIN_STATUS_SUCCESS = 0x00U, /*!< API execute successfully */ + LIN_STATUS_ERROR, /*!< API excute error */ + LIN_STATUS_BUSY, /*!< currently instance busy. */ + LIN_STATUS_TIMEOUT, /*!< timeout status */ + LIN_STATUS_PARAM_ERROR, /*!< Parameter error. */ + LIN_STATUS_NOT_INIT, /*!< LIN node has not been initialized. */ + LIN_STATUS_USEED, /*!< LIN node has not been initialized. */ + LIN_STATUS_NOT_START, /*!< LIN node has not been started. */ + LIN_STATUS_UNSUPPORTED, /*!< unsupport status */ +} LIN_StatusType; + +/** + * @brief LIN node type use in API, master or slave. + */ +typedef enum +{ + LIN_NODE_MASTER, /*!< LIN Master node. */ + LIN_NODE_SLAVE, /*!< LIN slave node. */ +} LIN_NodeType; + +/** + * @brief A callback function to get the interval time value in nanoseconds. + */ +typedef uint32_t (*lin_get_interval_time_t)(uint32_t *nanoSeconds); + +/** + * @brief Structure for LIN hardware configurations. + */ +typedef struct +{ + LIN_NodeType nodeMode; /*!< Node mode as Master node or Slave node. 0: slave 1: master */ + uint32_t baudRate; /*!< baudrate configurations for LIN protocol. */ + uint32_t clockSrcFreq; /*!< LIN instance clock source frequency. */ + lin_get_interval_time_t getIntervalTimeValueCallback; /*!< Callback function to get time interval in nanoseconds */ + uint8_t *classicPID; /*!< List of PIDs use classic checksum */ + uint8_t numOfClassicPID; /*!< Number of PIDs use classic checksum */ +} lin_config_t; + +/** + * @brief Types for an event related Identifier. + */ +typedef enum +{ + LIN_NO_EVENT = 0x00U, /*!< No event occurred. */ + LIN_WAKEUP_SIGNAL, /*!< Wakeup signal */ + LIN_BAUDRATE_ADJUSTED, /*!< Baudrate was adjusted in slave autobaud mode. */ + LIN_RECV_BREAK_FIELD_OK, /*!< Break Field was received */ + LIN_SYNC_OK, /*!< Sync field is correct */ + LIN_SYNC_ERROR, /*!< Sync field is incorrect */ + LIN_PID_OK, /*!< PID receive correct */ + LIN_PID_ERROR, /*!< PID receive incorrect */ + LIN_FRAME_ERROR, /*!< Frame receive error */ + LIN_READBACK_ERROR, /*!< Readback words are incorrect */ + LIN_CHECKSUM_ERROR, /*!< Checksum byte error */ + LIN_TX_COMPLETED, /*!< TX data completed */ + LIN_RX_COMPLETED, /*!< rx data completed */ + LIN_RX_OVERRUN, /*!< RX overflow occurred */ + LIN_TIMEOUT, /*!< RX overflow occurred */ +} lin_event_id_t; + +/*! + * @brief Define type for an enumerating LIN Node state. + */ +typedef enum +{ + LIN_NODE_STATE_UNINIT = 0x00U, /*!< LIN hardware uninitialized state */ + LIN_NODE_STATE_SLEEP_MODE, /*!< LIN node in sleep mode state */ + LIN_NODE_STATE_IDLE, /*!< LIN node in idle state */ + LIN_NODE_STATE_SEND_BREAK_FIELD, /*!< LIN node in send break field state */ + LIN_NODE_STATE_RECV_SYNC, /*!< LIN node in receive the synchronization byte state */ + LIN_NODE_STATE_SEND_PID, /*!< LIN node in rend PID state */ + LIN_NODE_STATE_RECV_PID, /*!< LIN node in receive PID state */ + LIN_NODE_STATE_RECV_DATA, /*!< LIN node in receive data state */ + LIN_NODE_STATE_RECV_DATA_COMPLETED, /*!< LIN node in receive data completed state */ + LIN_NODE_STATE_SEND_DATA, /*!< LIN node in send data state */ + LIN_NODE_STATE_SEND_DATA_COMPLETED /*!< LIN node in send data completed state */ +} lin_node_state_t; + +/*! + * @brief LIN Driver callback function type + */ +typedef void (*lin_callback_t)(uint8_t u8LinIndex, void *linState); + +/*! + * @brief Runtime state of the LIN driver. + * + * Note that the caller provides memory for the driver state structures during + * initialization because the driver does not statically allocate memory. + * Implements : lin_state_t_Class + */ +typedef struct +{ + const uint8_t *txBuff; /*!< The buffer of data being sent. */ + uint8_t *rxBuff; /*!< The buffer of received data. */ + uint8_t cntByte; /*!< To count number of bytes already transmitted or received. */ + volatile uint8_t txSize; /*!< The remaining number of bytes to be transmitted. */ + volatile uint8_t rxSize; /*!< The remaining number of bytes to be received. */ + uint8_t checkSum; /*!< Checksum byte. */ + volatile bool isTxBusy; /*!< True if the LIN interface is transmitting frame data. */ + volatile bool isRxBusy; /*!< True if the LIN interface is receiving frame data. */ + volatile bool isBusBusy; /*!< True if there are data, frame headers being transferred on bus */ + volatile bool isTxBlocking; /*!< True if transmit is blocking transaction. */ + volatile bool isRxBlocking; /*!< True if receive is blocking transaction. */ + lin_callback_t Callback; /*!< Callback function to invoke after receiving a byte or transmitting a byte. */ + uint8_t currentId; /*!< Current ID */ + uint8_t currentPid; /*!< Current PID */ + volatile lin_event_id_t currentEventId; /*!< Current ID Event */ + volatile lin_node_state_t currentNodeState; /*!< Current Node state */ + volatile uint32_t timeoutCounter; /*!< Value of the timeout counter */ + volatile bool timeoutCounterFlag; /*!< Timeout counter flag */ +} lin_xfer_state_t; + +/**@}*/ +/** + * @name API declaration for LIN driver. + * + */ +/**@{*/ + +/** + * @brief Init the LIN instance for LIN network. This API will help initialize the FCUART to expect state, + * but will nots start the TX&RX function, if users want to start the LIN protocol transfer, please + * call the function LIN_DrvStart() after this API is called. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pConfig Configuration for LIN hardware, must not be null. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_USEED : The instance has been used, user should use another instance or de-initialize this instance firstly. + * - LIN_STATUS_ERROR : the baudrate has not been set successfully. + */ +LIN_StatusType LIN_DrvInit(uint8_t u8LinIndex, lin_config_t *pConfig); + +/** + * @brief De-Init the LIN instance used by LIN network. + * This API will help disable the fcuart interrupts and stop the TX/RX transfer. + * + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : The instance has not been initialized. + */ +LIN_StatusType LIN_DrvDeInit(uint8_t u8LinIndex); + +/** + * @brief Help users get the default configuration of LIN node. users should provide the configuration structure + * in app code, and transfer the ptr address to driver code. uses can also set this parameters in the application code + * as designed. + * + * @param u8NodeMode LIN node mode select, 0 for slave mode and 1 for master mode. + * @param pConfig default configuration for LIN node, must not be null. + */ +void LIN_DrvGetDefaultConfig(LIN_NodeType eNodeMode, lin_config_t *pConfig); + +/** + * @brief Start LIN node transfer, this API should be called after LIN hardware has been initialized, and must + * be called before starting a LIN node transfer. Users should provide a tansfer structure for storing the + * transfer state, ant LIN node state changed will be stored to this xfer state. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pXferState Transfer state structure which will help store the trasnfer state. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_PARAM_ERROR: the parameter setting maybe not correct, maybe instance has bot been initialized. + */ +LIN_StatusType LIN_DrvStart(uint8_t u8LinIndex, lin_xfer_state_t *pXferState); + +/** + * @brief This function will help install callback function that used by application code. + * users can handle some needed operations in driver code or get some important states. + * or uses can also setting this in transfer state structure. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param callback user's callbak function that need be called in driver code. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : The instance required has bot been initialized. + */ +LIN_StatusType LIN_DrvInstallUserCallback(uint8_t u8LinIndex, lin_callback_t callback); + +/** + * @brief This function will help users send a header in master node which will help start a new + * frame transfer. please do not used this API will LIN instance is configured as slave node. + * This API will make a parity ID, and only send a break field to the protocol, all the other + * filed like sync filed and pid byte will be handled in FCUART IRQHandler. more details can + * refer to IRQ routine. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param u8Id The ID data that useds need to send in header. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required has not been intialized. + * - LIN_STATUS_UNSUPPORTED : Current node is slave not, could not send header to protocol. + * - LIN_STATUS_BUSY : Bus busy which means node is sending or receiving another frame. + */ +LIN_StatusType LIN_DrvSendHeader(uint8_t u8LinIndex, uint8_t u8Id); + +/** + * @brief This API will help users send a frame data through LIN protocol, and will return only when + * all frame data has been sent to the protocol, or while timeout occurred, so please configure + * the u32TimeOut parameter as needed. And currentlyt this API has not implement the OS feature, + * so do not call this API in interrupt routine, otherwise, routine maybe halted by this API. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pTxBuf TX buffer whihc will be sent to protocol, MUST NOT BE NULL. + * @param u8Length bytes lengths in TX buffer. + * @param u32TimeOut Timeout value, 0 indicates timeout feature is not used, in unit of millieconds. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required has not been initialized. + * - LIN_STATUS_BUSY : Bus busy, node is transfer state. + */ +LIN_StatusType LIN_DrvSendFrameBlocking(uint8_t u8LinIndex, uint8_t *pTxBuf, uint8_t u8Length, uint32_t u32TimeOut); + +/** + * @brief This API will help users send a frame data through LIN protocol, this API will return immediately. + * data will be stored in txbuffer, users can check the transmit status while data is sending. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pTxBuf TX buffer whihc will be sent to protocol, MUST NOT BE NULL. + * @param u8Length bytes lengths in TX buffer. + * @param u32TimeOut Timeout value, 0 indicates timeout feature is not used, in unit of millieconds. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required has not been initialized. + * - LIN_STATUS_BUSY : Bus busy, node is transfer state. + */ +LIN_StatusType LIN_DrvSendFrameNonBlocking(uint8_t u8LinIndex, uint8_t *pTxBuf, uint8_t u8Length); + +/** + * @brief This API will help users get the LIN transfer status while data is sending. and will also + * help user get remainning byte in transfer still need sending in buffer. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pRemainBytes Address to be stored the remain byte value, should not be NULL. + * @return operation status: + * - LIN_STATUS_TIMEOUT : node transfer timeout occurred. + * - LIN_STATUS_SUCCESS : transfer complete. + * - LIN_STATUS_BUSY : transfer is going + */ +LIN_StatusType LIN_DrvGetTransmitStatus(uint8_t u8LinIndex, uint8_t *pRemainBytes); + +/** + * @brief This API will help users receive frame data through LIN protocol, this API will return only when + * all frame data has been received from the protocol, or while timeout occurred, so please configure + * the u32TimeOut parameter as needed. And currently, this API has not implement the OS feature, + * so do not call this API in interrupt routine, otherwise, routine maybe halted by this API. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pRxBuf RX buffer which will be received from protocol, MUST not be NULL. + * @param u8Length bytes lengths should be received. + * @param u32TimeOut Timeout value, 0 indicates timeout feature is not used, in millieconds. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance has not been initialized + * - LIN_STATUS_BUSY : Bus in busy state, need wait bus idle. + * - LIN_STATUS_TIMEOUT : Timeout occurred, data received may not successful. + */ +LIN_StatusType LIN_DrvReceiveFrameBlocking(uint8_t u8LinIndex, uint8_t *pRxBuf, uint8_t u8Length, uint32_t u32TimeOut); + +/** + * @brief This API will help users received frame data through LIN protocol, this API will return immediately. + * data will be stored in rxbuffer, users can check the receive status while using this API. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pRxBuf RX buffer which will be received from protocol, MUST not be NULL. + * @param u8Length bytes lengths should be received. + * @param u32TimeOut Timeout value, 0 indicates timeout feature is not used, in millieconds. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance has not been initialized + * - LIN_STATUS_BUSY : Bus in busy state, need wait bus idle. + * - LIN_STATUS_TIMEOUT : Timeout occurred, data received may not successful. + */ +LIN_StatusType LIN_DrvReceiveFrameNonBlocking(uint8_t u8LinIndex, uint8_t *pRxBuf, uint8_t u8Length); + +/** + * @brief This API will help users get the LIN transfer status while data is receiving. and will also + * help user get remainning byte in transfer still need receiving in buffer. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pRemainBytes Address to be stored the remain byte value, should not be NULL. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - others are not successfully. + */ +LIN_StatusType LIN_DrvGetReceiveStatus(uint8_t u8LinIndex, uint8_t *pRemainBytes); + +/** + * @brief Abort transfer both sending or receiving data, actually, call this APU will enter IDLE state. + * will stop end and receive even data transfer is on going. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + */ +LIN_StatusType LIN_DrvAbortTransfer(uint8_t u8LinIndex); + +/** + * @brief This API should be called while no data is transferring, once this API is called, node will + * enter sleep mode, TX/RX and interrupts will also be disabled, and node will wait a wakeup signal + * on the protocol. This API will enable receive active interrupt, once a wakeup signal triggered, + * routine will entern uart IRQHandler to handle this case, and then wakeup the LIN node. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + */ +LIN_StatusType LIN_DrvGoToSleepMode(uint8_t u8LinIndex); + +/** + * @brief THis API will help confgure the mode into IDLE state. In IDLE state, node will enable receive interrupt and break + * field detect interrupt, slave node will wait the break field from master node, master node will prepare to send a + * new break filed to start a new frame. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + */ +LIN_StatusType LIN_DrvGoToIdleMode(uint8_t u8LinIndex); + +/** + * @brief Sending a wakeup signal to the protocol, all LIN network nodes receive this signal will + * wakeup from sleep mode. Actually, the master will send a character which will cause a 150us + * larger active level to the protocol. while receiving this signal, LIN node will wake up + * from sleep mode. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required is not initialized. + * - LIN_STATUS_BUSY :LIN node state is not correct, need update state firstly. + */ +LIN_StatusType LIN_DrvSendWakeupSignal(uint8_t u8LinIndex); + +/** + * @brief Get the LIN node state. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return the node current state, refer to @lin_node_state_t + */ +lin_node_state_t LIN_DrvGetNodeState(uint8_t u8LinIndex); + +/** + * @brief This API should be called by user's application code, and the timeout periods should be 500ms once. + * Better to provide a timer IRQhandler to call this APIs 500ms onces. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - others are not successfully. + */ +LIN_StatusType LIN_DrvTimeOutService(uint8_t u8LinIndex); + +/** + * @brief This API will help users set the timeout counter with one API, users should use this feature with LIN_DrvTimeOutService() + * called every fixed time. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param u32TimeOutValue Timeout value. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required is not initialized. + */ +LIN_StatusType LIN_DrvSetTimeOutCounter(uint8_t u8LinIndex, uint32_t u32TimeOutValue); + +/** + * @brief This API will help users get the Node timeout flag status. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return true for timeout occurred, false indicate no timeout. + */ +bool LIN_DrvGetTimeOutFlag(uint8_t u8LinIndex); + +/** + * @brief This is LIN IRQ routine code, uses should call this in the FCUART IRQhandler code. please must implement + * the feature in application code. + * + * @param u8LinIndex LIN hardware instance, 0U... + */ +void LIN_DrvIRQHandler(uint8_t u8LinIndex); + +/**@}*/ + +/** @}*/ /* fc4xxx_driver_lin */ +#if defined(__cplusplus) +} +#endif + +#endif /* _DRIVER_FC4XXX_DRIVER_LIN_H_ */ diff --git a/Inc/fc7xxx_driver_lu.h b/Inc/fc7xxx_driver_lu.h new file mode 100644 index 0000000..6b7166c --- /dev/null +++ b/Inc/fc7xxx_driver_lu.h @@ -0,0 +1,138 @@ +/** + * @file fc7xxx_driver_lu.h + * @author Flagchip0103 + * @brief FC7xxx LU driver header file + * @version 0.1.0 + * @date 2023-12-19 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2023-12-19 Flagchip0103 N/A First version for FC7240 + ******************************************************************************** */ + +#ifndef _DRIVER_FC4XXX_DRIVER_LU_H_ +#define _DRIVER_FC4XXX_DRIVER_LU_H_ +#include "HwA_lu.h" +/** + * @addtogroup fc7xxx_driver_lu + * @{ + */ + +#define LU_AOI_IN_N_CFG_N(AoiIn, AoiInN, InNCfgNType) ((((uint32_t)(InNType) & 0x3U) << (((uint32_t)3U - (uint32_t)(AoiInN)) << 3U)) << (((uint32_t)3U - (uint32_t)(AoiIn)) << 3U)) +#define LU_AOI_IN_N_CFG_N_MASK(AoiIn, AoiInN) (((uint32_t)0x3U << (((uint32_t)3U - (uint32_t)(AoiInN)) << 3U)) << (((uint32_t)3U - (uint32_t)(AoiIn)) << 3U)) + +#define LU_AOI_IN_CFG(AoiInN, CfgNType) ((((uint32_t)(CfgNType) & 0x3U) << (((uint32_t)3U - (uint32_t)(AoiInN)) << 1U))) +#define LU_AOI_IN_CFG_MASK(AoiInN) ((((uint32_t)0x3U) << (((uint32_t)3U - (uint32_t)(AoiInN)) << 1U))) + +#define LU_AOI_IN_N_CFG(AoiIn, InNType) ((((uint32_t)(InNType) & 0xFFU) << (((uint32_t)3U - (uint32_t)(AoiIn)) << 3U))) +#define LU_AOI_IN_N_CFG_MASK(AoiIn) ((((uint32_t)0xFFU) << (((uint32_t)3U - (uint32_t)(AoiIn)) << 3U))) + +#define LU_SYNC_CONTROL_INPUT_N(InputN, value) ((uint32_t)(value) << (InputN)) + +/** @brief LU return structure */ +typedef enum +{ + LU_STATUS_SUCCESS = 0U, + LU_STATUS_PARAM_INVALID = 1U +} LU_StatusType; + +/** @brief LU IN type */ +typedef enum +{ + LU_AOI_IN_0 = 0U, + LU_AOI_IN_1, + LU_AOI_IN_2, + LU_AOI_IN_3, +} LU_AoiInType; + +/** @brief LU IN(n) configuration type */ +typedef enum +{ + LU_AOI_IN_N_A = 0U, + LU_AOI_IN_N_B, + LU_AOI_IN_N_C, + LU_AOI_IN_N_D +} LU_AoiInNType; + +/** @brief LU IN(n) configuration */ +typedef enum +{ + FORCE_ITEM_AS_ZERO = 0U, /**< force item as logic zero */ + PASS_THROUGH_ITEM, /**< pass through item */ + COMPLEMENT_ITEM, /**< complement item */ + FORCE_ITEM_AS_ONE /**< force item as logic one */ +} LU_InModeType; + +/** @brief LU output initialization value */ +typedef enum +{ + LU_OUTPUT_INIT_ZERO = 0U, + LU_OUTPUT_INIT_ONE, + LU_OUTPUT_INIT_DISABLE +} LU_OutputInitValueType; + +/** @brief LU IN(n) configuration register type */ +typedef struct +{ + LU_InModeType eInNACfg; /**< AOI IN(n) A configuration */ + LU_InModeType eInNBCfg; /**< AOI IN(n) B configuration */ + LU_InModeType eInNCCfg; /**< AOI IN(n) C configuration */ + LU_InModeType eInNDCfg; /**< AOI IN(n) D configuration */ +} LU_InConfigType; + +/** @brief LU AOI IN(n) configuration type */ +typedef struct +{ + LU_InConfigType tIn0Config; /**< AOI IN0 configuration */ + LU_InConfigType tIn1Config; /**< AOI IN1 configuration */ + LU_InConfigType tIn2Config; /**< AOI IN2 configuration */ + LU_InConfigType tIn3Config; /**< AOI IN3 configuration */ +} LU_AoiConfigType; + +/** @brief LU LG inputs synchronous control */ +typedef struct +{ + bool bInputNA; /**< LU IN(n) A sync control */ + bool bInputNB; /**< LU IN(n) B sync control */ + bool bInputNC; /**< LU IN(n) C sync control */ + bool bInputND; /**< LU IN(n) D sync control */ +} LU_InputsSyncCtrlType; + +/** @brief LU initialization type */ +typedef struct +{ + LU_LgType eLgNum; /**< LG number */ + LU_AoiConfigType tAoi0Config; /**< aoi0 configuration */ + LU_AoiConfigType tAoi1Config; /**< aoi1 configuration */ + LU_InputsSyncCtrlType tSyncCtrl; /**< inputs sync control, when set, would sync input product with bus clock */ + LU_BypassModeType eAoiMode; /**< AOI mode */ + LU_ConfigModeType eFFMode; /**< flip-flop mode */ + LU_OutputInitValueType eFFInitValue; /**< flip-flop initial value */ + LU_InputNType eFbMode; /**< feedback override control in JKFF mode */ + uint8_t u8Aoi0FiltCnt; /**< aoi0 input filter sample count */ + uint8_t u8Aoi0Period; /**< aoi0 input filter sample period */ + uint8_t u8Aoi1FiltCnt; /**< aoi1 input filter sample count */ + uint8_t u8Aoi1Period; /**< aoi1 input filter sample period */ +} LU_InitType; + +/* global functions */ +/** + * @brief Initialize LU instance + * @param pInitStruct LU initialization structure + * @return LU return type + */ +LU_StatusType LU_Init(const LU_InitType *const pInitStruct); + +/** + * @brief De-initialize LU instance + */ +void LU_Deinit(void); + +/** @}*/ /* fc7xxx_driver_lu */ +#endif diff --git a/Inc/fc7xxx_driver_mam.h b/Inc/fc7xxx_driver_mam.h new file mode 100644 index 0000000..9f1a303 --- /dev/null +++ b/Inc/fc7xxx_driver_mam.h @@ -0,0 +1,109 @@ +/** + * @file fc7xxx_driver_mam.h + * @author Flagchip + * @brief FC7xxx MAM driver type definition and API + * @version 0.2.0 + * @date 2023-02-08 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2023-02-08 Flagchip095 N/A First version for FC7240 + ******************************************************************************** */ +#ifndef _DRIVER_FC7XXX_DRIVER_MAM_H_ +#define _DRIVER_FC7XXX_DRIVER_MAM_H_ + +#include "device_header.h" +#include "HwA_mam.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * @brief The master index of the mam peripheral + * + */ +typedef enum { + MAM_MASTER_CPU0_AXIM = 0, + MAM_MASTER_CPU0_AHBP, + MAM_MASTER_DMA0, + MAM_MASTER_HSM, + MAM_MASTER_NUM +} MAM_Master_Type; + +/** + * @brief The mam index + * + */ +typedef enum { + NVM_MAM0 = 0, + RAM_MAM1, + PERIPHERAL_MAM2 +} MAM_Index_Type; + + +/** + * @brief the MAM slave information + * + */ +typedef struct +{ + uint8_t error; + uint32_t block_num; +} MAM_Inf_Type; + + +typedef enum { + FORBID_READ_ACCESS = 1, + FORBID_WRITE_ACCESS = 2, + FORBID_EXECUTE_ACCESS = 4, + FORBID_USER_ACCESS = 8 +} MAM_Forbid_Access_Type; + +/** + * @brief The function of software reset to MAM + * + * @param number mam index + */ +void MAM_Reset(MAM_Index_Type idx); + +/** + * @brief The function to enable MAM watch dog + * + * @param1 Master The master index + * + * @param2 u32Addr The input address + */ +uint8_t MAM_Enable_Wdg(MAM_Master_Type Master,uint32_t u32Addr); + +/** + * @brief The function to disable MAM watch dog + * + * @param1 Master The master index + * + * @param2 u32Addr The input address + */ +uint8_t MAM_Disable_Wdg(MAM_Master_Type Master,uint32_t u32Addr); + +/** + * @brief The function to config MAM + * + * @param1 Master The master index + * + * @param2 u32Addr The input address + * + * @param3 u32Val The value to set + */ +uint8_t MAM_Config(MAM_Master_Type Master, uint32_t u32Addr, uint32_t u32Val); + +#if defined(__cplusplus) +} +#endif + +#endif /* end of DRIVER_UART_H_ */ diff --git a/Inc/fc7xxx_driver_mb.h b/Inc/fc7xxx_driver_mb.h new file mode 100644 index 0000000..12b55e4 --- /dev/null +++ b/Inc/fc7xxx_driver_mb.h @@ -0,0 +1,201 @@ +/** + * @file fc7xxx_driver_mb.h + * @author Flagchip070 + * @brief FC7xxx Mailbox driver type definition and API + * @version 0.1.0 + * @date 2022-11-15 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2022-11-15 Flagchip070 N/A First version for FC7300 +********************************************************************************/ + +#ifndef _DRIVER_fc7xxx_driver_mb_H_ +#define _DRIVER_fc7xxx_driver_mb_H_ + +#include "device_header.h" +#include "HwA_mb.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * @addtogroup fc7xxx_driver_mb + * @{ + */ + + +/** + * @brief Mailbox channel bit flag of security information + * + */ +#define MB_CHANNEL_STATUS_SECURE 2u + +/** + * @brief Mailbox channel bit flag of processing information + * + */ +#define MB_CHANNEL_STATUS_PRIVILEGED 1u + +/** + * @name Mailbox channel bit mask + * @brief Bit of channel indicate channel number + * + * @{ + */ +#define MB_CHANNEL_MASK_NONE 0u +#define MB_CHANNEL_MASK_ALL 0xFFFFu +#define MB_CHANNEL_MASK(ch) ((uint32_t)(1ul << (ch))) +/** @}*/ + +/** + * @brief Mailbox has not initialized, the core index will be MB_NOT_INIT + * + */ + +#define MB_NOT_INIT 0xFFFFFFFFu +/** + * @brief Mailbox operation return values + * + */ +typedef enum { + MB_STATUS_SUCCESS = 0u, /*!< The Mailbox operation is success */ + MB_STATUS_FAILED, /*!< The Mailbox operation is failed */ + MB_STATUS_PARAM_ERROR, /*!< The Mailbox operation is failed because of parameter error*/ + MB_STATUS_ALREADY_INITED, /*!< The Mailbox operation is failed because of + Mailbox has already initialized*/ + MB_STATUS_UNINIT, /*!< The Mailbox operation is failed because of + Mailbox has not initialized*/ + MB_STATUS_LOCKED, /*!< The Mailbox channel is locked */ + MB_STATUS_NO_REQUEST, /*!< No valid requests */ +} MB_StatusType; + +/** + * @brief Configuration of a Mailbox request + * + */ +typedef struct +{ + uint8_t u8Channel; /*!< The selected Mailbox channel */ + uint8_t u8RequestMask; /*!< The mask for issuing requests */ + uint8_t u8DoneMasterIndex; /*!< The master ID of the core that generates a done event */ + uint8_t u8DoneMask; /*!< The mask for the done events */ + uint8_t u8AutoReleaseFlag; /*!< Automatically clear the channel lock enable bit */ + uint8_t u8Reserved[3]; + uint32_t aData[2]; /*!< Sending data */ +} MB_RequestType; + +/** + * @brief Configuration of a receiving request + * + */ +typedef struct +{ + uint8_t u8Channel; /*!< The selected Mailbox channel */ + uint8_t u8MasterCoreIndex; /*!< Buffer to store the master core index */ + uint8_t u8ChannelStatus; /*!< Buffer to store the security information + and processing mode of the channel*/ + uint8_t u8Reserved; + uint32_t aData[2]; /*!< Buffer to store the receiving data */ +} MB_ReceiveType; + +/** + * @brief Configuration of the Mailbox + * + */ +typedef struct +{ + uint32_t u32EventMask; /*!< Mask for the request events and done events */ + uint32_t u32IntrMask; /*!< Mask for enable the interrupts */ + void (*pRequestCallback)(MB_ReceiveType *pReceive); /*!< Callback of the request events */ + void (*pDoneCallback)(uint32_t u32ChannelMask); /*!< Callback of the done events */ +} MB_InitType; + +/** + * @brief Initialize the Mailbox + * + * @param pInitConfig the configurations of the Mailbox + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_Init(const MB_InitType *pInitConfig); +/** + * @brief De-initialize the Mailbox + * + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_DeInit(void); +/** + * @brief Attempt to acquire a Mailbox channel + * + * @param u32Channel the selected Mailbox channel + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_LockChannel(uint32_t u32Channel); +/** + * @brief Release a Mailbox channel + * + * @param u32Channel the selected Mailbox channel + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_ReleaseChannel(uint32_t u32Channel); +/** + * @brief Get the index of the core + * + * @return uint32_t index of the core + */ +uint32_t MB_GetCoreIndex(void); +/** + * @brief Launching a Mailbox request + * + * @param pRequest Configuration of the request + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_SendRequest(MB_RequestType *pRequest); +/** + * @brief Attempt to receive a request from the selected channel + * + * @param pReceive Configuration of the receiving request + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_ReceiveChannel(MB_ReceiveType *pReceive); +/** + * @brief Software clears channel lock + * + * @param u32Channel the selected Mailbox channel + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_UnlockChannel(uint32_t u32Channel); +/** + * @brief Polling the done event of all channels + * + * @param u32PollMask mask of the done event + * @param pDoneMask buffer to store the done events + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_PollDone(uint32_t u32PollMask, uint32_t *pDoneMask); +/** + * @brief Issue a done event to the selected channel + * + * @param u32Channel the selected Mailbox channel + * @param u32DoneMask The mask for issuing done + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_DoneChannel(uint32_t u32Channel, uint32_t u32DoneMask); +/** + * @brief Interrupt IRQ handle of Mailbox + * + */ +void MB_IRQProcess(void); +/** @}*/ /* fc7xxx_driver_mb */ +#if defined(__cplusplus) +} +#endif +#endif diff --git a/Inc/fc7xxx_driver_mpu.h b/Inc/fc7xxx_driver_mpu.h new file mode 100644 index 0000000..7937cf7 --- /dev/null +++ b/Inc/fc7xxx_driver_mpu.h @@ -0,0 +1,242 @@ +/** + * @file fc7xxx_driver_mpu.h + * @author Flagchip085 + * @brief FC7xxx MPU driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + * @details The MPU only checks the CPU master access to CTCM and DTCM memory. When access denied, it will cause MemManage Interrupt. + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 + ******************************************************************************** */ +#ifndef _DRIVER_FC7XXX_DRIVER_MPU_H_ +#define _DRIVER_FC7XXX_DRIVER_MPU_H_ + +#include "HwA_mpu.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * @addtogroup fc7xxx_driver_mpu + * @{ + */ + +/** + * @brief Status enumeration used by Flagchip MPU Driver + * + */ +typedef enum { + MPU_STATUS_SUCCESS = 0, /*!< MPU API execute successfully */ + MPU_STATUS_ERROR, /*!< Some error occur in MPU API */ +} MPU_StatusType; + +/** + * @brief + * + */ +typedef enum { + MPU_EN_HFNMI_PRIVDEF_NONE = 0U, /*!< disables use of the default memory map. Any memory access to a location not covered by any enabled region causes a fault, + MPU is disabled during hard fault, NMI, and FAULTMASK handlers */ + MPU_EN_HARDFAULT_NMI = 1, /*!< Enables the operation of MPU during hard fault, NMI, and FAULTMASK handlers */ + MPU_EN_PRIVILEGED_DEFAULT = 2, /*!< enables use of the default memory map as a background region for privileged software accesses. + When enabled, the background region acts as if it is region number -1. + Any region that is defined and enabled has priority over this default map. */ + MPU_EN_HFNMI_PRIVDEF = 3, /*!< same with MPU_EN_HARDFAULT_NMI | MPU_EN_PRIVILEGED_DEFAULT */ +} MPU_EnableOptionType; + +/** + * @brief Enable Status for Sub-region configuration + * + */ +typedef enum { + MPU_REGION_SRD_ENABLE_SUBREGION = 0, /*!< sub-region is enabled */ + MPU_REGION_SRD_DISABLE_SUBREGION = 1, /*!< sub-region is not enabled */ +} MPU_RegionSubDisableType; + +/** + * @brief Configure the code in the region whether can be execute + * + */ +typedef enum { + MPU_REGION_XN_EXECUTE_ENABLE = 0x0, + MPU_REGION_XN_EXECUTE_DISABLE = 0x1 +} MPU_RegionExecuteNeverType; + +/** + * @brief region Shareable configuration + * + */ +typedef enum { + MPU_REGION_S_DISABLE = 0, + MPU_REGION_S_ENABLE = 1 +} MPU_RegionShareableType; + +/** + * @brief Region Cacheable configuration + * + */ +typedef enum { + MPU_REGION_C_DISABLE = 0, + MPU_REGION_C_ENABLE = 1 +} MPU_RegionCacheableType; + +/** + * @brief Region Bufferable configuration + * + */ +typedef enum { + MPU_REGION_B_DISABLE = 0, + MPU_REGION_B_ENABLE = 1 +} MPU_RegionBufferableType; + +/** + * @brief Region Type Extend Level configuration + * + */ +typedef enum { + MPU_REGION_TEX_LEVEL_0 = 0, + MPU_REGION_TEX_LEVEL_1 = 1, + MPU_REGION_TEX_LEVEL_2 = 2 +} MPU_RegionTypeExtLevelType; + +/** + * @brief Region size enumeration for enabling MPU region + * + */ +typedef enum { + MPU_REGION_SIZE_32B = 0x04, + MPU_REGION_SIZE_64B = 0x05, + MPU_REGION_SIZE_128B = 0x06, + MPU_REGION_SIZE_256B = 0x07, + MPU_REGION_SIZE_512B = 0x08, + MPU_REGION_SIZE_1KB = 0x09, + MPU_REGION_SIZE_2KB = 0x0A, + MPU_REGION_SIZE_4KB = 0x0B, + MPU_REGION_SIZE_8KB = 0x0C, + MPU_REGION_SIZE_16KB = 0x0D, + MPU_REGION_SIZE_32KB = 0x0E, + MPU_REGION_SIZE_64KB = 0x0F, + MPU_REGION_SIZE_128KB = 0x10, + MPU_REGION_SIZE_256KB = 0x11, + MPU_REGION_SIZE_512KB = 0x12, + MPU_REGION_SIZE_1MB = 0x13, + MPU_REGION_SIZE_2MB = 0x14, + MPU_REGION_SIZE_4MB = 0x15, + MPU_REGION_SIZE_8MB = 0x16, + MPU_REGION_SIZE_16MB = 0x17, + MPU_REGION_SIZE_32MB = 0x18, + MPU_REGION_SIZE_64MB = 0x19, + MPU_REGION_SIZE_128MB = 0x1A, + MPU_REGION_SIZE_256MB = 0x1B, + MPU_REGION_SIZE_512MB = 0x1C, + MPU_REGION_SIZE_1GB = 0x1D, + MPU_REGION_SIZE_2GB = 0x1E, + MPU_REGION_SIZE_4GB = 0x1F +} MPU_RegionSizeType; + +/** + * @brief MPU Permission Enumeration + * + */ +typedef enum { + MPU_REGION_AP_NO_ACCESS = 0x00, /*!< Any access generates a permission fault */ + MPU_REGION_AP_PRIV_RW = 0x01, /*!< Privileged access only, unprivileged no access */ + MPU_REGION_AP_PRIV_RW_URO = 0x02, /*!< Any unprivileged write generates a permission fault */ + MPU_REGION_AP_FULL_ACCESS = 0x03, /*!< Full access */ + MPU_REGION_AP_PRIV_RO = 0x05, /*!< Privileged read-only, unprivileged no access */ + MPU_REGION_AP_PRIV_RO_URO = 0x06 /*!< Privileged and unprivileged read-only */ +} MPU_RegionAccessPermissionType; + + +typedef enum { + MPU_REGION_NUMBER_0 = 0x0, /*!< lowest priority */ + MPU_REGION_NUMBER_1 = 0x1, + MPU_REGION_NUMBER_2 = 0x2, + MPU_REGION_NUMBER_3 = 0x3, + MPU_REGION_NUMBER_4 = 0x4, + MPU_REGION_NUMBER_5 = 0x5, + MPU_REGION_NUMBER_6 = 0x6, + MPU_REGION_NUMBER_7 = 0x7, + MPU_REGION_NUMBER_8 = 0x8, + MPU_REGION_NUMBER_9 = 0x9, + MPU_REGION_NUMBER_10 = 0xA, + MPU_REGION_NUMBER_11 = 0xB, + MPU_REGION_NUMBER_12 = 0xC, + MPU_REGION_NUMBER_13 = 0xD, + MPU_REGION_NUMBER_14 = 0xE, + MPU_REGION_NUMBER_15 = 0xF /*!< highest priority */ +} MPU_RegionNumberType; + + +typedef struct { + uint32_t u32BaseAddr; /*!< the start address of region, the least significant 5 bits should be 0 */ + MPU_RegionSizeType eRegionSize; /*!< region size */ + MPU_RegionAccessPermissionType eAccessPermission; /*!< region access permission */ + MPU_RegionExecuteNeverType eExecuteNever; /*!< region data can be execute or not */ + MPU_RegionTypeExtLevelType eTypeExtLevel; /*!< region type extend level */ + MPU_RegionShareableType eShareable; /*!< region shareable */ + MPU_RegionCacheableType eCacheable; /*!< region cacheable */ + MPU_RegionBufferableType eBufferable; /*!< region bufferable */ + MPU_RegionSubDisableType eSubRegionDis_0; /*!< sub-region 0 disable or not */ + MPU_RegionSubDisableType eSubRegionDis_1; /*!< sub-region 1 disable or not */ + MPU_RegionSubDisableType eSubRegionDis_2; /*!< sub-region 2 disable or not */ + MPU_RegionSubDisableType eSubRegionDis_3; /*!< sub-region 3 disable or not */ + MPU_RegionSubDisableType eSubRegionDis_4; /*!< sub-region 4 disable or not */ + MPU_RegionSubDisableType eSubRegionDis_5; /*!< sub-region 5 disable or not */ + MPU_RegionSubDisableType eSubRegionDis_6; /*!< sub-region 6 disable or not */ + MPU_RegionSubDisableType eSubRegionDis_7; /*!< sub-region 7 disable or not */ +} MPU_RegionConfigurationType; + + +/** + * @brief Check the MPU exist or not + * + * @return MPU_StatusType if exist return MPU_STATUS_SUCCESS, others not exist + */ +MPU_StatusType MPU_CheckExist(void); + +/** + * @brief Enable the MPU + * + * @param eOption Enable Options + */ +void MPU_Enable(MPU_EnableOptionType eOption); + +/** + * @brief Disable MPU + * + */ +void MPU_Disable(void); + +/** + * @brief Disable region + * + * @param eRegion Region index + * @return MPU_StatusType MPU_STATUS_SUCCESS when disable successfully, others fail + */ +MPU_StatusType MPU_RegionDisable(MPU_RegionNumberType eRegion); + +/** + * @brief Enable region + * + * @param eRegion Region index + * @param pConfig Region Configuration Parameter + * @return MPU_StatusType MPU_STATUS_SUCCESS when disable successfully, others fail + */ +MPU_StatusType MPU_RegionEnable(MPU_RegionNumberType eRegion, const MPU_RegionConfigurationType *pConfig); + + +/** @} */ /* fc7xxx_driver_mpu */ +#if defined(__cplusplus) +} +#endif +#endif /* _DRIVER_FC7XXX_DRIVER_MPU_H_ */ diff --git a/Inc/fc7xxx_driver_msc.h b/Inc/fc7xxx_driver_msc.h new file mode 100644 index 0000000..cc96c5d --- /dev/null +++ b/Inc/fc7xxx_driver_msc.h @@ -0,0 +1,402 @@ +/** + * @file fc7xxx_driver_msc.h + * @author Flagchip + * @brief FC7240 MSC driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-10 Flagchip084 N/A FC7240 release version + ******************************************************************************** */ + +#ifndef _DRIVER_FC7XXX_DRIVER_MSC_H_ +#define _DRIVER_FC7XXX_DRIVER_MSC_H_ +#include "device_header.h" +#include "HwA_msc.h" +/** + * @addtogroup fc7xxx_driver_msc + * @{ +. */ + +typedef enum +{ + MSC_RETURN_OK = 0x00U, /*!< The SENT operation is succeeded */ + MSC_RETURN_E_NOT_OK = 0x01U, /*!< The SENT operation is failed */ + MSC_RETURN_E_PARAM = 0x04U, /*!< The SENT parameter is incorrect or out of range. */ +} MSC_ReturnType; + +typedef enum +{ + MSC_RDR0 = 0x0U, + MSC_RDR1 = 0x1U, + MSC_RDR2 = 0x2U, + MSC_RDR3 = 0x3U, + MSC_RDRx_COUNT = 0x4U +} MSC_RDRxIndexType; + +typedef enum +{ + MSC_INSTANCE_0 = 0U, /*!< MSC instance 0 is selected. */ + MSC_INSTANCE_1 = 1U /*!< MSC instance 1 is selected. */ +} MSC_InstanceType; + +typedef enum +{ + MSC_RFIE_DISABLE = 0x0U, /*!< Interrupt generation disabled. */ + MSC_RFIE_MODE1 = 0x1U, /*!< The interrupt is generated when data is received and written into the RDRx. */ + MSC_RFIE_MODE2 = 0x2U, /*!< The interrupt is generated when received data is not equal to 0. */ + MSC_RFIE_MODE3 = 0x3U /*!< The interrupt is generated when data is received and written into register RDR3. */ +} MSC_RFIEModeType; + +typedef enum +{ + MSC_DFIE_DISABLE = 0x0U, /*!< Disable. */ + MSC_DFIE_MODE1 = 0x1U, /*!< Interrupt is generated when the last data bit has been shifted. */ + MSC_DFIE_MODE2 = 0x2U /*!< Interrupt is generated when the first data bit has been shifted. */ +} MSC_DFIEModeType; + +/** + * @brief MSC Channel ISR callback function prototype + * + */ +typedef void (*MSC_ISRCallbackType)(const MSC_InstanceType eInstance); + +/** @brief MSC interrupt configure structure. */ +typedef struct +{ + bool bCFIntEnable; /*!< MSC_INCR[CFIE] bit, interrupt enable, if this bit asserted, command frame can lead the interrupt. */ + bool bTFIntEnable; /*!< MSC_INCR[TFIE] bit, interrupt enable, if this bit asserted, time frame can lead the interrupt. */ + MSC_RFIEModeType eRFIEMode; /*!< Interrupt mode of RFIE. */ + MSC_DFIEModeType eDFIEMode; /*!< Interrupt mode of DFIE. */ + bool bTOIntEnable; /*!< Enable the interrupt of timeout. */ + uint16_t u16TimeoutValue; /*!< Timeout value of timeout interrupt. */ + MSC_ISRCallbackType pReceiveFrameISRCallback; /*!< Receive frame ISR callback. */ + MSC_ISRCallbackType pTimeFrameISRCallback; /*!< Time Frame ISR callback. */ + MSC_ISRCallbackType pCommandFrameISRCallback; /*!< Command Frame ISR callback. */ + MSC_ISRCallbackType pDataFrameISRCallback; /*!< Data Frame ISR callback. */ + MSC_ISRCallbackType pReceiveTimeOutISRCallback; /*!< Data Frame ISR callback. */ +} MSC_InterruptCfgType; + +typedef enum +{ + MSC_SDI_SEL_SDI0 = 0x0U, /*!< SDI0 input is selected for SDI. */ + MSC_SDI_SEL_SDI1 = 0x1U, /*!< SDI1 input is selected for SDI. */ + MSC_SDI_SEL_SDI2 = 0x2U, /*!< SDI2 input is selected for SDI. */ + MSC_SDI_SEL_SDI3 = 0x3U, /*!< SDI3 input is selected for SDI. */ + MSC_SDI_SEL_SDI4 = 0x4U, /*!< SDI4 input is selected for SDI. */ + MSC_SDI_SEL_SDI5 = 0x5U, /*!< SDI5 input is selected for SDI. */ + MSC_SDI_SEL_SDI6 = 0x6U, /*!< SDI6 input is selected for SDI. */ + MSC_SDI_SEL_SDI7 = 0x7U /*!< SDI7 input is selected for SDI. */ +} MSC_SDISelectionType; + +typedef enum +{ + MSC_ENC_SEL_EN0 = 0x0U, /*!< EN0 is selected for ENC. */ + MSC_ENC_SEL_EN1 = 0x1U, /*!< EN1 is selected for ENC. */ + MSC_ENC_SEL_EN2 = 0x2U, /*!< EN2 is selected for ENC. */ + MSC_ENC_SEL_EN3 = 0x3U /*!< EN3 is selected for ENC. */ +} MSC_ENCSelectionType; + +typedef enum +{ + MSC_ENH_SEL_EN0 = 0x0U, /*!< EN0 is selected for ENH. */ + MSC_ENH_SEL_EN1 = 0x1U, /*!< EN1 is selected for ENH. */ + MSC_ENH_SEL_EN2 = 0x2U, /*!< EN2 is selected for ENH. */ + MSC_ENH_SEL_EN3 = 0x3U /*!< EN3 is selected for ENH. */ +} MSC_ENHSelectionType; + +typedef enum +{ + MSC_ENL_SEL_EN0 = 0x0U, /*!< EN0 is selected for ENL. */ + MSC_ENL_SEL_EN1 = 0x1U, /*!< EN1 is selected for ENL. */ + MSC_ENL_SEL_EN2 = 0x2U, /*!< EN2 is selected for ENL. */ + MSC_ENL_SEL_EN3 = 0x3U /*!< EN3 is selected for ENL. */ +} MSC_ENLSelectionType; + +typedef enum +{ + MSC_EN_SELECTION_0 = 0x00, /*!< EN0 is selected for ENX. */ + MSC_EN_SELECTION_1 = 0x01, /*!< EN1 is selected for ENX. */ + MSC_EN_SELECTION_2 = 0x02, /*!< EN2 is selected for ENX. */ + MSC_EN_SELECTION_3 = 0x03, /*!< EN3 is selected for ENX. */ +} Msc_ENxActiveType; + +typedef enum +{ + MSC_ENC = 0x00, + MSC_ENL = 0x01, + MSC_ENH = 0x02, +} Msc_ENxType; + +typedef enum +{ + MSC_FLC_ACTIVE_ON_FRAMES = 0x0U, /*!< FCL is actived only during the active phases of frames. */ + MSC_FLC_ALWAYS_ACTIVE = 0x1U /*!< FCL is always active whether or not a downstream frame is transmitted currently.. */ +} MSC_FCLControlType; + +typedef enum +{ + MSC_INPUT_IDENTICAL = 0x0U, /*!< SDI and SI signal polarities are identical. */ + MSC_INPUT_INVERTED = 0x1U /*!< SDI and SI signal polarities are inverted. */ +} MSC_InputPolarityType; + +typedef enum +{ + MSC_ENX_IDENTICAL = 0x0U, /*!< Enx and ENL, ENH, ENC signal polarities are identical (high active). */ + MSC_ENX_INVERTED = 0x1U /*!< ENx and ENL, ENH, ENC signal polarities are inverted (low active). */ +} MSC_ENxPolarityType; + +typedef enum +{ + MSC_SO_IDENTICAL = 0x0U, /*!< SOP and SO signal polarity is identical. */ + MSC_SO_INVERTED = 0x1U /*!< SOP and SO signal polarity is inverted. */ +} MSC_SOPolarityType; + +typedef enum +{ + MSC_FLC_IDENTICAL = 0x0U, /*!< FCLP and FCL polarity is identical. */ + MSC_FLC_INVERTED = 0x1U /*!< FCLP and FCL polarity is inverted. */ +} MSC_FCLpolarityType; + +typedef struct +{ + MSC_SDISelectionType eSDIsel; /*!< SDI seletion. */ + MSC_ENCSelectionType eENCSel; /*!< ENC seletion. */ + MSC_ENHSelectionType eENHSel; /*!< ENH seletion. */ + MSC_ENLSelectionType eENLSel; /*!< ENL seletion. */ + MSC_FCLControlType eFclCtrl; /*!< FCL Control. */ + MSC_InputPolarityType eSDIPol; /*!< SDI Polarity. */ + MSC_ENxPolarityType eENXPol; /*!< ENX Polarity. */ + MSC_SOPolarityType eSOPPol; /*!< SO Polarity. */ + MSC_FCLpolarityType eFCLPPol; /*!< FCL Polarity. */ +} MSC_IOControlInitType; + +typedef enum +{ + MSC_TRANS_SOURCE_DATA_REG = 0x0U, /*!< SSL[x] is taken from TCDAR.DL[x]. */ + MSC_TRANS_SOURCE_ALTIN = 0x2U, /*!< SSL[x] is taken from the ALTINL input line x. */ + MSC_TRANS_SOURCE_ALTIN_INV = 0x3U, /*!< SSL[x] is taken from the ALTINL input line x in inverted state. */ +} MSC_TransSourceType; + +typedef enum +{ + MSC_TRIGGER_MODE = 0x00U, /*!< Trigger work mode. */ + MSC_REPETITION_MODE = 0x01U /*!< Repetition work mode. */ +} MSC_WorkModeType; + +typedef enum +{ + MSC_EVEN_PARITY = 0x00U, /*!< Reception even parity. */ + MSC_ODD_PARITY = 0x01U /*!< Reception odd parity. */ +} MSC_ParityType; + +typedef enum +{ + MSC_RECEIVE_DISABLED = 0x00U, /*!< Receiving channel is disabled. */ + MSC_BAUDRATE_FMSC_DIV4 = 0x01U, /*!< Baud rate=fmsc/4. */ + MSC_BAUDRATE_FMSC_DIV8 = 0x02U, /*!< Baud rate=fmsc/8. */ + MSC_BAUDRATE_FMSC_DIV16 = 0x03U, /*!< Baud rate=fmsc/16. */ + MSC_BAUDRATE_FMSC_DIV32 = 0x04U, /*!< Baud rate=fmsc/32. */ + MSC_BAUDRATE_FMSC_DIV64 = 0x05U, /*!< Baud rate=fmsc/64. */ + MSC_BAUDRATE_FMSC_DIV128 = 0x06U, /*!< Baud rate=fmsc/128. */ + MSC_BAUDRATE_FMSC_DIV256 = 0x07U /*!< Baud rate=fmsc/256. */ +} MSC_ReceiveBaudRateType; + +typedef enum +{ + MSC_FRAME_12_BIT = 0x00U, /*!< 12-bit frame selected. */ + MSC_FRAME_16_BIT = 0x01U /*!< 16-bit frame selected. */ +} MSC_ReceiveFrameType; + +typedef struct +{ + uint8_t u8PassiveLength; /*!< Frame Passive length. */ + uint8_t u8PTFNumber; /*!< The number of passive time frames that are inserted in repetition mode between two data frames. */ + MSC_WorkModeType eWorkMode; /*!< MSC work mode. */ + uint8_t u8CommandBitLength; /*!< Bit length of command frame. */ + bool bSelSRH; /*!< Select SRH. */ + uint8_t u8SRHDataBitLength; /*!< Bit length of SRH. */ + bool bSelSRL; /*!< Select SRL. */ + uint8_t u8SRLDataBitLength; /*!< Bit length of SRL. */ + bool bDelayControl; /*!< Hardware Receive Interrupt Delay Control. */ + MSC_ParityType eParity; /*!< Parity mode. */ + MSC_ReceiveBaudRateType eBaudRate; /*!< Baudrate. */ + MSC_ReceiveFrameType eRsvFrameType; /*!< Frame type. */ +} MSC_InitCfgType; + +/** + * @brief Init the MSC. + * + * @param eInstance MSCInstance. + * @param pInitConfig MSCInstance initial configuration. + */ +MSC_ReturnType MSC_init(const MSC_InstanceType eInstance, const MSC_InitCfgType *pInitConfig); + +/** + * @brief Init the MSC interrupt. + * + * @param eInstance MSCInstance. + * @param pInteruptConfig MSCInstance interrupt configuration. + */ +void MSC_initInterrupt(const MSC_InstanceType eInstance, const MSC_InterruptCfgType *pInteruptConfig); + +/** + * @brief Select the transmitting sources. + * + * @param eInstance MSCInstance. + * @param u32SourceMask Transmitting sources. + * @param eSourceType Transmitting sources type. + */ +void MSC_SelTranmittingSource(const MSC_InstanceType eInstance, uint32_t u32SourceMask, MSC_TransSourceType eSourceType); + +/** + * @brief Set Emergency load value. + * + * @param eInstance MSCInstance. + * @param u32Value Emergency load value. + */ +void MSC_SetEmergencyLoad(const MSC_InstanceType eInstance, uint32_t u32Value); + +/** + * @brief Configure the MSC IO control. + * + * @param eInstance MSCInstance. + * @param pIOConfig MSC IO control configuration. + */ +void MSC_SetIOControl(const MSC_InstanceType eInstance, const MSC_IOControlInitType *pIOConfig); + +/** + * @brief Enable MSC. + * + * @param eInstance MSCInstance. + */ +void MSC_Enable(const MSC_InstanceType eInstance); + +/** + * @brief Disable MSC. + * + * @param eInstance MSCInstance. + */ +void MSC_Disable(const MSC_InstanceType eInstance); + +/** + * @brief MSC set data frame. + * + * @param eInstance MSCInstance. + * @param u32Data Data to be sent. + */ +void MSC_SetDataFrame(const MSC_InstanceType eInstance, uint32_t u32Data); + +/** + * @brief MSC send data frame. + * + * @param eInstance MSCInstance. + */ +void MSC_SendDataFrame(const MSC_InstanceType eInstance); + +/** + * @brief MSC send command frame. + * + * @param eInstance MSCInstance. + * @param u32Command command to be sent. + */ +void MSC_SendCommandFrame(const MSC_InstanceType eInstance, uint32_t u32Command); + +/** + * @brief Get the msc received data address. + * + * @param eInstance MSCInstance. + * @param eIndex Receive data register index. + * @return uint8_t Receiverd data address. + */ +uint8_t MSC_GetReceivedFrameAddr(const MSC_InstanceType eInstance, MSC_RDRxIndexType eIndex); + +/** + * @brief Get the msc received data. + * + * @param eInstance MSCInstance. + * @param eIndex Receive data register index. + * @param pData Received data value. + * @return MSC_ReceiveStatusType Status of getting received data. + */ +MSC_ReceiveStatusType MSC_GetReceivedFrame(const MSC_InstanceType eInstance, MSC_RDRxIndexType eIndex, uint8_t *pData); + +/** + * @brief Get the msc interrupt status. + * + * @param eInstance MSCInstance. + * @return uint32_t Interrupt status. + */ +uint32_t MSC_GetInterruptStatus(const MSC_InstanceType eInstance); + +/** + * @brief Get the msc interrupt status. + * + * @param eInstance MSCInstance. + * @param bEnable Enable transmit channel. + */ +void MSC_EnableTrasmit(const MSC_InstanceType eInstance, bool bEnable); + +/** + * @brief Enable the msc data frame interrupt. + * + * @param eInstance MSCInstance. + */ +void MSC_EnableDataFrameInterrupt(const MSC_InstanceType eInstance, bool bEnable); + +/** + * @brief Enable the msc command frame interrupt. + * + * @param eInstance MSCInstance. + */ +void MSC_EnableCommandFrameInterrupt(const MSC_InstanceType eInstance, bool bEnable); + +/** + * @brief Enable the msc time frame interrupt. + * + * @param eInstance MSCInstance. + */ +void MSC_EnableTimeFrameInterrupt(const MSC_InstanceType eInstance, bool bEnable); + +/** + * @brief Enable the msc receive interrupt. + * + * @param eInstance MSCInstance. + */ +void MSC_EnableReceiveInterrupt(const MSC_InstanceType eInstance, bool bEnable); + +/** + * @brief Enable the msc timeout interrupt. + * + * @param eInstance MSCInstance. + */ +void MSC_EnableTimeoutInterrupt(const MSC_InstanceType eInstance, bool bEnable); + +/** + * @brief Switch ENC/ENH/ENL active EN selection. + * @param eInstance MSCInstance. + * @param eEnx ENC/ENH/ENL. + * @param eENn ENX selection. + * @param u32TimeoutLoops Wait timeout if transmission is busy. + * @return + */ +MSC_ReturnType Msc_SwitchENXChannel(const MSC_InstanceType eInstance, Msc_ENxType eEnx, Msc_ENxActiveType eENn, uint32_t u32TimeoutLoops); + +/** + * @brief Switch the SDI Channel. + * @param eInstance MSCInstance. + * @param eSDIChannel SDI channel. + * @param u32TimeoutLoops Wait timeout if receiving is busy. + * @return + */ +MSC_ReturnType Msc_SwitchSDIChannel(const MSC_InstanceType eInstance, MSC_SDISelectionType eSDIChannel, uint32_t u32TimeoutLoops); + +/** @}*/ /* fc7xxx_driver_msc. */ +#endif diff --git a/Inc/fc7xxx_driver_overlay.h b/Inc/fc7xxx_driver_overlay.h new file mode 100644 index 0000000..d6921f6 --- /dev/null +++ b/Inc/fc7xxx_driver_overlay.h @@ -0,0 +1,172 @@ +/** + * @file fc7xxx_driver_overlay.h + * @author Flagchip + * @brief FC7xxx overlay driver type definition and API + * @version 0.1.0 + * @date 2023-12-25 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ + +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2023-12-25 Flagchip0038 N/A First version for FC7240 +********************************************************************************/ + +#ifndef _DRIVER_FC7XXX_DRIVER_OVERLAY_H_ +#define _DRIVER_FC7XXX_DRIVER_OVERLAY_H_ +#include "HwA_overlay.h" + +/** + * @addtogroup fc7xxx_driver_overlay + * @{ + */ + + +/** + * @brief Overlay Error Information + * + */ +typedef enum +{ + OVERLAY_ERROR_OK, /**< no error */ + OVERLAY_ERROR_ADDR, /**< error address */ + OVERLAY_ERROR_SIZE, /**< error size */ + OVERLAY_ERROR_FLAG, /**< error flag */ +} OVERLAY_ErrorType; + + +/** + * @brief Overlay Region parameters + * + */ +typedef struct +{ + uint32_t aOverlayRegionEn[OVERLYA_REGION_CNT]; /**< Overlay region enable array */ + uint32_t aOverlayRegionSrc[OVERLYA_REGION_CNT]; /**< Overlay region source array, pflash */ + uint32_t aOverlayRegionDst[OVERLYA_REGION_CNT]; /**< Overlay region destination array, sram */ + OVERLAY_OverlaySizeType aOverlayRegionSize[OVERLYA_REGION_CNT]; /**< Overlay region size array */ +}OVERLAY_OverlayRegionInitType; + +/** + * @brief FAR parameter + * + */ +typedef struct +{ + uint32_t u32FAREn; /**< Overlay region enable array */ + uint32_t u32FARDst; /**< Overlay region destination array, pflash, source always is 0x08000000 */ + uint32_t u32FARSize; /**< Overlay region size array, must align to 64KB */ +}OVERLAY_FARInitType; + + +/** + * @brief Error Info + * + */ +typedef struct +{ + uint8_t bError_FAR_SIZE_INTR; /**< bit 17, The FAR of size value is invalid */ + uint8_t bError_FAR_DST_OVERFLOW_INTR; /**< bit 16, FAR of destination region is overflow with size */ + uint8_t bError_FAR_DST_NO_FLASH_INTR; /**< bit 15, FAR of destination address is not flash */ + uint8_t bError_REGION2_D_CROS_INTR; /**< bit 14, The range of region 2 destination address is crossed with other region */ + uint8_t bError_REGION2_S_CROS_INTR; /**< bit 13, The range of region 2 source address is crossed with other region */ + uint8_t bError_REGION2_SIZE_INTR; /**< bit 12, The region 2 of size value is invalid */ + uint8_t bError_REGION2_DST_INTR; /**< bit 11, The region 2 of destination address is not aligned with size */ + uint8_t bError_REGION2_SRC_INTR; /**< bit 10, The region 2 of source address is not aligned with size */ + uint8_t bError_REGION1_D_CROS_INTR; /**< bit 9, The range of region 1 destination address is crossed with other region */ + uint8_t bError_REGION1_S_CROS_INTR; /**< bit 8, The range of region 1 source address is crossed with other region */ + uint8_t bError_REGION1_SIZE_INTR; /**< bit 7, The region 1 of size value is invalid */ + uint8_t bError_REGION1_DST_INTR; /**< bit 6, The region 1 of destination address is not aligned with size */ + uint8_t bError_REGION1_SRC_INTR; /**< bit 5, The region 1 of source address is not aligned with size */ + uint8_t bError_REGION0_D_CROS_INTR; /**< bit 4, The range of region 0 destination address is crossed with other region */ + uint8_t bError_REGION0_S_CROS_INTR; /**< bit 3, The range of region 0 source address is crossed with other region */ + uint8_t bError_REGION0_SIZE_INTR; /**< bit 2, The region 0 of size value is invalid */ + uint8_t bError_REGION0_DST_INTR; /**< bit 1, The region 0 of destination address is not aligned with size */ + uint8_t bError_REGION0_SRC_INTR; /**< bit 0, The region 0 of source address is not aligned with size */ +}OVERLAY_ErrorInfoType; + + +/** Overlay Setting Error callback type */ +typedef void (*OVERLAY_ErrorCallback_Type)(OVERLAY_ErrorInfoType u16ErrorFlag); + + +/** + * @brief Interrupt Parameter + * + */ +typedef struct +{ + uint32_t bEnableInterrupt; /**< Enable interrupt, 0 is disable, 1 is enable */ + OVERLAY_ErrorCallback_Type pCallBack; /**< Callback function for error interrupt */ +}OVERLAY_InterruptType; + + +/** + * @brief Overlay region initial function + * + * @param pOverlayInitCfg initial parameters + * @return ERROR_OK is ok, others are not ok + */ +OVERLAY_ErrorType OVERLAY_RegionInit(OVERLAY_OverlayRegionInitType *pOverlayInitCfg); + +/** + * @brief De-Init Overlay Region + * + * @return ERROR_OK is ok, others are not ok + */ +OVERLAY_ErrorType OVERLAY_RegionDeInit(void); + +/** + * @brief Far initial function + * + * @param pFarInitCfg initial parameters + * @return ERROR_OK is ok, others are not ok + */ +OVERLAY_ErrorType OVERLAY_FARInit(OVERLAY_FARInitType *pFarInitCfg); + +/** + * @brief De-Init FAR Region + * + * @return ERROR_OK is ok, others are not ok + */ +OVERLAY_ErrorType OVERLAY_FARDeInit(void); + +/** + * @brief Enable or Disable Interrupt + * + * @param pInterruptCfg interrupt config parameter + */ +void OVERLAY_SetInterrupt(OVERLAY_InterruptType *pInterruptCfg); + +/** + * @brief Get Error Info + * + * @param pErrorInfo error info point + */ +void OVERLAY_GetErrorInfo(OVERLAY_ErrorInfoType *pErrorInfo); + +/** + * @brief Clear Error Info + * + * @param pErrorInfo error info point + */ +void OVERLAY_ClrErrorInfo(OVERLAY_ErrorInfoType *pErrorInfo); + +/** + * @brief Call Me in Overlay Error interrupt handler + * + */ +void OVERLAY_ErrorInterruptRoutine(void); + + +/** @}*/ /* fc7xxx_driver_overlay */ + + +#endif + + diff --git a/Inc/fc7xxx_driver_pcc.h b/Inc/fc7xxx_driver_pcc.h new file mode 100644 index 0000000..40aaf5f --- /dev/null +++ b/Inc/fc7xxx_driver_pcc.h @@ -0,0 +1,157 @@ +/** + * @file fc7xxx_driver_pcc.h + * @author Flagchip085 + * @brief FC7xxx PCC driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 + ******************************************************************************** */ +#ifndef _DRIVER_FC7XXX_DRIVER_PCC_H_ +#define _DRIVER_FC7XXX_DRIVER_PCC_H_ +#include "HwA_pcc.h" +/** + * @addtogroup fc7xxx_driver_pcc + * @{ + */ + + +#define PCC_MUX_MAX_NUMBER 8U + +/** @brief PCC clock list */ +typedef enum +{ + PCC_CLK_DMA0 = 0U, + PCC_CLK_DMAMUX0, + PCC_CLK_ROMC, + PCC_CLK_ERM0, + PCC_CLK_EIM0, + PCC_CLK_INTM0, + PCC_CLK_ISM0, + PCC_CLK_WDOG0, + PCC_CLK_TRGSEL0, + PCC_CLK_TRGSEL1, + PCC_CLK_TRGSEL2, + PCC_CLK_TRGSEL3, + PCC_CLK_CRC0, + PCC_CLK_CORDIC, + PCC_CLK_TSTMP0, + PCC_CLK_TSTMP1, + PCC_CLK_FCPIT0, + PCC_CLK_AONTIMER0, + PCC_CLK_RTC, + PCC_CLK_CMU0, + PCC_CLK_CMU1, + PCC_CLK_CMU2, + PCC_CLK_CMU3, + PCC_CLK_CMU4, + PCC_CLK_PTIMER0, + PCC_CLK_PTIMER1, + PCC_CLK_ADC0, + PCC_CLK_ADC1, + PCC_CLK_WKU0, + PCC_CLK_CMP0, + PCC_CLK_CMP1, + PCC_CLK_TMU0, + PCC_CLK_SENT0, + PCC_CLK_MB0, + PCC_CLK_FTU0, + PCC_CLK_FTU1, + PCC_CLK_FTU2, + PCC_CLK_FTU3, + PCC_CLK_FCSPI0, + PCC_CLK_FCSPI1, + PCC_CLK_FCSPI2, + PCC_CLK_FCIIC0, + PCC_CLK_FCUART0, + PCC_CLK_FCUART1, + PCC_CLK_FCUART2, + PCC_CLK_FCUART3, + PCC_CLK_LU0, + PCC_CLK_FREQM, + PCC_CLK_STCU, + PCC_CLK_FLEXCAN0, + PCC_CLK_FLEXCAN1, + PCC_CLK_WDOG1, + PCC_CLK_TRGSEL4, + PCC_CLK_TRGSEL5, + PCC_CLK_FCSPI3, + PCC_CLK_FCSPI4, + PCC_CLK_FCSPI5, + PCC_CLK_FTU4, + PCC_CLK_FTU5, + PCC_CLK_FTU6, + PCC_CLK_FTU7, + PCC_CLK_FCIIC1, + PCC_CLK_FCUART4, + PCC_CLK_FCUART5, + PCC_CLK_FCUART6, + PCC_CLK_FCUART7, + PCC_CLK_MSC0, + PCC_CLK_FLEXCAN2, + PCC_CLK_FLEXCAN3, + PCC_END_OF_CLOCKS +} PCC_ClkSrcType; + +/** + * @brief Pcc clock status +*/ +typedef enum +{ + PCC_STATUS_SUCCESS = 0U, + PCC_STATUS_CLOCK_INVALID = 1U, + PCC_STATUS_CONFIGURED_NOT_SUPPORT = 1U, +} PCC_StatusType; + +/** + * @brief define the PCC module initialization structure. + */ +typedef struct +{ + PCC_ClkSrcType eClockName; /*!< Peripheral clock */ + bool bEn; /*!< Peripheral clock enable or disable */ + PCC_ClkGateSrcType eClkSrc; /*!< Peripheral function clock source select */ + PCC_ClkDivType eDivider; /*!< Peripheral clock divider value */ +} PCC_CtrlType; + +/** + * @brief get PCC function clock status and value. + * + * @param pcc_ClkSrcType eClockName: used for choose PCC clock source to query. + * @return uint32_t Pcc function clock frequency, if PCC is not enable or do not have clock mux configuration, + * the function will return 0 + */ +uint32_t PCC_GetPccFunctionClock(const PCC_ClkSrcType eClockName); + +/** + * @brief get PCC interface clock status and value. + * + * @param pcc_ClkSrcType eClockName: used for choose PCC clock source to query. + */ +uint32_t PCC_GetPccInterfaceClock(const PCC_ClkSrcType eClockName); + +/** + * @brief set PCC one peripheral clock configuration. + * + * @param PCC_CtrlType* pConfig: the PCC initialize value point set by user. + * @return PCC_StatusType pcc function status + */ +PCC_StatusType PCC_SetPcc(const PCC_CtrlType *const pConfig); + +/** + * @brief Generate peripheral reset + * + */ +void PCC_GenPeripheralReset(const PCC_ClkSrcType eClockName); + + +/** @}*/ /* fc7xxx_driver_pcc */ +#endif diff --git a/Inc/fc7xxx_driver_pmc.h b/Inc/fc7xxx_driver_pmc.h new file mode 100644 index 0000000..57542e8 --- /dev/null +++ b/Inc/fc7xxx_driver_pmc.h @@ -0,0 +1,181 @@ +/* @file fc7xxx_driver_pmc.h +* @author Flagchip032 +* @brief FC7xxx PMC driver type definition and API +* @version 0.1.0 +* @date 2022-11-21 +* +* @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. +* +*/ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials Descriptions + * --------- ---------- ------------ --------------- + * 0.1.0 2022-11-21 Flagchip032 First version for FC7xxx + ******************************************************************************** */ +#ifndef _DRIVER_FC7XXX_DRIVER_PMC_H_ +#define _DRIVER_FC7XXX_DRIVER_PMC_H_ +#include "HwA_pmc.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** + * @addtogroup fc7xxx_driver_pmc + * @{ + */ + +/***************** typedef *********************/ +/** + * @brief PMC voltage flags. + * + */ +typedef enum +{ + PMC_HVD5V_FLAG = PMC_LVSCR_HVD5V_FLAG_MASK, /**< interrupt flag on V5 domain in FPM */ + PMC_HVD2P5V_FLAG = PMC_LVSCR_HVD2P5V_FLAG_MASK, /**< interrupt flag on V25 domain in FPM */ + PMC_HVD1P1V_FLAG = PMC_LVSCR_HVD1P1V_FLAG_MASK, /**< interrupt flag on V11 domain in FPM */ + PMC_LVD5V_FLAG = PMC_LVSCR_LVD5V_FLAG_MASK, /**< interrupt flag on V5 domain in FPM */ + PMC_LVD1P5V_FLAG = PMC_LVSCR_LVD1P5V_FLAG_MASK, /**< interrupt flag on V15 domain in FPM */ + PMC_HVD1P5V_FLAG = PMC_LVSCR_HVD1P5V_FLAG_MASK, /**< interrupt flag on V15 domain in FPM */ + PMC_LVR5V_FPM_FLAG = PMC_LVSCR_LVR5V_FPM_FLAG_MASK, /**< Low voltage reset flag of V5 domain in FPM */ + PMC_LVR5V_RPM_FLAG = PMC_LVSCR_LVR5V_RPM_FLAG_MASK, /**< Low voltage reset flag of V5 domain in RPM */ + PMC_LVR2P5V_FPM_FLAG = PMC_LVSCR_LVR2P5V_FPM_FLAG_MASK, /**< Low voltage reset flag of V25 domain in FPM */ + PMC_LVR2P5V_RPM_FLAG = PMC_LVSCR_LVR2P5V_RPM_FLAG_MASK, /**< Low voltage reset flag of V25 domain in RPM */ + PMC_LVR1P1V_FPM_FLAG = PMC_LVSCR_LVR1P1V_FPM_FLAG_MASK, /**< Low voltage reset flag of V11 domain in FPM */ + PMC_LVR1P1V_RPM_FLAG = PMC_LVSCR_LVR1P1V_RPM_FLAG_MASK, /**< Low voltage reset flag of V11 domain in RPM */ + PMC_POR_FLAG = PMC_LVSCR_POR_FLAG_MASK /**< POR flag */ +} PMC_FlagType; + +/** + * @brief PMC voltage status. + * + */ +typedef enum +{ + PMC_HVD5V_STATUS = PMC_LVSCR_HVD5V_STATUS_MASK, /**< HVD5V status on V5 domain in FPM */ + PMC_HVD2P5V_STATUS = PMC_LVSCR_HVD2P5V_STATUS_MASK, /**< HVD25 status on V25 domain in FPM */ + PMC_HVD1P1V_STATUS = PMC_LVSCR_HVD1P1V_STATUS_MASK, /**< HVD11 status on V11 domain in FPM */ + PMC_LVD5V_STATUS = PMC_LVSCR_LVD5V_STATUS_MASK, /**< LVD5V status on V5 domain in FPM */ + PMC_LVD1P5V_STATUS = PMC_LVSCR_LVD1P5V_STATUS_MASK, /**< LVD1P5V status on V15 domain in FPM */ + PMC_HVD1P5V_STATUS = PMC_LVSCR_HVD1P5V_STATUS_MASK, /**< HVD1P5V status on V15 domain in FPM */ + PMC_V15_LDO_STATUS = PMC_LVSCR_V15_STATUS(0U), /**< V15 is working on internal V15 LDO */ + PMC_V15_ON_BOARD_NPN_STATUS = PMC_LVSCR_V15_STATUS(1U), /**< V15 is working on internal V15 controller with on board NPN */ + PMC_V15_DRIVEN_BY_EXTERNAL_STATUS = PMC_LVSCR_V15_STATUS(2U) /**< V15 is driven by external driver such as on board DCDC, V15_CFG PAD is driven high */ +} PMC_StatusType; + +typedef void (*PMC_VolIntCallbackType)(void); + +/** @brief Pmc control type */ +typedef struct +{ + boolean bLvdIntEn; /**< bit9, low voltage detect interrupt enable */ + boolean bHvdIntEn; /**< bit8, high voltage detect interrupt enable */ + boolean b5VBMonEn; /**< bit6, VDD5V_B LVR monitor enable during RPM */ + boolean bV15CtrlEn; /**< bit5, V15 controller with on board NPN enable */ + boolean bV15AutoswEn; /**< bit4, V15 auto switch enable */ + boolean bRpmV25En; /**< bit3, V25 domain enable during RPM */ + PMC_VolIntCallbackType pIsrNotify; /**< interrupt notification */ +} PMC_CtrlType; + +/***************** macro *********************/ +/**< All flags of LVCSR MSASK */ +#define PMC_LVCSR_ALLFLAG_MASK (uint32_t)(PMC_LVSCR_HVD5V_FLAG_MASK|\ + PMC_LVSCR_HVD2P5V_FLAG_MASK|\ + PMC_LVSCR_HVD1P1V_FLAG_MASK|\ + PMC_LVSCR_LVD5V_FLAG_MASK|\ + PMC_LVSCR_LVD1P5V_FLAG_MASK|\ + PMC_LVSCR_HVD1P5V_FLAG_MASK|\ + PMC_LVSCR_LVR5V_FPM_FLAG_MASK|\ + PMC_LVSCR_LVR5V_RPM_FLAG_MASK|\ + PMC_LVSCR_LVR2P5V_FPM_FLAG_MASK|\ + PMC_LVSCR_LVR2P5V_RPM_FLAG_MASK|\ + PMC_LVSCR_LVR1P1V_FPM_FLAG_MASK|\ + PMC_LVSCR_LVR1P1V_RPM_FLAG_MASK|\ + PMC_LVSCR_POR_FLAG_MASK) + +#define PMC_LVCSR_ALLSTATUS_MASK (uint32_t)(PMC_LVSCR_HVD5V_STATUS_MASK|\ + PMC_LVSCR_HVD2P5V_STATUS_MASK|\ + PMC_LVSCR_HVD1P1V_STATUS_MASK|\ + PMC_LVSCR_LVD5V_STATUS_MASK|\ + PMC_LVSCR_LVD1P5V_STATUS_MASK|\ + PMC_LVSCR_HVD1P5V_STATUS_MASK|\ + PMC_LVSCR_V15_STATUS_MASK) + + + + + + +/***************** API *********************/ +/** + * @brief Get LVCSRRegister Value + * + * @return uint32_t LVCSRRegister Value + */ +uint32_t PMC_GetLVCSRRegister(void); +/** + * @brief Get All voltage flag + * + * @return uint32_t All voltage flag + */ +uint32_t PMC_GetAllVolFlag(void); + +/** + * @brief Get specific voltage flag + * + * @param eFlag Voltage flag + * @return boolean If return true, the specific voltage flag is 0, otherwise, the flag is 1. + */ +boolean PMC_GetSpecificVolFlag(const PMC_FlagType eFlag); + +/** + * @brief Clear all voltage flag + * + */ +void PMC_ClearAllVolFlag(void); + +/** + * @brief Clear specific voltage flag + * + * @param eFlag Voltage flag + */ +void PMC_ClearSpecificVolFlag(const PMC_FlagType eFlag); + +/** + * @brief Get All voltage status + * + * @return uint32_t All voltage status + */ +uint32_t PMC_GetAllVolStatus(void); + +/** + * @brief Get specific voltage status + * + * @param eStatus Specific voltage status + * @return boolean If return true, the specific voltage status is 0, otherwise, the status is 1. + */ +boolean PMC_GetSpecificVolStatus(const PMC_StatusType eStatus); + +/** + * @brief Configure Voltage + * + * @param pCtrl Configuration of voltage + */ +void PMC_ConfigVoltage(const PMC_CtrlType *const pCtrl); + +/** + * @brief Clear all PMC register + * + */ +void PMC_Deinit(void); + + +#if defined(__cplusplus) +} +#endif +/** @}*/ /* fc7xxx_driver_pmc */ +#endif diff --git a/Inc/fc7xxx_driver_port.h b/Inc/fc7xxx_driver_port.h new file mode 100644 index 0000000..d384331 --- /dev/null +++ b/Inc/fc7xxx_driver_port.h @@ -0,0 +1,239 @@ +/** + * @file fc7xxx_driver_port.h + * @author Flagchip + * @brief FC7xxx PORT driver type definition and API + * @version 0.1.0 + * @date 2023-2-14 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2022/12/31 Flagchip0121 N/A First version for FC7240 +********************************************************************************/ +#ifndef _DRIVER_FC7XXX_DRIVER_PORT_H_ +#define _DRIVER_FC7XXX_DRIVER_PORT_H_ +#include "HwA_port.h" +#include +/** + * @addtogroup fc7xxx_driver_port + * @{ + */ + +/********* global define ************/ +/** @brief Max number of Port */ +#define MAX_PORT_NUM 5U + +/** @brief Max number of Port Pin */ +#define PORT_PIN_NUM_MAX (uint32_t)(MAX_PORT_NUM*PORT_PCR_COUNT) + +/** @brief number of Port Pin */ +#define PORT_PIN_NUM(port,pin) (((uint32_t)(port) << 5U)+(uint32_t)(pin)) + +#define PORT_PIN_0 ((uint32_t)0x00000001) /**< PORT Pin 0 select */ +#define PORT_PIN_1 ((uint32_t)0x00000002) /**< PORT Pin 1 select */ +#define PORT_PIN_2 ((uint32_t)0x00000004) /**< PORT Pin 2 select */ +#define PORT_PIN_3 ((uint32_t)0x00000008) /**< PORT Pin 3 select */ +#define PORT_PIN_4 ((uint32_t)0x00000010) /**< PORT Pin 4 select */ +#define PORT_PIN_5 ((uint32_t)0x00000020) /**< PORT Pin 5 select */ +#define PORT_PIN_6 ((uint32_t)0x00000040) /**< PORT Pin 6 select */ +#define PORT_PIN_7 ((uint32_t)0x00000080) /**< PORT Pin 7 select */ +#define PORT_PIN_8 ((uint32_t)0x00000100) /**< PORT Pin 8 select */ +#define PORT_PIN_9 ((uint32_t)0x00000200) /**< PORT Pin 9 select */ +#define PORT_PIN_10 ((uint32_t)0x00000400) /**< PORT Pin 10 select */ +#define PORT_PIN_11 ((uint32_t)0x00000800) /**< PORT Pin 11 select */ +#define PORT_PIN_12 ((uint32_t)0x00001000) /**< PORT Pin 12 select */ +#define PORT_PIN_13 ((uint32_t)0x00002000) /**< PORT Pin 13 select */ +#define PORT_PIN_14 ((uint32_t)0x00004000) /**< PORT Pin 14 select */ +#define PORT_PIN_15 ((uint32_t)0x00008000) /**< PORT Pin 15 select */ +#define PORT_PIN_16 ((uint32_t)0x00010000) /**< PORT Pin 16 select */ +#define PORT_PIN_17 ((uint32_t)0x00020000) /**< PORT Pin 17 select */ +#define PORT_PIN_18 ((uint32_t)0x00040000) /**< PORT Pin 18 select */ +#define PORT_PIN_19 ((uint32_t)0x00080000) /**< PORT Pin 19 select */ +#define PORT_PIN_20 ((uint32_t)0x00100000) /**< PORT Pin 20 select */ +#define PORT_PIN_21 ((uint32_t)0x00200000) /**< PORT Pin 21 select */ +#define PORT_PIN_22 ((uint32_t)0x00400000) /**< PORT Pin 22 select */ +#define PORT_PIN_23 ((uint32_t)0x00800000) /**< PORT Pin 23 select */ +#define PORT_PIN_24 ((uint32_t)0x01000000) /**< PORT Pin 24 select */ +#define PORT_PIN_25 ((uint32_t)0x02000000) /**< PORT Pin 25 select */ +#define PORT_PIN_26 ((uint32_t)0x04000000) /**< PORT Pin 26 select */ +#define PORT_PIN_27 ((uint32_t)0x08000000) /**< PORT Pin 27 select */ +#define PORT_PIN_28 ((uint32_t)0x10000000) /**< PORT Pin 28 select */ +#define PORT_PIN_29 ((uint32_t)0x20000000) /**< PORT Pin 29 select */ +#define PORT_PIN_30 ((uint32_t)0x40000000) /**< PORT Pin 30 select */ +#define PORT_PIN_31 ((uint32_t)0x80000000) /**< PORT Pin 31 select */ + +#define PORT_DWP_CPU0_ALLOWED ((uint32_t)0x00000001) /**< Only CPU0 is allowed to write PCR and GPIO register corresponding to this pin. */ +#define PORT_DWP_DMA0_ALLOWED ((uint32_t)0x00000008) /**< Only DMA0 is allowed to write PCR and GPIO register corresponding to this pin. */ +#define PORT_DWP_FlexCore_ALLOWED ((uint32_t)0x00000010) /**< Only DMA1 is allowed to write PCR and GPIO register corresponding to this pin. */ + +/** @brief Port Alternate 0 Mode */ +#define PORT_ALT0_FUNC_MODE ((Port_PinModeType)0) +/** @brief Port GPIO Mode */ +#define PORT_GPIO_MODE ((Port_PinModeType)1) +/** @brief Port Alternate 2 Mode */ +#define PORT_ALT2_FUNC_MODE ((Port_PinModeType)2) +/** @brief Port Alternate 3 Mode */ +#define PORT_ALT3_FUNC_MODE ((Port_PinModeType)3) +/** @brief Port Alternate 4 Mode */ +#define PORT_ALT4_FUNC_MODE ((Port_PinModeType)4) +/** @brief Port Alternate 5 Mode */ +#define PORT_ALT5_FUNC_MODE ((Port_PinModeType)5) +/** @brief Port Alternate 6 Mode */ +#define PORT_ALT6_FUNC_MODE ((Port_PinModeType)6) +/** @brief Port Alternate 7 Mode */ +#define PORT_ALT7_FUNC_MODE ((Port_PinModeType)7) + + +/********* global typedef ************/ +/** @brief Port return structure */ +typedef enum +{ + PORT_STATUS_SUCCESS = 0U, + PORT_STATUS_PARAM_INVALID = 1U +} PORT_StatusType; + +/** @brief Port instance number */ +typedef enum +{ + PORT_A = 0U, + PORT_B, + PORT_C, + PORT_D, + PORT_E +} PORT_InstanceType; + +typedef enum +{ + PORT_TRIGGER_DISABLE = 0U, + PORT_TRIGGER_INPUT_CONSISTENT_WITH_PAD = 1U, + PORT_TRIGGER_INPUT_OPPOSITE_WITH_PAD = 2U +} PORT_TriggerInputType; + +/** @brief Port interrupt notification type */ +typedef void (*PORT_PinInterruptCallBackType)(void); + +/** @brief Port initialization structure */ +typedef struct +{ + uint32_t u32PortPins; /**< Port pin, 0~31 bit indicates the pin 0~31 */ + Port_PinMuxType uPortPinMux; /**< Port pin mode */ + PORT_TriggerInputType eTriggrtMode; /**< Port trigger mode */ + bool bPullEn; /**< whether to pull the port pin */ + PORT_PullStatusType ePullSel; /**< pull status, pull up or pull down */ + bool bDrvStrength0En; /**< whether to enable pad drive strength 0 , only hs PAD used */ + bool bDrvStrength1En; /**< whether to enable pad drive strength 1, only uhs PAD used */ + bool u8PassiveFilterEn; /**< whether to use passive filter, please refer to reference manual for details */ +} PORT_InitType; + +/** @brief Port interrupt configuration structure */ +typedef struct +{ + uint32_t u32PortPins; /**< Port pin, 0~31 bit indicates the pin 0~31 */ + PORT_IntConfigType ePortIsrMode; /**< Port interrupt mode */ + PORT_PinInterruptCallBackType pIsrNotify; /**< Port interrupt notification pointer */ +} PORT_InterruptType; + +/** @brief Port digital filter configuration structure */ +typedef struct +{ + uint32_t u32PortPinsEn; /**< Port pin, 0~31 bit indicates the pin 0~31 */ + PORT_DigitalFilterClkSrcType eClkSrc; /**< Port clock source */ + uint8_t u8FilterLength; /**< digital filter length, the range is :0~31 */ +} PORT_DigitalFilterType; + + +/********* global API ************/ +/** + * @brief Initialize port pins + * + * @param ePort Port instance + * @param pInitStruct Initialization structure of port + * @return Port return type. + */ +PORT_StatusType PORT_InitPins(const PORT_InstanceType ePort, const PORT_InitType *const pInitStruct); + +/** + * @brief De-initialize the Port instance + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + * @return Port return type. + */ +PORT_StatusType PORT_Deinit(const PORT_InstanceType ePort, const uint32_t u32Pins); + +/** + * @brief Enable interrupt function of port + * + * @param ePort Port instance enumeration + * @param pIntStruct Interrupt structure of port. + * @return Port return type. + */ +PORT_StatusType PORT_InitInterrupt(const PORT_InstanceType ePort, const PORT_InterruptType *const pIntStruct); + +/** + * @brief Enable interrupt function of port + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + * @return Port return type. + */ +PORT_StatusType PORT_EnableInterrupt(const PORT_InstanceType ePort, const uint32_t u32Pins); + +/** + * @brief Disable interrupt function of port + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + * @return Port return type. + */ +PORT_StatusType PORT_DisableInterrupt(const PORT_InstanceType ePort, const uint32_t u32Pins); + +PORT_StatusType PORT_SetPinsDmaReqMode(const PORT_InstanceType ePort, const uint32_t u32Pins, const PORT_DMAReqType eDMAReqMode); +/** + * @brief Initialize digital filter for Port instance + * + * @param ePort Port instance enumeration + * @param pDFStruct Digital filter initialization structure of port + * @return Port return type. + */ +PORT_StatusType PORT_InitDigitalFilterPort(const PORT_InstanceType ePort, + const PORT_DigitalFilterType *pDFStruct); + +/** + * @brief De-initialize digital filter for Port instance + * + * @param ePort Port instance enumeration + * @return Port return type. + */ +PORT_StatusType PORT_DeinitDigitalFilterPort(const PORT_InstanceType ePort); + +/** + * @brief Enable the digital filter function for the specific pin. + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + * @return Port return type. + */ +PORT_StatusType PORT_EnableDigitalFilterPin(const PORT_InstanceType ePort, const uint32_t u32Pins); + +/** + * @brief Disable the digital filter function for the specific pin. + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + * @return Port return type. + */ +PORT_StatusType PORT_DisableDigitalFilterPin(const PORT_InstanceType ePort, const uint32_t u32Pins); + + + +/** @}*/ /* fc7xxx_driver_port */ + +#endif + diff --git a/Inc/fc7xxx_driver_ptimer.h b/Inc/fc7xxx_driver_ptimer.h new file mode 100644 index 0000000..5196609 --- /dev/null +++ b/Inc/fc7xxx_driver_ptimer.h @@ -0,0 +1,226 @@ +/** + * @file fc7xxx_driver_ptimer.h + * @author Flagchip0126 + * @brief FC7xxx PTIMER driver type definition and API + * @version 0.1.0 + * @date 2024-01-15 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-15 Flagchip0126 N/A First version for FC7240 + ******************************************************************************** */ + +#ifndef _DRIVER_FC7XXX_DRIVER_PTIMER_H_ +#define _DRIVER_FC7XXX_DRIVER_PTIMER_H_ +#include "device_header.h" +#include "HwA_ptimer.h" +#include "HwA_scm.h" + +#if defined(__cplusplus) +extern "C" { +#endif +/** + * @addtogroup fc7xxx_driver_ptimer + * @{ + */ + +/** + * @brief PTIMER interrupt callback function prototype + * + */ +typedef void (*PTIMER_InterruptCallbackType)(void); + +/** + * @brief PTIMER sequence error callback function prototype + * + */ +typedef void (*PTIMER_SeqErrorCallbackType)(uint8_t u8Channel); + +/** + * @brief The instance index of the PTIMER peripheral + * + */ +typedef enum +{ + PTIMER_INSTANCE_0 = 0U, + PTIMER_INSTANCE_1 = 1U +} PTIMER_InstanceType; + +/** + * @brief Ptimer instance initialization parameters + * + */ +typedef struct +{ + PTIMER_LoadValueModeType eLoadValueMode; /*!< Select the load mode */ + PTIMER_ClockPreDividerType eClkPreDiv; /*!< Select the prescaler divider */ + PTIMER_ClockPreDivMultiplyFactorType eClkPreMultFactor; /*!< Select multiplication factor for prescaler */ + PTIMER_TrgSrcType eTriggerInput; /*!< Select the trigger input source */ + bool bContinuousModeEnable; /*!< Enable the continuous mode */ + bool bDmaEnable; /*!< Enable the dma for timer */ +} PTIMER_InitType; + +/** + * @brief Ptimer interrupt configuration parameters + * + */ +typedef struct +{ + bool bDelayIntEnable; /*!< Enable the interrupt for timer */ + uint32_t u32IntDelayPeriodUs; /*!< The period in micro second */ + PTIMER_InterruptCallbackType pIntNotify; /*!< Ptimer interrupt callback function pointer */ + bool bSeqErrIntEnable; /*!< Enable PTIMER Sequence Error Interrupt */ + PTIMER_SeqErrorCallbackType pSeqErrorNotify; /*!< Ptimer sequence error callback function pointer */ +} PTIMER_InterruptType; + +/** + * @brief Ptimer channel configuration parameters + * + */ +typedef struct +{ + uint32_t u32DelayUs; /*!< Setting pre_trigger's delay in microsecond. */ + bool bPreTriggerEnable; /*!< Enable the pre_trigger. */ + bool bPreTriggerOutputEnable; /*!< Enable the pre_trigger output. */ + bool bPreTriggerBackToBackEnable; /*!< Enable the back to back mode for ADC pre_trigger. */ +} PTIMER_ChannelCfgType; + +/** + * @brief Ptimer pulse out configgurations + * + * When the Ptimer counter time reaches u32PulseOutDlyHighUs, the pulse-out goes high; + * When the Ptimer counter time reaches u32PulseOutDlyLowUs, the pulse-out goes low. + * + */ +typedef struct +{ + uint32_t u32PulseOutDlyHighUs; /*!< Microsecond delay for pulse out to output high */ + uint32_t u32PulseOutDlyLowUs; /*!< Microsecond delay for pulse out to output low */ +} PTIMER_PulseOutType; + +/** + * @brief Initialize the Ptimer instance + * + * @param eInstance the Ptimer instance to use + * @param pInitCfg the Ptimer initialization parameters + */ +void PTIMER_Init(const PTIMER_InstanceType eInstance, const PTIMER_InitType *const pInitCfg); + +/** + * @brief De-initialize the Ptimer instance + * Disable the Ptimer instance and reset the configurations to its reset values + * + * @param eInstance the Ptimer instance to use + */ +void PTIMER_DeInit(const PTIMER_InstanceType eInstance); + +/** + * @brief Initialize the Ptimer interrupt + * + * @note the interrupt delay value is buffered and will take effect only after called PTIMER_LoadValue() + * function. + * + * @param eInstance the Ptimer instance to configure + * @param pInterruptCfg the Ptimer initialization parameters + */ +void PTIMER_InitInterrupt(const PTIMER_InstanceType eInstance, + const PTIMER_InterruptType *const pInterruptCfg); + +/** + * @brief Initialize the Ptimer channels + * + * @note the channel delay value is buffered and will take effect only after called PTIMER_LoadValue() + * function. + * + * @param eInstance the Ptimer instance to use + * @param aChannelCfg the array of channels to config + * @param u8ChnNum the channel numbers in the channel array + */ +void PTIMER_InitChannel(const PTIMER_InstanceType eInstance, + const PTIMER_ChannelCfgType aChannelCfg[], const uint8_t u8ChnNum); + +/** + * @brief Set the Ptimer max counter period in microsecond + * When the Ptimer counter reaches the period, it will return to zero + * + * @note the period parameter is buffered and will take effect only after called PTIMER_LoadValue() + * function. + * + * @param eInstance the Ptimer instance to use + * @param u32PeriodUs the max counter period in microsecond + */ +void PTIMER_SetPeriod(const PTIMER_InstanceType eInstance, uint32_t u32PeriodUs); + +/** + * @brief Set the Ptimer pulse-out function + * + * @note the pulse-out delay values are buffered and will take effect only after called PTIMER_LoadValue() + * function. + * + * @param eInstance the Ptimer instance to use + * @param pPulseOutCfg the pulse-out configuration + */ +void PTIMER_SetPulseOut(const PTIMER_InstanceType eInstance, const PTIMER_PulseOutType *pPulseOutCfg); + +/** + * @brief Load the buffered values into register + * + * Some Ptimer registers are buffered and will only take effect after called + * this function + * + * @param eInstance the Ptimer instance to use + */ +void PTIMER_LoadValue(const PTIMER_InstanceType eInstance); + +/** + * @brief Enable the Ptimer instance + * + * @param eInstance the Ptimer instance to use + */ +void PTIMER_Enable(const PTIMER_InstanceType eInstance); + +/** + * @brief Disable the Ptimer instance + * + * @param eInstance the Ptimer instance to use + */ +void PTIMER_Disable(const PTIMER_InstanceType eInstance); + +/** + * @brief Enable the Ptimer pulse-out function + * + * @param eInstance the Ptimer instance to use + */ +void PTIMER_EnablePulseOut(const PTIMER_InstanceType eInstance); + +/** + * @brief Disable the Ptimer pulse-out function + * + * @param eInstance the Ptimer instance to use + */ +void PTIMER_DisablePulseOut(const PTIMER_InstanceType eInstance); + +void PTIMER_SelectInstance01BackToBackMode(SCM_PTimerLMSelType ePTimerLoopMode); + +/** + * @brief Generate the software trigger signal for the Ptimer instance + * + * If the Ptimer trigger source is selected as PTIMER_TRGSRC_SW, call this function + * will make the Ptimer instance to start. + * + * @param eInstance the Ptimer instance to use + */ +void PTIMER_GenerateSWTrigger(const PTIMER_InstanceType eInstance); + +/** @}*/ /* fc7xxx_driver_ptimer */ + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/Inc/fc7xxx_driver_rgm.h b/Inc/fc7xxx_driver_rgm.h new file mode 100644 index 0000000..166438b --- /dev/null +++ b/Inc/fc7xxx_driver_rgm.h @@ -0,0 +1,182 @@ +/** + * @file fc7xxx_driver_rgm.h + * @author Flagchip + * @brief FC7xxx RGM driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-12 Flagchip119 N/A First version for FC7240 +********************************************************************************/ +#ifndef _DRIVER_FC7XXX_DRIVER_RCM_H_ +#define _DRIVER_FC7XXX_DRIVER_RCM_H_ + +#include "HwA_rgm.h" + +/** + * @addtogroup fc7xxx_driver_rcgm + * @{ + */ + +/** @brief Get which core currently belongs to. */ +#define GET_CORE_NUM (*(uint32_t *)0xE0080004) + +/** @brief Rgm return type. */ +typedef enum +{ + RGM_STATUS_SUCCESS = 0U, + RGM_STATUS_PARAM_INVALID = 1U, + RGM_STATUS_COREID_INVALID = 2U +} RGM_StatusType; + +/** @brief Rgm reset pin filter clock type. */ +typedef enum +{ + RGM_RESET_FILTER_BUS_CLOCK = 0U, + RGM_RESET_FILTER_AON32K_CLOCK = 1U +} RGM_FilterClkSrc; + +/** @brief Rgm interrupt notification type */ +typedef void (*RGM_InterruptCallBackType)(uint32_t u32SRS); + +/** + * @brief This api can get RGM_SRS register that indicate the source of the most recent reset. + * + * @return RGM->RGM_SRS register, bit 0-15,29-31 corresponding to RGM_ResetEventType, refer to reference manual for details. + * @note Multiple flags can be set if multiple reset events occur at the same time + */ +uint32_t RGM_GetLastResetFLag(void); + +/** + * @brief This api can get RGM_SSRS register that indicate all reset sources since the last POR or LVD that have not been cleared by software. + * + * @returnRGM->RGM_SSRS register, bit 0-15,29-31 corresponding to RGM_ResetEventType, refer to reference manual for details. + */ +uint32_t RGM_GetAllResetFlag(void); + +/** + * @brief This api can clear reset flag of RGM_SSRS register which indicate all reset sources since the last POR or LVD that have not been cleared by software. + * + * @param eReset Enumeration of reset event flag + */ +void RGM_ClearResetFlagAfterPOR(const RGM_ResetEventType eReset); + +/** + * @brief This api can clear all reset flag of RGM_SSRS register which indicate all reset sources since the last POR or LVD that have not been cleared by software. + * + */ +void RGM_ClearAllResetFlagAfterPOR(void); + +/** + * @brief Enable reset pin filter + * + * @param eClk Reset pin filter clock source + * @param u8BusClockFilterWidth Bus clock filter width + * @param bLpClkEn select whether enable reset pin filter using AON32clock in low power mode + * @return RGM return type + * @note If use AON32K clock, A reset signal whose length is less than 2 AON32K clock periods will be filtered + */ +RGM_StatusType RGM_EnableResetFilter(RGM_FilterClkSrc eClk, uint8_t u8BusClockFilterWidth, bool bLpClkEn); + +/** + * @brief Disable reset pin filter + * + * @param eClk Reset pin filter clock source + * @param bLpClkEn select whether disable reset pin filter using AON32clock in low power mode + * @return RGM return type + */ +RGM_StatusType RGM_DisableResetFilter(RGM_FilterClkSrc eClk, bool bLpClkEn); + +/** + * @brief This api can enable interrupt before an system reset appear. + * + * @param eDelay Enumeration of delay cycles + * @param eResetInterrupt Reset event flag, like: RGM_INT_CLKERR0 | RGM_INT_FCSMU + * @return RGM return type + */ +RGM_StatusType RGM_EnableSystemResetInt(RGM_ResetDelayType eDelay, RGM_ResetIntMangerType eResetInterrupt); + +/** + * @brief This api can disable interrupt before an system reset appear. + * + * @param eResetInterrupt Reset event flag, like: RGM_INT_CLKERR0 | RGM_INT_FCSMU + * @param bClearDelay Whether to clear delay configuration + * @return RGM return type + */ +RGM_StatusType RGM_DisableSystemResetInt(RGM_ResetIntMangerType eResetInterrupt, bool bClearDelay); + +/** + * @brief Generate software reset through cotex-m register + * + */ +void RGM_GenerateSwReset(void); + +/** + * @brief This api can enable interrupt before an CPU0 core related reset appear. + * + * @param eCPU0Interrupt Reset event flag, like: RGM_CPU_INT_SWRST | RGM_CPU_INT_SYSRST + * @param pIsrNotify Interrupt function + * @return RGM return type + */ +RGM_StatusType RGM_EnableCPU0CoreResetInt(RGM_CPUIntMangerType eCPU0Interrupt,RGM_InterruptCallBackType pIsrNotify); + +/** + * @brief This api can disable interrupt before an CPU0 core related reset appear. + * + * @param eCPU0Interrupt Reset event flag, like: RGM_CPU_INT_SWRST | RGM_CPU_INT_SYSRST + * @return RGM return type + */ +RGM_StatusType RGM_DisableCPU0CoreResetInt(RGM_CPUIntMangerType eCPU0Interrupt); + +/** + * @brief Get the CPU0 exit reset flag + * + * @return RGM_CPU_OUT_RST_UNDER CPU0 is under reset + * @return RGM_CPU_OUT_RST_OUT CPU0 is out of reset + */ +RGM_CPUOutResetType RGM_GetCPU0OutResetFlag(void); + +/** + * @brief Generate a CPU0 software reset. + * + */ +void RGM_GenerateCPU0SwReset(void); + +/** + * @brief This api can get RGM_C0_SRS register that indicate the source of the most recent CPU0 reset. + * + * @return RGM->RGM_C0_SRS register, bit 0-20 corresponding to RGM_ResetEventType, refer to reference manual for details. + * @note Multiple flags can be set if multiple reset events occur at the same time + */ +uint32_t RGM_GetCPU0LastResetFLag(void); + +/** + * @brief This api can get RGM_C0_SSRS register that indicate all CPU0 reset sources since the last POR or LVD that have not been cleared by software. + * + * @returnRGM->RGM_C0_SSRS register, bit 0-20,29-31 corresponding to RGM_CPUResetEventType, refer to reference manual for details. + */ +uint32_t RGM_GetCPU0AllResetFlag(void); + +/** + * @brief This api can clear reset flag of RGM_C0_SSRS register which indicate CPU0 all reset sources since the last POR or LVD that have not been cleared by software. + * + * @param eReset Enumeration of reset event flag + */ +void RGM_ClearCPU0ResetFlagAfterPOR(const RGM_CPUResetEventType eReset); + +/** + * @brief This api can clear all reset flag of RGM_C0_SSRS register which indicate CPU0 all reset sources since the last POR or LVD that have not been cleared by software. + * + */ +void RGM_ClearCPU0AllResetFlagAfterPOR(void); + +/** @}*/ /* fc7xxx_driver_rgm */ +#endif /* end of _DRIVER_FC7XXX_DRIVER_RGM_H_ */ diff --git a/Inc/fc7xxx_driver_rtc.h b/Inc/fc7xxx_driver_rtc.h new file mode 100644 index 0000000..599a6f8 --- /dev/null +++ b/Inc/fc7xxx_driver_rtc.h @@ -0,0 +1,152 @@ +/** + * @file fc7xxx_driver_rtc.h + * @author Flagchip + * @brief FC7xxx rtc driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-10 Flagchip0076 N/A First version for FC7240 +********************************************************************************/ + + +#ifndef DRIVER_INCLUDE_FC7XXX_DRIVER_RTC_H_ +#define DRIVER_INCLUDE_FC7XXX_DRIVER_RTC_H_ + +#include"HwA_rtc.h" + + +/** + * @addtogroup fc7xxx_driver_rtc + * @{ + */ + +/** @brief Rtc return type. */ +typedef enum +{ + RTC_STATUS_SUCCESS = 0U, /**< rtc status is success */ + RTC_STATUS_PARAM_INVALID = 1U, /**< rtc status is failed because the param is invalid */ + RTC_STATUS_FUNCTION_ERROR = 2U, /**< rtc status is failed because the function is error */ + RTC_STATUS_CLOCK_INVALID = 3U /**< rtc status is failed because the clock is invalid */ +} RTC_StatusType; + +/** @brief Rtc mode */ +typedef enum +{ + RTC_ALARM_INT = 0U, /**< rtc interrupt mode is alarm */ + RTC_SECOND_INT = 1U, /**< rtc interrupt mode is second */ + RTC_OVERFLOW_INT = 2U /**< rtc interrupt mode is overflow */ +} RTC_IntEventType; + +/** @brief Rtc interrupt notification type */ +typedef void (*RTC_InterruptCallBackType)(void); + +/** @brief Rtc interrupt configuration type */ +typedef struct +{ + bool bAlarmIntEn; /**< whether enable rtc alarm interrupt */ + RTC_InterruptCallBackType pIsrAlarmNotify; /**< rtc alarm notification function pointer */ + bool bSecondIntEn; /**< whether to use the second interrupt */ + RTC_InterruptCallBackType pIsrSecondNotify; /**< second interrupt notification function pointer */ + bool bOverflowIntEn ; /**< overflow interrupt notification function pointer */ + RTC_InterruptCallBackType pIsrOverflowNotify; /**< overflow interrupt notification function pointer */ +} RTC_InterruptType; + +/** @brief Rtc initialization type */ +typedef struct +{ + uint32_t u32AlarmValue; /**< rtc alarm value */ + RTC_ClkoutSecIntFreqType eSecIntAndClkoutFreq; /**< Select the RTC Seconds interrupt and the RTC_CLKOUT prescaler output frequency */ + bool bStableClkoutFreq; /**< Select the RTC Seconds interrupt and the RTC_CLKOUT prescaler output frequency or RTC_CLKOUT is from the 32.768 kHz clock. */ +} RTC_InitType; + +/* global functions */ +/** + * @brief Initialize Rtc instance + * @param pInitStruct Rtc initialization structure + */ +void RTC_Init(const RTC_InitType *const pInitStruct); + +/** + * @brief Rtc set interrupt + * + * @param pIntStruct interrupt structure pointer + * @return Rtc return type + * @note this function will stop Rtc timer + */ +RTC_StatusType RTC_InitInterrupt(const RTC_InterruptType *const pIntStruct); + +/** + * @brief De-initialize Rtc instance + * + */ +void RTC_Deinit(void); + +/** + * @brief Rtc enable interrupt + * + * @param bAlarmIntEn whether enable alarm interrupt + * @param bSecondIntEn whether enable second interrupt + */ +void RTC_EnableInterrupt(const bool bAlarmIntEn, const bool bSecondIntEn, const bool bOverflowIntEn); + +/** + * @brief Rtc disable interrupt + * + * @param bAlarmIntEn whether disable alarm interrupt + * @param bSecondIntEn whether disable second interrupt + */ +void RTC_DisableInterrupt(const bool bAlarmIntEn, const bool bSecondIntEn, const bool boverflowIntEn); + +/** + * @brief Rtc start + * + */ +void RTC_Start(void); + +/** + * @brief Rtc stop + * + */ +void RTC_Stop(void); + +/** + * @brief Rtc alarm value + * + * @param u32AlarmValue Input value + */ +void RTC_UpdateAlarmValue(const uint32_t u32AlarmValue); + +/** + * @brief Get Rtc counter value + * + * @return Rtc counter value + */ +uint32_t RTC_GetTime(void); + +/** + * @brief Check RTC overflow flag + * + * @return Overflow flag + */ +bool RTC_CheckOverflowFlag(void); + + +/** + * @brief Set second counter value + * @param u32Value the second value. + * */ + +void RTC_SetSecondCounterValue(uint32_t u32Value); + + +/** @}*/ /* fc7xxx_driver_rtc */ +#endif /* DRIVER_INCLUDE_FC7XXX_DRIVER_RTC_H_ */ diff --git a/Inc/fc7xxx_driver_scg.h b/Inc/fc7xxx_driver_scg.h new file mode 100644 index 0000000..64bd5a1 --- /dev/null +++ b/Inc/fc7xxx_driver_scg.h @@ -0,0 +1,459 @@ +/** + * @file fc7xxx_driver_scg.h + * @author Flagchip085 + * @brief FC7xxx SCG driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 + ******************************************************************************** */ +#ifndef _DRIVER_FC7XXX_DRIVER_SCG_H_ +#define _DRIVER_FC7XXX_DRIVER_SCG_H_ +#include "HwA_scg.h" +#include "HwA_csc.h" +/** + * @addtogroup fc7xxx_driver_scg + * @{ + */ + +/** @brief clock list for internal clock tree */ +typedef enum +{ + /* Main clocks */ + SCG_CORE_CLK = 0U, /*!< Core clock */ + SCG_BUS_CLK = 1U, /*!< Bus clock */ + SCG_SLOW_CLK = 2U, /*!< Slow clock */ + + /* Other internal clocks used by peripherals. */ + SCG_FOSC_CLK = 3U, /*!< FOSC clock */ + SCG_FIRC_CLK = 4U, /*!< FIRC clock */ + SCG_PLL0_CLK = 5U, /*!< PLL0 clock */ + SCG_PLL1_CLK = 6U, /*!< PLL1 clock */ + SCG_SIRC_CLK = 7U, /*!< SIRC clock */ + SCG_SIRC32K_CLK = 8U, /*!< SIRC32K clock */ + SCG_SOSC_CLK = 9U, /*!< SOSC clock */ + SCG_SCG_CLKOUT_CLK = 10U, /*!< SCG CLK_OUT clock */ + SCG_SIRCDIVH_CLK = 11U, /*!< SIRCDIVH functional clock */ + SCG_SIRCDIVM_CLK = 12U, /*!< SIRCDIVM functional clock */ + SCG_SIRCDIVL_CLK = 13U, /*!< SIRCDIVL functional clock */ + SCG_FIRCDIVH_CLK = 14U, /*!< FIRCDIVH functional clock */ + SCG_FIRCDIVM_CLK = 15U, /*!< FIRCDIVM functional clock */ + SCG_FIRCDIVL_CLK = 16U, /*!< FIRCDIVL functional clock */ + SCG_FOSCDIVH_CLK = 17U, /*!< FOSCDIVH functional clock */ + SCG_FOSCDIVM_CLK = 18U, /*!< FOSCDIVM functional clock */ + SCG_FOSCDIVL_CLK = 19U, /*!< FOSCDIVL functional clock */ + SCG_PLL0DIVH_CLK = 20U, /*!< PLL0DIVH functional clock */ + SCG_PLL0DIVM_CLK = 21U, /*!< PLL0DIVM functional clock */ + SCG_PLL0DIVL_CLK = 22U, /*!< PLL0DIVL functional clock */ + SCG_PLL1DIVH_CLK = 23U, /*!< PLL1DIVH functional clock */ + SCG_PLL1DIVM_CLK = 24U, /*!< PLL1DIVM functional clock */ + SCG_PLL1DIVL_CLK = 25U, /*!< PLL1DIVL functional clock */ + SCG_NVMINIT_CLK = 26U, /*!< NVM initial clock source */ + SCG_CMU4REF_CLK = 27U, /*!< CMU4 reference clock */ + SCG_END_OF_CLOCKS = 28U /*!< End of SCG clocks */ +} SCG_ClkSrcType; + +/** + * @brief PLL clock type + */ +typedef enum +{ + SCG_PLL0 = 0U, /*!< PLL0 clock */ + SCG_PLL1 = 1U /*!< PLL1 clock */ +} SCG_PllClkType; + +/** + * @brief indicate the clock function status + * + */ +typedef enum +{ + SCG_STATUS_SUCCESS = 0U, /*!< function called success */ + SCG_STATUS_SEQUENCE_ERROR = 1U, /*!< function called report sequence error */ + SCG_STATUS_TIMEOUT = 2U, /*!< function called report timeout error */ + SCG_STATUS_IRC_ERROR = 3U, /*!< function called report internal clock error */ + SCG_STATUS_PARAM_ERROR = 4U /*!< function called report internal clock error */ +} SCG_StatusType; + +/** + * @brief indicate the CRC check result + * + */ +typedef enum +{ + SCG_CRC_CHECK_SUCCESS = 0U, /*!< CRC check success *//**< SCG_CRC_CHECK_SUCCESS */ + SCG_CRC_GEN_TIMEOUT = 1U, /*!< CRC Generate Timeout *//**< SCG_CRC_GEN_TIMEOUT */ + SCG_CRC_CHECK_FAILED = 2U /*!< CRC check failed */ /**< SCG_CRC_CHECK_FAILED */ +} SCG_CrcCheckResType; + +/** + * @brief SCG xxxIRC TRIMSRC type. +*/ +typedef enum +{ + SCG_IRC_TRIMSRC_RESERVE0 = 0U, /*!< Clock Trim source reserve0 */ + SCG_IRC_TRIMSRC_RESERVE1 = 1U, /*!< Clock Trim source reserve1 */ + SCG_IRC_TRIMSRC_FOSC = 2U, /*!< Clock Trim source FOSC */ + SCG_IRC_TRIMSRC_SOSC = 3U, /*!< Clock Trim source SOSC */ +} SCG_IrcTrimSrcType; + +/** + * @brief SCG_CCR [SCS] to Select system clock source + * + */ +typedef enum +{ + SCG_CLOCK_SRC_FOSC = 1U, /*!< System OSC. */ + SCG_CLOCK_SRC_SIRC = 2U, /*!< Slow IRC 12MHz. */ + SCG_CLOCK_SRC_FIRC = 3U, /*!< Fast IRC. */ + SCG_CLOCK_SRC_PLL0 = 6U, /*!< System PLL. */ + SCG_CLOCK_SRC_NONE = 255U /*!< MAX value. */ +} SCG_ClockSrcType; + +/** + * @brief SCG_CCR [DIVCORE ]/ SCG_CCR [DIVBUS ]/ SCG_CCR [DIVSLOW ] to Select system clock source. + * + */ +typedef enum +{ + SCG_CLOCK_DIV_BY1 = 0U, /*!< Divided by 1. */ + SCG_CLOCK_DIV_BY2 = 1U, /*!< Divided by 2. */ + SCG_CLOCK_DIV_BY3 = 2U, /*!< Divided by 3. */ + SCG_CLOCK_DIV_BY4 = 3U /*!< Divided by 4. */ +} SCG_ClockDivType; + +/** + * @brief SCG_ CLKOUTCFG [CLKOUTSEL] to Select system clock source. + */ +typedef enum +{ + SCG_CLOCKOUT_SRC_OFF = 0U, /*!< SCG OFF. */ + SCG_CLOCKOUT_SRC_FOSC = 1U, /*!< Fast OSC. */ + SCG_CLOCKOUT_SRC_SIRC = 2U, /*!< Slow IRC. */ + SCG_CLOCKOUT_SRC_FIRC = 3U, /*!< Fast IRC. */ + SCG_CLOCKOUT_SRC_SOSC = 4U, /*!< Slow OSC. */ + SCG_CLOCKOUT_SRC_PLL1 = 5U, /*!< System PLL1. */ + SCG_CLOCKOUT_SRC_PLL0 = 6U, /*!< System PLL0. */ + SCG_CLOCKOUT_SRC_SIRC32K = 7U, /*!< SIRC32K_CLK.*/ +} SCG_ClockoutSrcType; + +/** + * @brief NVM clock source enumeration + */ +typedef enum +{ + SCG_NVMCLK_SRC_SIRC = 30u, /*!< NVM source choose SIRC. */ + SCG_NVMCLK_SRC_FIRC = 31u /*!< NVM source choose FIRC. */ +} SCG_NvmClkSrcType; + +/** + * @brief CMU4 clock source enumeration + */ +typedef enum +{ + SCG_CMU4CLK_SRC_SIRC = 28u, /*!< NVM source choose SIRC. */ + SCG_CMU4CLK_SRC_FOSC = 29u /*!< NVM source choose FORC. */ +} SCG_Cmu4ClkSrcType; + +/** + * @brief SCG registers CRC trigger mode + */ +typedef enum +{ + SCG_CRC_SW_MODE = 0U, /*!< SCG registers CRC software mode. */ + SCG_CRC_TRIGGER_MODE = 1U /*!< SCG registers CRC trigger mode. */ +} SCG_CrcModeType; + +/** @brief [DIVL]/[DIVM]/[DIVH] bit field definition for SCG_SIRC/ SCG_FIRC/ SCG_FOSC/ SCG_PLL0 registers */ +typedef enum +{ + SCG_ASYNC_CLOCK_DISABLE = 0U, /*!< Clock output is disabled. */ + SCG_ASYNCCLOCKDIV_BY1 = 1U, /*!< Divided by 1. */ + SCG_ASYNCCLOCKDIV_BY2 = 2U, /*!< Divided by 2. */ + SCG_ASYNCCLOCKDIV_BY4 = 3U, /*!< Divided by 4. */ + SCG_ASYNCCLOCKDIV_BY8 = 4U, /*!< Divided by 8. */ + SCG_ASYNCCLOCKDIV_BY16 = 5U, /*!< Divided by 16. */ + SCG_ASYNCCLOCKDIV_BY32 = 6U, /*!< Divided by 32. */ + SCG_ASYNCCLOCKDIV_BY64 = 7U /*!< Divided by 64. */ +} SCG_AsyncClockDivType; + +/** @brief SCG_ PLLCFG[PREDIV] for PLL clock calculation. The pre-div value range is 0 ~ 31 */ +typedef uint8_t SCG_PllPredivType; + +/** @brief SCG_ PLLCFG[PSTDIV] for PLL clock calculation */ +typedef enum +{ + SCG_PLLPSTDIV_BY2 = 1U, + SCG_PLLPSTDIV_BY4 = 2U, + SCG_PLLPSTDIV_BY8 = 3U +} SCG_PllPstdivType; + +/** @brief SCG_ PLLCFG[SOURCE] to Select PLL clock source */ +typedef enum +{ + SCG_PLLSOURCE_FOSC = 0U, + SCG_PLLSOURCE_FIRC = 1U +} SCG_PllSourceType; + +/** @brief SCG_ PLLCFG [MULT] for PLL clock calculation. The mult value range is 96 ~ 512 */ +typedef uint16_t SCG_PllMultiplyType; + +/** @brief FOSC initial definition, include register SCG_FOSCCSR/SCG_FOSCDIV/SCG_FOSCCFG. */ +typedef struct +{ + bool bLock; /*!< SCG_FOSCCSR[LK] bit, Write to set the register can be written or not */ + bool bCm; /*!< SCG_FOSCCSR[CM] bit, Clock Monitor is enable */ + bool bCmre; /*!< SCG_FOSCCSR[CMRE] bit, Clock Monitor Reset Enable + 0 Generates interrupt, 1 Generates rese */ + bool bSten; /*!< SCG_FOSCCSR[STEN] bit, Clock Stop in Stop modes */ + bool bBypass; /*!< SCG_FOSCCFG[BYPASS] bit, Configures FOSC for bypassing the internal oscillator.*/ + SCG_AsyncClockDivType eDivH; /*!< SCG_FOSCDIV[DIVH] bit field definition, 0 means disable. */ + SCG_AsyncClockDivType eDivM; /*!< SCG_FOSCDIV[DIVM] bit field definition, 0 means disable. */ + SCG_AsyncClockDivType eDivL; /*!< SCG_FOSCDIV[DIVL] bit field definition, 0 means disable. */ +} SCG_FoscType; + +/** @brief SIRC initial definition, include register SCG_ SIRCCSR/ SCG_ SIRCDIV/ SCG_ SIRCTCCFG. */ +typedef struct +{ + bool bLock; /*!< SCG_SIRCCSR[LK] bit, Write to set the register can be written or not */ + bool bCm; /*!< SCG_SIRCCSR[CM] bit, SIRC Clock Monitor Enable */ + bool bTrEn; /*!< SCG_SIRCCSR[TREN] bit, IRC software trim enable (auto trim) */ + bool bLpen; /*!< SCG_SIRCCSR[LPEN] bit, Clock Stop Enable */ + bool bSten; /*!< SCG_SIRCCSR[STEN] bit, Clock Standby Enable */ + SCG_AsyncClockDivType eDivH; /*!< SCG_SIRCDIV[DIVH] bit field definition.*/ + SCG_AsyncClockDivType eDivM; /*!< SCG_SIRCDIV[DIVM] bit field definition.*/ + SCG_AsyncClockDivType eDivL; /*!< SCG_SIRCDIV[DIVL] bit field definition.*/ + uint8_t u8TrimSrc; /*!< SCG_SIRCTCFG[TRIMSRC] IRC clock auto trim reference clock source select.*/ +} SCG_SircType; + +typedef struct +{ + bool bLock; /*!< SIRC32KCSR[LK] bit, Write to set the register can be written or not */ +} SCG_Sirc32kType; + +/** @brief FIRC initial definition, include register SCG_ FIRCCSR/ SCG_ FIRCDIV/ SCG_ FIRCFG. */ +typedef struct +{ + bool bLock; /*!< SCG_FIRCCSR[LK] bit, Write to set the register can be written or not */ + bool bCm; /*!< SCG_FIRCCSR[CM] bit, FIRC Clock Monitor Enable */ + bool bTrEn; /*!< SCG_FIRCCSR[TREN] bit, IRC software trim enable (auto trim) */ + bool bSten; /*!< SCG_FIRCCSR[STEN] bit, Clock Standby Enable */ + SCG_AsyncClockDivType eDivH; /*!< SCG_FIRCDIV[DIVH] bit field definition.*/ + SCG_AsyncClockDivType eDivM; /*!< SCG_FIRCDIV[DIVM] bit field definition.*/ + SCG_AsyncClockDivType eDivL; /*!< SCG_FIRCDIV[DIVL] bit field definition.*/ + uint8_t u8TrimSrc; /*!< SCG_FIRCTCFG[TRIMSRC] IRC clock auto trim reference clock source select.*/ +} SCG_FircType; + +/** @brief SOSC definition, include register SCG_SOSCCFG. */ +typedef struct +{ + bool bLock; /*!< SCG_SOSCCSR[LK] bit, Write to set the register can be written or not.*/ + bool bBypass; /*!< SCG_SOSCCSR[BYPASS] bit, Configures SOSC for bypassing the internal oscillator.*/ + bool bCm; /*!< SCG_SOSCCSR[CM] bit,Clock Monitor enable.*/ + bool bCmre; /*!< SCG_SOSCCSR[CMRE] bit, 1:Clock Monitor Reset, 0: interrupt*/ +} SCG_SoscType; + +/** @brief PLL definition, include register SCG_PLLCSR/ SCG_PLLDIV/SCG_PLL0CFG. */ +typedef struct +{ + bool bLock; /*!< SCG_PLLCSR[LK] bit, Write to set the register can be written or not.*/ + bool bCm; /*!< SCG_PLLCSR[CM] bit,Clock Monitor enable.*/ + bool bCmre; /*!< SCG_PLLCSR[CMRE] bit, 1:Clock Monitor Reset, 0: interrupt*/ + bool bSten; /*!< SCG_PLLCSR[STEN] bit, Clock Standby Enable */ + SCG_AsyncClockDivType eDivH; /*!< SCG_PLLDIV[DIVH] bit field definition.*/ + SCG_AsyncClockDivType eDivM; /*!< SCG_PLLDIV[DIVM] bit field definition.*/ + SCG_AsyncClockDivType eDivL; /*!< SCG_PLLDIV[DIVL] bit field definition.*/ + SCG_PllPredivType u8Prediv; /*!< SCG_PLLCFG[PREDIV] bit field definition, the range is 0~31. [Pre-divider = u8Prediv + 1] */ + SCG_PllPstdivType ePstDiv; /*!< SCG_PLLCFG[PSTDIV] bit field definition. [Post Divider = (ePstDiv == 0 ? 2 : 2^ePstDiv)] */ + SCG_PllMultiplyType u16Mult; /*!< SCG_PLLCFG[MULT] bit field definition, this value need to be greater than 95. + [Multiplier = u16Mult + 1] */ + SCG_PllSourceType eSrc; /*!< SCG_PLLCFG[SOURCE] bit field definition.*/ +} SCG_PllType; + +/** @brief Current system clock definition, include register SCG_CCR. */ +typedef struct +{ + bool bSysClkMonitor; /*!< SCG_CCR[SYSCLK_CME], System Clock monitor bit.*/ + SCG_ClockSrcType eSrc; /*!< SCG_CCR[SCS], System Clock Source.*/ + SCG_ClockDivType eDivSlow; /*!< SCG_CCR[DIVSLOW], Slow Clock Divide Ratio.*/ + SCG_ClockDivType eDivBus; /*!< SCG_CCR[DIVBUS], Bus Clock Divide Ratio.*/ + SCG_ClockDivType eDivCore; /*!< SCG_CCR[DIVCORE], Core Clock Divide Ratio.*/ +} SCG_ClockCtrlType; + +/** + * @brief Enable SOSC + * + * @param pSoscConfig SOSC configuration + * @return SCG_StatusType Function status + */ +SCG_StatusType SCG_EnableSOSC(const SCG_SoscType *const pSoscConfig); + +/** + * @brief Disable SOSC + * + * @return SCG_StatusType Funtion status + */ +SCG_StatusType SCG_DisableSOSC(void); + +/** + * @brief Enable FOSC clock with input configuration + * + * @param pFoscConfig FOSC configuration + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_EnableFOSC(const SCG_FoscType *const pFoscConfig); + +/** + * @brief Disable FOSC + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_DisableFOSC(void); + +/** + * @brief Set SIRC configuration and configure SIRC DIV + * + * @param pSircConfig SIRC configuation + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_SetSIRC(const SCG_SircType *const pSircConfig); + +/** + * @brief Disable SIRC DIV and clear DIV configuration + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_ClearSIRC(void); + +/** + * @brief Enable SIRC32K + * + * @param pSirc32kConfig SIRC32K configuration + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_EnableSIRC32K(const SCG_Sirc32kType *const pSirc32kConfig); + +/** + * @brief Disable SIRC32K + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_DisableSIRC32K(void); + +/** + * @brief Enable FIRC + * + * @param pFircConfig FIRC configuration + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_EnableFIRC(const SCG_FircType *const pFircConfig); + +/** + * @brief Disable FIRC + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_DisableFIRC(void); + +/** + * @brief Enable PLL + * + * @param ePll PLL instance + * @param pPllConfig PLL configuration + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_EnablePLL(const SCG_PllClkType ePll, const SCG_PllType *const pPllConfig); + +/** + * @brief Disable PLL + * + * @param ePll PLL instance + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_DisablePLL(const SCG_PllClkType ePll); + +/** + * @brief Set system run time clock and related CORE/BUS/SLOW clock. + * + * @param pSysClkConfig pointer to the clockCtrlType structure data instance,which defined for system clock selection. + * @return SCG_StatusType function status + * SCG_STATUS_SUCCESS : clock source and dividers are valid,and switch system clock successfully + * SCG_STATUS_SEQUENCE_ERROR: new clock source is not enabled + * SCG_STATUS_PARAM_ERROR: the core bus slow divider are invalid + * SCG_STATUS_TIMEOUT: switch system clock procedure time out + */ +SCG_StatusType SCG_SetClkCtrl(const SCG_ClockCtrlType *const pSysClkConfig); + +/** + * @brief Get clock frequency + * + * @param eScgClockName Clock source type + * @return uint32_t frequency value + */ +uint32_t SCG_GetScgClockFreq(const SCG_ClkSrcType eScgClockName); + +/** + * @brief Select clock out source + * + * @param eClkoutSel clock out source + */ +void SCG_SetClkOut(const SCG_ClockoutSrcType eClkoutSel); + +/** + * @brief Select NVM clock source + * + * @param eNvmClkSrc NVM clock source + * @return uint32_t function status + */ +SCG_StatusType SCG_SetNvmClk(const SCG_NvmClkSrcType eNvmClkSrc); + +/** + * @brief Select CMU4 clock source + * + * @param eCmu4ClkSrc CMU4 clock source + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_SetCmu4Clk(const SCG_Cmu4ClkSrcType eCmu4ClkSrc); + +/** + * @brief Generate the origion SCG register CRC result, and configure the SCG register CRC option. + * + * @param eMode The SCG register CRC trigger mode + * @return CRC configure status + * SCG_STATUS_SUCCESS : CRC configure successfully + * SCG_STATUS_TIMEOUT : CRC configure time out + */ +SCG_StatusType SCG_RegCrcConfig(SCG_CrcModeType eMode); + +/** + * @brief Trigger the SCG register CRC generation by software + * + */ +void SCG_RegCrcGenerate(void); + +/** + * @brief Trigger the SCG register CRC generation by software,and wait the CRC check result + * + * @return CRC check result + */ +SCG_CrcCheckResType SCG_RegCrcGenerateWaitResult(void); + +/** + * @brief Clock source De-init + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_Deinit(void); + + + +/** @}*/ /* fc7xxx_driver_scg */ +#endif diff --git a/Inc/fc7xxx_driver_scm.h b/Inc/fc7xxx_driver_scm.h new file mode 100644 index 0000000..dd3c071 --- /dev/null +++ b/Inc/fc7xxx_driver_scm.h @@ -0,0 +1,232 @@ +/** + * @file fc7xxx_driver_scm.h + * @author Flagchip085 + * @brief FC7xxx SCM driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 + ******************************************************************************** */ + +#ifndef _DRIVER_SCM_H_ +#define _DRIVER_SCM_H_ + +#include "HwA_scm.h" +#include "HwA_csc.h" +#include "interrupt_manager.h" + +/********* Local typedef ************/ +/** + * @brief SCM return status + * + */ +typedef enum +{ + SCM_E_OK = 0U, /*!< Return ok */ + SCM_E_NOT_OK, /*!< Return not ok */ + SCM_E_PARAM, /*!< Return invalid parameters */ + SCM_E_LOCK, /*!< Return register has been locked */ + SCM_E_TIMEOUT, /*!< Return operation timeout */ + SCM_E_CRC /*!< Return CRC check failed */ +} SCM_RetStatusType; + +/** + * @brief CCMx type + * + */ +typedef enum +{ + SCM_CCM0 = 0U /*!< CCM0 */ +} SCM_CCM_Type; + +/** + * @brief Matrixx type + * + */ +typedef enum +{ + SCM_MatrixStatus_0 = 0U, /*!< Matrix status 0 */ + SCM_MatrixStatus_1, /*!< Matrix status 1 */ + SCM_MatrixStatus_2, /*!< Matrix status 2 */ + SCM_MatrixStatus_5, /*!< Matrix status 5 */ + SCM_MatrixStatus_6, /*!< Matrix status 6 */ + SCM_MatrixStatus_7, /*!< Matrix status 7 */ + SCM_MatrixStatus_ID /*!< Matrix ID status */ +} SCM_MatrixStatusType; + +/** + * @brief SCM registers CRC trigger mode + */ +typedef enum +{ + SCM_CRC_SW_MODE = 0U, /*!< SCM registers CRC software mode. */ + SCM_CRC_TRIGGER_MODE = 1U /*!< SCM registers CRC trigger mode. */ +} SCM_CrcModeType; + +/********* Local function ************/ +/** + * @brief Get unique identification for the chip, loaded from NVR. + * + * @param pUid Pointer to UID + * + */ +void SCM_GetChip_UID(uint32 *pUid); + +/** + * @brief Get CCMx status. + * + * @param eCCMType CCM type + * @param u32Value The or value of SCM_CCMxStatusType to select the status to get + * + */ +uint32_t SCM_GetStatus_CCMx(SCM_CCM_Type eCCMType, uint32_t u32Value); + +/** + * @brief Get matrix status. + * + * @param eMatrixType Matrix type + * @param u32Value selection to get + * + */ +uint32_t SCM_GetStatus_Matrix(SCM_MatrixStatusType eMatrixType, uint32_t u32Value); + +/** + * @brief Set cpu to control MAM ECC enable register 0. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_MAMECCR0(const SCM_WPB_CpuType eCpuType, bool bLockStatus); + +/** + * @brief Set cpu to control MAM ECC enable register 1. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_MAMECCR1(const SCM_WPB_CpuType eCpuType, bool bLockStatus); + +/** + * @brief Set cpu to control CPU0 ECC enable register. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_CPU0ECCEN(const SCM_WPB_CpuType eCpuType, bool bLockStatus); + +/** + * @brief Set cpu to control SOCMISC register. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_SOCMISC(const SCM_WPB_CpuType eCpuType, bool bLockStatus); + +/** + * @brief Set cpu to control Subsystem pcc register. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_SUBSYS_PCC(const SCM_WPB_CpuType eCpuType, bool bLockStatus); + +/** + * @brief Set cpu to control master halt request register. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_MASTER_HALT_REQ(const SCM_WPB_CpuType eCpuType, bool bLockStatus); + +/** + * @brief Set lock FTU_ROUTING register. + * + */ +void SCM_SetLock_FTU_ROUTING(void); + +/** + * @brief Set lock FTU_GTB register. + * + */ +void SCM_SetLock_FTU_GTB(void); + +/** + * @brief Set lock DEBUG_TRACE register. + * + */ +void SCM_SetLock_DEBUG_TRACE(void); + +/** + * @brief Set lock FLEXCAN_ROUTING register. + * + */ +void SCM_SetLock_FLEXCAN_ROUTING(void); + +/** + * @brief Set lock MSC0_ROUTING register. + * + */ +void SCM_SetLock_MSC0_ROUTING(void); + +/** + * @brief Set lock INT_ROUTER_NMI register. + * + */ +void SCM_SetLock_INT_ROUTER_NMI(void); + +/** + * @brief Set NMI interrupt router . + * + * @param eCpuType Cpu to use + * @param bEnable Enable/Disable + * @return Set operation success/failed + * SCM_E_OK: Set NMI interrupt router successfully + * SCM_E_PARAM: eCpuType invalid + */ +SCM_RetStatusType SCM_SetEnable_NMIIntRouter(const SCM_WPB_CpuType eCpuType, bool bEnable); + +/** + * @brief Generate the origion SCM register CRC result, and configure the SCM register CRC option. + * + * @param eMode The SCM register CRC trigger mode + * @return CRC configure status + * SCM_E_OK : CRC configure successfully + * SCM_E_TIMEOUT : CRC configure time out + */ +SCM_RetStatusType SCM_RegCrcConfig(SCM_CrcModeType eMode); + +/** + * @brief Trigger the SCM register CRC generation by software + * + */ +void SCM_RegCrcGenerate(void); + +/** + * @brief Trigger the SCM register CRC generation by software,and wait the CRC check result + * + * @return CRC check result + */ +SCM_RetStatusType SCM_RegCrcGenerateWaitResult(void); + + +#endif /* end of _DRIVER_SCM_H_ */ diff --git a/Inc/fc7xxx_driver_scst.h b/Inc/fc7xxx_driver_scst.h new file mode 100644 index 0000000..7a11c88 --- /dev/null +++ b/Inc/fc7xxx_driver_scst.h @@ -0,0 +1,137 @@ +/** + * @file fc7xxx_driver_scst.h + * @author Flagchip + * @brief FC7xxx scst driver type definition and API + * @version 0.1.0 + * @date 2023-12-29 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/********************************************************************************* +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2023-12-29 qxw074 N/A First version for FC7240 +******************************************************************************** */ + +#ifndef _DRIVER_FC7XXX_DRIVER_SCST_H_ +#define _DRIVER_FC7XXX_DRIVER_SCST_H_ + +#include "device_header.h" + +/** + * @addtogroup fc7xxx_driver_scst + * @{ + */ + +/** + * @brief typed of test result returned + * + */ +typedef enum +{ + M7ST_FaultInjectError, + M7ST_ErrorAluTest, + M7ST_ErrorAluMLATest, + M7ST_ErrorAluSHIFTTest, + M7ST_ErrorAluTes1t, + M7ST_ErrorAluTest2, + M7ST_ErrorAluTest3, + M7ST_ErrorAluTest4, + M7ST_ErrorAluTest5, + M7ST_ErrorAluTest6, + M7ST_ErrorRegbankTest1, + M7ST_ErrorRegbankTest2, + M7ST_ErrorRegbankTest3, + M7ST_ErrorRegbankTest4, + M7ST_ErrorRegbankTest5, + M7ST_ErrorRegbankTest6, + M7ST_ErrorLoadStoreTest1, + M7ST_ErrorLoadStoreTest2, + M7ST_ErrorLoadStoreTest3, + M7ST_ErrorLoadStoreTest4, + M7ST_ErrorLoadStoreTest5, + M7ST_ErrorLoadStoreTest6, + M7ST_ErrorSimdSatTest1, + M7ST_ErrorSimdSatTest2, + M7ST_ErrorSimdSatTest3, + M7ST_ErrorSimdSatTest4, + M7ST_ErrorMacTest1, + M7ST_ErrorMacTest2, + M7ST_ErrorFetchTest, + M7ST_ErrorStatusTest1, + M7ST_ErrorStatusTest2, + M7ST_ErrorBranchTest1, + M7ST_ErrorBranchTest2, + M7ST_ErrorIntSvcTest, + M7ST_ErrorIntBusFaultTest, + M7ST_ErrorIntHardFaultTest1, + M7ST_ErrorIntHardFaultTest2, + M7ST_ErrorIntUsageFaultTest, + M7ST_ErrorIntSystickTest, + M7ST_ErrorIntPendSvTest, + M7ST_ErrorIntMemFaultTest, + M7ST_ErrorIntMaskingTest, + M7ST_ErrorIntHandlerThreadsTest, + M7ST_ErrorIntNMIHfTest, + M7ST_ErrorIntTailChainTest, + M7ST_ErrorIntAluTest, + M7ST_ErrorIntBranchTest, + M7ST_ErrorIntStatusTest, + M7ST_ErrorM7ST_TestPass +} Type_M7ST_AtomicStatus; + +/** + * @brief typed of test index + * + */ +typedef enum +{ + M7ST_AluTest, + M7ST_AluMLATest, + M7ST_AluSHIFTTest, + M7ST_AluTes1t, + M7ST_AluTest2, + M7ST_AluTest3, + M7ST_AluTest4, + M7ST_AluTest5, + M7ST_AluTest6, + M7ST_RegbankTest1, + M7ST_RegbankTest2, + M7ST_RegbankTest3, + M7ST_RegbankTest4, + M7ST_RegbankTest5, + M7ST_RegbankTest6, + M7ST_LoadStoreTest1, + M7ST_LoadStoreTest2, + M7ST_LoadStoreTest3, + M7ST_LoadStoreTest4, + M7ST_LoadStoreTest5, + M7ST_LoadStoreTest6, + M7ST_SimdSatTest1, + M7ST_SimdSatTest2, + M7ST_SimdSatTest3, + M7ST_SimdSatTest4, + M7ST_MacTest1, + M7ST_MacTest2, + M7ST_FetchTest, + M7ST_StatusTest1, + M7ST_StatusTest2, + M7ST_BranchTest1, + M7ST_BranchTest2, + M7ST_RegressionTest +} SCST_TestIndexType; + +/** + * @brief This function is used to get the result of the executed test + * + * @param test_index is test number,0U..32U + * @param s_u32RamBase The first address of the 1k memory that the program needs to run + * @return M7ST_ErrorM7ST_TestPass is ok, others are not ok + */ +Type_M7ST_AtomicStatus SCST_ExecuteTest(SCST_TestIndexType test_index,uint32_t *s_u32RamBase); + +/** @}*/ /* fc7xxx_driver_scst */ +#endif diff --git a/Inc/fc7xxx_driver_sec.h b/Inc/fc7xxx_driver_sec.h new file mode 100644 index 0000000..9f842af --- /dev/null +++ b/Inc/fc7xxx_driver_sec.h @@ -0,0 +1,371 @@ +/** + * @file fc7xxx_driver_sec.h + * @author Flagchip + * @brief FC7xxx sec driver type definition and API + * @version 0.2.0 + * @date 2023-2-7 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.2.0 2023-2-7 Flagchip076 N/A First version for FC7300 +********************************************************************************/ + + +#ifndef _DRIVER_SEC_H_ +#define _DRIVER_SEC_H_ + +#include "HwA_sec.h" +#include "device_header.h" + +/** + * @addtogroup fc7xxx_driver_sec + * @{ + */ + +/** + * @brief Debug Re-Enable Key + * @note Only if four 32-bit writes match, it will set the DEN to 0x5 to enable + debug and unlock SEC registers. The key is up to the user to decide in advance. + * */ +typedef struct +{ + uint32_t Re_key0; /*!< The Debug Re-enable key 0*/ + uint32_t Re_key1; /*!< The Debug Re-enable key 1*/ + uint32_t Re_key2; /*!< The Debug Re-enable key 2*/ + uint32_t Re_key3; /*!< The Debug Re-enable key 3*/ + +} ReEnDebug_Keys; + +typedef enum +{ + SEC_STATUS_SUCCESS = 0U, /*!< SEC status success */ + SEC_STATUS_FAILED = 1U /*!< SEC status failed */ +}SEC_RetType; + +/** + * @brief NVR write and read Permissions. + * @*/ +typedef struct +{ + bool WritEn; /*!< The NVR write permission*/ + bool ReadEn; /*!< The NVR read permission*/ + bool EraseEn; /*!< The NVR Erase permission*/ +} NVR_Per; + +/** + * @brief Indicate the system state + * + * */ +typedef enum +{ + Securedstate = 0u, /*!< The system is in secured state*/ + UnSecuredstate = 1u /*!< The system is in no secured state*/ +} Systemstate; + +/** + * @brief Indicate the ISP instance + * + * */ +typedef enum +{ + ISP_FCUART1 = 0U, /*!< The ISP instance is FCUART1 */ + ISP_FCUART3 = 1U, /*!< The ISP instance is FCUART3 */ + ISP_FLEXCAN1 = 2U, /*!< The ISP instance is FLEXCAN1 */ + ISP_FLEXCAN5 = 3U /*!< The ISP instance is FLEXCAN3 */ +}Isp_Instance; + +/** + * @brief Indicate the FCUART Baud Rate for ISP + * + * */ +typedef enum +{ + ISP_FCUART_2MBPS =0u, /*!< the FCUART Baud Rate is 2Mbps*/ + ISP_FCUART_1MBPS =1u, /*!< the FCUART Baud Rate is 1Mbps*/ + ISP_FCUART_512KBPS =2u, /*!< the FCUART Baud Rate is 512kbps*/ + ISP_FCUART_115200BPS =3u, /*!< the FCUART Baud Rate is 115200bps*/ + ISP_FCUART_INVALID = 4u /*!< the ISP instance is not FCUART*/ +}FCUART_ISP_BAUDRATE; + +/** + * @brief Indicate the FLEXCAN Baud Rate for ISP + * + * */ +typedef enum +{ + ISP_FLEXCANFD_4MBPS =0u, /*!< the CANFD Baud Rate is 4Mbps*/ + ISP_FLEXCANFD_2MBPS =1u, /*!< the CANFD Baud Rate is 2Mbps*/ + ISP_FLEXCAN_1MBPS =2u, /*!< the CAN Baud Rate is 1Mbps*/ + ISP_FLEXCAN_500kBPS =3u, /*!< the FCUART Baud Rate is 500kbps*/ + ISP_FLEXCAN_INVALID = 4u /*!< the ISP instance is not FLEXCAN*/ +}FLEXCAN_ISP_BAUDRATE; + +/** + * @brief Indicate the ISP information. + * + * */ +typedef struct +{ + bool IspModeEn; /*!< true means - ISP mode is active.*/ + bool IspPinEn; /*!< true means - ISP pin is active.The associated pin defaults to internal pull up enabled.*/ + bool IspAuthEn; /*!<*true means - ISP Auth Enable. Only valid in secure boot. (Value loaded from NVR sector)*/ + Isp_Instance Ispinstance; /*!< the Isp instance*/ + FCUART_ISP_BAUDRATE Ispfcuartbaudrate; /*!< Indicate the FCUART Baud Rate for ISP*/ + FLEXCAN_ISP_BAUDRATE Ispflexcanbaudrate; /*!< Indicate the FLEXCAN Baud Rate for ISP*/ + +}SEC_IspInfo; + +/** + * @brief Indicate the fast boot speed. + * + * */ +typedef enum +{ + FASTBOOT_300MHZ = 0u, /*!< Select PLL0 as the core clock source; the core clock is 300MHz.*/ + FASTBOOT_96MHZ = 1u /*!< Select FIRC as the core clock source; the core clock is 96MHz.*/ +}FastBoot_Speed; + +/** + * @brief Indicate the OSC Frequency + * + * */ +typedef enum +{ + OSC_8MHZ = 0u, /*!SENT_CHN[echannel].CHN_DFD)) +#define SENT_GET_FAST_MSG_DMA_BYTELENGTH (12U) +#define SENT0_GET_SLOW_MSG_DMA_ADDR(echannel) (&(SENT->SENT_CHN[echannel].CHN_DSB3)) +#define SENT_GET_SLOW_MSG_DMA_BYTELENGTH (12U) + + /** + * @brief SENT operation return values + * + */ + typedef enum + { + SENT_RETURN_OK = 0x00U, /*!< The SENT operation is succeeded */ + SENT_RETURN_E_NOT_OK = 0x01U, /*!< The SENT operation is failed */ + SENT_RETURN_E_ALREADY_INIT = 0x02U, /*!< The SENT has been initialized. */ + SENT_RETURN_E_UNINIT = 0x03U, /*!< The SENT is not initialized */ + SENT_RETURN_E_PARAM = 0x04U, /*!< The SENT parameter is incorrect or out of range. */ + } + Sent_ReturnType; + + /** + * @brief SENT Channel index + * + */ + typedef enum + { + SENT_CHANNEL_0 = 0x00U, /*!< The SENT channel 0 */ + SENT_CHANNEL_1 = 0x01U, /*!< The SENT channel 1 */ + SENT_CHANNEL_2 = 0x02U, /*!< The SENT channel 2 */ + SENT_CHANNEL_3 = 0x03U, /*!< The SENT channel 3 */ + SENT_CHANNEL_MAX = SENT_CHANNEL_COUNT + } Sent_ChannelType; + + /** + * @brief SENT instance index + * + */ + typedef enum + { + SENT_INSTANCE_0 = 0x00U, /*!< The SENT channel 0 */ + SENT_INSTANCE_1 = 0x01U, /*!< The SENT channel 1 */ + SENT_INSTANCE_MAX = SENT_INSTANCE_COUNT + } Sent_InstanceType; + + /** + * @brief SENT nibble data mode control. Refer to SENT SAE J2716 2010 for detail protocol definition + * + */ + typedef enum + { + SENT_DATA_NIBBLE_MODE_A = 0x0U, /*!< Frame format A */ + SENT_DATA_NIBBLE_MODE_H1 = 0x1U, /*!< Frame format H1 */ + SENT_DATA_NIBBLE_MODE_H2 = 0x2U, /*!< Frame format H2 */ + SENT_DATA_NIBBLE_MODE_H3 = 0x3U, /*!< Frame format H3 */ + SENT_DATA_NIBBLE_MODE_H4 = 0x4U, /*!< Frame format H4 */ + SENT_DATA_NIBBLE_MODE_H5 = 0x5U, /*!< Frame format H5 */ + SENT_DATA_NIBBLE_MODE_H6 = 0x6U, /*!< Frame format H6 */ + SENT_DATA_NIBBLE_MODE_H7 = 0x7U /*!< Frame format H7 */ + } Sent_DataNibbleModeType; + + /** + * @brief SENT calibration valid type + * + */ + typedef enum + { + SENT_CALIBRATION_VALID_DISABLE = 0x0U, /*!< The successive calibration pulses diagnostic will be disabled */ + SENT_CALIBRATION_VALID_WITHIN_20 = 0x1U, /*!< The difference of received calibration pulse and receiver configuration is within 20%, the message is deemed to be valid */ + SENT_CALIBRATION_VALID_FROM_20_TO_25 = 0x2U, /*!< The difference of received calibration pulse and receiver configuration is more than 20% but less than 25%, the message is deemed to be valid */ + } Sent_CalibrationValidType; + + /** + * @brief SENT Successive calibration pulses diagnostic option + * + */ + typedef enum + { + SENT_CALIBRATION_PULSE_DIAG_OPTION2 = 0x0U, /*!< Option 2 i.e. Low Latency Option as per SAE Specification */ + SENT_CALIBRATION_PULSE_DIAG_OPTION1 = 0x1U, /*!< Option 1 i.e. Preferred but High Latency Option as per SAE Specification */ + } Sent_CalDiagOptionType; + + /** + * @brief Determines how long the bus idle flag will assert when SENT bus is idle + * + */ + typedef enum + { + SENT_IDLE_COUNT_FLAG_DISABLE = 0x0U, /*!< The bus idle flag will never assert */ + SENT_IDLE_COUNT_FLAG_254_TICKS = 0x1U, /*!< The bus is idle for more than 127*2 ticks, then the bus idle flag will assert */ + SENT_IDLE_COUNT_FLAG_508_TICKS = 0x2U, /*!< The bus is idle for more than 127*2 ticks, then the bus idle flag will assert */ + SENT_IDLE_COUNT_FLAG_1016_TICKS = 0x4U, /*!< The bus is idle for more than 127*2 ticks, then the bus idle flag will assert */ + SENT_IDLE_COUNT_FLAG_2032_TICKS = 0x8U, /*!< The bus is idle for more than 127*2 ticks, then the bus idle flag will assert */ + } Sent_IdleCountType; + + /** + * @brief SENT Slow message type. + * + */ + typedef enum + { + SENT_SERIAL_MESSAGE_SHORT = 0x0U, /*!< short serial data message */ + SENT_SERIAL_MESSAGE_ENHANCE_12DATA_8ID = 0x1U, /*!< enhanced serial data message with 12-bit data and 8-bit ID */ + SENT_SERIAL_MESSAGE_ENHANCE_16DATA_4ID = 0x2U, /*!< enhanced serial data message with 16-bit data and 4-bit ID */ + } Sent_SerialMessageType; + + /** + * @brief SENT trigger type in SPC mode + * + */ + typedef enum + { + SENT_SPC_SOFTWARE_TRIGGER = 0x0U, /*!< SPC pulse triggered by software method */ + SENT_SPC_EXTERNAL_TRIGGER = 0x1U, /*!< SPC pulse triggered by external trigger */ + } Sent_SpcTriggerType; + + /** + * @brief Select the tick base in SPC mode + * + */ + typedef enum + { + SENT_SPC_TICK_BASE_PRE_MSG = 0x0U, /*!< Previous received message tick base */ + SENT_SPC_TICK_BASE_CONFIGURED = 0x1U, /*!< SENT configured tick base */ + } Sent_SpcTickBaseType; + + /** + * @brief Sent global interrupt type. + * + */ + typedef enum + { + SENT_SLOW_MSG_DMA_UF_IT = 0U, /*!< Slow message dma read underflow interrupt enable. */ + SENT_FAST_MSG_DMA_DF_IT = 1U, /*!< Fast message dma read underflow interrupt enable. */ + SENT_FAST_MSG_READY_IT = 2U, /*!< Fast message ready interrupt enable. */ + SENT_SLOW_MSG_READY_IT = 3U, /*!< Slow message ready interrupt enable. */ + SENT_FAST_MSG_FIFO_OF_IT = 4U, /*!< Fast message FIFO overflow interrupt enable. */ + } Sent_GlobalInterruptType; + + /** + * @brief Structure to enable or disable the channel interrupts. + * + */ + typedef struct + { + bool bBusIdleITEn; /*!< Bus idle interrupt enable. */ + bool bSpcOverrunITEn; /*!< SPC overrun interrupt enable. */ + bool bCalResyncErrITEn; /*!< Continuous 2 sync/calibration pulse difference exceed 1.5625% error interrupt enable. */ + bool bCalFailITEn; /*!< Calibation 20% pass 25% fail interrupt enable. */ + bool bSlowMsgOFITEn; /*!< Slow message overflow interrupt enable. */ + bool bFastMsgOFITEn; /*!< Fast message overflow interrupt enable. */ + bool bNibbleValueErrITEn; /*!< Nibble value more than 15 or less than 0 error interrupt enable. */ + bool bPrePulseDiagErrITEn; /*!< Previous pulse diagnosis error interrupt enable. */ + bool bCalDiagErrITEn; /*!< Calibration diagnosis over 25% error interrupt enable. */ + bool bCalErrITEn; /*!< Sync/calibration pulse difference eceed 1.5625% error interrupt enable. */ + bool bSlowMsgCrcErrITEn; /*!< Slow message CRC check error interrupt enable. */ + bool bFastMsgCrcErrITEn; /*!< Fast message CRC check error interrupt enable. */ + bool bFallingEdgeNumErrITEn; /*!< Falling edge number error interrupt enable. */ + } Sent_ChannelInterruptType; + + /** + * @brief Structure for fast message buffer. + * + */ + typedef struct + { + uint8_t u8CRC; /*!< Receied fast message CRC data. */ + uint8_t u8SC; /*!< Fast message status communication nibble value. */ + uint32_t u32Timestamp; /*!< Fast message timestamp value. */ + uint32_t u32Data; /*!< Received fast message data nibble. */ + } Sent_FastMessageDataType; + + /** + * @brief Structure for slow message buffer. + * + */ + typedef struct + { + Sent_SerialMessageType eMsgType; /*!< Slow message type. */ + uint8_t u8CRC; /*!< Slow message crc data. */ + uint8_t u8ID; /*!< Slow message ID. */ + uint16_t u16Data; /*!< Slow message data. */ + uint32_t u32Timestamp; /*!< Slow message timestamp value. */ + } Sent_SlowMessageDataType; + + /** + * @brief SENT Global ISR callback function prototype + * + */ + typedef void (*SENT_GBISRCallbackType)(Sent_ChannelType eChannel, const Sent_GlobalInterruptType eInterrupt); + + /** + * @brief SENT Channel ISR callback function prototype + * + */ + typedef void (*SENT_CHISRCallbackType)(Sent_ChannelType eChannel, const uint32_t u32ChannelStatus); + + /** + * @brief structure to configure the SENT. + * + */ + typedef struct + { + uint8_t u8PreScaler; /**/ + STCU_SELFTEST_DONE = 0x01U, /***/ + STCU_SELFTEST_ABORT = 0x02U, /***/ + STCU_SELFTEST_LBIST_ERROR = 0x10U, /***/ + STCU_SELFTEST_MBIST_ERROR = 0x20U, /***/ + STCU_SELFTEST_TIMEOUT_ERROR = 0x40U, /***/ + STCU_SELFTEST_NVRLOAD_ERROR = 0x100U, /***/ + STCU_SELFTEST_SELFCHECK_ERROR = 0x200u /***/ +}STCU_SelfTestStatusType; + +/** @brief STCU interrupt flag */ +typedef enum +{ + STCU_INTERRUPT_FLAG_NONE = 0x00U, /***/ + STCU_INTERRUPT_FLAG_SIZE_ERR = 0x01U, /***/ + STCU_INTERRUPT_FLAG_SEQ_ERR = 0x02U, /***/ +}STCU_InterruptFlagType; + +/** @brief The items select for MBIST */ +typedef enum +{ + STCU_MBIST_SEL_NONE = 0x00U, /***/ + STCU_MBIST_SEL_SRAM = 0x01U, /***/ + STCU_MBIST_SEL_ITCM_CPU0 = 0x02U, /***/ + STCU_MBIST_SEL_DTCM0_CPU0 = 0x04U, /***/ + STCU_MBIST_SEL_DTCM1_CPU0 = 0x08U, /***/ + STCU_MBIST_SEL_CACHE_CPU0 = 0x10U, /***/ + STCU_MBIST_SEL_SUBSYS = 0x20U, /***/ + STCU_MBIST_SEL_SRAM_HSM = 0x40U, /***/ + STCU_MBIST_SEL_SRAM_DMACAN = 0x80U, /***/ + STCU_MBIST_SEL_ROM_HOST = 0x100U, /***/ + STCU_MBIST_SEL_ROM_HSM = 0x200U /***/ +}STCU_MbistSelType; + +/** @brief MBIST done status flag. */ +typedef enum +{ + STCU_MBIST_DONE_NONE = 0x00U, /***/ + STCU_MBIST_DONE_SRAM = 0x01U, /***/ + STCU_MBIST_DONE_ITCM_CPU0 = 0x02U, /***/ + STCU_MBIST_DONE_DTCM0_CPU0 = 0x04U, /***/ + STCU_MBIST_DONE_DTCM1_CPU0 = 0x08U, /***/ + STCU_MBIST_DONE_CACHE_CPU0 = 0x10U, /***/ + STCU_MBIST_DONE_SUBSYS = 0x20U, /***/ + STCU_MBIST_DONE_SRAM_HSM = 0x40U, /***/ + STCU_MBIST_DONE_SRAM_DMACAN = 0x80U, /***/ + STCU_MBIST_DONE_ROM_HOST = 0x100U, /***/ + STCU_MBIST_DONE_ROM_HSM = 0x200U /***/ +}STCU_MbistDoneType; + +/** @brief MBIST fail status flag. */ +typedef enum +{ + STCU_MBIST_FAIL_NONE = 0x00U, /***/ + STCU_MBIST_FAIL_SRAM = 0x01U, /***/ + STCU_MBIST_FAIL_ITCM_CPU0 = 0x02U, /***/ + STCU_MBIST_FAIL_DTCM0_CPU0 = 0x04U, /***/ + STCU_MBIST_FAIL_DTCM1_CPU0 = 0x08U, /***/ + STCU_MBIST_FAIL_CACHE_CPU0 = 0x10U, /***/ + STCU_MBIST_FAIL_SUBSYS = 0x20U, /***/ + STCU_MBIST_FAIL_SRAM_HSM = 0x40U, /***/ + STCU_MBIST_FAIL_SRAM_DMACAN = 0x80U, /***/ + STCU_MBIST_FAIL_ROM_HOST = 0x100U, /***/ + STCU_MBIST_FAIL_ROM_HSM = 0x200U /***/ +}STCU_MbistFailedType; + +/** @brief Hardware SRAM initialization mode. */ +typedef enum +{ + STCU_INIT_RAM_MODE_POR_OR_WAKEUP4STANDBY0 = 0U, /***/ + STCU_INIT_RAM_MODE_AFTER_WAKEUP4STANDBY1, /***/ + STCU_INIT_RAM_MODE_AFTER_WAKEUP4STANDBY2, /***/ + STCU_INIT_RAM_MODE_AFTER_WAKEUP4STANDBY3 /***/ +}STCU_InitRamModeType; + +/** @brief The items select for Hardware SRAM Initialization. */ +typedef enum +{ + STCU_INIT_RAM_TYPE_NONE = 0x00U, /***/ + STCU_INIT_RAM_TYPE_SRAM = 0x01U, /***/ + STCU_INIT_RAM_TYPE_ITCM_CPU0 = 0x02U, /***/ + STCU_INIT_RAM_TYPE_DTCM0_CPU0 = 0x04U, /***/ + STCU_INIT_RAM_TYPE_DTCM1_CPU0 = 0x08U, /***/ +}STCU_InitRamType; + +/** @brief Init Ram done status flag. */ +typedef enum +{ + STCU_INIT_RAM_DONE_TYPE_NONE = 0x00U, /***/ + STCU_INIT_RAM_DONE_TYPE_SRAM = 0x01U, /***/ + STCU_INIT_RAM_DONE_TYPE_ITCM_CPU0 = 0x02U, /***/ + STCU_INIT_RAM_DONE_TYPE_DTCM0_CPU0 = 0x04U, /***/ + STCU_INIT_RAM_DONE_TYPE_DTCM1_CPU0 = 0x08U, /***/ +}STCU_InitRamDoneType; + +/** @brief Init Ram status flag. */ +typedef enum +{ + STCU_HARDWARE_INIT_RAM_STATUS_NONE = 0U, /***/ + STCU_HARDWARE_INIT_RAM_STATUS_DONE = 1U, /***/ + STCU_HARDWARE_INIT_RAM_STATUS_BUSY = 2U, /***/ + STCU_HARDWARE_INIT_RAM_STATUS_ABORT = 4U /***/ +}STCU_HardwareInitRamStatusType; + +/** @brief LBIST status flag. */ +typedef enum +{ + STCU_LBIST_STATUS_NONE = 0U, /***/ + STCU_LBIST_STATUS_DONE = 1U, /***/ + STCU_LBIST_STATUS_FAILED = 2U /***/ +}STCU_LbistStatusType; + +/** @brief LBIST Clock Divider. */ +typedef enum +{ + STCU_LBIST_CLK_DIVIDER_BY_2 = 1U, /***/ + STCU_LBIST_CLK_DIVIDER_BY_3 = 2U, /***/ + STCU_LBIST_CLK_DIVIDER_BY_4 = 3U, /***/ +}STCU_LbistClkDivType; + +/** @brief clock source of self-test. */ +typedef enum +{ + STCU_CLK_SOURCE_FIRC = 0U, /***/ + STCU_CLK_SOURCE_PLL = 1U /***/ +}STCU_ClkSourceType; + +/** @brief Self-test Port Pull Selection. */ +typedef enum +{ + STCU_PORT_PULL_DISABLE = 0U, /***/ + STCU_PORT_PULL_DOWN, /***/ + STCU_PORT_PULL_UP /***/ +}STCU_PortPullModeType; + +/** @brief Stcu call back function type, the u32status should refer to "STCU_InterruptFlagType" */ +typedef void (*Stcu_IRQCallback)(uint32_t u32Status); + +typedef struct +{ + bool bLbistEn; /***/ + bool bMbistLPC; /***/ + bool bMbistEn; /***/ + bool bMbistFullTest; /***/ + bool bMbistSramInit; /***/ + bool bInterruptEn; /***/ + STCU_PortPullModeType ePortPullMode; /***/ + STCU_ClkSourceType eClkSource; /***/ + STCU_LbistClkDivType eLbistClkDivider; /***/ + uint16_t u16MaxTime; /***/ + uint32_t u32MbistSel; /***/ +}STCU_ConfigType; + + +typedef struct +{ + STCU_InitRamModeType eInitMode; /**< RAM Initial Mode */ + uint8_t bLockAfterEn; /**< Lock STCU after RAM Initial */ + uint32_t u32InitRamType; /**< RAM Type, DTCM, ITCM, SRAM, refer to "STCU_InitRamType" and use OR to combine them */ +}STCU_InitRamConfigType; + + +/** + * \brief Init the STCU module + * + * \param pConfig the configuration structure + */ +void STCU_Init(STCU_ConfigType *pConfig); + +/** + * \brief Trigger to start Software self test + * + */ +void STCU_StartSelfTest(void); + +/** + * \brief Check Software Trigger Self-test result + * + * \return refer to "STCU_SelfTestStatusType" enum. + */ +uint32_t STCU_CheckTriggerResult(void); + +/** + * \brief Initial RAM with hardware + * + * \param pConfig the configuration structure + */ +void STCU_StartRamInit(STCU_InitRamConfigType *pInitCfg); + +/** + * \brief Get status of RAM initialize action + * + * \return the status of ram initialize action, refer to "STCU_HardwareInitRamStatusType" + */ +uint32_t STCU_GetRamInitStatus(void); + +/** + * \brief Get if the LBIST test result is Fail + * + * \return true means LBIST fail. false means LBIST pass. + */ +bool STCU_GetLbistFailResult(void); +/** + * \brief Get each MBIST Fail result + * + * \return refer to "STCU_MbistFailedType" enum. + */ +uint32_t STCU_GetMbistFailResult(void); + +/** + * \brief Get each done status of SRAM initialize + * + * \return the done status of SRAM initialize action, refer to "STCU_InitRamDoneType" + */ +uint32_t STCU_GetRamInitDoneStatus(void); + +/** + * \brief Set the LBIST Pattern value and expected misr value. + * The two value should be load from NVR, but also can reconfigure by this API. + * The expected misr value is calculated from pattern, so please make sure this two value is right, or the LBST would fail. + * + * \param u16Pattern the LBIST Pattern value + * \param u16Pattern the LBIST expected misr value + */ +void STCU_LBIST_Set_Pattern_Misr(uint16_t u16Pattern, uint32_t u32ExpectedMisr); + +/** + * \brief Get LBIST actual MISR value, the value should be read and use DFT tool to decode it, if LBIST test resault is fail. + * + * \return the LBIST actual MISR value + */ +uint32_t STCU_GetLbistAcutalMisr(void); + +/** + * @brief STCU 0 interrupt handler + * + * @note This function should be called as/in STCU 0 interrupt handler + */ +void STCU0_IRQHandler(void); +#endif /* end of _DRIVER_STCU_H_ */ diff --git a/Inc/fc7xxx_driver_systick.h b/Inc/fc7xxx_driver_systick.h new file mode 100644 index 0000000..5517e64 --- /dev/null +++ b/Inc/fc7xxx_driver_systick.h @@ -0,0 +1,28 @@ +#ifndef _DRIVER_CORE_SYSTICK_H_ +#define _DRIVER_CORE_SYSTICK_H_ + +#include "device_header.h" + + +/** + * \brief Config system tick + * + * \param u32ReloadVal reload value, val is decrease from reload value + * \return 0 is ok, and others are not ok + */ +uint8_t Core_SysTick_Config(uint32_t u32ReloadVal); + +void Core_SysTick_DeConfig(void); + +void Core_SysTick_SetValue(uint32_t u32Value); + +void Core_SysTick_ClearValue(void); + +uint32_t Core_SysTick_GetValue(void); + +void Core_SysTick_Enable(void); + +void Core_SysTick_Disable(void); + + +#endif /* end of _DRIVER_CORE0_SYSTICK_H_ */ diff --git a/Inc/fc7xxx_driver_tmu.h b/Inc/fc7xxx_driver_tmu.h new file mode 100644 index 0000000..711afec --- /dev/null +++ b/Inc/fc7xxx_driver_tmu.h @@ -0,0 +1,156 @@ +/** + * @file fc7xxx_driver_tmu.h + * @author Flagchip + * @brief FC7xxx TMU driver type definition and API + * @version 0.1.0 + * @date 2023-12-29 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/********************************************************************************* +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2023-12-29 qxw074 N/A First version for FC7240 +******************************************************************************** */ + +#ifndef _DRIVER_FC7XXX_DRIVER_TMU_H_ +#define _DRIVER_FC7XXX_DRIVER_TMU_H_ +#include "device_header.h" +#include "HwA_tmu.h" + +#if defined(__cplusplus) +extern "C" { +#endif +/** + * @addtogroup fc7xxx_driver_tmu + * @{ + */ + +/** + * @brief The Flag-based temperature sensor over 150 Celsius callback function prototype + * + */ +typedef void (*TMU_TempOver150InterruptCallbackType)(void); + +/** + * @brief The Flag-based temperature sensor over 125 Celsius callback function prototype + * + */ +typedef void (*TMU_TempOver125InterruptCallbackType)(void); + +/** + * @brief The Flag-based temperature sensor ready callback function prototype + * + */ +typedef void (*TMU_TempFlagReadyInterruptCallbackType)(void); + +/** + * @brief The Voltage-based temperature sensor ready callback function prototype + * + */ +typedef void (*TMU_TempVoltageReadyInterruptCallbackType)(void); + +/** + * @brief TMU operation return values + * + */ +typedef enum +{ + TMU_STATUS_ERROR = 0x0U, /*!< The TMU operation is failed */ + TMU_STATUS_SUCCESS = 0x1U, /*!< The TMU operation is succeed */ + TMU_STATUS_TIMEOUT = 0x2U /*!< The TMU operation is failed because of time out */ +} TMU_StatusType; + +/** + * @brief Defines the temperature sensor configuration + * + * This structure is used to configure for Flag-based temperature sensor ane Voltage-based temperature sensor + * + * Implements : TMU_InitType + */ +typedef struct +{ + TMU_LockType eTempRegisterLockCon; /*!eResolution = ADC_RESOLUTION_12_BIT; /* 12 bit Resolution */ + pInitCfg->eAlign = ADC_ALIGN_RIGHT; /* Align right */ + pInitCfg->eTriggerMode = ADC_TRIGMODE_SW; /* Software trigger */ + pInitCfg->bWaitEnable = false; /* Disable wait conversion mode */ + pInitCfg->bSequenceGroupModeEnable = false; /* Disable sequence group mode */ + pInitCfg->eTrgLatchUnitPri = TRG_LATCH_UNIT_PRI_ROUND_ROBIN; /* Round Robin priority */ + pInitCfg->eClockDivider = ADC_CLOCK_DIV_1; /* Adc clock divided by 1 */ + pInitCfg->eSequenceMode = ADC_SEQMODE_SINGLE; /* Single sequence mode */ + pInitCfg->bAutoDis = false; /* Disable auto disable mode */ + pInitCfg->eOverrunMode = ADC_OVERRUN_MODE_PRESERVE; /* Old conversion data preserved when overrun occured */ + pInitCfg->eVoltageRef = ADC_REF_INTERNAL; /* Use internal reference */ + pInitCfg->bHwAvgEnable = false; /* Disable averaging functionality */ + pInitCfg->eHwAverage = ADC_AVERAGE_4; /* Average by 4 samples if average is enabled */ + pInitCfg->aSampleTimes[0] = ADC_DEFAULT_SAMPLE_TIME_OPTION_0; /* Sample time option 0 is 4 ADC Clock */ + pInitCfg->aSampleTimes[1] = ADC_DEFAULT_SAMPLE_TIME_OPTION_1; /* Sample time option 1 is 10 ADC Clock */ + pInitCfg->aSampleTimes[2] = ADC_DEFAULT_SAMPLE_TIME_OPTION_2; /* Sample time option 2 is 34 ADC Clock */ + pInitCfg->aSampleTimes[3] = ADC_DEFAULT_SAMPLE_TIME_OPTION_3; /* Sample time option 3 is 130 ADC Clock */ +} + +void ADC_Init(const ADC_InstanceType eInstance, const ADC_InitType *const pInitCfg) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + DEV_ASSERT(pInitCfg != NULL); + + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + uint32_t u32TimeOut = 15000000U; + uint32_t u32Cfg1; + uint32_t u32Cfg2; + uint32_t u32Cal; + ADC_TrigSrcType eTriggerSrc; + ADC_TrigModeType eTriggerMode; + uint32_t u32ClockDiv; + uint32_t u32StartupCnt; + + if (pInitCfg->bSequenceGroupModeEnable == false) + { + if (pInitCfg->eSequenceMode == ADC_SEQMODE_DISCONTINUOUS_1) + { + eTriggerSrc = ADC_TRIGSRC_PTIMER; + eTriggerMode = ADC_TRIGMODE_RISING_EDGE; + } + else + { + eTriggerSrc = ADC_TRIGSRC_TRGSEL; + eTriggerMode = pInitCfg->eTriggerMode; + } + } + else + { + eTriggerSrc = ADC_TRIGSRC_TRIG_LATCH_UNIT; + eTriggerMode = ADC_TRIGMODE_RISING_EDGE; + } + + PCC_ClkSrcType eAdcClkName = PCC_CLK_ADC0; + uint32_t u32AdcClk; + + switch (eInstance) + { + case ADC_INSTANCE_0: + { + eAdcClkName = PCC_CLK_ADC0; + break; + } + + case ADC_INSTANCE_1: + { + eAdcClkName = PCC_CLK_ADC1; + break; + } + + default: + break; + } + u32ClockDiv = 1U << pInitCfg->eClockDivider; + + u32AdcClk = PCC_GetPccFunctionClock(eAdcClkName); + + /* The start up count shall be around 5us */ + u32StartupCnt = u32AdcClk / u32ClockDiv / 1000000U * 5U + 1U; + if (u32StartupCnt < 2U) + { + u32StartupCnt = 2U; + } + else if (u32StartupCnt > 255U) + { + u32StartupCnt = 255U; + } + else + {} + + ADC_HWA_Reset(pAdc); + + u32Cfg1 = ADC_CFG1_OVRMOD(pInitCfg->eOverrunMode) | + ADC_CFG1_SEQGP_EN(pInitCfg->bSequenceGroupModeEnable) | + ADC_CFG1_SEQ_LEN(0) | + ADC_CFG1_SEQ_MOD(pInitCfg->eSequenceMode) | + ADC_CFG1_AUTO_DIS(pInitCfg->bAutoDis) | + ADC_CFG1_WAIT(pInitCfg->bWaitEnable) | + ADC_CFG1_TRIGSRC(eTriggerSrc) | + ADC_CFG1_TRIGMODE(eTriggerMode) | + ADC_CFG1_ALIGN(pInitCfg->eAlign) | + ADC_CFG1_RES(pInitCfg->eResolution) | + ADC_CFG1_DMAEN(false); + ADC_HWA_SetConfig1(pAdc, u32Cfg1); + + u32Cfg2 = ADC_CFG2_FWMARK(ADC_DEFAULT_WATER_MARK) | + ADC_CFG2_TRG_PRI(pInitCfg->eTrgLatchUnitPri) | + ADC_CFG2_TRG_CLR(1U) | + ADC_CFG2_AVG_EN(pInitCfg->bHwAvgEnable) | + ADC_CFG2_AVG_LEN(pInitCfg->eHwAverage) | + ADC_CFG2_REF_EXT(pInitCfg->eVoltageRef) | + ADC_CFG2_STCNT(u32StartupCnt); + ADC_HWA_SetConfig2(pAdc, u32Cfg2); + + u32Cal = ADC_CAL_CAL_EN(pInitCfg->bCalEnable) | + ADC_CAL_OFFSET(pInitCfg->s32CalOffset) | + ADC_CAL_GAIN(pInitCfg->s32CalGain); + + ADC_HWA_SetCal(pAdc, u32Cal); + + ADC_HWA_SetClockGatingEnableFlag(pAdc, true); + while ((ADC_HWA_GetClockGatingAck(pAdc) != true) && (u32TimeOut != 0)) + { + u32TimeOut--; + } + if (ADC_HWA_GetClockGatingAck(pAdc) == true) + { + ADC_HWA_SetClockDivider(pAdc, pInitCfg->eClockDivider); + } + u32TimeOut = 15000000U; + ADC_HWA_SetClockGatingEnableFlag(pAdc, false); + while ((ADC_HWA_GetClockGatingAck(pAdc) != false) && (u32TimeOut != 0)) + { + u32TimeOut--; + } + + uint8_t u8SmprIndex; + for (u8SmprIndex = 0U; u8SmprIndex < ADC_SAMPLE_TIME_OPTION_CNT; u8SmprIndex++) + { + ADC_HWA_SetSampleTime(pAdc, u8SmprIndex, pInitCfg->aSampleTimes[u8SmprIndex] - 2U); + } +} + +void ADC_DeInit(const ADC_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + uint32_t u32Cfg1; + uint32_t u32Cfg2; + + ADC_HWA_Reset(pAdc); + + ADC_HWA_SetInterruptEnable(pAdc, 0U); + + u32Cfg1 = ADC_CFG1_OVRMOD(ADC_OVERRUN_MODE_PRESERVE) | + ADC_CFG1_SEQGP_EN(false) | + ADC_CFG1_SEQ_LEN(0U) | + ADC_CFG1_SEQ_MOD(ADC_SEQMODE_SINGLE) | + ADC_CFG1_AUTO_DIS(false) | + ADC_CFG1_WAIT(false) | + ADC_CFG1_TRIGSRC(ADC_TRIGSRC_PTIMER) | + ADC_CFG1_TRIGMODE(ADC_TRIGMODE_SW) | + ADC_CFG1_ALIGN(ADC_ALIGN_RIGHT) | + ADC_CFG1_RES(ADC_RESOLUTION_12_BIT) | + ADC_CFG1_DMAEN(false); + ADC_HWA_SetConfig1(pAdc, u32Cfg1); + + u32Cfg2 = ADC_CFG2_FWMARK(ADC_DEFAULT_WATER_MARK) | + ADC_CFG2_TRG_PRI(TRG_LATCH_UNIT_PRI_ROUND_ROBIN) | + ADC_CFG2_TRG_CLR(1U) | + ADC_CFG2_AVG_EN(false) | + ADC_CFG2_AVG_LEN(ADC_AVERAGE_4) | + ADC_CFG2_REF_EXT(ADC_REF_INTERNAL) | + ADC_CFG2_STCNT(ADC_DEFAULT_STARTUP_COUNTER); + ADC_HWA_SetConfig2(pAdc, u32Cfg2); + + ADC_HWA_SetSampleTime(pAdc, 0U, ADC_DEFAULT_SAMPLE_TIME_OPTION_0 - 2U); + ADC_HWA_SetSampleTime(pAdc, 1U, ADC_DEFAULT_SAMPLE_TIME_OPTION_1 - 2U); + ADC_HWA_SetSampleTime(pAdc, 2U, ADC_DEFAULT_SAMPLE_TIME_OPTION_2 - 2U); + ADC_HWA_SetSampleTime(pAdc, 3U, ADC_DEFAULT_SAMPLE_TIME_OPTION_3 - 2U); + + ADC_HWA_SetHwCompareEnableFlag(pAdc, false); + ADC_HWA_SetHwCompareChannel(pAdc, ADC_CMP_CHANNEL_ALL, 0U); + + ADC_HWA_SetHwCompareThreshold(pAdc, ADC_DEFAULT_COMPARE_LOW_THRESHOLD, ADC_DEFAULT_COMPARE_HIGH_THRESHOLD); + + uint8_t u8ChnIndex; + for (u8ChnIndex = 0U; u8ChnIndex < ADC_SC_COUNT; u8ChnIndex++) + { + ADC_HWA_SetChannelSampleTimeIndex(pAdc, u8ChnIndex, 0U); + ADC_HWA_SetChannelInterruptEnable(pAdc, u8ChnIndex, false); + ADC_HWA_SetChannelInput(pAdc, u8ChnIndex, ADC_DEFAULT_SC_CHANNEL); + } + + /* TODO : CAL Rregister */ +} + +void ADC_InitChannel(const ADC_InstanceType eInstance, const ADC_ChannelCfgType aChannels[], + const uint8_t u8ChnCnt) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + DEV_ASSERT(u8ChnCnt < ADC_SC_COUNT); + DEV_ASSERT(aChannels != NULL); + + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + + s_u8ChannelCnt[eInstance] = u8ChnCnt; + + uint8_t u8ChnIndex; + for (u8ChnIndex = 0U; u8ChnIndex < u8ChnCnt; u8ChnIndex++) + { + ADC_HWA_SetChannelDiff(pAdc, u8ChnIndex, aChannels[u8ChnIndex].bDiff); + ADC_HWA_SetChannelSampleTimeIndex(pAdc, u8ChnIndex, aChannels[u8ChnIndex].eSampleTimeOption); + ADC_HWA_SetChannelInterruptEnable(pAdc, u8ChnIndex, false); + ADC_HWA_SetChannelInput(pAdc, u8ChnIndex, aChannels[u8ChnIndex].eChannel); + } + + if (ADC_HWA_GetSeqGpEn(pAdc) != true && ADC_HWA_GetSequenceMode(pAdc) != ADC_SEQMODE_DISCONTINUOUS_1) + { + ADC_HWA_SetSequenceLength(pAdc, u8ChnCnt - 1U); + ADC_HWA_SetFIFOWaterMark(pAdc, u8ChnCnt - 1U); + } +} + +void ADC_InitSequenceGroup(const ADC_InstanceType eInstance, const ADC_SequenceGroupType aSeqGroup[], + const uint8_t u8SeqGroupCnt) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + DEV_ASSERT(u8SeqGroupCnt < ADC_SEQUENCE_GROUP_CNT); + DEV_ASSERT(aSeqGroup != NULL); + + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + + s_u8SeqGroupCnt[eInstance] = u8SeqGroupCnt; + + uint8_t u8ChnIndex; + for (u8ChnIndex = 0U; u8ChnIndex < u8SeqGroupCnt; u8ChnIndex++) + { + ADC_HWA_SetSeqGroupStartEndPoint(pAdc, u8ChnIndex, aSeqGroup[u8ChnIndex].u8Start, aSeqGroup[u8ChnIndex].u8Start + aSeqGroup[u8ChnIndex].u8Len); + ADC_HWA_SetEndOfSequenceGroupInterruptEnable(pAdc, u8ChnIndex, false); + } +} + +void ADC_InitCompare(const ADC_InstanceType eInstance, const ADC_CompareType *const pCmpCfg) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + DEV_ASSERT(pCmpCfg != NULL); + + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + + ADC_HWA_SetHwCompareChannel(pAdc, pCmpCfg->eCmpSingleChn, pCmpCfg->u8CmpChnSel); + ADC_HWA_SetHwCompareThreshold(pAdc, pCmpCfg->u16LowThres, pCmpCfg->u16HighThres); + ADC_HWA_SetHwCompareEnableFlag(pAdc, pCmpCfg->bCmpEnable); +} + +void ADC_InitInterrupt(const ADC_InstanceType eInstance, const ADC_InterruptType *const pInterruptCfg) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + DEV_ASSERT(pInterruptCfg != NULL); + DEV_ASSERT(s_u8ChannelCnt[eInstance] > 0U); + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + uint32_t u32InterruptCfg; + uint8_t u8SeqGroupIndex; + + if (ADC_HWA_GetSeqGpEn(pAdc) == false) + { + s_apAdcResultBuffer[eInstance] = pInterruptCfg->pResultBuffer; + if (ADC_HWA_GetSequenceMode(pAdc) == ADC_SEQMODE_DISCONTINUOUS_1) + { + u32InterruptCfg = ADC_INT_ENABLE_TRGERR_IE(false) | + ADC_INT_ENABLE_FIFO_RDY_IE(false) | + ADC_INT_ENABLE_ACMP_IE(pInterruptCfg->bAnalogCmpIntEn) | + ADC_INT_ENABLE_OVRIE(false) | + ADC_INT_ENABLE_EOSEQIE(false) | + ADC_INT_ENABLE_EOCIE(false) | + ADC_INT_ENABLE_EOSMPIE(false) | + ADC_INT_ENABLE_ADRDYIE(false); + ADC_HWA_SetInterruptEnable(pAdc, u32InterruptCfg); + ADC_HWA_SetChannelInterruptEnable(pAdc, s_u8ChannelCnt[eInstance] - 1U, pInterruptCfg->bConversionCompleteIntEn); + } + else + { + u32InterruptCfg = ADC_INT_ENABLE_TRGERR_IE(false) | + ADC_INT_ENABLE_FIFO_RDY_IE(false) | + ADC_INT_ENABLE_ACMP_IE(pInterruptCfg->bAnalogCmpIntEn) | + ADC_INT_ENABLE_OVRIE(pInterruptCfg->bOverRunIntEn) | + ADC_INT_ENABLE_EOSEQIE(pInterruptCfg->bConversionCompleteIntEn) | + ADC_INT_ENABLE_EOCIE(false) | + ADC_INT_ENABLE_EOSMPIE(false) | + ADC_INT_ENABLE_ADRDYIE(false); + ADC_HWA_SetInterruptEnable(pAdc, u32InterruptCfg); + } + } + else + { + for (u8SeqGroupIndex = 0U; u8SeqGroupIndex < ADC_SEQUENCE_GROUP_CNT; u8SeqGroupIndex++) + { + s_apAdcSeqGroupResultBuffer[eInstance][u8SeqGroupIndex] = pInterruptCfg->pSequenceGroupResultBuffer[u8SeqGroupIndex]; + } + u32InterruptCfg = ADC_INT_ENABLE_TRGERR_IE(false) | + ADC_INT_ENABLE_FIFO_RDY_IE(false) | + ADC_INT_ENABLE_ACMP_IE(pInterruptCfg->bAnalogCmpIntEn) | + ADC_INT_ENABLE_OVRIE(false) | + ADC_INT_ENABLE_EOSEQIE(false) | + ADC_INT_ENABLE_EOCIE(false) | + ADC_INT_ENABLE_EOSMPIE(false) | + ADC_INT_ENABLE_ADRDYIE(false); + ADC_HWA_SetInterruptEnable(pAdc, u32InterruptCfg); + for (u8SeqGroupIndex = 0U; u8SeqGroupIndex < s_u8SeqGroupCnt[eInstance]; u8SeqGroupIndex++) + { + ADC_HWA_SetEndOfSequenceGroupInterruptEnable(pAdc, u8SeqGroupIndex, true); + } + } + + s_apAdcCoCoNotify[eInstance] = pInterruptCfg->pConvCompleteNotify; + s_apAdcOvrNotify[eInstance] = pInterruptCfg->pOverRunNotify; + s_apAdcCmpNotify[eInstance] = pInterruptCfg->pCompareNotify; + s_apEndOfSeqGroupNotify[eInstance] = pInterruptCfg->pEndOfSeqGroupNotify; +} + +void ADC_InitDmaChannel(const ADC_InstanceType eInstance, const ADC_DmaType *const pAdcDmaCfg) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + DEV_ASSERT(pAdcDmaCfg != NULL); + uint32_t u32ResultStart; + uint32_t u32ResultEnd; + + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + + if (pAdcDmaCfg->bDmaEnable == true) + { + s_apAdcResultBuffer[eInstance] = pAdcDmaCfg->pResultBuffer; + s_apAdcCoCoNotify[eInstance] = pAdcDmaCfg->pConvCompleteNotify; + + DMA_ChannelCfgType tDmaCfg; + if (ADC_HWA_GetSeqGpEn(pAdc) == true) + { + u32ResultStart = ADC_HWA_GetSeqGroupStartPoint(pAdc, (uint8_t)pAdcDmaCfg->eSeqGroupIndex); + u32ResultEnd = ADC_HWA_GetSeqGroupEndPoint(pAdc, (uint8_t)pAdcDmaCfg->eSeqGroupIndex); + tDmaCfg.pSrcBuffer = &pAdc->RESULT[u32ResultStart]; + tDmaCfg.pDestBuffer = pAdcDmaCfg->pResultBuffer; + tDmaCfg.u32BlockSize = 4U; + tDmaCfg.u16BlockCount = u32ResultStart - u32ResultEnd; + tDmaCfg.eSrcIncMode = DMA_INCREMENT_DATA_SIZE; + } + else if (ADC_HWA_GetSequenceMode(pAdc) == ADC_SEQMODE_DISCONTINUOUS_1) + { + tDmaCfg.pSrcBuffer = &pAdc->RESULT[0U]; + tDmaCfg.pDestBuffer = pAdcDmaCfg->pResultBuffer; + tDmaCfg.u32BlockSize = 4U; + tDmaCfg.u16BlockCount = s_u8ChannelCnt[eInstance]; + tDmaCfg.eSrcIncMode = DMA_INCREMENT_DATA_SIZE; + } + else + { + tDmaCfg.pSrcBuffer = &pAdc->FIFO_DATA; + tDmaCfg.pDestBuffer = pAdcDmaCfg->pResultBuffer; + tDmaCfg.u32BlockSize = 4U * s_u8ChannelCnt[eInstance]; + tDmaCfg.u16BlockCount = 1U; + tDmaCfg.eSrcIncMode = DMA_INCREMENT_DISABLE; + } + tDmaCfg.eDestIncMode = DMA_INCREMENT_DATA_SIZE; + tDmaCfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B; + tDmaCfg.eDestDataSize = DMA_TRANSFER_SIZE_4B; + tDmaCfg.u8ChannelPriority = pAdcDmaCfg->u8ChannelPriority; + tDmaCfg.bSrcBlockOffsetEn = false; + tDmaCfg.bDestBlockOffsetEn = false; + tDmaCfg.s32BlockOffset = 0; + tDmaCfg.bSrcAddrLoopbackEn = true; + tDmaCfg.bDestAddrLoopbackEn = true; + tDmaCfg.bAutoStop = false; + tDmaCfg.bSrcCircularBufferEn = false; + tDmaCfg.u32SrcCircBufferSize = DMA_CIRCULAR_BUFFER_SIZE_1B; + tDmaCfg.bDestCircularBufferEn = false; + tDmaCfg.u32DestCircBufferSize = DMA_CIRCULAR_BUFFER_SIZE_1B; + if (eInstance == ADC_INSTANCE_0) + { + tDmaCfg.eTriggerSrc = DMA_REQ_ADC0; + } + else if (eInstance == ADC_INSTANCE_1) + { + tDmaCfg.eTriggerSrc = DMA_REQ_ADC1; + } + else + {} + + DMA_InterruptCfgType dmaIntCfg = {0}; + dmaIntCfg.bTransferCompleteIntEn = true; + if (eInstance == ADC_INSTANCE_0) + { + dmaIntCfg.pTransferCompleteNotify = ADC0_DMAHandler; + } + else if (eInstance == ADC_INSTANCE_1) + { + dmaIntCfg.pTransferCompleteNotify = ADC1_DMAHandler; + } + else + {} + + dmaIntCfg.bTransferErrorIntEn = false; + dmaIntCfg.pTransferErrorNotify = NULL; + + ADC_HWA_SetDMAEnableFlag(pAdc, true); + + DMA_InitChannel(pAdcDmaCfg->eDmaInstance, pAdcDmaCfg->eDmaChannel, &tDmaCfg); + DMA_InitChannelInterrupt(pAdcDmaCfg->eDmaInstance, pAdcDmaCfg->eDmaChannel, &dmaIntCfg); + } + else + { + ADC_HWA_SetDMAEnableFlag(pAdc, false); + } +} + +ADC_StatusType ADC_Enable(const ADC_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + ADC_StatusType eRet = ADC_STATUS_SUCCESS; + uint32_t u32TimeOut = 15000000U; + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + + ADC_HWA_Enable(pAdc); + while ((ADC_HWA_GetReady(pAdc) != true) && (u32TimeOut != 0U)) + { + u32TimeOut--; + } + if (u32TimeOut != 0U) + { + ADC_HWA_ClearReady(pAdc); + eRet = ADC_STATUS_SUCCESS; + } + else + { + eRet = ADC_STATUS_TIMEOUT; + } + return eRet; +} + +ADC_StatusType ADC_Disable(const ADC_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + ADC_StatusType eRet = ADC_STATUS_SUCCESS; + uint32_t u32TimeOut = 15000000U; + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + + if (ADC_HWA_GetStart(pAdc) == true) + { + eRet = ADC_Stop(eInstance); + } + + if (eRet == ADC_STATUS_SUCCESS) + { + ADC_HWA_Disable(pAdc); + while ((ADC_HWA_GetEnable(pAdc) == true) && (u32TimeOut != 0U)) + { + u32TimeOut--; + } + if (u32TimeOut != 0U) + { + eRet = ADC_STATUS_SUCCESS; + } + else + { + eRet = ADC_STATUS_TIMEOUT; + } + } + return eRet; +} + +void ADC_Start(const ADC_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + ADC_HWA_Start(pAdc); +} + +ADC_StatusType ADC_Stop(const ADC_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + ADC_StatusType eRet = ADC_STATUS_ERROR; + uint32_t u32TimeOut = 15000000U; + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + + ADC_HWA_Stop(pAdc); + + while ((ADC_HWA_GetStop(pAdc) == true) && (u32TimeOut != 0U)) + { + u32TimeOut--; + } + if (u32TimeOut != 0U) + { + eRet = ADC_STATUS_SUCCESS; + } + else + { + eRet = ADC_STATUS_TIMEOUT; + } + return eRet; +} + +void ADC_Reset(const ADC_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < ADC_INSTANCE_COUNT); + ADC_Type *const pAdc = s_apAdcBase[eInstance]; + ADC_HWA_Reset(pAdc); +} diff --git a/Src/fc7xxx_driver_aontimer.c b/Src/fc7xxx_driver_aontimer.c new file mode 100644 index 0000000..a36ecae --- /dev/null +++ b/Src/fc7xxx_driver_aontimer.c @@ -0,0 +1,187 @@ +/** + * @file fc7xxx_driver_aontimer.c + * @author Flagchip + * @brief FC7xxx aontimer driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-10 Flagchip0076 N/A First version for FC7240 +********************************************************************************/ +#include "fc7xxx_driver_aontimer.h" + +#include "fc7xxx_driver_csc.h" + +extern void AONTIMER_IRQHandler(void); + +/** @brief Aontimer common interrupt handle function */ +static void Aontimer_CommonProcessInterrupt(void); + +/** @brief Aontimer user defined interrupt function */ +static Aontimer_InterruptCallBackType s_pAontimerNotifyPtr = NULL; + +/** + * @brief Initialize aontimer instance + * + * @param pInitStruct Aontimer Initialize structure + */ +void AONTIMER_Init(const AONTIMER_InitType *const pInitStruct) +{ + DEV_ASSERT(pInitStruct != NULL); + /* Disable the Aontimer, and clear control register. */ + AONTIMER_HWA_ConfigModule((uint32_t)0U); + AONTIMER_HWA_ConfigModulePrescale((uint32_t)0U); + AONTIMER->CSR |= AONTIMER_CSR_DBGEN(pInitStruct->eDbgMode); + if (AONTIMER_PULSE_MODE == pInitStruct->eMode) + { + AONTIMER_HWA_SelectClkSrcOnPulseMode(pInitStruct->ePulseClkSrc); + AONTIMER_HWA_ConfigModulePolarity(pInitStruct->ePulsePol); + AONTIMER_HWA_EnablePulseMode(); + if (pInitStruct->bBypassEn) + { + AONTIMER_HWA_EnableBypassMode(); + } + else + { + AONTIMER_HWA_DisableBypassMode(); + } + AONTIMER_HWA_SetPrescale(pInitStruct->u8PulseFilterWidth); + } + else + { + AONTIMER_HWA_SetPrescale(pInitStruct->u8Prescaler); + } + AONTIMER_HWA_SetModuleRunOnDebug(); + AONTIMER_HWA_SelectModuleClkSrc(pInitStruct->eClkSrc); + AONTIMER_HWA_SetModuleCompareValue((uint32_t)pInitStruct->u16StartValue); +} + +/** + * @brief De-initialize aontimer instance + * + */ +void AONTIMER_Deinit(void) +{ + AONTIMER_HWA_ConfigModule((uint32_t)0U); + AONTIMER_HWA_ConfigModulePrescale((uint32_t)0U); + AONTIMER_HWA_SetModuleCompareValue((uint32_t)0xFFFFFFFFU); + s_pAontimerNotifyPtr = NULL; +} + +/** + * @brief Initialize aontimer interrupt functionality + * + * @param pIntStruct Aontimer interrupt structure + * @return Aontimer return type + * @note this function will disable timer + */ +AONTIMER_StatusType AONTIMER_InitInterrupt(const AONTIMER_IntType *const pIntStruct) +{ + AONTIMER_StatusType eRet = AONTIMER_STATUS_SUCCESS; + if (NULL == pIntStruct) + { + eRet = AONTIMER_STATUS_PARAM_INVALID; + } + else + { + AONTIMER_HWA_DisableTimer(); + if (pIntStruct->bIntEn) + { + AONTIMER_HWA_EnableModuleInterrupt(); + s_pAontimerNotifyPtr = pIntStruct->pIsrNotify; + } + else + { + AONTIMER_HWA_DisableModuleInterrupt(); + s_pAontimerNotifyPtr = NULL; + } + } + return eRet; +} + +/** + * @brief Enable AONTIMER interrupt + * @note this function will enable AONTIEMR timer. + */ +void AONTIMER_EnableInterrupt(void) +{ + AONTIMER_HWA_DisableTimer(); + AONTIMER_HWA_EnableModuleInterrupt(); + AONTIMER_HWA_EnableTimer(); +} + +/** + * @brief Disable AONTIMER interrupt + * @note this function will enable AONTIEMR timer. + * + */ +void AONTIMER_DisableInterrupt(void) +{ + AONTIMER_HWA_DisableTimer(); + AONTIMER_HWA_DisableModuleInterrupt(); + AONTIMER_HWA_EnableTimer(); +} + +/** + * @brief Start Aontimer + * + */ +void AONTIMER_StartTimer(void) +{ + AONTIMER_HWA_EnableTimer(); +} + +/** + * @brief Stop Aontimer + * + */ +void AONTIMER_StopTimer(void) +{ + AONTIMER_HWA_DisableTimer(); +} + +/** + * @brief Update value of aontimer counter + * + * @param u16StartValue input value, range : 0~65535 + */ +void AONTIMER_UpdateCounterValue(const uint16_t u16StartValue) +{ + if (0U == (AONTIMER->CSR & AONTIMER_CSR_TMS_MASK)) + { + AONTIMER_HWA_DisableTimer(); + AONTIMER_HWA_SetModuleCompareValue((uint32_t)u16StartValue); + AONTIMER_HWA_EnableTimer(); + } +} + +/** + * @brief Aontimer common interrupt handle function + * + */ +static void Aontimer_CommonProcessInterrupt(void) +{ + if (NULL != s_pAontimerNotifyPtr) + { + s_pAontimerNotifyPtr(); + } +} + +/** + * @brief Aontimer interrupt entry + * + */ +void AONTIMER_IRQHandler(void) +{ + Aontimer_CommonProcessInterrupt(); + AONTIMER_HWA_ClearInterruptFlag(); + AONTIMER_HWA_EnableTimer(); +} diff --git a/Src/fc7xxx_driver_cmp.c b/Src/fc7xxx_driver_cmp.c new file mode 100644 index 0000000..260ff16 --- /dev/null +++ b/Src/fc7xxx_driver_cmp.c @@ -0,0 +1,324 @@ +/** + * @file fc7xxx_driver_cmp.c + * @author Flagchip0126 + * @brief FC7xxx CMP driver source code + * @version 0.1.0 + * @date 2024-01-15 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Author CR# Descriptions +* --------- ---------- ------------ ---------- ------------------------ +* 0.1.0 2024-01-15 Flagchip0126 N/A First version for FC7240 +**********************************************************************************/ + +#include "fc7xxx_driver_cmp.h" +#include "interrupt_manager.h" + +/********* Local Variables ************/ +static CMP_Type *const s_apCmpBase[CMP_INSTANCE_COUNT] = CMP_BASE_PTRS; +static CMP_CompleteIntCallback s_apCmpIntNotify[CMP_INSTANCE_COUNT] = {NULL}; + +/******* Local Function Prototype *********/ + +/** + * @brief set CMPn IRQHandler + * + * @param eInstance the CMP instance to use + */ +static void CMPn_IRQHandler(const CMP_InstanceType eInstance); + +void CMP0_IRQHandler(void); + +void CMP1_IRQHandler(void); + +static void CMPn_IRQHandler(const CMP_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + + /*callback function*/ + if (s_apCmpIntNotify[eInstance] != NULL) + { + s_apCmpIntNotify[eInstance](); + } + else + { + /*Noting to do*/ + } + + /*clear interrupter status regs*/ + CMP_ClearIntFlag(eInstance); +} + +void CMP0_IRQHandler(void) +{ + CMPn_IRQHandler(CMP_INSTANCE_0); +} + +void CMP1_IRQHandler(void) +{ + CMPn_IRQHandler(CMP_INSTANCE_1); +} + +/********* Local Functions ************/ +void CMP_Enable(const CMP_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + CMP_HWA_Enable(pCmp); +} + +void CMP_Disable(const CMP_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + CMP_HWA_Disable(pCmp); +} + +void CMP_CSEnable(const CMP_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + CMP_HWA_CSEnable(pCmp); +} + +void CMP_CSDisable(const CMP_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + CMP_HWA_CSDisable(pCmp); +} + +bool CMP_GetCmpOut(const CMP_InstanceType eInstance) +{ + bool CmpOut; + + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + CmpOut = CMP_HWA_GetCmpOut(pCmp); + return CmpOut; +} + +void CMP_SetDacData(const CMP_InstanceType eInstance, uint8_t u8Data) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + CMP_HWA_SetDacData(pCmp, u8Data); +} + +CMP_OutStatus CMP_GetOutFlagStatus(const CMP_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + bool bCFF_Status = false; + bool bCFR_Status = false; + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + CMP_OutStatus eRetVal = CMP_OUT_NONE; + + bCFF_Status = CMP_HWA_GetIntFlag_Falling(pCmp); + bCFR_Status = CMP_HWA_GetIntFlag_Rising(pCmp); + + if ((bCFF_Status == true) && (bCFR_Status == false)) + { + eRetVal = CMP_OUT_FALLING_EDGE; + } + else if ((bCFF_Status == false) && (bCFR_Status == true)) + { + eRetVal = CMP_OUT_RISING_EDGE; + } + else + { + eRetVal = CMP_OUT_NONE; + } + + return eRetVal; +} + +bool CMP_GetChannelScanFlagStatus(const CMP_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + bool bCSF_Status = false; + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + bCSF_Status = CMP_HWA_GetIntFlag_ChannelScan(pCmp); + + return bCSF_Status; +} + +void CMP_ClearIntFlag(const CMP_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + CMP_HWA_ClearIntFlag_Rising(pCmp); + CMP_HWA_ClearIntFlag_Falling(pCmp); + CMP_HWA_ClearIntFlag_ChannelScan(pCmp); +} + +void CMP_Init(const CMP_InstanceType eInstance, const CMP_InitType *const pInitCfg) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + DEV_ASSERT(pInitCfg != NULL); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + /* disable CMP module */ + CMP_HWA_Disable(pCmp); + + /* determine comparator function mode */ + CMP_HWA_SetComparatorMod(pCmp, (pInitCfg->tComparatorConfig).eModSel, ((pInitCfg->tComparatorConfig).u8FilterPeriod), ((pInitCfg->tComparatorConfig).eFilterCnt)); + + /* configure CMP module */ + /* CCR0 register */ + CMP_HWA_SetEnStopMod(pCmp, (pInitCfg->tComparatorConfig).bStopModEn); + CMP_HWA_SetDacEnableSrc(pCmp, (pInitCfg->tDacConfig).eDacEnsrc); + + /* CCR1 register */ + CMP_HWA_SetCmpOutInvert(pCmp, (pInitCfg->tComparatorConfig).eInvert); + CMP_HWA_SetCmpOutSel(pCmp, (pInitCfg->tComparatorConfig).eOutSelect); + CMP_HWA_SetEnCmpOutPack(pCmp, (pInitCfg->tComparatorConfig).bOutToPackagePinEn); + CMP_HWA_SetCmpOutWinLevel(pCmp, (pInitCfg->tComparatorConfig).eOutWinLevel); + CMP_HWA_SetCmpOutWin(pCmp, (pInitCfg->tComparatorConfig).eOutWin); + CMP_HWA_SetEnWinSampleInvert(pCmp, (pInitCfg->tComparatorConfig).bWinSampleInvertEn); + CMP_HWA_SetEnEventCloseWin(pCmp, (pInitCfg->tComparatorConfig).bEventCloseWinEn); + CMP_HWA_SetEventCloseWin(pCmp, (pInitCfg->tComparatorConfig).eEventSelect); + + /* CCR2 register */ + CMP_HWA_SetSpeedMod(pCmp, (pInitCfg->tComparatorConfig).eSpeedMod); + CMP_HWA_SetHystCtrl(pCmp, (pInitCfg->tComparatorConfig).eHystCrtl); + CMP_HWA_SetPSelMux(pCmp, (pInitCfg->tMuxConfig).ePSelMux); + CMP_HWA_SetNSelMux(pCmp, (pInitCfg->tMuxConfig).eNSelMux); + CMP_HWA_SetINPSel(pCmp, (pInitCfg->tMuxConfig).eINPSel); + CMP_HWA_SetINNSel(pCmp, (pInitCfg->tMuxConfig).eINNSel); + + /* CCR3 register */ + CMP_HWA_SetAnalogConfTransByp(pCmp, (pInitCfg->tComparatorConfig).bAnalogConfTransByp); + CMP_HWA_SetAnalogConfTransBypCnt(pCmp, (pInitCfg->tComparatorConfig).u16AnalogConfTransBypCnt); + + /* DCR register */ + CMP_HWA_SetEnDac(pCmp, (pInitCfg->tDacConfig).bDacEn); + CMP_HWA_SetVinRefSel(pCmp, (pInitCfg->tDacConfig).eVinRefSel); + CMP_HWA_SetDacData(pCmp, (pInitCfg->tDacConfig).u8DacData); + + if ((pInitCfg->tComparatorConfig).eModSel == CMP_MOD_CHANNEL_SCAN) + { + /* CSCR0 register */ + CMP_HWA_SetCSInitModulus(pCmp, (pInitCfg->tChannelScanConfig).u8ChannelScanInitModulus); + CMP_HWA_SetCSNumOfSampleClocks(pCmp, (pInitCfg->tChannelScanConfig).u8ChannelScanNumOfSampleClocks); + + /* CSCR1 register */ + CMP_HWA_SetCSFixedChannel(pCmp, (pInitCfg->tMuxConfig).eChannelScanFixedChannel); + CMP_HWA_SetCSFixedPort(pCmp, (pInitCfg->tMuxConfig).eChannelScanFixedPort); + + /* CSCSR register */ + CMP_HWA_SetCSComparisonResultsAutoClearEn(pCmp, (pInitCfg->tChannelScanConfig).bComparisonResultAutoClear); + } +} + +void CMP_InitInterrupt(const CMP_InstanceType eInstance, const CMP_InterruptType *const pInterruptCfg) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + DEV_ASSERT(pInterruptCfg != NULL); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + /*disable DMA*/ + CMP_HWA_DmaDisable(pCmp); + + /*clear interrupter flag*/ + CMP_ClearIntFlag(eInstance); + + /*configure interrupter */ + CMP_SetIntEn(eInstance, pInterruptCfg); + + s_apCmpIntNotify[eInstance] = pInterruptCfg->pInterrupterNotify; +} + +void CMP_InitInterrupt_Dma(const CMP_InstanceType eInstance, const CMP_DmaType *const pInterruptDmaCfg) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + DEV_ASSERT(pInterruptDmaCfg != NULL); + + CMP_InterruptType pInterruptCfg; + + pInterruptCfg.bRisingIntEn = pInterruptDmaCfg->bRisingDmaEn; + pInterruptCfg.bFallingIntEn = pInterruptDmaCfg->bFallingDmaEn; + pInterruptCfg.bChannelScanFlagIntEn = false; + pInterruptCfg.pInterrupterNotify = NULL; + + /* Set rising/falling edge interrupt to trigger Dma*/ + CMP_SetIntEn(eInstance, &pInterruptCfg); + + if ((pInterruptDmaCfg->bRisingDmaEn == true) || (pInterruptDmaCfg->bFallingDmaEn == true)) + { + CMP_DmaEnable(eInstance); + } + else + { + CMP_DmaDisable(eInstance); + } +} + +void CMP_SetIntEn(const CMP_InstanceType eInstance, const CMP_InterruptType *const pInterruptCfg) +{ + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + /*set rising edges interrupter enable*/ + CMP_HWA_SetIntEn_Rising(pCmp, pInterruptCfg->bRisingIntEn); + /*set falling edges interrupter enable*/ + CMP_HWA_SetIntEn_Falling(pCmp, pInterruptCfg->bFallingIntEn); + /*set channel scan flag interrupter enable*/ + CMP_HWA_SetIntEn_ChannelScan(pCmp, pInterruptCfg->bChannelScanFlagIntEn); +} + +void CMP_DmaEnable(const CMP_InstanceType eInstance) +{ + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + CMP_HWA_DmaEnable(pCmp); +} + +void CMP_DmaDisable(const CMP_InstanceType eInstance) +{ + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + CMP_HWA_DmaDisable(pCmp); +} + +void CMP_SetCSChannls(const CMP_InstanceType eInstance, const CMP_ChannelScanChannelCfgType s_tChnCfg[], const uint8_t u8ChnCnt) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + uint8_t u8ChnIndex; + + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + for (u8ChnIndex = 0U; u8ChnIndex < u8ChnCnt; u8ChnIndex++) + { + CMP_HWA_SetCSChannelEn(pCmp, s_tChnCfg[u8ChnIndex].eChannel, true); + CMP_HWA_SetCSChannelPresetstate(pCmp, s_tChnCfg[u8ChnIndex].eChannel, s_tChnCfg[u8ChnIndex].bPreSetState); + } +} + +void CMP_GetCSChannlsOut(const CMP_InstanceType eInstance, CMP_ChannelScanChannelCfgType s_tChnCfg[], const uint8_t u8ChnCnt) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + uint8_t u8ChnIndex; + + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + for (u8ChnIndex = 0U; u8ChnIndex < u8ChnCnt; u8ChnIndex++) + { + s_tChnCfg[u8ChnIndex].bCurState = CMP_HWA_GetCSChannelsOut(pCmp, s_tChnCfg[u8ChnIndex].eChannel); + } +} + +bool CMP_GetCmpCSActive(const CMP_InstanceType eInstance) +{ + DEV_ASSERT(eInstance < CMP_INSTANCE_COUNT); + CMP_Type *const pCmp = s_apCmpBase[eInstance]; + + return CMP_HWA_GetCSActive(pCmp); +} diff --git a/Src/fc7xxx_driver_cmu.c b/Src/fc7xxx_driver_cmu.c new file mode 100644 index 0000000..594849e --- /dev/null +++ b/Src/fc7xxx_driver_cmu.c @@ -0,0 +1,386 @@ +/** + * @file fc7xxx_driver_cmu.c + * @author Flagchip085 + * @brief FC7xxx CMU driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 +********************************************************************************/ +#include "fc7xxx_driver_cmu.h" +#include "fc7xxx_driver_scg.h" +#include "fc7xxx_driver_csc.h" +#include "HwA_cmu.h" + +#define CMU_MULTIPLY_FACTOR 100U +#define CMU_PERCENT_FACTOR 100U +#define CMU_DIVID_FACTOR_1K 1000U + +/** @brief CMU Reference clock div type. */ + +/** + * @brief Defines the CMU_ClkFrequenceType + * + * This structure is used to configure the CMU frequence include Reference clock and monitor clock + * + */ +typedef struct +{ + uint32_t u32RefClk; /*!< The Reference clock frequence */ + uint32_t u32MonitorClk; /*!< The target monitored clock frequence. */ +} CMU_ClkFrequenceType; + +typedef struct +{ + uint32_t u32RefWindow; /*!< CMU_REF_WINDOW (Reference Window). */ + uint32_t u32IdealMonitorCnts; /*!< Ideal monitor counter value, used to calculate the MIN,Max threshold. */ + uint32_t u32MinThreshold; /*!< CMU_MIN (Minimum threshold). */ + uint32_t u32MaxThreshold; /*!< CMU_MAX (Maximum threshold). */ + uint32_t u32PerWindow; /*!< CMU_PERIOD (Period monitor mode configuration). */ +} CMU_RegMapType; + + +static CMU_Type *const s_apCmuBase[CMU_INSTANCE_COUNT] = CMU_BASE_PTRS; +static CMU_ISRCallbackType s_apCmuISRCallback[CMU_INSTANCE_COUNT] = {NULL}; + +void CMU0_IRQHandler(void); +void CMU1_IRQHandler(void); +void CMU2_IRQHandler(void); +void CMU3_IRQHandler(void); +void CMU4_IRQHandler(void); + +/* Check Reference clock and monitor clock status.*/ +static CMU_StatusType CMU_ClkStatusCheck(CMU_InstanceType eInstance, CMU_ClkFrequenceType *ptCmuFreq) +{ + CSC_RetStatusType bCscClkStatus; + CMU_StatusType bCmuClkStatus = CMU_VALID; + + if (eInstance == CMU_INSTANCE_0) + { + /* Instance ---- Reference CLK ---- Monitored CLK.*/ + /* CMU0 ---- SIRC ---- RTC_CLK.*/ + ptCmuFreq->u32RefClk = SCG_GetScgClockFreq(SCG_SIRC_CLK); + + bCscClkStatus = CSC0_GetCSC0ClockFreq(CSC0_RTC_CLK, &(ptCmuFreq->u32MonitorClk)); + if (bCscClkStatus != CSC_E_OK) + { + bCmuClkStatus = CMU_CLK_ERROR; + } + } + else if (eInstance == CMU_INSTANCE_1) + { + /* Instance ---- Reference CLK ---- Monitored CLK.*/ + /* CMU1 ---- SIRC ---- FOSC.*/ + ptCmuFreq->u32RefClk = SCG_GetScgClockFreq(SCG_SIRC_CLK); + ptCmuFreq->u32MonitorClk = SCG_GetScgClockFreq(SCG_FOSC_CLK); + } + else if (eInstance == CMU_INSTANCE_2) + { + /* Instance ---- Reference CLK ---- Monitored CLK.*/ + /* CMU2 ---- SIRC ---- FIRC.*/ + ptCmuFreq->u32RefClk = SCG_GetScgClockFreq(SCG_SIRC_CLK); + ptCmuFreq->u32MonitorClk = SCG_GetScgClockFreq(SCG_FIRC_CLK); + } + else if (eInstance == CMU_INSTANCE_3) + { + /* Instance ---- Reference CLK ---- Monitored CLK.*/ + /* CMU3 ---- FIRC ---- SIRC.*/ + ptCmuFreq->u32RefClk = SCG_GetScgClockFreq(SCG_FIRC_CLK); + ptCmuFreq->u32MonitorClk = SCG_GetScgClockFreq(SCG_SIRC_CLK); + } + else if (eInstance == CMU_INSTANCE_4) + { + /* Instance ---- Reference CLK ---- Monitored CLK.*/ + /* CMU4 ---- SIRC ---- SLOW CLOCK.*/ + ptCmuFreq->u32MonitorClk = SCG_GetScgClockFreq(SCG_SLOW_CLK); + ptCmuFreq->u32RefClk = SCG_GetScgClockFreq(SCG_CMU4REF_CLK); + } + else + { + /* Never come here */ + bCmuClkStatus = CMU_CLK_ERROR; + } + + if(bCmuClkStatus == CMU_VALID) + { + if ((ptCmuFreq->u32MonitorClk == 0U) || (ptCmuFreq->u32RefClk == 0U)) + { + bCmuClkStatus = CMU_CLK_ERROR; + } + } + + return bCmuClkStatus; +} + +CMU_StatusType CMU_Init(CMU_InstanceType eInstance, const CMU_CfgType *pInitCfg) +{ + CMU_StatusType eStatus; + CMU_Type *pCmu; + CMU_RefClockDivType eDiv; + CMU_ClkFrequenceType tCmuFreq; + uint32_t u32RefWindow, u32MaxRefWindow, u32MinRefWindow; + uint32_t u32MonitorCnts, u32MinMonitorCnts, u32MaxMonitorCnts; + uint32_t u32RefClk, u32MonitorClk; + uint32_t u32Temp; + + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + DEV_ASSERT(pInitCfg != NULL); + pCmu = s_apCmuBase[(uint8_t)eInstance]; + eDiv = pInitCfg->eDiv; + + /* Check Reference clock and monitor clock status.*/ + eStatus = CMU_ClkStatusCheck(eInstance, &tCmuFreq); + + if (eStatus == CMU_VALID) + { + /* divide the clock value by 1K_factor */ + u32RefClk = (tCmuFreq.u32RefClk >> eDiv) / CMU_DIVID_FACTOR_1K; + u32MonitorClk = tCmuFreq.u32MonitorClk / CMU_DIVID_FACTOR_1K; + + if (u32RefClk / u32MonitorClk <= 0x100U) + { + u32MaxRefWindow = (0xffffffU - 3U) / u32MonitorClk * u32RefClk / 105U * CMU_PERCENT_FACTOR - 2U; + + if (u32MaxRefWindow > 0xffffffU) + { + u32MaxRefWindow = 0xffffffU; + } + } + else + { + u32MaxRefWindow = 0xffffffU; + } + + u32MinRefWindow = 6U + 5U * u32RefClk / u32MonitorClk; + u32RefWindow = 100U * u32MinRefWindow; + + if (u32RefWindow > u32MaxRefWindow) + { + u32RefWindow = u32MaxRefWindow; + } + + u32MonitorCnts = u32MonitorClk * (u32RefWindow + 2U) / u32RefClk; + u32MinMonitorCnts = u32MonitorCnts * 95U / CMU_PERCENT_FACTOR - 3U; + u32MaxMonitorCnts = u32MonitorCnts * 105U / CMU_PERCENT_FACTOR + 3U; + + CMU_HWA_SetRefWindow(pCmu, u32RefWindow); + CMU_HWA_SetMinCnts(pCmu, u32MinMonitorCnts); + CMU_HWA_SetMaxCnts(pCmu, u32MaxMonitorCnts); + + /* Program program PERIOD[EN] and PERIOD[WINDOW]. */ + CMU_HWA_SetPeriodEnable(pCmu, false); + if (pInitCfg->bPerMonitorEnable == true) + { + uint8_t u8MaxPeriod = (uint8_t)(u32RefClk / u32RefWindow); + + if ((u8MaxPeriod >> (uint8_t)CMU_PERIOD_WINDOW_WIDTH) != 0U) + { + u8MaxPeriod = (1U << (uint8_t)CMU_PERIOD_WINDOW_WIDTH) - 1U; + } + + if (u8MaxPeriod != 0U) + { + if (pInitCfg->u8PerMonitorWindow <= u8MaxPeriod) + { + CMU_HWA_SetPeriodWindow(pCmu, (uint32_t)(pInitCfg->u8PerMonitorWindow)); + } + else + { + CMU_HWA_SetPeriodWindow(pCmu, (uint32_t)(u8MaxPeriod)); + } + CMU_HWA_SetPeriodEnable(pCmu, pInitCfg->bPerMonitorEnable); + } + } + + /* Program DIV,IRQ_EN,LP_EN,STOP_EN,ENABLE */ + u32Temp = CMU_HWA_GetCTRL(pCmu); + u32Temp &= ~(uint32_t)(CMU_CTRL_REF_DIV_MASK | CMU_CTRL_IRQ_EN_MASK | \ + CMU_CTRL_LP_EN_MASK | CMU_CTRL_STOP_EN_MASK | CMU_CTRL_ENABLE_MASK); + u32Temp |= (uint32_t)(CMU_CTRL_REF_DIV(eDiv) | CMU_CTRL_IRQ_EN(pInitCfg->bIntEnable) | \ + CMU_CTRL_LP_EN(pInitCfg->bLpen) | CMU_CTRL_STOP_EN(pInitCfg->bSten) | \ + CMU_CTRL_ENABLE(pInitCfg->bEnable)); + CMU_HWA_SETCTRL(pCmu, u32Temp); + + s_apCmuISRCallback[(uint8_t)eInstance] = pInitCfg->pIsrCallback; + } + else + { + /* clock status invalid, change, do nothing */ + } + + return eStatus; +} + +void CMU_Enable(CMU_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + CMU_HWA_Enable(s_apCmuBase[(uint8_t)eInstance]); +} + +void CMU_Disable(CMU_InstanceType eInstance) +{ + CMU_Type *pCmu; + + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + pCmu = s_apCmuBase[(uint8_t)eInstance]; + + CMU_HWA_Disable(pCmu); + CMU_HWA_ClearST(pCmu); +} + +void CMU_EnableInterrupt(CMU_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + CMU_HWA_IrqEnable(s_apCmuBase[(uint8_t)eInstance],true); +} + +void CMU_DisableInterrupt(CMU_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + CMU_HWA_IrqEnable(s_apCmuBase[(uint8_t)eInstance],false); +} + +CMU_InterruptType CMU_GetInterruptType(CMU_InstanceType eInstance) +{ + uint32_t u32Temp; + CMU_InterruptType eStatus; + + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + + u32Temp = CMU_HWA_GetST(s_apCmuBase[(uint8_t)eInstance]); + if ((u32Temp & CMU_ST_LOC_MASK) != 0U) + { + eStatus = CMU_INTERRUPT_LOC; + } + else if ((u32Temp & CMU_ST_MIS_MASK) != 0U) + { + eStatus = CMU_INTERRUPT_MIS; + } + else + { + eStatus = CMU_INTERRUPT_NONE; + } + + return eStatus; +} + +CMU_StatusType CMU_SetCmu4RefSrc(CMU_Cmu4ClkSrcType eSrc) +{ + SCG_StatusType eStatus; + + SCG_HWA_SetCmu4Clk(0U); + + if (CMU_CMU4_REF_CLK_FOSC == eSrc) + { + eStatus = SCG_SetCmu4Clk(SCG_CMU4CLK_SRC_FOSC); + } + else if (CMU_CMU4_REF_CLK_SIRC == eSrc) + { + eStatus = SCG_SetCmu4Clk(SCG_CMU4CLK_SRC_SIRC); + } + else + { + eStatus = SCG_STATUS_PARAM_ERROR; + } + + return (eStatus == SCG_STATUS_SUCCESS) ? CMU_VALID : CMU_CLK_ERROR; +} + +uint32_t CMU_GetCount(CMU_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + + return CMU_HWA_GetCount(s_apCmuBase[(uint8_t)eInstance]); +} + +uint32_t CMU_GetMinCount(CMU_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + + return CMU_HWA_GetMinCnts(s_apCmuBase[(uint8_t)eInstance]); +} + +uint32_t CMU_GetMaxCount(CMU_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + + return CMU_HWA_GetMaxCnts(s_apCmuBase[(uint8_t)eInstance]); +} + +void CMU_LowPowerModeEnable(CMU_InstanceType eInstance, CMU_LowpowerModeType eMode, bool bModeEnable, bool bRestartEnable) +{ + CMU_Type *pCmu; + + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + pCmu = s_apCmuBase[(uint8_t)eInstance]; + + if (eMode == CMU_STANDBY_MODE) + { + CMU_HWA_StopModeEnable(pCmu, bModeEnable); + CMU_HWA_StanbyModeEnable(pCmu, bModeEnable); + } + else if (eMode == CMU_STOP_MODE) + { + CMU_HWA_StopModeEnable(pCmu, bModeEnable); + } + else + { + + } + + CMU_HWA_LPRestartEnable(pCmu, bRestartEnable); +} + + +/***************CMU IRQ Functions*****************/ + +static void CMU_IRQHandler(CMU_InstanceType eInstance) +{ + CMU_Type *pCmu; + CMU_InterruptType eStatus; + + DEV_ASSERT((uint8_t)eInstance < CMU_INSTANCE_COUNT); + pCmu = s_apCmuBase[(uint8_t)eInstance]; + + eStatus = CMU_GetInterruptType(eInstance); + + if (s_apCmuISRCallback[(uint8_t)eInstance] != NULL) + { + s_apCmuISRCallback[(uint8_t)eInstance](eInstance, eStatus); + } + + CMU_HWA_ClearST(pCmu); +} + +void CMU0_IRQHandler(void) +{ + CMU_IRQHandler(CMU_INSTANCE_0); +} + +void CMU1_IRQHandler(void) +{ + CMU_IRQHandler(CMU_INSTANCE_1); +} + +void CMU2_IRQHandler(void) +{ + CMU_IRQHandler(CMU_INSTANCE_2); +} + +void CMU3_IRQHandler(void) +{ + CMU_IRQHandler(CMU_INSTANCE_3); +} + +void CMU4_IRQHandler(void) +{ + CMU_IRQHandler(CMU_INSTANCE_4); +} diff --git a/Src/fc7xxx_driver_cordic.c b/Src/fc7xxx_driver_cordic.c new file mode 100644 index 0000000..4f4162a --- /dev/null +++ b/Src/fc7xxx_driver_cordic.c @@ -0,0 +1,280 @@ +/** + * @file fc7xxx_driver_cordic.c + * @author Flagchip + * @brief FC7xxx Cordic driver source code + * @version 0.1.0 + * @date 2024-01-11 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-11 Flagchip054 N/A First version for FC7240 + ******************************************************************************** */ +#include "fc7xxx_driver_cordic.h" +#include "interrupt_manager.h" + +#define CORDIC_SIGN_BIT 0x80000000UL +#define CORDIC_EXP_BIT 0x7F800000UL +#define CORDIC_TAIL_BIT 0x007FFFFFUL + +#define REVERSE_SCALEING_FACTOR_K 0x4dba76b2 +#define REVERSE_SCALEING_FACTOR_KA 0x9A8F4314 + +#define USE_FPU_HARDWARE 0 + + +/** + * @brief Floating-point conversion to 24 bit fixed-point + * + * @param nFloat Input value + */ + + +/*************** Local Functions ***************/ +/** + * @brief Clips Q63 to Q31 values. + */ +__attribute__((always_inline)) static inline int32_t clip_q63_to_q31( + int64_t x) +{ + return ((int32_t)(x >> 32) != ((int32_t) x >> 31)) ? + ((0x7FFFFFFF ^ ((int32_t)(x >> 63)))) : (int32_t) x; +} + + +static int32_t Float2Fix_Convert(const float data) +{ + return clip_q63_to_q31((int64_t)(data * 2147483648.0f)); +} + +/***************** Global Functions *******************/ +/** + * @brief The function to calculate sin & cos + * + * @param radian the input value to calculate + * + * input range (−90°, +90°)/180° + */ +CORDIC_SinCos_Type Cordic_Circular_Sin_Cos(const float radian) +{ + /* angles are expressed in radian, multiplied by a constant number. 𝜃/180 * 𝜋c (where 𝜋c is 13.42177) */ + CORDIC_SinCos_Type tRetVal; + //float tmp = REVERSE_SCALEING_FACTOR_K; + float tmp = 0; + int32_t fix_radian = Float2Fix_Convert(radian); + int32_t x_input = REVERSE_SCALEING_FACTOR_K; + Cordic_HWA_Set_XInput(x_input); + Cordic_HWA_Set_YInput(0); + Cordic_HWA_Set_ZInput(fix_radian); + /* Disable interrupt + Iteration Number16 + Trigonometric system + Rotate mode */ + Cordic_HWA_SetCtrl(CORDIC_CTR_VAL(0, false, (uint32_t)CORDIC_Iteration_16, (uint32_t)CORDIC_Trigonometric, (uint32_t)CORDIC_Rotate)); + while (!Cordic_HWA_Get_Stat()) {} + tmp = (int32_t)Cordic_HWA_Get_YOutput() / 2147483648.f; //134217728.f; + tRetVal.sinx = tmp; + tmp = (int32_t)Cordic_HWA_Get_XOutput() / 2147483648.f; //134217728.f; + tRetVal.cosx = tmp; + return tRetVal; +} + +/** + * @brief The function to calculate circular radical add + * + * @param1 x the first input value + * + * @param2 y the second input value + */ +CORDIC_Radical_Type Cordic_Circular_Radical_Add(const float x, const float y) +{ + CORDIC_Radical_Type tRetVal; + /*** 40752053.5625 = REVERSE_SCALEING_FACTOR_K / 32 ***/ + int32_t x_input = (int32_t)(40752053.5625 * x); + int32_t y_input = (int32_t)(40752053.5625 * y); + Cordic_HWA_Set_XInput(x_input); + Cordic_HWA_Set_YInput(y_input); + Cordic_HWA_Set_ZInput(0); + /* Disable interrupt + Iteration Number16 + Trigonometric system + Vector mode */ + Cordic_HWA_SetCtrl(CORDIC_CTR_VAL(5, false, (uint32_t)CORDIC_Iteration_16, (uint32_t)CORDIC_Trigonometric, (uint32_t)CORDIC_Vector)); + while (!Cordic_HWA_Get_Stat()) {} + /*** 67,108,864 = 2147483648.f / 32 ***/ + tRetVal = Cordic_HWA_Get_XOutput() / 67108864.f; + return tRetVal; +} + +/** + * @brief The function to calculate circular arctan + * + * @param y the input value + */ +CORDIC_Arctan_Type Cordic_Circular_Arctan_F(const float y) +{ + CORDIC_Arctan_Type tRetVal; + if ((y > 96.6) || (y < -96.6)) + { + tRetVal = 89.4069; + } + else + { + int32_t x_input = 2147484; + int32_t y_input = (int32_t)(y * 2147484); + Cordic_HWA_Set_XInput(x_input); + Cordic_HWA_Set_YInput(y_input); + Cordic_HWA_Set_ZInput(0); + /* Disable interrupt + Iteration Number16 + Trigonometric system + Vector mode */ + Cordic_HWA_SetCtrl(CORDIC_CTR_VAL(0, false, (uint32_t)CORDIC_Iteration_16, (uint32_t)CORDIC_Trigonometric, (uint32_t)CORDIC_Vector)); + while (!Cordic_HWA_Get_Stat()) {} + /*** 11,930,464.711111 = 12147483648 / 180 ***/; + tRetVal = (int32_t)Cordic_HWA_Get_ZOutput() / 11930464.711111; + } + return tRetVal; +} + +/** + * @brief The function to calculate circular arctan + * + * @param1 x the first input value + * + * @param2 y the second input value + */ +CORDIC_Arctan_Type Cordic_Circular_Arctan(const int32_t x, const int32_t y) +{ + CORDIC_Arctan_Type tRetVal; + + Cordic_HWA_Set_XInput(x); + Cordic_HWA_Set_YInput(y); + Cordic_HWA_Set_ZInput(0); + /* Disable interrupt + Iteration Number16 + Trigonometric system + Vector mode */ + Cordic_HWA_SetCtrl(CORDIC_CTR_VAL(0, false, (uint32_t)CORDIC_Iteration_16, (uint32_t)CORDIC_Trigonometric, (uint32_t)CORDIC_Vector)); + while (!Cordic_HWA_Get_Stat()) {} + /*** 11,930,464.711111 = 12147483648 / 180 ***/; + tRetVal = (int32_t)Cordic_HWA_Get_ZOutput() / 11930464.711111; + return tRetVal; +} + +/** + * @brief The function to calculate circular Sinh & Cosh + * + * @param z the input value + */ +CORDIC_SinhCosh_Type Cordic_Circular_Sinh_Cosh(const float z) +{ + CORDIC_SinhCosh_Type tRetVal; + float tmp = 0; + + /*** 1073741824 = 2147483648 / 2 ***/ + int32_t z_input = (int32_t)(z * 1073741824.f); + /*** 1296540042 = REVERSE_SCALEING_FACTOR_KA / 2 ***/ + int32_t x_input = 1296540042; + + Cordic_HWA_Set_XInput(x_input); + Cordic_HWA_Set_YInput(0); + Cordic_HWA_Set_ZInput(z_input); + /* Scale 1 + Disable interrupt + Iteration Number16 + Hyperbolic system + Rotate mode */ + Cordic_HWA_SetCtrl(CORDIC_CTR_VAL(1, false, (uint32_t)CORDIC_Iteration_16, (uint32_t)CORDIC_Hyperbolic, (uint32_t)CORDIC_Rotate)); + while (!Cordic_HWA_Get_Stat()) {} + /*** 1073741824 = 2147483648 / 2 ***/ + tmp = (int32_t)Cordic_HWA_Get_YOutput() / 1073741824.f ; + tRetVal.sinxh = tmp; + /*** 1073741824 = 2147483648 / 2 ***/ + tmp = (int32_t)Cordic_HWA_Get_XOutput() / 1073741824.f; + tRetVal.cosxh = tmp; + return tRetVal; +} + +/** + * @brief The function to calculate circular radical sub + * + * @param1 x the first input value + * + * @param2 y the second input value + */ +CORDIC_Radical_Type Cordic_Circular_Radical_Sub(const float x, const float y) +{ + CORDIC_Radical_Type tRetVal; + /*** 162067505 = REVERSE_SCALEING_FACTOR_KA / 16 ***/ + int32_t x_input = (int32_t)(162067505.f * x); + int32_t y_input = (int32_t)(162067505.f * y); + + Cordic_HWA_Set_XInput(x_input); + Cordic_HWA_Set_YInput(y_input); + Cordic_HWA_Set_ZInput(0); + /* Disable interrupt + Iteration Number16 + Hyperbolic system + Vector mode */ + Cordic_HWA_SetCtrl(CORDIC_CTR_VAL(4, false, (uint32_t)CORDIC_Iteration_16, (uint32_t)CORDIC_Hyperbolic, (uint32_t)CORDIC_Vector)); + while (!Cordic_HWA_Get_Stat()) {} + /*** 134217728 = 2147483648.f / 16 ***/ + tRetVal = Cordic_HWA_Get_XOutput() / 134217728.f; + return tRetVal; +} + +/** + * @brief The function to calculate circular arctanh + * + * @param y the input value + */ +CORDIC_Arctanh_Type Cordic_Circular_Arctanh(const float y) +{ + CORDIC_Arctanh_Type tRetVal; + + /*** 1073741824 = 2147483648 / 2 ***/ + int32_t x_input = 1073741824; + int32_t y_input = (int32_t)(y * 1073741824.f); + + Cordic_HWA_Set_XInput(x_input); + Cordic_HWA_Set_YInput(y_input); + Cordic_HWA_Set_ZInput(0); + /* Disable interrupt + Iteration Number16 + Hyperbolic system + Vector mode */ + Cordic_HWA_SetCtrl(CORDIC_CTR_VAL(1, false, (uint32_t)CORDIC_Iteration_16, (uint32_t)CORDIC_Hyperbolic, (uint32_t)CORDIC_Vector)); + while (!Cordic_HWA_Get_Stat()) {} + /*** 1073741824 = 2147483648 / 2 ***/ + tRetVal = (int32_t)Cordic_HWA_Get_ZOutput() / 1073741824.f; + return tRetVal; +} + +/** + * @brief The function to calculate ln + * + * @param y the input value (0.1068482375 , 9.3590687463) + */ +CORDIC_Ln_Type Cordic_Extended_LN(const float y) +{ + CORDIC_Ln_Type tRetVal; + /*** 134217728 = 2147483648 / 16 ***/ + int32_t x_input = (int32_t)((y + 1) * 134217728.f); + int32_t f_input = (int32_t)((y - 1) * 134217728.f); + Cordic_HWA_Set_XInput(x_input); + Cordic_HWA_Set_YInput(f_input); + Cordic_HWA_Set_ZInput(0); + /* Disable interrupt + Iteration Number16 + Hyperbolic system + Vector mode */ + Cordic_HWA_SetCtrl(CORDIC_CTR_VAL(4, false, (uint32_t)CORDIC_Iteration_16, (uint32_t)CORDIC_Hyperbolic, (uint32_t)CORDIC_Vector)); + while (!Cordic_HWA_Get_Stat()) {} + /*** 67108864 = 12147483648.f / 32 ***/; + tRetVal = (int32_t)Cordic_HWA_Get_ZOutput() / 67108864.f; + return tRetVal; +} + +/** + * @brief The function to calculate sqrt + * + * @param y the input value (0.0267120594,2.3397671865) + */ +CORDIC_Ln_Type Cordic_Extended_Sqrt(const float y) +{ + CORDIC_Radical_Type tRetVal; + /*** 648270021 = 2593080084 / 4 ***/ + int32_t x_input = (int32_t)(648270021.f * (y + 0.25)); + int32_t y_input = (int32_t)(648270021.f * (y - 0.25)); + + Cordic_HWA_Set_XInput(x_input); + Cordic_HWA_Set_YInput(y_input); + Cordic_HWA_Set_ZInput(0); + /* Disable interrupt + Iteration Number16 + Hyperbolic system + Vector mode */ + Cordic_HWA_SetCtrl(CORDIC_CTR_VAL(2, false, (uint32_t)CORDIC_Iteration_16, (uint32_t)CORDIC_Hyperbolic, (uint32_t)CORDIC_Vector)); + while (!Cordic_HWA_Get_Stat()) {} + /*** 536870912 = 2147483648 / 4 ***/ + tRetVal = Cordic_HWA_Get_XOutput() / 536870912.f; + return tRetVal; +} diff --git a/Src/fc7xxx_driver_cpm.c b/Src/fc7xxx_driver_cpm.c new file mode 100644 index 0000000..688ce50 --- /dev/null +++ b/Src/fc7xxx_driver_cpm.c @@ -0,0 +1,210 @@ + /* @file fc7xxx_driver_cpm.c + * @author Flagchip + * @brief FC7xxx CPM driver type definition and API + * @version 0.1.0 + * @date 2024-01-5 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ + + /* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-1-5 Flagchip120 N/A First version for FC7240 + ******************************************************************************** */ +#include "fc7xxx_driver_cpm.h" +#include "interrupt_manager.h" +#include "fc7xxx_driver_fcuart.h" + +/** + * @brief Cpm user defined interrupt function + * */ +static CPM_InterruptCallBackType s_pCpmNotifyPtr = NULL; + +/* ################################################################################## */ +/* ########################### Local Prototype Functions ############################ */ +void CPM_IRQHandler(void); + +/* ################################################################################## */ +/* ################################ Global Functions ################################ */ +/** + * + * @brief Configures the CPM module interrupts. + * + * This function configures the CPM module interrupts to enable/disable various interrupt sources. + * + * @param eIntSrc CPM FPU interrupt type. refer CPM FISCR register + * @param bEnable 1: interrupt enable, 0:interrupt disable. + */ +void CPM_FpuIntMode(FPU_IntType eIntSrc, bool bEnable) +{ + switch (eIntSrc) + { + case CPM_FPU_FIO: + CPM_HWA_SetFioceInt(bEnable); + break; + case CPM_FPU_FDZ: + CPM_HWA_SetFdzceInt(bEnable); + break; + case CPM_FPU_FOF: + CPM_HWA_SetFofceInt(bEnable); + break; + case CPM_FPU_FUF: + CPM_HWA_SetFufceInt(bEnable); + break; + case CPM_FPU_FIX: + CPM_HWA_SetFixceInt(bEnable); + break; + case CPM_FPU_FID: + CPM_HWA_SetFidceInt(bEnable); + break; + default : + /* Invalid parameter: return */ + break; + } +} + +/** + * @brief Get CPM Interrupt occurred flag + * + * This function returns the interrupt flag. + * + * @param eIntSrc CPM FPU interrupt type. refer CPM FISCR register + * @return true interrupt occurred + * @return false No interrupt + */ +bool CPM_GetFpuIntStatus(FPU_IntType eIntSrc) +{ + bool bRetVal = false; + switch(eIntSrc){ + case CPM_FPU_FIO: + bRetVal = CPM_HWA_GetFpuFiocFlag(); + break; + case CPM_FPU_FDZ: + bRetVal = CPM_HWA_GetFpuFdzcFlag(); + break; + case CPM_FPU_FOF: + bRetVal = CPM_HWA_GetFpuFofcFlag(); + break; + case CPM_FPU_FUF: + bRetVal = CPM_HWA_GetFpuFufcFlag(); + break; + case CPM_FPU_FIX: + bRetVal = CPM_HWA_GetFpuFixcFlag(); + break; + case CPM_FPU_FID: + bRetVal = CPM_HWA_GetFpuFidcFlag(); + break; + default: + break; + + } + return bRetVal; +} + + +#ifdef FPU_USED_ENABLE +/** + * @brief CPM_Read_FPSCR + * Return the current value of FPSCR + * @return u32RetVal + */ +uint32_t CPM_Read_FPSCR(void) +{ + uint32_t u32RetVal = 0U; + __asm( + "vmrs %0, fpscr" : "=r" (u32RetVal) + ); + return u32RetVal; +} + +/** + * @brief CPM_Write_FPSCR + * + * @param u32SetVal set the value for FPSCR + */ +void CPM_Write_FPSCR(uint32_t u32SetVal) +{ + __asm( + "vmsr fpscr, %0" : : "r" (u32SetVal) + ); +} + +/** + * @brief Deinit Cpm set interrupt + * + * Restore the Cpm FISCR to its reset state + */ +void CPM_DeInitInterrupt(void) +{ + uint32_t u32RetVal; + CPM_HWA_SetFiscr(0x0U); + u32RetVal = CPM_Read_FPSCR(); + /* Clear FPSCR IDC/IXC/UFC/OPF/DZC/IOC flag*/ + u32RetVal &=0xFFFFFF90u; + CPM_Write_FPSCR(u32RetVal); +} +#endif + +/** + * @brief CPM interrupt function + * + */ +void CPM_IRQHandler(void) +{ + if(s_pCpmNotifyPtr != NULL) + { + s_pCpmNotifyPtr(); + } +} + +/** + * @brief Cpm set interrupt + * + * @param pIntStruct interrupt structure pointer + * @return Cpm return type + */ +CPM_RetType CPM_InitInterrupt(const CPM_InterruptType *pIntStruct) +{ + CPM_RetType eRet = CPM_STATUS_SUCCESS; + if(NULL == pIntStruct) + { + eRet = CPM_STATUS_PARAM_INVALID; + } + else + { + if(pIntStruct->u8CpmEnable != 0U) + { + if(((uint32_t)(pIntStruct->eFPU_IntType) & CPM_FISCR_FIOC_MASK) == CPM_FPU_FIO) + { + CPM_FpuIntMode(CPM_FPU_FIO,true); + } + if(((uint32_t)(pIntStruct->eFPU_IntType) & CPM_FISCR_FDZC_MASK) == CPM_FPU_FDZ) + { + CPM_FpuIntMode(CPM_FPU_FDZ,true); + } + if(((uint32_t)(pIntStruct->eFPU_IntType) & CPM_FISCR_FUFC_MASK) == CPM_FPU_FUF) + { + CPM_FpuIntMode(CPM_FPU_FUF,true); + } + if(((uint32_t)(pIntStruct->eFPU_IntType) & CPM_FISCR_FOFC_MASK) == CPM_FPU_FOF) + { + CPM_FpuIntMode(CPM_FPU_FOF,true); + } + if(((uint32_t)(pIntStruct->eFPU_IntType) & CPM_FISCR_FIDC_MASK) == CPM_FPU_FID) + { + CPM_FpuIntMode(CPM_FPU_FID,true); + } + if(((uint32_t)(pIntStruct->eFPU_IntType) & CPM_FISCR_FIXC_MASK) == CPM_FPU_FIX) + { + CPM_FpuIntMode(CPM_FPU_FIX,true); + } + } + s_pCpmNotifyPtr = pIntStruct->pIsrNotify; + } + return eRet; +} + diff --git a/Src/fc7xxx_driver_crc.c b/Src/fc7xxx_driver_crc.c new file mode 100644 index 0000000..feacc2f --- /dev/null +++ b/Src/fc7xxx_driver_crc.c @@ -0,0 +1,167 @@ +/** + * @file fc7xxx_driver_crc.c + * @author Flagchip + * @brief FC7xxx CRC driver source code + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-12 Flagchip119 N/A First version for FC7240 +********************************************************************************/ + +#include "fc7xxx_driver_crc.h" + + + +/********* Local Variables ************/ +static CRC_Type *const s_apCrcBase[CRC_INSTANCE_COUNT] = CRC_BASE_PTRS; + + +/********* Local Functions ************/ + +void CRC_Init(uint8_t u8Instance, const CRC_InitType *const pInitCfg) +{ + DEV_ASSERT(u8Instance < CRC_INSTANCE_COUNT); + DEV_ASSERT(pInitCfg != NULL); + CRC_Type *const pCrc = s_apCrcBase[u8Instance]; + + if (pInitCfg->eBitWidth == CRC_BIT_8) + { + /* set CRC bit width(8-bit) */ + CRC_HWA_Set_8Bit_Width(pCrc, (CRC_BitWidthType)(pInitCfg->eBitWidth - 1)); + CRC_HWA_SetBitWidth(pCrc, (CRC_BitWidthType)0); + } + else + { + /* set CRC bit width(16-bit or 32-bit) */ + CRC_HWA_Set_8Bit_Width(pCrc, (CRC_BitWidthType)0); + CRC_HWA_SetBitWidth(pCrc, pInitCfg->eBitWidth); + } + + /* set CRC write/read swap and FXOR */ + CRC_HWA_SetWriteDataSwap(pCrc, pInitCfg->eWriteDataSwap); + CRC_HWA_SetReadDataSwap(pCrc, pInitCfg->eReadDataSwap); + CRC_HWA_SetReadDataFXOR(pCrc, pInitCfg->eReadDataFXOR); + + /* set CRC polynomial value */ + CRC_HWA_SetPolyVal(pCrc, pInitCfg->u32Polynomial); + + /* set CRC seed value */ + CRC_SetSeed(u8Instance, pInitCfg->u32SeedValue); +} + +void CRC_DeInit(uint8_t u8Instance) +{ + DEV_ASSERT(u8Instance < CRC_INSTANCE_COUNT); + CRC_Type *const pCrc = s_apCrcBase[u8Instance]; + + /* set CRC bit width(32-bit) */ + CRC_HWA_SetBitWidth(pCrc, CRC_BIT_32); + + /* set CRC write/read swap and FXOR */ + CRC_HWA_SetWriteDataSwap(pCrc, WRITE_DATASWAP_NONE); + CRC_HWA_SetReadDataSwap(pCrc, READ_DATASWAP_NONE); + CRC_HWA_SetReadDataFXOR(pCrc, READ_DATA_NORMAL); + + /* set CRC polynomial value */ + CRC_HWA_SetPolyVal(pCrc, CRC_DEFAULT_POLY); + + /* set CRC seed value */ + CRC_SetSeed(u8Instance, CRC_DEFAULT_INTVAL); +} + +uint32_t CRC_GetCrcResult(uint8_t u8Instance) +{ + DEV_ASSERT(u8Instance < CRC_INSTANCE_COUNT); + CRC_Type *const pCrc = s_apCrcBase[u8Instance]; + CRC_ReadDataSwapType eTempVal; + uint32_t u32Ret; + + eTempVal = CRC_HWA_GetReadDataSwap(pCrc); + + if (CRC_BIT_8 == CRC_HWA_Get8BitWidth(pCrc)) + { + /* Returns upper 8 bits of CRC because of swap in 8 bits mode */ + if ((eTempVal == READ_DATASWAP_BIT_BYTE) || (eTempVal == READ_DATASWAP_BYTE)) + { + u32Ret = CRC_HWA_GetData_U8_H(pCrc); + } + else + { + u32Ret = CRC_HWA_GetData_U8_L(pCrc); + } + return u32Ret; + } + else if (CRC_BIT_16 == CRC_HWA_GetBitWidth(pCrc)) + { + /* Returns upper 16 bits of CRC because of swap in 16 bits mode */ + if ((eTempVal == READ_DATASWAP_BIT_BYTE) || (eTempVal == READ_DATASWAP_BYTE)) + { + u32Ret = CRC_HWA_GetData_U16_H(pCrc); + } + else + { + u32Ret = CRC_HWA_GetData_U16_L(pCrc); + } + } + else + { + u32Ret = CRC_HWA_GetData_U32(pCrc); + } + + return u32Ret; +} + +void CRC_SetCalcData_U8(uint8_t u8Instance, uint8_t u8Data) +{ + DEV_ASSERT(u8Instance < CRC_INSTANCE_COUNT); + CRC_Type *const pCrc = s_apCrcBase[u8Instance]; + + CRC_HWA_SetData_U8(pCrc, u8Data); +} + +void CRC_SetCalcData_U16(uint8_t u8Instance, uint16_t u16Data) +{ + DEV_ASSERT(u8Instance < CRC_INSTANCE_COUNT); + CRC_Type *const pCrc = s_apCrcBase[u8Instance]; + + CRC_HWA_SetData_U16(pCrc, u16Data); +} + +void CRC_SetCalcData_U32(uint8_t u8Instance, uint32_t u32Data) +{ + DEV_ASSERT(u8Instance < CRC_INSTANCE_COUNT); + CRC_Type *const pCrc = s_apCrcBase[u8Instance]; + + CRC_HWA_SetData_U32(pCrc, u32Data); +} + +void CRC_SetSeed(uint8_t u8Instance, uint32_t u32SeedVal) +{ + DEV_ASSERT(u8Instance < CRC_INSTANCE_COUNT); + CRC_Type *const pCrc = s_apCrcBase[u8Instance]; + + CRC_HWA_SetDataOrSeed(pCrc, WRITE_COMMAND_SEED); + CRC_HWA_SetData_U32(pCrc, u32SeedVal); + CRC_HWA_SetDataOrSeed(pCrc, WRITE_COMMAND_DATA); +} + +void CRC_SetInputData(uint8_t u8Instance, const uint8_t pData[], uint32_t u32DataSize) +{ + DEV_ASSERT(u8Instance < CRC_INSTANCE_COUNT); + uint32_t i; + + for (i = 0U; i < u32DataSize; i++) + { + CRC_SetCalcData_U8(u8Instance, pData[i]); + } +} + + diff --git a/Src/fc7xxx_driver_csc.c b/Src/fc7xxx_driver_csc.c new file mode 100644 index 0000000..71e091d --- /dev/null +++ b/Src/fc7xxx_driver_csc.c @@ -0,0 +1,1698 @@ +/** + * @file fc7xxx_driver_csc.h + * @author Flagchip + * @brief FC7xxx csc driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ + +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_csc.h" +#include "fc7xxx_driver_scg.h" + +/********* Local Macros ************/ +#define CSC_GET_CPU_ID() ((CSC_WPB_CpuType)1U) + +/********* Local Variables ************/ + +/********* Local functions ************/ + +/** + * @brief Get the frequency of AONCLK clock selected by CSC0_AONCLKSR[AONCLKSEL]. + * + * @return the frequency of AONCLK + */ +static uint32_t CSC0_GetAONClkFreq(void) +{ + CSC0_AONClkSrcType eAonClkSrc; + uint32_t u32Freq; + + eAonClkSrc = CSC0_HWA_GetAONClkSrc(); + + if (CSC0_AON_SIRCDIV_128K_CLK == eAonClkSrc) + { + u32Freq = CSC0_AONCLK_128K; + } + else if (CSC0_AON_SIRC32_1K_CLK == eAonClkSrc) + { + u32Freq = CSC0_AONCLK_1K; + } + else + { + u32Freq = CSC0_AONCLK_32K; + } + return u32Freq; +} + +/** + * @brief Get the frequency of AON32K clock selected by CSC0_AONCLKSR[AON32KCLKSEL]. + * + * @return the frequency of AON32K + */ +static uint32_t CSC0_GetAON32kClkFreq(void) +{ + CSC0_AON32KClkSrcType eAon32KSrc; + uint32_t u32Freq; + + eAon32KSrc = CSC0_HWA_GetAON32kClkSrc(); + + if (CSC0_AON32K_SOSC32K_CLK == eAon32KSrc) + { + u32Freq = CSC0_AONCLK_SOSC_32K; + } + else + { + u32Freq = CSC0_AONCLK_32K; + } + return u32Freq; +} + +/** + * @brief Get the frequency of RTC clock selected by CSC0_AONCLKSR[RTCCLKSEL]. + * + * @return the frequency of RTC + */ +static uint32_t CSC0_GetRTCClkFreq(void) +{ + CSC0_RTCClkSrcType eRtcClkSrc; + uint32_t u32Freq; + + eRtcClkSrc = CSC0_HWA_GetRTCClkSrc(); + if (CSC0_RTC_FOSCDIVL_CLK == eRtcClkSrc) + { + u32Freq = SCG_GetScgClockFreq(SCG_FOSCDIVL_CLK); + } + else if (CSC0_RTC_SOSC_CLK == eRtcClkSrc) + { + u32Freq = CSC0_AONCLK_SOSC_32K; + } + else + { + u32Freq = CSC0_AONCLK_32K; + } + + return u32Freq; +} + +/** + * @brief Get the frequency of output clock selected by CSC0_CLKOUT_CTRL[CLKOUT_SEL]. + * + * @return the frequency of CSC0 output clock + */ +static uint32_t CSC0_GetClockOutFreq(void) +{ + uint32_t u32Freq; + CSC0_ClockOutSrcType eClkOutSrc; + CSC0_ClockOutDivType eClkOutDiv; + + + eClkOutSrc = CSC0_HWA_GetClkOutSel(); + eClkOutDiv = CSC0_HWA_GetClkOutDiv(); + + if(eClkOutSrc == CSC0_CLKOUT_SCG_CLKOUT) + { + u32Freq = SCG_GetScgClockFreq(SCG_SCG_CLKOUT_CLK); + } + else if(eClkOutSrc == CSC0_CLKOUT_FOSC_DIVM_CLK) + { + u32Freq = SCG_GetScgClockFreq(SCG_FOSCDIVM_CLK); + } + else if(eClkOutSrc == CSC0_CLKOUT_SLOW_CLK) + { + u32Freq = SCG_GetScgClockFreq(SCG_SLOW_CLK); + } + else if(eClkOutSrc == CSC0_CLKOUT_SIRC_DIVM_CLK) + { + u32Freq = SCG_GetScgClockFreq(SCG_SIRCDIVM_CLK); + } + else if(eClkOutSrc == CSC0_CLKOUT_PLL1_DIVM_CLK) + { + u32Freq = SCG_GetScgClockFreq(SCG_PLL1DIVM_CLK); + } + else if(eClkOutSrc == CSC0_CLKOUT_FIRC_DIVM_CLK) + { + u32Freq = SCG_GetScgClockFreq(SCG_FIRCDIVM_CLK); + } + else if(eClkOutSrc == CSC0_CLKOUT_CORE_CLK) + { + u32Freq = SCG_GetScgClockFreq(SCG_CORE_CLK); + } + else if(eClkOutSrc == CSC0_CLKOUT_PLL0_DIVM_CLK) + { + u32Freq = SCG_GetScgClockFreq(SCG_PLL0DIVM_CLK); + } + else if(eClkOutSrc == CSC0_CLKOUT_BUS_CLK) + { + u32Freq = SCG_GetScgClockFreq(SCG_BUS_CLK); + } + else if(eClkOutSrc == CSC0_CLKOUT_SIRC_128K_CLK) + { + u32Freq = CSC0_AONCLK_128K; + } + else if(eClkOutSrc == CSC0_CLKOUT_AON_CLK) + { + u32Freq = CSC0_GetAONClkFreq(); + } + else if(eClkOutSrc == CSC0_CLKOUT_RTC_CLK) + { + u32Freq = CSC0_GetRTCClkFreq(); + } + else + { + u32Freq = 0U; + } + + return u32Freq / ((uint32_t)eClkOutDiv + 1U); +} + +/** + * @brief Set cpu to control peripheral group 0 in CSC0. + * + * @param eCpuType Cpu to use + * @param eTarget Target to be set stop ack/request + * @param bLockStatus Lock current register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return Set clock out operation success/failed + */ +static CSC_RetStatusType CSC0_SetCpuCtrlGrp0(const CSC_WPB_CpuType eCpuType, CSC_SetTargetType eTarget, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_LOCK; + + if (CSC_STOPACK == eTarget) + { + if (0U == CSC0_HWA_MODER0_GetWPBLockStatus()) + { + CSC0_HWA_MODER0_SetCpuWritePermit(eCpuType); + + if(bLockStatus != false) + { + CSC0_HWA_MODER0_LockWritePermit(); + } + eRetVal = CSC_E_OK; + } + } + else + { + if (0U == CSC0_HWA_REQR0_GetWPBLockStatus()) + { + CSC0_HWA_REQR0_SetCpuWritePermit(eCpuType); + if(bLockStatus != false) + { + CSC0_HWA_REQR0_LockWritePermit(); + } + eRetVal = CSC_E_OK; + } + } + + return eRetVal; +} + +/** + * @brief Set cpu to control peripheral group 1 in CSC0. + * + * @param eCpuType Cpu to use + * @param eTarget Target to be set stop ack/request + * + * @return Set clock out operation success/failed + */ +static CSC_RetStatusType CSC0_SetCpuCtrlGrp1(const CSC_WPB_CpuType eCpuType, CSC_SetTargetType eTarget, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_LOCK; + + if (CSC_STOPACK == eTarget) + { + if (0U == CSC0_HWA_MODER1_GetWPBLockStatus()) + { + CSC0_HWA_MODER1_SetCpuWritePermit(eCpuType); + if(bLockStatus != false) + { + CSC0_HWA_MODER1_LockWritePermit(); + } + eRetVal = CSC_E_OK; + } + } + else + { + if (0U == CSC0_HWA_REQR1_GetWPBLockStatus()) + { + CSC0_HWA_REQR1_SetCpuWritePermit(eCpuType); + if(bLockStatus != false) + { + CSC0_HWA_REQR1_LockWritePermit(); + } + eRetVal = CSC_E_OK; + } + } + + return eRetVal; +} + +/** + * @brief Set cpu to control peripheral group 2 in CSC0. + * + * @param eCpuType Cpu to use + * @param eTarget Target to be set stop ack/request + * + * @return Set clock out operation success/failed + */ +static CSC_RetStatusType CSC0_SetCpuCtrlGrp2(const CSC_WPB_CpuType eCpuType, CSC_SetTargetType eTarget, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_LOCK; + + if (CSC_STOPACK == eTarget) + { + if (0U == CSC0_HWA_MODER2_GetWPBLockStatus()) + { + CSC0_HWA_MODER2_SetCpuWritePermit(eCpuType); + if(bLockStatus != false) + { + CSC0_HWA_MODER2_LockWritePermit(); + } + eRetVal = CSC_E_OK; + } + } + else + { + if (0U == CSC0_HWA_REQR2_GetWPBLockStatus()) + { + CSC0_HWA_REQR2_SetCpuWritePermit(eCpuType); + if(bLockStatus != false) + { + CSC0_HWA_REQR2_LockWritePermit(); + } + eRetVal = CSC_E_OK; + } + } + + return eRetVal; +} + +/** + * @brief Set the stop mode ACK of all group peripherals in CSC0. + * + * @param ePeriphGrp the group of peripherals to set the stop mode ACK value + * @param u32Value the CSCx_STOP_MODERx register value + * + * @return Operation success/failed + */ +static CSC_RetStatusType CSC0_SetStopModeAck(const CSC_PeriphGrpType ePeriphGrp,uint32_t u32Value) +{ + CSC_RetStatusType eRetVal = CSC_E_NO_PERM; + CSC_WPB_CpuType eCtrlCpu; + + if(ePeriphGrp == CSC_STOP_CTRL_GROUP_0) + { + eCtrlCpu = CSC0_HWA_MODER0_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + CSC0_HWA_MODER0_SetMultiStopAck(u32Value); + eRetVal = CSC_E_OK; + } + + } + else if(ePeriphGrp == CSC_STOP_CTRL_GROUP_1) + { + eCtrlCpu = CSC0_HWA_MODER1_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + CSC0_HWA_MODER1_SetMultiStopAck(u32Value); + eRetVal = CSC_E_OK; + } + + } + else + { + eCtrlCpu = CSC0_HWA_MODER2_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + CSC0_HWA_MODER2_SetMultiStopAck(u32Value); + eRetVal = CSC_E_OK; + } + + } + + return eRetVal; +} + +/** + * @brief Set the stop request of all group peripherals in CSC0. + * + * @param eTargetCpuType The target CPU which acknowledges the peripherals when entering stop mode. + * @param ePeriphGrp the group of peripherals to set the stop request value + * @param u32Value the CSCx_STOP_REQRx register value + * + * @return Operation success/failed + */ +static CSC_RetStatusType CSC0_SetStopRequest(const CSC_PeriphGrpType ePeriphGrp,uint32_t u32Value) +{ + CSC_RetStatusType eRetVal = CSC_E_NO_PERM; + CSC_WPB_CpuType eCtrlCpu; + + if(ePeriphGrp == CSC_STOP_CTRL_GROUP_0) + { + eCtrlCpu = CSC0_HWA_REQR0_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + CSC0_HWA_REQR0_SetMultiStopRequest(u32Value); + eRetVal = CSC_E_OK; + } + + } + else if(ePeriphGrp == CSC_STOP_CTRL_GROUP_1) + { + eCtrlCpu = CSC0_HWA_REQR1_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + CSC0_HWA_REQR1_SetMultiStopRequest(u32Value); + eRetVal = CSC_E_OK; + } + + } + else + { + eCtrlCpu = CSC0_HWA_REQR2_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + CSC0_HWA_REQR2_SetMultiStopRequest(u32Value); + eRetVal = CSC_E_OK; + } + + } + + return eRetVal; +} + +/** + * @brief Get the stop Acknowledge status of all group peripherals in CSC0. + * + * @param ePeriphType the peripheral to get stop acknowledge status + * @return uint32_t the stop ACK status of all the peripherals in the group indicated by ePeriphGrp. + */ +static uint32_t CSC0_GetStopAckStatus(const CSC_PeriphGrpType ePeriphGrp) +{ + uint32_t eRetVal; + + if(CSC_STOP_CTRL_GROUP_0 == ePeriphGrp) + { + eRetVal = CSC0_HWA_ACKR0_GetMultiStopAckStatus(CSC_STOP_PERIPH_GROUP0_MASK); + } + else if(CSC_STOP_CTRL_GROUP_1 == ePeriphGrp) + { + eRetVal = CSC0_HWA_ACKR1_GetMultiStopAckStatus(CSC_STOP_PERIPH_GROUP1_MASK); + } + else + { + eRetVal = CSC0_HWA_ACKR2_GetMultiStopAckStatus(CSC_STOP_PERIPH_GROUP2_MASK); + } + return eRetVal; +} + + + + + + +/********* Global functions ************/ +/** + * @brief set clock out. with clock out pin configure, the clock would be monitored. + * This Function may combined with SCG_ClkOut setting + * need to call SCG_SetClkOut,if clock out source set to SCG_CLKOUT. * + * @param pCsc0ClkOut to Csc0ClkOut instance for clock out configuration + * @param bLockStatus to lock current register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_LOCK: The register has been locked and can not be written + * @note configuration sequence: + * 1. Disable CLKOUTEN + * 2. Set CLKOUTSEL + * 3. Enable CLKOUTEN + */ +CSC_RetStatusType CSC0_SetClockOut(const CSC0_ClkoutType *const pCsc0ClkOut, bool bLockStatus) +{ + DEV_ASSERT(pCsc0ClkOut != NULL); + CSC_RetStatusType eRetVal; + + /* Check CSC0_CLKOUT_CTRL register lock status */ + if (0U == CSC0_HWA_CLKOUT_CTRL_GetLockStatus()) + { + eRetVal = CSC_E_OK; + /* Disable CLKOUTEN */ + CSC0_HWA_DisableClockOut(); + /* Set CLKOUTDIV */ + CSC0_HWA_SetClkOutDiv(pCsc0ClkOut->eDivider); + /* Set CLKOUTSEL */ + CSC0_HWA_SetClkOutSel(pCsc0ClkOut->eClkOutSrc); + /* Enable CLKOUTEN */ + CSC0_HWA_EnableClockOut(); + + if (true == bLockStatus) + { + /* Lock CSC0_CLKOUT_CTRL register */ + CSC0_HWA_LockCLKOUT_CTRL(); + } + } + else + { + eRetVal = CSC_E_LOCK; + } + + return eRetVal; +} + +/** + * @brief set always on clock source configuration include AON32K, RTC, AONCLK clock. + * + * @param pAonclkSrcType pointer to AONCLKSR instance for AON clock source configuration + * @param bLockStatus to lock current register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_LOCK: The register has been locked and can not be written + */ +CSC_RetStatusType CSC0_SetAonClkSrc(const CSC0_AONCLKSRType *const pAonclkSrcType, bool bLockStatus) +{ + CSC_RetStatusType eRetVal; + + DEV_ASSERT(pAonclkSrcType != NULL); + DEV_ASSERT(pAonclkSrcType->eAon32KSel == CSC0_AON32K_SIRCDIV_32K_CLK || + pAonclkSrcType->eAon32KSel == CSC0_AON32K_SOSC32K_CLK || + pAonclkSrcType->eAon32KSel == CSC0_AON32K_SIRC32K_CLK); + DEV_ASSERT(pAonclkSrcType->eRtcSel == CSC0_RTC_FOSCDIVL_CLK || + pAonclkSrcType->eRtcSel == CSC0_RTC_SIRCDIV_32K_CLK || + pAonclkSrcType->eRtcSel == CSC0_RTC_SOSC_CLK || + pAonclkSrcType->eRtcSel == CSC0_RTC_SIRC32K_CLK); + DEV_ASSERT(pAonclkSrcType->eAonSel == CSC0_AON_SIRCDIV_128K_CLK || + pAonclkSrcType->eAonSel == CSC0_AON_SIRC32K_CLK || + pAonclkSrcType->eAonSel == CSC0_AON_SIRCDIV_32K_CLK || + pAonclkSrcType->eAonSel == CSC0_AON_SIRC32_1K_CLK); + + + /* Check CSC0_AONCLKSR register lock status */ + if (0U == CSC0_HWA_AONCLKSR_GetLockStaus()) + { + eRetVal = CSC_E_OK; + + /* Gating SIRC_32K clock*/ + if ((CSC0_AON32K_SIRCDIV_32K_CLK == pAonclkSrcType->eAon32KSel) || + (CSC0_AON_SIRCDIV_32K_CLK == pAonclkSrcType->eAonSel) || + (CSC0_RTC_SIRCDIV_32K_CLK == pAonclkSrcType->eRtcSel)) + { + CSC0_HWA_EnableSIRCDIV_32KClkOut(); + } + + /* Gating SIRC32_1K clock*/ + if (CSC0_AON_SIRC32_1K_CLK == pAonclkSrcType->eAonSel) + { + CSC0_HWA_EnableSIRC32_1KClkOut(); + } + + /* Set AONCLOCK configuration */ + CSC0_HWA_SetAON32kClkSrc(pAonclkSrcType->eAon32KSel); + CSC0_HWA_SetRTCClkSrc(pAonclkSrcType->eRtcSel); + CSC0_HWA_SetAONClkSrc(pAonclkSrcType->eAonSel); + + if (true == bLockStatus) + { + /* Lock CSC0_AONCLKSR register */ + CSC0_HWA_LockAONCLKSR(); + } + } + else + { + eRetVal = CSC_E_LOCK; + } + + return eRetVal; +} + +/** + * @brief Report the clock source status and frequency configured in MCU run time. + * The clock frequency and status would change by clock set function. + * + * @param eClkkName: the CSC0 clock source to query + * @param pFreq: frequency variable point to get the frequency value + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eClkkName invalid + */ +CSC_RetStatusType CSC0_GetCSC0ClockFreq(CSC0_ClkSrcType eClkkName, uint32_t *const pFreq) +{ + CSC_RetStatusType eRetVal; + DEV_ASSERT(pFreq != NULL); + + if ((uint32_t)eClkkName >= (uint32_t)CSC0_END_OF_CLOCKS) + { + eRetVal = CSC_E_NOT_OK; + *pFreq = 0U; + } + else + { + eRetVal = CSC_E_OK; + + if (CSC0_AON_CLK == eClkkName) + { + *pFreq = CSC0_GetAONClkFreq(); + } + else if (CSC0_AON32K_CLK == eClkkName) + { + *pFreq = CSC0_GetAON32kClkFreq(); + } + else if (CSC0_RTC_CLK == eClkkName) + { + *pFreq = CSC0_GetRTCClkFreq(); + } + else + { + /* CSC0_CLKOUT_CLK */ + *pFreq = CSC0_GetClockOutFreq(); + } + } + + return eRetVal; +} + +/** + * @brief SCG MAM stall request. + * @details Need to assert the SCG_STALL to stall MAM when configuring the SCG clock source. + * + * @param bEnable: true asserts SCG MAM stall request + * false do not asserts SCG MAM stall request + * @param bLockStatus: Lock the register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_LOCK: The register has been locked + */ +CSC_RetStatusType CSC0_ScgMAMStallRequest(bool bEnable, bool bLockStatus) +{ + CSC_RetStatusType eRetVal= CSC_E_LOCK; + + if (0U == CSC0_HWA_SCG_MAM_STALL_GetLockStatus()) + { + if(bEnable != false) + { + CSC0_HWA_EnalbeSCGStall(); + } + else + { + CSC0_HWA_DisableSCGStall(); + } + + if(bLockStatus != false) + { + CSC0_HWA_LockSCG_MAM_STALL(); + } + + eRetVal = CSC_E_OK; + } + + return eRetVal; +} + +/** + * @brief Set request to SMU of group 0. + * + * @param u32Value Value to be set(the or bits defined in CSC_SMU_CtrlGrp0Type,do not involve lock bit) + * @param bLockStatus Lock the register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: The u32Value contains invalid bits + * CSC_E_LOCK: The register has been locked + */ +CSC_RetStatusType CSC0_SetReqToSMUGrp0(uint32_t u32Value, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_PARAM; + + /* Check register bits invalid */ + if((u32Value & (~CSC_SMU_CTRL_GROUP0_MASK)) == 0U) + { + + /* Check register lock status */ + if (0U == CSC0_HWA_SMU_CTRL0_GetLockStatus()) + { + eRetVal = CSC_E_OK; + /* Set value(do not involve lock bit) */ + CSC0_HWA_CTRL0_SetMultiReqToSMU(u32Value); + if (true == bLockStatus) + { + /* Lock register */ + CSC0_HWA_LockSMU_CTRL0(); + } + } + else + { + eRetVal = CSC_E_LOCK; + } + } + + return eRetVal; +} + +/** + * @brief Set request to SMU of group 1. + * + * @param u32Value Value to be set(the or bits defined in CSC_SMU_CtrlGrp1Type,do not involve lock bit) + * @param bLockStatus Lock the register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: The u32Value contains invalid bits + * CSC_E_LOCK: The register has been locked + */ +CSC_RetStatusType CSC0_SetReqToSMUGrp1(uint32_t u32Value, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_PARAM; + + /* Check register bits invalid */ + if((u32Value & (~CSC_SMU_CTRL_GROUP1_MASK)) == 0U) + { + + /* Check register lock status */ + if (0U == CSC0_HWA_SMU_CTRL1_GetLockStatus()) + { + eRetVal = CSC_E_OK; + /* Set value(do not involve lock bit) */ + CSC0_HWA_CTRL1_SetMultiReqToSMU(u32Value); + if (true == bLockStatus) + { + /* Lock register */ + CSC0_HWA_LockSMU_CTRL1(); + } + } + else + { + eRetVal = CSC_E_LOCK; + } + } + + return eRetVal; +} + +/** + * @brief Set request to SMU of group 4. + * + * @param u32Value Value to be set(the or bits defined in CSC_SMU_CtrlGrp4Type,do not involve lock bit) + * @param bLockStatus Lock the register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: The u32Value contains invalid bits + * CSC_E_LOCK: The register has been locked + */ +CSC_RetStatusType CSC0_SetReqToSMUGrp4(uint32_t u32Value, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_PARAM; + + /* Check register bits invalid */ + if((u32Value & (~CSC_SMU_CTRL_GROUP4_MASK)) == 0U) + { + + /* Check register lock status */ + if (0U == CSC0_HWA_SMU_CTRL4_GetLockStatus()) + { + eRetVal = CSC_E_OK; + /* Set value(do not involve lock bit) */ + CSC0_HWA_CTRL4_SetMultiReqToSMU(u32Value); + if (true == bLockStatus) + { + /* Lock register */ + CSC0_HWA_LockSMU_CTRL4(); + } + } + else + { + eRetVal = CSC_E_LOCK; + } + } + + return eRetVal; +} + +/** + * @brief Set request to SMU of group 5. + * + * @param u32Value Value to be set(the or bits defined in CSC_SMU_CtrlGrp5Type,do not involve lock bit) + * @param bLockStatus Lock the register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: The u32Value contains invalid bits + * CSC_E_LOCK: The register has been locked + */ +CSC_RetStatusType CSC0_SetReqToSMUGrp5(uint32_t u32Value, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_PARAM; + + /* Check register bits invalid */ + if((u32Value & (~CSC_SMU_CTRL_GROUP5_MASK)) == 0U) + { + + /* Check register lock status */ + if (0U == CSC0_HWA_SMU_CTRL5_GetLockStatus()) + { + eRetVal = CSC_E_OK; + /* Set value(do not involve lock bit) */ + CSC0_HWA_CTRL5_SetMultiReqToSMU(u32Value); + if (true == bLockStatus) + { + /* Lock register */ + CSC0_HWA_LockSMU_CTRL5(); + } + } + else + { + eRetVal = CSC_E_LOCK; + } + } + + return eRetVal; +} + +/** + * @brief Set request to SMU . + * + * @param eCtrlGrp CSC0_SMU control group + * @param u32Value Value to be set(the or bits defined in CSC_SMU_CtrlGrp5Type,do not involve lock bit) + * @param bLockStatus Lock the register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_PARAM: The eCtrlGrp is invalid + * CSC_E_NOT_OK: The u32Value contains invalid bits + * CSC_E_LOCK: The register has been locked + * @note Group must be matched with u32Value which select from CSC0_SmuCtrlGrpType + */ +CSC_RetStatusType CSC0_SetReqToSMU(CSC0_SmuCtrlGrpType eCtrlGrp, uint32_t u32Value, bool bLockStatus) +{ + CSC_RetStatusType eRetVal; + + if (CSC0_SMU_CTRL_GROUP_0 == eCtrlGrp) + { + eRetVal = CSC0_SetReqToSMUGrp0(u32Value, bLockStatus); + } + else if (CSC0_SMU_CTRL_GROUP_1 == eCtrlGrp) + { + eRetVal = CSC0_SetReqToSMUGrp1(u32Value, bLockStatus); + } + else if (CSC0_SMU_CTRL_GROUP_4 == eCtrlGrp) + { + eRetVal = CSC0_SetReqToSMUGrp4(u32Value, bLockStatus); + } + else if (CSC0_SMU_CTRL_GROUP_5 == eCtrlGrp) + { + eRetVal = CSC0_SetReqToSMUGrp5(u32Value, bLockStatus); + } + else + { + eRetVal = CSC_E_NOT_OK; + } + + return eRetVal; +} + +/** + * @brief Configure the low power wakeup PAD output in CSC0_LP_WAKEUP register. + * + * @param eLPWakeupCfg: the low power wakeup PAD source and polarity configuration + * @param bLockStatus: Lock the register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_LOCK: The WPB of CSCx_STOP_MODERx is already locked + */ +CSC_RetStatusType CSC0_LP_WakeupPadOutputCfg(const CSC0_LPWakeupCfgType * const eLPWakeupCfg, bool bLockStatus) +{ + CSC_RetStatusType eRetVal; + + DEV_ASSERT(eLPWakeupCfg != NULL_PTR); + DEV_ASSERT((uint32_t)eLPWakeupCfg->eCfgGrp0 <= (uint32_t)CSC_LP_WAKEUP_FCPIT0_TRIGGER_OUT3); + DEV_ASSERT((uint32_t)eLPWakeupCfg->eCfgGrp1 <= (uint32_t)CSC_LP_WAKEUP_FCPIT0_TRIGGER_OUT3); + DEV_ASSERT((uint32_t)eLPWakeupCfg->eCfgGrp2 <= (uint32_t)CSC_LP_WAKEUP_FCPIT0_TRIGGER_OUT3); + DEV_ASSERT((uint32_t)eLPWakeupCfg->eCfgGrp3 <= (uint32_t)CSC_LP_WAKEUP_FCPIT0_TRIGGER_OUT3); + DEV_ASSERT((uint32_t)eLPWakeupCfg->eCfgGrp4 <= (uint32_t)CSC_LP_WAKEUP_FCPIT0_TRIGGER_OUT3); + DEV_ASSERT((uint32_t)eLPWakeupCfg->ePolGrp0 <= (uint32_t)CSC_LP_WAKEUP_POL_INVERT); + DEV_ASSERT((uint32_t)eLPWakeupCfg->ePolGrp1 <= (uint32_t)CSC_LP_WAKEUP_POL_INVERT); + DEV_ASSERT((uint32_t)eLPWakeupCfg->ePolGrp2 <= (uint32_t)CSC_LP_WAKEUP_POL_INVERT); + DEV_ASSERT((uint32_t)eLPWakeupCfg->ePolGrp3 <= (uint32_t)CSC_LP_WAKEUP_POL_INVERT); + DEV_ASSERT((uint32_t)eLPWakeupCfg->ePolGrp4 <= (uint32_t)CSC_LP_WAKEUP_POL_INVERT); + + if (0U == CSC0_HWA_LP_WAKEUP_GetLockStatus()) + { + CSC0_HWA_SetLP_WAKEUPCfgSrc(CSC_LP_WAKEUP_GROUP_0,eLPWakeupCfg->eCfgGrp0); + CSC0_HWA_SetLP_WAKEUPCfgSrc(CSC_LP_WAKEUP_GROUP_1,eLPWakeupCfg->eCfgGrp1); + CSC0_HWA_SetLP_WAKEUPCfgSrc(CSC_LP_WAKEUP_GROUP_2,eLPWakeupCfg->eCfgGrp2); + CSC0_HWA_SetLP_WAKEUPCfgSrc(CSC_LP_WAKEUP_GROUP_3,eLPWakeupCfg->eCfgGrp3); + CSC0_HWA_SetLP_WAKEUPCfgSrc(CSC_LP_WAKEUP_GROUP_4,eLPWakeupCfg->eCfgGrp4); + CSC0_HWA_SetLP_WAKEUPCfgPol(CSC_LP_WAKEUP_GROUP_0,eLPWakeupCfg->ePolGrp0); + CSC0_HWA_SetLP_WAKEUPCfgPol(CSC_LP_WAKEUP_GROUP_1,eLPWakeupCfg->ePolGrp1); + CSC0_HWA_SetLP_WAKEUPCfgPol(CSC_LP_WAKEUP_GROUP_2,eLPWakeupCfg->ePolGrp2); + CSC0_HWA_SetLP_WAKEUPCfgPol(CSC_LP_WAKEUP_GROUP_3,eLPWakeupCfg->ePolGrp3); + CSC0_HWA_SetLP_WAKEUPCfgPol(CSC_LP_WAKEUP_GROUP_4,eLPWakeupCfg->ePolGrp4); + + if(bLockStatus != false) + { + CSC0_HWA_LockLP_WAKEUP(); + } + + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_LOCK; + } + return eRetVal; +} + + +/** + * @brief Set CPU stop mode control permission. + * @detail This API is used to set the CPU write permission of a CPU's stop mode registers. + * eg.If the CPU(eTargetCpuType) enter stop mode, it acknowledges the peripherals according to the configuration + * in CSCx_STOP_MODERy (x: (CPUID) range[0] , y:(GROUP) range[0,1,2]), and the CPU(eCtrlCpuType) + * has the write permission of CSCx_STOP_MODERy registers, the permission is controlled by this API. + * + * @param eTargetCpuType The target CPU to set. + * @param eCtrlCpuType The CPU that has the write permission to the CSCx_STOP_MODERy register. + * @param ePeriphGrp Peripheral group (range:0,1,2) + * @param bLockStatus Lock the WPB of CSCx_STOP_MODERy.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_LOCK: The WPB of CSCx_STOP_MODERx is already locked + */ +CSC_RetStatusType CSC_SetStopModeAckPermission(CSC_WPB_CpuType eTargetCpuType, CSC_WPB_CpuType eCtrlCpuType, + CSC_PeriphGrpType ePeriphGrp, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + DEV_ASSERT((uint32_t)eCtrlCpuType < (uint32_t)CSC_WP_CPU_NONE); + DEV_ASSERT((uint32_t)ePeriphGrp <= (uint32_t)CSC_STOP_CTRL_GROUP_2); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + if (CSC_STOP_CTRL_GROUP_0 == ePeriphGrp) + { + eRetVal = CSC0_SetCpuCtrlGrp0(eCtrlCpuType, CSC_STOPACK, bLockStatus); + } + else if (CSC_STOP_CTRL_GROUP_1 == ePeriphGrp) + { + eRetVal = CSC0_SetCpuCtrlGrp1(eCtrlCpuType, CSC_STOPACK, bLockStatus); + } + else + { + eRetVal = CSC0_SetCpuCtrlGrp2(eCtrlCpuType, CSC_STOPACK, bLockStatus); + } + } + + return eRetVal; +} + +/** + * @brief Set CPU stop mode request control permission. + * @detail This API is used to set the CPU write permission of a CPU's stop mode request registers + * to generate a stop request to peripherals + * + * @param eTargetCpuType The target CPU to acknowledges stop mode to the enabled peripherals. + * @param eCtrlCpuType The CPU that has the write permission to the CSCx_STOP_REQRx register. + * @param ePeriphGrp Peripheral group (range:0,1,2) + * @param bLockStatus Lock the WPB of CSCx_STOP_REQRx.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_LOCK: The WPB of CSCx_STOP_REQRx is already locked + */ +CSC_RetStatusType CSC_SetStopRequestPermission(CSC_WPB_CpuType eTargetCpuType, CSC_WPB_CpuType eCtrlCpuType, + CSC_PeriphGrpType ePeriphGrp, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + DEV_ASSERT((uint32_t)eCtrlCpuType < (uint32_t)CSC_WP_CPU_NONE); + DEV_ASSERT((uint32_t)ePeriphGrp <= (uint32_t)CSC_STOP_CTRL_GROUP_2); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + if (CSC_STOP_CTRL_GROUP_0 == ePeriphGrp) + { + eRetVal = CSC0_SetCpuCtrlGrp0(eCtrlCpuType, CSC_STOPREQ, bLockStatus); + } + else if (CSC_STOP_CTRL_GROUP_1 == ePeriphGrp) + { + eRetVal = CSC0_SetCpuCtrlGrp1(eCtrlCpuType, CSC_STOPREQ, bLockStatus); + } + else + { + eRetVal = CSC0_SetCpuCtrlGrp2(eCtrlCpuType, CSC_STOPREQ, bLockStatus); + } + } + + return eRetVal; +} + +/** + * @brief Set the stop mode ACK of peripheral group 0 in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the ePeriphType when entering stop mode. + * @param ePeriphType the peripheral to enable or disable the stop mode ACK + * @param bEnable true: enable the stop mode ACK + * false: disable the stop mode ACK + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_NO_PERM: Current CPU has no permission to access the register + */ +CSC_RetStatusType CSC_SetStopModeAckGrp0(CSC_WPB_CpuType eTargetCpuType, CSCx_Reg0_PeriphType ePeriphType, bool bEnable) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + CSC_WPB_CpuType eCtrlCpu; + + DEV_ASSERT((ePeriphType == CSC_STOPMODE_FLEXCAN1) || + (ePeriphType == CSC_STOPMODE_FLEXCAN0) || + (ePeriphType == CSC_STOPMODE_FREQM) || + (ePeriphType == CSC_STOPMODE_FCUART3) || + (ePeriphType == CSC_STOPMODE_FCUART2) || + (ePeriphType == CSC_STOPMODE_FCUART1) || + (ePeriphType == CSC_STOPMODE_FCSPI2) || + (ePeriphType == CSC_STOPMODE_FCSPI1) || + (ePeriphType == CSC_STOPMODE_SENT0) || + (ePeriphType == CSC_STOPMODE_TMU) || + (ePeriphType == CSC_STOPMODE_ADC1) || + (ePeriphType == CSC_STOPMODE_ADC0) || + (ePeriphType == CSC_STOPMODE_CMU4) || + (ePeriphType == CSC_STOPMODE_WDOG0) || + (ePeriphType == CSC_STOPMODE_ISM0) || + (ePeriphType == CSC_STOPMODE_DMA0)); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eCtrlCpu = CSC0_HWA_MODER0_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + /* Set peripheral stop ack enable */ + if(bEnable != false) + { + CSC0_HWA_MODER0_EnableStopAck(ePeriphType); + } + else + { + CSC0_HWA_MODER0_DisableStopAck(ePeriphType); + } + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_NO_PERM; + } + } + + return eRetVal; +} + +/** + * @brief Set the stop request of peripheral group 0 in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the ePeriphType when entering stop mode. + * @param ePeriphType the peripheral to set stop request + * @param bEnable true: set the stop request + * false: clear the stop request + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_NO_PERM: Current CPU has no permission to access the register + */ +CSC_RetStatusType CSC_SetStopRequestGrp0(CSC_WPB_CpuType eTargetCpuType, CSCx_Reg0_PeriphType ePeriphType, bool bEnable) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + CSC_WPB_CpuType eCtrlCpu; + + DEV_ASSERT((ePeriphType == CSC_STOPMODE_FLEXCAN1) || + (ePeriphType == CSC_STOPMODE_FLEXCAN0) || + (ePeriphType == CSC_STOPMODE_FREQM) || + (ePeriphType == CSC_STOPMODE_FCUART3) || + (ePeriphType == CSC_STOPMODE_FCUART2) || + (ePeriphType == CSC_STOPMODE_FCUART1) || + (ePeriphType == CSC_STOPMODE_FCSPI2) || + (ePeriphType == CSC_STOPMODE_FCSPI1) || + (ePeriphType == CSC_STOPMODE_SENT0) || + (ePeriphType == CSC_STOPMODE_TMU) || + (ePeriphType == CSC_STOPMODE_ADC1) || + (ePeriphType == CSC_STOPMODE_ADC0) || + (ePeriphType == CSC_STOPMODE_CMU4) || + (ePeriphType == CSC_STOPMODE_WDOG0) || + (ePeriphType == CSC_STOPMODE_ISM0) || + (ePeriphType == CSC_STOPMODE_DMA0)); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eCtrlCpu = CSC0_HWA_REQR0_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + /* Set peripheral stop ack enable */ + if(bEnable != false) + { + CSC0_HWA_REQR0_SetStopRequest(ePeriphType); + } + else + { + CSC0_HWA_REQR0_ClearStopRequest(ePeriphType); + } + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_NO_PERM; + } + } + + return eRetVal; +} + +/** + * @brief Set the stop mode ACK of peripheral group 1 in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the ePeriphType when entering stop mode. + * @param ePeriphType the peripheral to enable or disable the stop mode ACK + * @param bEnable true: enable the stop mode ACK + * false: disable the stop mode ACK + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_NO_PERM: Current CPU has no permission to access the register + */ +CSC_RetStatusType CSC_SetStopModeAckGrp1(CSC_WPB_CpuType eTargetCpuType, CSCx_Reg1_PeriphType ePeriphType, bool bEnable) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + CSC_WPB_CpuType eCtrlCpu; + + DEV_ASSERT((ePeriphType == CSC_STOPMODE_FLEXCAN3) || + (ePeriphType == CSC_STOPMODE_FLEXCAN2) || + (ePeriphType == CSC_STOPMODE_MSC0) || + (ePeriphType == CSC_STOPMODE_FCUART7) || + (ePeriphType == CSC_STOPMODE_FCUART6) || + (ePeriphType == CSC_STOPMODE_FCUART5) || + (ePeriphType == CSC_STOPMODE_FCUART4) || + (ePeriphType == CSC_STOPMODE_FCIIC1) || + (ePeriphType == CSC_STOPMODE_FCSPI5) || + (ePeriphType == CSC_STOPMODE_FCSPI4) || + (ePeriphType == CSC_STOPMODE_FCSPI3) || + (ePeriphType == CSC_STOPMODE_WDOG1)); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eCtrlCpu = CSC0_HWA_MODER1_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + /* Set peripheral stop ack enable */ + if(bEnable != false) + { + CSC0_HWA_MODER1_EnableStopAck(ePeriphType); + } + else + { + CSC0_HWA_MODER1_DisableStopAck(ePeriphType); + } + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_NO_PERM; + } + } + + return eRetVal; +} + +/** + * @brief Set the stop request of peripheral group 1 in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the ePeriphType when entering stop mode. + * @param ePeriphType the peripheral to set stop request + * @param bEnable true: set the stop request + * false: clear the stop request + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_NO_PERM: Current CPU has no permission to access the register + */ +CSC_RetStatusType CSC_SetStopRequestGrp1(CSC_WPB_CpuType eTargetCpuType, CSCx_Reg1_PeriphType ePeriphType, bool bEnable) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + CSC_WPB_CpuType eCtrlCpu; + + DEV_ASSERT((ePeriphType == CSC_STOPMODE_FLEXCAN3) || + (ePeriphType == CSC_STOPMODE_FLEXCAN2) || + (ePeriphType == CSC_STOPMODE_MSC0) || + (ePeriphType == CSC_STOPMODE_FCUART7) || + (ePeriphType == CSC_STOPMODE_FCUART6) || + (ePeriphType == CSC_STOPMODE_FCUART5) || + (ePeriphType == CSC_STOPMODE_FCUART4) || + (ePeriphType == CSC_STOPMODE_FCIIC1) || + (ePeriphType == CSC_STOPMODE_FCSPI5) || + (ePeriphType == CSC_STOPMODE_FCSPI4) || + (ePeriphType == CSC_STOPMODE_FCSPI3) || + (ePeriphType == CSC_STOPMODE_WDOG1)); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eCtrlCpu = CSC0_HWA_REQR1_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + /* Set peripheral stop ack enable */ + if(bEnable != false) + { + CSC0_HWA_REQR1_SetStopRequest(ePeriphType); + } + else + { + CSC0_HWA_REQR1_ClearStopRequest(ePeriphType); + } + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_NO_PERM; + } + } + + return eRetVal; +} + +/** + * @brief Set the stop mode ACK of peripheral group 2 in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the ePeriphType when entering stop mode. + * @param ePeriphType the peripheral to enable or disable the stop mode ACK + * @param bEnable true: enable the stop mode ACK + * false: disable the stop mode ACK + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_NO_PERM: Current CPU has no permission to access the register + */ +CSC_RetStatusType CSC_SetStopModeAckGrp2(CSC_WPB_CpuType eTargetCpuType, CSCx_Reg2_PeriphType ePeriphType, bool bEnable) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + CSC_WPB_CpuType eCtrlCpu; + + DEV_ASSERT((ePeriphType == CSC_STOPMODE_FCUART0) || + (ePeriphType == CSC_STOPMODE_FCIIC0) || + (ePeriphType == CSC_STOPMODE_FCSPI0) || + (ePeriphType == CSC_STOPMODE_CMP1) || + (ePeriphType == CSC_STOPMODE_CMP0) || + (ePeriphType == CSC_STOPMODE_CMU3) || + (ePeriphType == CSC_STOPMODE_CMU2) || + (ePeriphType == CSC_STOPMODE_CMU1) || + (ePeriphType == CSC_STOPMODE_CMU0)); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eCtrlCpu = CSC0_HWA_MODER2_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + /* Set peripheral stop ack enable */ + if(bEnable != false) + { + CSC0_HWA_MODER2_EnableStopAck(ePeriphType); + } + else + { + CSC0_HWA_MODER2_DisableStopAck(ePeriphType); + } + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_NO_PERM; + } + } + + return eRetVal; +} + +/** + * @brief Set the stop request of peripheral group 2 in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the ePeriphType when entering stop mode. + * @param ePeriphType the peripheral to set stop request + * @param bEnable true: set the stop request + * false: clear the stop request + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_NO_PERM: Current CPU has no permission to access the register + */ +CSC_RetStatusType CSC_SetStopRequestGrp2(CSC_WPB_CpuType eTargetCpuType, CSCx_Reg2_PeriphType ePeriphType, bool bEnable) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + CSC_WPB_CpuType eCtrlCpu; + + DEV_ASSERT((ePeriphType == CSC_STOPMODE_FCUART0) || + (ePeriphType == CSC_STOPMODE_FCIIC0) || + (ePeriphType == CSC_STOPMODE_FCSPI0) || + (ePeriphType == CSC_STOPMODE_CMP1) || + (ePeriphType == CSC_STOPMODE_CMP0) || + (ePeriphType == CSC_STOPMODE_CMU3) || + (ePeriphType == CSC_STOPMODE_CMU2) || + (ePeriphType == CSC_STOPMODE_CMU1) || + (ePeriphType == CSC_STOPMODE_CMU0)); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eCtrlCpu = CSC0_HWA_REQR2_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + /* Set peripheral stop ack enable */ + if(bEnable != false) + { + CSC0_HWA_REQR2_SetStopRequest(ePeriphType); + } + else + { + CSC0_HWA_REQR2_ClearStopRequest(ePeriphType); + } + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_NO_PERM; + } + } + + return eRetVal; +} + +/** + * @brief Set the stop mode ACK of all group peripherals in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the peripherals when entering stop mode. + * @param ePeriphGrp the group of peripherals to set the stop mode ACK value + * @param u32Value the CSCx_STOP_MODERx register value + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_PARAM: ePeriphGrp or u32Value invalid + * CSC_E_NO_PERM: Current CPU has no permission to access the register + */ +CSC_RetStatusType CSC_SetStopModeAck(CSC_WPB_CpuType eTargetCpuType, CSC_PeriphGrpType ePeriphGrp, uint32_t u32Value) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + uint32_t eGrpMask[CSC_STOP_PERIPH_GROUP_MAX] = {CSC_STOP_PERIPH_GROUP0_MASK, + CSC_STOP_PERIPH_GROUP1_MASK, + CSC_STOP_PERIPH_GROUP2_MASK + }; + + if((uint32_t)ePeriphGrp >= (uint32_t)CSC_STOP_PERIPH_GROUP_MAX) + { + eRetVal = CSC_E_PARAM; + } + else if(((~eGrpMask[(uint32_t)ePeriphGrp]) & u32Value) != 0U) + { + eRetVal = CSC_E_PARAM; + } + else + { + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eRetVal = CSC0_SetStopModeAck(ePeriphGrp,u32Value); + } + } + + return eRetVal; +} + +/** + * @brief Set the stop request of all group peripherals in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the peripherals when entering stop mode. + * @param ePeriphGrp the group of peripherals to set the stop request value + * @param u32Value the CSCx_STOP_REQRx register value + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_PARAM: ePeriphGrp or u32Value invalid + * CSC_E_NO_PERM: Current CPU has no permission + */ +CSC_RetStatusType CSC_SetStopRequest(CSC_WPB_CpuType eTargetCpuType, CSC_PeriphGrpType ePeriphGrp, uint32_t u32Value) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + uint32_t eGrpMask[CSC_STOP_PERIPH_GROUP_MAX] = {CSC_STOP_PERIPH_GROUP0_MASK, + CSC_STOP_PERIPH_GROUP1_MASK, + CSC_STOP_PERIPH_GROUP2_MASK + }; + + if((uint32_t)ePeriphGrp >= (uint32_t)CSC_STOP_PERIPH_GROUP_MAX) + { + eRetVal = CSC_E_PARAM; + } + else if(((~eGrpMask[(uint32_t)ePeriphGrp]) & u32Value) != 0U) + { + eRetVal = CSC_E_PARAM; + } + else + { + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eRetVal = CSC0_SetStopRequest(ePeriphGrp,u32Value); + } + } + + return eRetVal; +} + +/** + * @brief Get the stop Acknowledge status of peripherals group0 in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the peripherals when entering stop mode. + * @param ePeriphType the peripheral to get stop acknowledge status + * @param bool true: Stop acknowledge is asserted (the module is in Stop mode) + * false: Stop acknowledge is not asserted + * @return Operation success/failed + */ +CSC_RetStatusType CSC_GetStopAckStatusGrp0(CSC_WPB_CpuType eTargetCpuType,CSCx_Reg0_PeriphType ePeriphType, bool * const pStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + DEV_ASSERT((ePeriphType == CSC_STOPMODE_FLEXCAN1) || + (ePeriphType == CSC_STOPMODE_FLEXCAN0) || + (ePeriphType == CSC_STOPMODE_FREQM) || + (ePeriphType == CSC_STOPMODE_FCUART3) || + (ePeriphType == CSC_STOPMODE_FCUART2) || + (ePeriphType == CSC_STOPMODE_FCUART1) || + (ePeriphType == CSC_STOPMODE_FCSPI2) || + (ePeriphType == CSC_STOPMODE_FCSPI1) || + (ePeriphType == CSC_STOPMODE_SENT0) || + (ePeriphType == CSC_STOPMODE_TMU) || + (ePeriphType == CSC_STOPMODE_ADC1) || + (ePeriphType == CSC_STOPMODE_ADC0) || + (ePeriphType == CSC_STOPMODE_CMU4) || + (ePeriphType == CSC_STOPMODE_WDOG0) || + (ePeriphType == CSC_STOPMODE_ISM0) || + (ePeriphType == CSC_STOPMODE_DMA0)); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + *pStatus = (bool)(0U != CSC0_HWA_ACKR0_GetStopAckStatus(ePeriphType)); + eRetVal = CSC_E_OK; + } + return eRetVal; +} + +/** + * @brief Get the stop Acknowledge status of peripherals group1 in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the peripherals when entering stop mode. + * @param ePeriphType the peripheral to get stop acknowledge status + * @param bool true: Stop acknowledge is asserted (the module is in Stop mode) + * false: Stop acknowledge is not asserted + * @return Operation success/failed + */ +CSC_RetStatusType CSC_GetStopAckStatusGrp1(CSC_WPB_CpuType eTargetCpuType, CSCx_Reg1_PeriphType ePeriphType, bool * const pStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + DEV_ASSERT((ePeriphType == CSC_STOPMODE_FLEXCAN3) || + (ePeriphType == CSC_STOPMODE_FLEXCAN2) || + (ePeriphType == CSC_STOPMODE_MSC0) || + (ePeriphType == CSC_STOPMODE_FCUART7) || + (ePeriphType == CSC_STOPMODE_FCUART6) || + (ePeriphType == CSC_STOPMODE_FCUART5) || + (ePeriphType == CSC_STOPMODE_FCUART4) || + (ePeriphType == CSC_STOPMODE_FCIIC1) || + (ePeriphType == CSC_STOPMODE_FCSPI5) || + (ePeriphType == CSC_STOPMODE_FCSPI4) || + (ePeriphType == CSC_STOPMODE_FCSPI3) || + (ePeriphType == CSC_STOPMODE_WDOG1)); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + *pStatus = (bool)(0U != CSC0_HWA_ACKR1_GetStopAckStatus(ePeriphType)); + eRetVal = CSC_E_OK; + } + return eRetVal; +} + +/** + * @brief Get the stop Acknowledge status of peripherals group2 in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the peripherals when entering stop mode. + * @param ePeriphType the peripheral to get stop acknowledge status + * @param bool true: Stop acknowledge is asserted (the module is in Stop mode) + * false: Stop acknowledge is not asserted + * @return Operation success/failed + */ +CSC_RetStatusType CSC_GetStopAckStatusGrp2(CSC_WPB_CpuType eTargetCpuType,CSCx_Reg2_PeriphType ePeriphType, bool * const pStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + DEV_ASSERT((ePeriphType == CSC_STOPMODE_FCUART0) || + (ePeriphType == CSC_STOPMODE_FCIIC0) || + (ePeriphType == CSC_STOPMODE_FCSPI0) || + (ePeriphType == CSC_STOPMODE_CMP1) || + (ePeriphType == CSC_STOPMODE_CMP0) || + (ePeriphType == CSC_STOPMODE_CMU3) || + (ePeriphType == CSC_STOPMODE_CMU2) || + (ePeriphType == CSC_STOPMODE_CMU1) || + (ePeriphType == CSC_STOPMODE_CMU0)); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + *pStatus = (bool)(0U != CSC0_HWA_ACKR2_GetStopAckStatus(ePeriphType)); + eRetVal = CSC_E_OK; + } + return eRetVal; +} + +/** + * @brief Get the stop Acknowledge status of all group peripherals in CSC. + * + * @param eTargetCpuType The target CPU which acknowledges the peripherals when entering stop mode. + * @param ePeriphType the peripheral to get stop acknowledge status + * @param pU32Status Output parameter,to save the stop ACK status of all the peripherals in the group indicated by ePeriphGrp. + * The corresponding bit is 1, indicates that stop acknowledge is asserted,and 0 not asserted. + * @return CSC_RetStatusType Operation success/failed + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + */ +CSC_RetStatusType CSC_GetStopAckStatus(CSC_WPB_CpuType eTargetCpuType,CSC_PeriphGrpType ePeriphGrp, uint32_t * const pU32Status) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + DEV_ASSERT((uint32_t)ePeriphGrp <= (uint32_t)CSC_STOP_CTRL_GROUP_2); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + *pU32Status = CSC0_GetStopAckStatus(ePeriphGrp); + eRetVal = CSC_E_OK; + } + return eRetVal; +} + +/** + * @brief Set the CPU write permission of CSCx_CCMx_CFG register in CSC. + * + * @param eTargetCpuType The target CPU controlled by CSCx_CCMx_CFG register. + * @param eCtrlCpuType The CPU that has the permission to access the CSCx_CCMx_CFG register. + * @param bLockStatus Lock the WPB of CSCx_CCMx_CFG register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_LOCK: WPB is locked(WPB_LOCK set 1) and can not be written + */ +CSC_RetStatusType CSC_SetCCMCfgPermission(CSC_WPB_CpuType eTargetCpuType, CSC_WPB_CpuType eCtrlCpuType, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + DEV_ASSERT((uint32_t)eCtrlCpuType < (uint32_t)CSC_WP_CPU_NONE); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + if (0U == CSC0_HWA_CCM0_GetWPBLockStatus()) + { + CSC0_HWA_CCM0_SetCpuWritePermit(eCtrlCpuType); + + if(bLockStatus != false) + { + CSC0_HWA_CCM0_LockWritePermit(); + } + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_LOCK; + } + } + return eRetVal; +} + +/** + * @brief Set the CCM configuration of CPUx indicated by eTargetCpuType. + * + * @param eTargetCpuType The target CPU controlled by CSCx_CCMx_CFG register. + * @param pCCMCfg Pointer to the configuration of CSCx_CCMx_CFG register. + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_LOCK: Current CPU has no permission + */ +CSC_RetStatusType CSC_SetCCMConfiguration(CSC_WPB_CpuType eTargetCpuType,const CSC_CCMCfgType *const pCCMCfg) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + CSC_WPB_CpuType eCtrlCpu; + + DEV_ASSERT(pCCMCfg != NULL_PTR); + DEV_ASSERT(pCCMCfg->eHandShakeMode == CSC_WAIT_ALL_ACK || + pCCMCfg->eHandShakeMode == CSC_WAIT_REQ_ACK); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eCtrlCpu = CSC0_HWA_CCM0_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + CSC0_HWA_HClockEnable(pCCMCfg->HclkEn); + CSC0_HWA_SetHandShakeMode(pCCMCfg->eHandShakeMode); + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_LOCK; + } + } + return eRetVal; +} + +/** + * @brief Get the CCM stop clock status. + * + * @param eTargetCpuType The target CPU controlled by CSCx_CCMx_CFG register. + * @param eCCMType CCM stop clock type. + * @param pStatus Pointer to memory to save the clock status. + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + */ +CSC_RetStatusType CSC_GetCCMStopClockStatus(CSC_WPB_CpuType eTargetCpuType, CSCx_CCM_StopClockType eCCMType, bool * const pStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + + DEV_ASSERT(pStatus != NULL_PTR); + DEV_ASSERT(eCCMType == CSC_CCM_STOPCLOCK_STATUS_SYS_SLAVE || + eCCMType == CSC_CCM_STOPCLOCK_STATUS_MASTER || + eCCMType == CSC_CCM_STOPCLOCK_STATUS_SLOW_SLAVE || + eCCMType == CSC_CCM_STOPCLOCK_STATUS_BUS_SLAVE); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + *pStatus = (bool)(0u != CSC0_HWA_CCM0_GetClockStatus(eCCMType)); + eRetVal = CSC_E_OK; + } + return eRetVal; +} + +/** + * @brief Set the CPU write permission of CSCx_CPUx_INT register in CSC. + * + * @param eTargetCpuType The target CPU controlled by CSCx_CPUx_INT register. + * @param eCtrlCpuType The CPU that has the permission to access the CSCx_CPUx_INT register. + * @param bLockStatus Lock the WPB of CSCx_CPUx_INT register.Once locked, calling the API returns an error(CSC_E_LOCK). + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_LOCK: WPB is locked(WPB_LOCK set 1) and can not be written + */ +CSC_RetStatusType CSC_SetCpuIntPermission(CSC_WPB_CpuType eTargetCpuType, CSC_WPB_CpuType eCtrlCpuType, bool bLockStatus) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + DEV_ASSERT((uint32_t)eCtrlCpuType < (uint32_t)CSC_WP_CPU_NONE); + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + if (0U == CSC0_HWA_CPU0INT_GetWPBLockStatus()) + { + CSC0_HWA_CPU0INT_SetCpuWritePermit(eCtrlCpuType); + + if(bLockStatus != false) + { + CSC0_HWA_CPU0INT_LockWritePermit(); + } + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_LOCK; + } + } + return eRetVal; +} + +/** + * @brief Generate software interrupt via CSCx_CPUx_INT. + * + * @param eTargetCpuType The target CPU to generate interrupt. + * @param bEnable true: Generate software interrupt. + * false: Do not generate software interrupt. + * + * @return CSC_RetStatusType + * CSC_E_OK: The API is successfully called + * CSC_E_NOT_OK: eTargetCpuType invalid + * CSC_E_LOCK: The current CPU has no permission to access this bit + */ +CSC_RetStatusType CSC_CpuSwInterruptGen(CSC_WPB_CpuType eTargetCpuType, bool bEnable) +{ + CSC_RetStatusType eRetVal = CSC_E_NOT_OK; + CSC_WPB_CpuType eCtrlCpu; + + if (CSC_WP_CPU_0 == eTargetCpuType) + { + eCtrlCpu = CSC0_HWA_CPU0INT_GetCpuWritePermit(); + + if((eCtrlCpu == CSC_GET_CPU_ID()) || (eCtrlCpu == CSC_WP_CPU_ALL)) + { + if(bEnable != false) + { + CSC0_HWA_CPU0INT_EnableSWInterrupt(); + } + else + { + CSC0_HWA_CPU0INT_DisableSWInterrupt(); + } + eRetVal = CSC_E_OK; + } + else + { + eRetVal = CSC_E_LOCK; + } + } + return eRetVal; +} diff --git a/Src/fc7xxx_driver_dma.c b/Src/fc7xxx_driver_dma.c new file mode 100644 index 0000000..df65d5c --- /dev/null +++ b/Src/fc7xxx_driver_dma.c @@ -0,0 +1,795 @@ +/** + * @file fc7xxx_driver_dma.c + * @author Flagchip0126 + * @brief FC7xxx DMA driver source code + * @version 0.1.0 + * @date 2024-01-15 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Author CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-15 Flagchip0126 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_dma.h" +#include "interrupt_manager.h" + +#define DMA_CHANNEL_INVALID (0xFFU) + +#define CPM_CORE_ID_CORE0 (0x0U) +#define CPM_CORE_ID_CORE1 (0x2U) +#define CPM_CORE_ID_CORE2 (0x4U) + +static uint8_t s_aDmaDumoUsedStatus[DMA_DUMO_COUNT] = {DMA_CHANNEL_INVALID, DMA_CHANNEL_INVALID, DMA_CHANNEL_INVALID, DMA_CHANNEL_INVALID}; + +static DMA_TransferCompleteCallbackType s_dmaTransferCompleteNotify[DMA_INSTANCE_COUNT][DMA_CFG_COUNT] = {NULL}; +static DMA_TransferErrorCallbackType s_dmaTransferErrorNotify[DMA_INSTANCE_COUNT][DMA_CFG_COUNT] = {NULL}; + +/** + * @brief DMA IRQ function prototypes + * + */ +void DMA0_IRQHandler(void); +void DMA1_IRQHandler(void); +void DMA2_IRQHandler(void); +void DMA3_IRQHandler(void); +void DMA4_IRQHandler(void); +void DMA5_IRQHandler(void); +void DMA6_IRQHandler(void); +void DMA7_IRQHandler(void); +void DMA8_IRQHandler(void); +void DMA9_IRQHandler(void); +void DMA10_IRQHandler(void); +void DMA11_IRQHandler(void); +void DMA12_IRQHandler(void); +void DMA13_IRQHandler(void); +void DMA14_IRQHandler(void); +void DMA15_IRQHandler(void); +void DMA_Error_IRQHandler(void); + + +/** + * @brief Get the first unused DUMO register index + * + * @param [out] pDumoIndex the DUMO register index + * @return DMA_StatusType whether there is unused DUMO index + * @return DMA_STATUS_SUCCESS the DUMO register index is successfully get + * @return DMA_STATUS_NO_RESOURCE all DUMO registers are already occupied + */ +static inline DMA_StatusType DMA_GetDumoIndex(uint8_t *pDumoIndex); + +/** + * @brief Check whether the value is power of 2 and return the ceil value of the log2(u32Value) + * + * @param [in] u32Value the value to check + * @param [out] u8Log2 the ceil value of log2(u32Value) + * @return true the u32Value is power of 2 + * @return false the u32Value is not power of 2 + */ +static bool DMA_IsPowerOf2(uint32_t u32Value, uint8_t *u8Log2); + +/** + * @brief Reset the DMAMUX config values + * @param Dmamux_Instance the selected DMA Instance + * + */ +static inline void Dmamux_Reset(DMAMUX_Type * const Dmamux_Instance); + +/** + * @brief Get the data offset value of the selected increment mode and data size + * + * @param eIncMode the selected increment mode + * @param eDataSize the selected data size + * @return int16_t the calculated data offset + */ +static inline uint16_t DMA_GetDataOffset(DMA_IncrementModeType eIncMode, + DMA_TransferSizeType eDataSize); + +/** + * @brief Get the IRQ number of the selected DMA channel + * + * @param u8Channel the selected DMA channel + * @return IRQn_Type the IRQ number of the selected DMA channel + */ +//static inline IRQn_Type DMA_GetChannelIRQn(const DMA_InstanceType eDma_Instance); + +/** + * @brief The internal interrupt handler for DMA transfer complete + * + * @param u8Channel the channel of the DMA interrpt + */ +static inline void DMA_Transfer_Complete_IRQHandler(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel); + +static inline DMA_StatusType DMA_GetDumoIndex(uint8_t *pDumoIndex) +{ + DMA_StatusType ret = DMA_STATUS_ERROR; + for (*pDumoIndex = 0U; *pDumoIndex < DMA_DUMO_COUNT; (*pDumoIndex)++) + { + if (s_aDmaDumoUsedStatus[*pDumoIndex] == DMA_CHANNEL_INVALID) + { + ret = DMA_STATUS_SUCCESS; + break; + } + } + if (*pDumoIndex == DMA_DUMO_COUNT) + { + ret = DMA_STATUS_NO_RESOURCE; + } + return ret; +} + +static bool DMA_IsPowerOf2(uint32_t u32Value, uint8_t *u8Log2) +{ + bool ret = (bool)false; + *u8Log2 = 0U; + while (u32Value > (1UL << *u8Log2)) + { + (*u8Log2)++; + } + if ((u32Value & ((1UL << *u8Log2) - 1U)) == 0U) + { + ret = (bool)true; + } + return ret; +} + +static inline uint16_t DMA_GetDataOffset(DMA_IncrementModeType eIncMode, + DMA_TransferSizeType eDataSize) +{ + uint16_t u16DataOffset = 0U; + switch (eIncMode) + { + case DMA_INCREMENT_DISABLE: + { + u16DataOffset = 0U; + break; + } + + case DMA_INCREMENT_DATA_SIZE: + { + u16DataOffset = (uint16_t)(1UL << ((uint8_t)eDataSize)); + break; + } + + case DMA_INCREMENT_DATA_SIZE_4BYTE_ALIGNED: + { + switch (eDataSize) + { + case DMA_TRANSFER_SIZE_1B: + case DMA_TRANSFER_SIZE_2B: + case DMA_TRANSFER_SIZE_4B: + u16DataOffset = 4U; + break; + + case DMA_TRANSFER_SIZE_8B: + u16DataOffset = 8U; + break; + + case DMA_TRANSFER_SIZE_32B: + u16DataOffset = 32U; + break; + + default: + break; + } + break; + } + + default: + break; + } + return u16DataOffset; +} + +void DMA0_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_0); +} + +void DMA1_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_1); +} + +void DMA2_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_2); +} + +void DMA3_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_3); +} + +void DMA4_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_4); +} + +void DMA5_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_5); +} + +void DMA6_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_6); +} + +void DMA7_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_7); +} + +void DMA8_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_8); +} + +void DMA9_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_9); +} + +void DMA10_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_10); +} + +void DMA11_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_11); +} + +void DMA12_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_12); +} + +void DMA13_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_13); +} + +void DMA14_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_14); +} + +void DMA15_IRQHandler(void) +{ + DMA_Transfer_Complete_IRQHandler(DMA_INSTANCE_0, DMA_CHANNEL_15); +} + +void DMA_Error_IRQHandler(void) +{ + uint8_t u8Channel; + DMA_InstanceType eDma_Instance; + DMA_Type *pDma; + DMA_Type * aDma[] = DMA_BASE_PTRS; + + eDma_Instance = DMA_INSTANCE_0; + + pDma = aDma[DMA_INSTANCE_0]; + for (u8Channel = 0U; u8Channel < DMA_CFG_COUNT; u8Channel++) + { + if (DMA_HWA_GetChannelErrorFlag(pDma, u8Channel) == true) + { + DMA_HWA_ClearChannelErrorFlag(pDma, u8Channel); + if (s_dmaTransferErrorNotify[eDma_Instance][u8Channel] != NULL) + { + s_dmaTransferErrorNotify[eDma_Instance][u8Channel](); + } + } + } +} + +static inline void DMA_Transfer_Complete_IRQHandler(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel) +{ + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + + DMA_HWA_ClearChannelInterruptFlag(pDma, (uint8_t)eChannel); + if (s_dmaTransferCompleteNotify[eDma_Instance][eChannel] != NULL) + { + s_dmaTransferCompleteNotify[eDma_Instance][eChannel](); + } +} + +static inline void Dmamux_Reset(DMAMUX_Type * const Dmamux_Instance) +{ + uint8_t u8Index; + for (u8Index = 0U; u8Index < DMAMUX_CHCFG_COUNT; u8Index++) + { + DMAMUX_HWA_SetRequestSource(Dmamux_Instance, u8Index, false, DMA_REQ_DISABLED); + } + for (u8Index = 0U; u8Index < DMAMUX_CHTRG_TRG_COUNT; u8Index++) + { + //DMAMUX_HWA_SetPeriodicTrigFlag(Dmamux_Instance, u8Index, false); + } +} + +void DMA_Init(const DMA_InstanceType eDma_Instance, const DMA_InitType *const pInitCfg) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(pInitCfg != NULL); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + + DMA_DeInit(eDma_Instance); + DMA_HWA_SetHaltOnErrorFlag(pDma, pInitCfg->bHaltOnError); + DMA_HWA_SetArbitrationAlgorithm(pDma, pInitCfg->eArbitrationAlgorithm); + DMA_HWA_SetInnerLoopMappingEnableFlag(pDma, true); +} + +void DMA_DeInit(const DMA_InstanceType eDma_Instance) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + + uint8_t u8Index; + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + DMAMUX_Type * aDmamux[] = DMAMUX_BASE_PTRS; + DMAMUX_Type *const pDmamux = aDmamux[eDma_Instance]; + + DMA_HWA_SetControlRegister(pDma, 0U); + DMA_HWA_DisableAllChannelErrorInterrupt(pDma); + DMA_HWA_DisableAllChannelRequest(pDma); + DMA_HWA_ClearAllChannelDoneStatus(pDma); + DMA_HWA_ClearAllChannelErrorFlag(pDma); + DMA_HWA_ClearAllChannelInterruptFlag(pDma); + pDma->DUME[0] = 0U; + for (u8Index = 0U; u8Index < DMA_DUMO_COUNT; u8Index++) + { + DMA_HWA_SetUnalignModulo(pDma, u8Index, 0U, 0U); + } + for (u8Index = 0U; u8Index < DMA_CFG_COUNT; u8Index++) + { + DMA_HWA_SetUnalignModuloEnableFlag(pDma, u8Index, false, false); + DMA_HWA_SetPriority(pDma, u8Index, u8Index); + DMA_HWA_SetSrcAddr(pDma, u8Index, 0U); + DMA_HWA_SetSrcOffset(pDma, u8Index, 0); + DMA_HWA_SetSrcLastAddrAdjustment(pDma, u8Index, 0); + DMA_HWA_SetDestAddr(pDma, u8Index, 0U); + DMA_HWA_SetDestOffset(pDma, u8Index, 0); + DMA_HWA_SetDestLastAddrAdjustment(pDma, u8Index, 0); + DMA_HWA_SetSrcDataSize(pDma, u8Index, DMA_TRANSFER_SIZE_1B); + DMA_HWA_SetSrcModulo(pDma, u8Index, 0U); + DMA_HWA_SetDestDataSize(pDma, u8Index, DMA_TRANSFER_SIZE_1B); + DMA_HWA_SetDestModulo(pDma, u8Index, 0U); + DMA_HWA_SetInnerLoopSize(pDma, u8Index, 0U); + DMA_HWA_SetChannelControlStatus(pDma, u8Index, 0U); + DMA_HWA_SetChannelToChannelTrig(pDma, u8Index, false, 0U); + DMA_HWA_SetLoopCount(pDma, u8Index, 0U); + } + Dmamux_Reset(pDmamux); + +} + +DMA_StatusType DMA_InitChannel(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel, const DMA_ChannelCfgType *const pChnCfg) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(eChannel < DMA_CHANNEL_MAX); + DEV_ASSERT(pChnCfg != NULL); + DEV_ASSERT(pChnCfg->u16BlockCount > 0U); + DEV_ASSERT(pChnCfg->u32BlockSize > 0U); + DEV_ASSERT(((pChnCfg->u32BlockSize >> pChnCfg->eSrcDataSize) << pChnCfg->eSrcDataSize == pChnCfg->u32BlockSize) && + ((pChnCfg->u32BlockSize >> pChnCfg->eDestDataSize) << pChnCfg->eDestDataSize == pChnCfg->u32BlockSize)); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + DMAMUX_Type * aDmamux[] = DMAMUX_BASE_PTRS; + DMAMUX_Type *const pDmamux = aDmamux[eDma_Instance]; + + DMA_StatusType ret; + + uint16_t u16SrcDataOffset = DMA_GetDataOffset(pChnCfg->eSrcIncMode, pChnCfg->eSrcDataSize); + uint16_t u16DestDataOffset = DMA_GetDataOffset(pChnCfg->eDestIncMode, pChnCfg->eDestDataSize); + + int32_t s32SrcLastOffset; + int32_t s32DestLastOffset; + + uint8_t u8SrcMod = 0U; + uint8_t u8DestMod = 0U; + + bool bUseSrcDumo = (bool)false; + bool bUseDestDumo = (bool)false; + uint8_t u8DumoIndex = 0U; + uint16_t u16Sumo = 0U; + uint16_t u16Dumo = 0U; + + if ((pChnCfg->bSrcCircularBufferEn == true) || (pChnCfg->bDestCircularBufferEn == true)) + { + /* If the circular buffer size is not power of 2 aligned, need to use the DUMO */ + if (pChnCfg->bSrcCircularBufferEn == true) + { + DEV_ASSERT(pChnCfg->u32SrcCircBufferSize != 0U); + bUseSrcDumo = (bool)(DMA_IsPowerOf2(pChnCfg->u32SrcCircBufferSize, &u8SrcMod) ? false : true); + } + if (pChnCfg->bDestCircularBufferEn == true) + { + DEV_ASSERT(pChnCfg->u32DestCircBufferSize != 0U); + bUseDestDumo = (bool)(DMA_IsPowerOf2(pChnCfg->u32DestCircBufferSize, &u8DestMod) ? false : true); + } + + /* If circular buffer is enabled, the buffer address must be power of 2 aligned */ + if (((pChnCfg->bSrcCircularBufferEn == true) && + (((uint32_t)pChnCfg->pSrcBuffer & ((1UL << u8SrcMod) - 1U)) != 0U)) || + ((pChnCfg->bDestCircularBufferEn == true) && + (((uint32_t)pChnCfg->pDestBuffer & ((1UL << u8DestMod) - 1U)) != 0U))) + { + ret = DMA_STATUS_INVALID_ADDRESS; + } + /* If circular buffer is enabled, the buffer size must not less than the data offset */ + else if (((pChnCfg->bSrcCircularBufferEn == true) && + (pChnCfg->u32SrcCircBufferSize < u16SrcDataOffset)) || + ((pChnCfg->bDestCircularBufferEn == true) && + (pChnCfg->u32DestCircBufferSize < u16SrcDataOffset))) + { + ret = DMA_STATUS_UNSUPPORTED; + } + /* If source or destination unalign modulo is used, check whether all DUMO registers are occupied */ + else if ((bUseSrcDumo == true) || (bUseDestDumo == true)) + { + ret = DMA_GetDumoIndex(&u8DumoIndex); + if (ret == DMA_STATUS_SUCCESS) + { + s_aDmaDumoUsedStatus[u8DumoIndex] = (uint8_t)eChannel; + } + } + else + { + ret = DMA_STATUS_SUCCESS; + } + } + else + { + ret = DMA_STATUS_SUCCESS; + } + + if (ret == DMA_STATUS_SUCCESS) + { + if (pChnCfg->bSrcAddrLoopbackEn == true) + { + if (pChnCfg->bSrcBlockOffsetEn == false) + { + s32SrcLastOffset = -((int32_t)((pChnCfg->u32BlockSize >> pChnCfg->eSrcDataSize) * u16SrcDataOffset) * + (int32_t)(pChnCfg->u16BlockCount)); + } + else + { + s32SrcLastOffset = -(((int32_t)((pChnCfg->u32BlockSize >> pChnCfg->eSrcDataSize) * u16SrcDataOffset)) * + (int32_t)(pChnCfg->u16BlockCount)) - ((pChnCfg->s32BlockOffset) * (int32_t)(pChnCfg->u16BlockCount - 1U)); + } + } + else + { + s32SrcLastOffset = 0; + } + if (pChnCfg->bDestAddrLoopbackEn == true) + { + if (pChnCfg->bDestBlockOffsetEn == false) + { + s32DestLastOffset = -(((pChnCfg->u32BlockSize >> pChnCfg->eDestDataSize) * u16DestDataOffset) * + (pChnCfg->u16BlockCount)); + } + else + { + s32DestLastOffset = -(((int32_t)((pChnCfg->u32BlockSize >> pChnCfg->eDestDataSize) * u16DestDataOffset)) * + (int32_t)(pChnCfg->u16BlockCount)) - ((pChnCfg->s32BlockOffset) * (int32_t)(pChnCfg->u16BlockCount - 1U)); + } + } + else + { + s32DestLastOffset = 0; + } + + DMA_HWA_SetSrcAddr(pDma, (uint8_t)eChannel, (uint32_t)pChnCfg->pSrcBuffer); + DMA_HWA_SetDestAddr(pDma, (uint8_t)eChannel, (uint32_t)pChnCfg->pDestBuffer); + DMA_HWA_SetPriority(pDma, (uint8_t)eChannel, pChnCfg->u8ChannelPriority); + + if ((pChnCfg->bSrcCircularBufferEn == true) && (pChnCfg->bDestCircularBufferEn == true)) + { + DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, pChnCfg->eSrcDataSize); + DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, u8SrcMod); + DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, pChnCfg->eDestDataSize); + DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, u8DestMod); + } + else if (pChnCfg->bSrcCircularBufferEn == true) + { + DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, pChnCfg->eSrcDataSize); + DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, u8SrcMod); + DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, pChnCfg->eDestDataSize); + DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, 0U); + } + else if (pChnCfg->bDestCircularBufferEn == true) + { + DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, pChnCfg->eSrcDataSize); + DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, 0U); + DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, pChnCfg->eDestDataSize); + DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, u8DestMod); + } + else + { + DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, pChnCfg->eSrcDataSize); + DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, 0U); + DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, pChnCfg->eDestDataSize); + DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, 0U); + } + + if (bUseSrcDumo == true) + { + u16Sumo = (uint16_t)((pChnCfg->u32SrcCircBufferSize / u16SrcDataOffset - 1U) * u16SrcDataOffset); + } + if (bUseDestDumo == true) + { + u16Dumo = (uint16_t)((pChnCfg->u32DestCircBufferSize / u16DestDataOffset - 1U) * u16DestDataOffset); + } + if ((bUseSrcDumo == true) || (bUseDestDumo == true)) + { + DMA_HWA_SetUnalignModulo(pDma, u8DumoIndex, u16Sumo, u16Dumo); + DMA_HWA_SetUnalignModuloEnableFlag(pDma, (uint8_t)eChannel, bUseSrcDumo, bUseDestDumo); + DMA_HWA_SetUnalignModuloSel(pDma, (uint8_t)eChannel, u8DumoIndex); + } + DMA_HWA_SetAutoDisableReuqestEnableFlag(pDma, (uint8_t)eChannel, pChnCfg->bAutoStop); + + DMA_HWA_SetSrcOffset(pDma, (uint8_t)eChannel, (int16_t)u16SrcDataOffset); + DMA_HWA_SetDestOffset(pDma, (uint8_t)eChannel, (int16_t)u16DestDataOffset); + + DMA_HWA_SetInnerLoopOffset(pDma, (uint8_t)eChannel, pChnCfg->bSrcBlockOffsetEn, pChnCfg->bDestBlockOffsetEn, + pChnCfg->s32BlockOffset); + DMA_HWA_SetInnerLoopSize(pDma, (uint8_t)eChannel, pChnCfg->u32BlockSize); + + if ((pChnCfg->u16BlockCount > 1U) && (true == pChnCfg->bInnerChannelChain)) + { + DMA_HWA_SetChannelToChannelTrig(pDma, (uint8_t)eChannel, true, (uint8_t)eChannel); + DMA_HWA_SetLoopCount(pDma, (uint8_t)eChannel, pChnCfg->u16BlockCount); + } + else + { + DMA_HWA_SetChannelToChannelTrig(pDma, (uint8_t)eChannel, false, 0U); + DMA_HWA_SetLoopCount(pDma, (uint8_t)eChannel, pChnCfg->u16BlockCount); + } + + DMA_HWA_SetSrcLastAddrAdjustment(pDma, (uint8_t)eChannel, s32SrcLastOffset); + DMA_HWA_SetDestLastAddrAdjustment(pDma, (uint8_t)eChannel, s32DestLastOffset); + + if (pChnCfg->eTriggerSrc == DMA_REQ_DISABLED) + { + DMAMUX_HWA_SetRequestSource(pDmamux, (uint8_t)eChannel, false, DMA_REQ_DISABLED); + } + else + { + DMAMUX_HWA_SetRequestSource(pDmamux, (uint8_t)eChannel, true, pChnCfg->eTriggerSrc); + } + } + return ret; +} + +void DMA_DeinitChannel(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(eChannel < DMA_CHANNEL_MAX); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + uint8_t u8DumoIndex; + + for (u8DumoIndex = 0U; u8DumoIndex < DMA_DUMO_COUNT; u8DumoIndex++) + { + if (s_aDmaDumoUsedStatus[u8DumoIndex] == (uint8_t)eChannel) + { + s_aDmaDumoUsedStatus[u8DumoIndex] = DMA_CHANNEL_INVALID; + DMA_HWA_SetUnalignModulo(pDma, u8DumoIndex, 0U, 0U); + } + } + DMA_HWA_SetUnalignModuloEnableFlag(pDma, (uint8_t)eChannel, false, false); + DMA_HWA_DisableChannelErrorInterrupt(pDma, (uint8_t)eChannel); + DMA_HWA_DisableChannelRequest(pDma, (uint8_t)eChannel); + DMA_HWA_ClearChannelDoneStatus(pDma, (uint8_t)eChannel); + DMA_HWA_ClearChannelErrorFlag(pDma, (uint8_t)eChannel); + DMA_HWA_ClearChannelInterruptFlag(pDma, (uint8_t)eChannel); + + DMA_HWA_SetSrcAddr(pDma, (uint8_t)eChannel, 0U); + DMA_HWA_SetSrcOffset(pDma, (uint8_t)eChannel, 0); + DMA_HWA_SetSrcLastAddrAdjustment(pDma, (uint8_t)eChannel, 0); + DMA_HWA_SetDestAddr(pDma, (uint8_t)eChannel, 0U); + DMA_HWA_SetDestOffset(pDma, (uint8_t)eChannel, 0); + DMA_HWA_SetDestLastAddrAdjustment(pDma, (uint8_t)eChannel, 0); + DMA_HWA_SetSrcDataSize(pDma, (uint8_t)eChannel, DMA_TRANSFER_SIZE_1B); + DMA_HWA_SetSrcModulo(pDma, (uint8_t)eChannel, 0U); + DMA_HWA_SetDestDataSize(pDma, (uint8_t)eChannel, DMA_TRANSFER_SIZE_1B); + DMA_HWA_SetDestModulo(pDma, (uint8_t)eChannel, 0U); + DMA_HWA_SetInnerLoopOffset(pDma, (uint8_t)eChannel, false, false, 0); + DMA_HWA_SetInnerLoopSize(pDma, (uint8_t)eChannel, 0U); + DMA_HWA_SetChannelControlStatus(pDma, (uint8_t)eChannel, 0U); + DMA_HWA_SetChannelToChannelTrig(pDma, (uint8_t)eChannel, false, 0U); + DMA_HWA_SetLoopCount(pDma, (uint8_t)eChannel, 0U); +} + +void DMA_InitChannelInterrupt(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel, const DMA_InterruptCfgType *const pInterruptCfg) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(eChannel < DMA_CHANNEL_MAX); + DEV_ASSERT(pInterruptCfg != NULL); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + + if (pInterruptCfg->bTransferCompleteIntEn) + { + s_dmaTransferCompleteNotify[eDma_Instance][eChannel] = pInterruptCfg->pTransferCompleteNotify; + DMA_HWA_EnableTransferCompleteInterrupt(pDma, (uint8_t)eChannel); + //IntMgr_EnableInterrupt(DMA_GetChannelIRQn(eChannel)); + } + else + { + DMA_HWA_DisableTransferCompleteInterrupt(pDma, (uint8_t)eChannel); + s_dmaTransferCompleteNotify[eDma_Instance][eChannel] = NULL; + //IntMgr_DisableInterrupt(DMA_GetChannelIRQn(eChannel)); + } + + if (pInterruptCfg->bTransferErrorIntEn) + { + s_dmaTransferErrorNotify[eDma_Instance][eChannel] = pInterruptCfg->pTransferErrorNotify; + DMA_HWA_EnableChannelErrorInterrupt(pDma, (uint8_t)eChannel); + //IntMgr_EnableInterrupt(DMA_error_IRQn); + } + else + { + DMA_HWA_DisableChannelErrorInterrupt(pDma, (uint8_t)eChannel); + s_dmaTransferErrorNotify[eDma_Instance][eChannel] = NULL; + //if (DMA_HWA_GetAllChannelErrorInterruptEnableFlag(pDma) == 0U) + //{ + //IntMgr_DisableInterrupt(DMA_error_IRQn); + //} + } +} + +void DMA_ConfigChainedTransfer(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel, + const DMA_ChainTransferType *const pChainTransferCfg) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(eChannel < DMA_CHANNEL_MAX); + DEV_ASSERT(pChainTransferCfg != NULL); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + + DMA_HWA_SetOuterLoopTrigEnableFlag(pDma, (uint8_t)eChannel, pChainTransferCfg->bChanelChainEn); + DMA_HWA_SetOuterLoopTrigChannel(pDma, (uint8_t)eChannel, pChainTransferCfg->u8ChainedChannel); +} + +DMA_StatusType DMA_ModifyAddress(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel, + const volatile void *pSrcBuffer, const volatile void *pDestBuffer) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(eChannel < DMA_CHANNEL_MAX); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + DMA_StatusType ret; + + if (DMA_GetChannelStatus(eDma_Instance, eChannel) == DMA_RUNNING_STATUS_IDLE) + { + if (pSrcBuffer != NULL) + { + DMA_HWA_SetSrcAddr(pDma, (uint8_t)eChannel, (uint32_t)pSrcBuffer); + } + if (pDestBuffer != NULL) + { + DMA_HWA_SetDestAddr(pDma, (uint8_t)eChannel, (uint32_t)pDestBuffer); + } + ret = DMA_STATUS_SUCCESS; + } + else + { + ret = DMA_STATUS_BUSY; + } + return ret; +} + +void DMA_StartChannel(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(eChannel < DMA_CHANNEL_MAX); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + + if (DMA_GetChannelRequestSrc(eDma_Instance, eChannel) == DMA_REQ_DISABLED) + { + DMA_HWA_SetChannelStart(pDma, (uint8_t)eChannel); + } + else + { + DMA_HWA_EnableChannelRequest(pDma, (uint8_t)eChannel); + } +} + +void DMA_StopChannel(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(eChannel < DMA_CHANNEL_MAX); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + + DMA_HWA_DisableChannelRequest(pDma, (uint8_t)eChannel); +} + +DMA_StatusType DMA_CancelTransfer(const DMA_InstanceType eDma_Instance, bool bGenerateErr) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + DMA_StatusType eRet; + uint32_t u32TimeOut = 15000000U; + + if (bGenerateErr) + { + DMA_HWA_ErrorCancelTransfer(pDma); + while ((DMA_HWA_GetErrorCancelTransferStatus(pDma) == true) && (u32TimeOut != 0U)) + { + u32TimeOut--; + } + } + else + { + DMA_HWA_CancelTransfer(pDma); + while ((DMA_HWA_GetCancelTransferStatus(pDma) == true) && (u32TimeOut != 0U)) + { + u32TimeOut--; + } + } + if (u32TimeOut != 0U) + { + eRet = DMA_STATUS_SUCCESS; + } + else + { + eRet = DMA_STATUS_TIMEOUT; + } + return eRet; +} + +DMA_RequestSourceType DMA_GetChannelRequestSrc(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(eChannel < DMA_CHANNEL_MAX); + + DMAMUX_Type * aDmamux[] = DMAMUX_BASE_PTRS; + DMAMUX_Type *const pDmamux = aDmamux[eDma_Instance]; + + DMA_RequestSourceType eReqSrc = DMAMUX_HWA_GetRequestSource(pDmamux, (uint8_t)eChannel); + + return eReqSrc; +} + +DMA_RunningStatusType DMA_GetStatus(const DMA_InstanceType eDma_Instance) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + DMA_RunningStatusType eDMAStatus = DMA_HWA_GetStatus(pDma); + return eDMAStatus; +} + +DMA_RunningStatusType DMA_GetChannelStatus(const DMA_InstanceType eDma_Instance, const DMA_ChannelType eChannel) +{ + DEV_ASSERT(eDma_Instance < DMA_INSTANCE_MAX); + DEV_ASSERT(eChannel < DMA_CHANNEL_MAX); + + DMA_Type * aDma[] = DMA_BASE_PTRS; + DMA_Type *const pDma = aDma[eDma_Instance]; + DMA_RunningStatusType eChannelStatus = DMA_HWA_GetChannelActiveStatus(pDma, (uint8_t)eChannel); + return eChannelStatus; +} diff --git a/Src/fc7xxx_driver_dsp.c b/Src/fc7xxx_driver_dsp.c new file mode 100644 index 0000000..51f181b --- /dev/null +++ b/Src/fc7xxx_driver_dsp.c @@ -0,0 +1,38 @@ +/** + * @file fc7xxx_driver_dsp.c + * @author Flagchip051 + * @brief FC4xxx DSP driver type definition and API + * @version 0.1.0 + * @date 2022-04-23 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2022-04-23 Flagchip054 N/A First version for FC7300 + ******************************************************************************** */ + +#include "fc7xxx_driver_dsp.h" + + +/* + * @details @verbatim +If only want use FPU, +1) configure FCIDE to enable FPU compiler support, "Properties" -> C/C++ Build -> Settings -> Tool Settings -> Target Processor -> Float ABI -> FP instructions(hard) -> FPU Type set to "fpv5-sp-d16" +2) configure FCIDE to enable FPU compiler support, "Properties" -> C/C++ Build -> Settings -> Tool Settings -> GNU Arm Cross C Compiler -> Preprocessor -> Defined symbols(-D) -> Add "__FPU_PRESENT=1" (without ") +3) and call FPU_Enable to enable FPU at the beginning of program. + +If want to use DSP, +1) configure FCIDE to enable FPU compiler support, Properties -> C/C++ Build -> Settings -> Tool Settings -> Target Processor -> Float ABI -> FP instructions(hard) +2) add MACRO "DRIVER_CM7_DSP_ENABLE" in FCIDE Properties -> C/C++ General -> Paths and Symbols -> Symbols -> GNU C and GNU C++ and Assembly +3) add Include Path to project Properties -> C/C++ General -> Paths and Symbols -> Includes -> GNU C and GNU C++ and Assembly: + ../../../../../../Template/Device/CMSIS5_590/DSP/Include + ../../../../../../Template/Device/CMSIS5_590/Core/Include + ../../../../../../Template/Device/CMSIS5_590/DSP/PrivateInclude +4) and call FPU_Enable to enable FPU at the beginning of program. + @endverbatim + */ diff --git a/Src/fc7xxx_driver_eim.c b/Src/fc7xxx_driver_eim.c new file mode 100644 index 0000000..b18e4e6 --- /dev/null +++ b/Src/fc7xxx_driver_eim.c @@ -0,0 +1,217 @@ +/** + * @file fc7xxx_driver_eim.c + * @author Flagchip + * @brief FC7xxx EIM driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-14 qxw0100 N/A First version for FC7240 +********************************************************************************/ + +#include "fc7xxx_driver_eim.h" +#include "fc7xxx_driver_pcc.h" + +/******************* Local Variables ***********************/ + +/******************* Local Function Prototype **************/ + + +/****************** Global Functions ***********************/ +/** + * @brief Initialize EIM function + * + * @param pEimInitCfg Initialization structure of EIM + * @return return 0: initialize successful. 1: invalid parameter + */ +EIM_RetType EIM_Init(const EIM_InitType *pEimInitCfg) +{ + EIM_RetType eRet = EIM_STATUS_SUCCESS; + uint32_t u32CtrlVal = 0U; + uint32_t u32BusVal = 0U; + uint8_t u8BusChn; + if (NULL == pEimInitCfg) + { + eRet = EIM_STATUS_PARAM_INVALID; + } + else + { + u32CtrlVal |= EIM_CTRL_REG_BUS_SEL(pEimInitCfg->u8BusSelIdx); + u8BusChn = (uint8_t)pEimInitCfg->u8BusSelIdx; + if(pEimInitCfg->u8Attreenable != 0U) + { + if((pEimInitCfg->u8EimChn>=1U) && (pEimInitCfg->u8EimChn<=23U)) + { + u32CtrlVal |= EIM_CTRL_REG_ATTREIE(1U); + u32BusVal |= EIM_BUS_REG_ATTR(pEimInitCfg->u8AttrPosition); + } + else + { + eRet = EIM_STATUS_PARAM_INVALID; + } + + } + if(pEimInitCfg->u8Addreenable != 0U) + { + if((pEimInitCfg->u8EimChn>=1U) && (pEimInitCfg->u8EimChn<=23U)) + { + u32CtrlVal |= EIM_CTRL_REG_ADDREIE(1U); + u32BusVal |= EIM_BUS_REG_ADDR(pEimInitCfg->u8AddrePosition); + } + else + { + eRet = EIM_STATUS_PARAM_INVALID; + } + } + if(pEimInitCfg->u8Data0enable != 0U) + { + u32CtrlVal |= EIM_CTRL_REG_DATA0EIE(1U); + u32BusVal |= EIM_BUS_REG_DATA0(pEimInitCfg->u8Data0Val); + } + if(pEimInitCfg->u8Data1enable != 0U) + { + u32CtrlVal |= EIM_CTRL_REG_DATA1EIE(1U); + u32BusVal |= EIM_BUS_REG_DATA1(pEimInitCfg->u8Data1Val); + } + EIM_HWA_Set_BUSRegn(u8BusChn,u32BusVal); + EIM_HWA_Set_CtrlRegn((uint8_t)pEimInitCfg->u8EimChn,u32CtrlVal); + EIM_HWA_EnableGlobalErrorInjection(); + } + + return eRet; +} + +/** + * @brief Initialize EIM function + * + * @param eEimChannel channel want to set + * @param eDwpType Cpu to use + * @param bLockStatus Lock the cpu control settings + * @return Set operation success/failed + */ +EIM_RetType EIM_SetDwpMode(const EIM_ChannelType eEimChannel, const EIM_DWPType eDwpType, bool bLockStatus) +{ + uint8_t u8ChnIdx = (uint8_t)eEimChannel; + EIM_RetType eRet = EIM_STATUS_SUCCESS; + if (0U == EIM_HWA_GetCtrlDWPLockStatus(u8ChnIdx)) + { + EIM_HWA_Set_CtrlLockMode((uint8_t)eEimChannel,(uint8_t)eDwpType); + if(true == bLockStatus) + { + /* Lock the dwp mode until reset */ + EIM_HWA_CtrlRegnWritePermit(u8ChnIdx); + } + } + else + { + eRet = EIM_STATUS_PARAM_INVALID; + } + + return eRet; +} + +/** + * @brief Enable CPU lockstep monitor + * + * @param eEimCpuType EIM_CPU0_LOCKSTEP or EIM_CPU1_LOCKSTEP + * @param eMonitorType EIM_MONITOR0 or EIM_MONITOR1 + */ +void EIM_CpuLockStepMonitorSet_MonSet(const EIM_CPU_ChnType eEimCpuType,const EIM_MONType eMonitorType) +{ + uint32_t u32val = 0U; + + u32val = EIM_HWA_Get_CPULockstep((uint8_t)eEimCpuType); + + if(eMonitorType == EIM_MONITOR0) + { + u32val &= 0xFFFFFFFD;//clear mon0 clr + u32val |= EIM_CPU0_LOCKSTEP_LOCKSTEP_MON0_SET(1U); + } + + if(eMonitorType == EIM_MONITOR1) + { + u32val &= 0xFFFFFFFE;//clear mon1 clr + u32val |= EIM_CPU0_LOCKSTEP_LOCKSTEP_MON1_SET(1U); + } + + EIM_HWA_Set_CPULockstep((uint8_t)eEimCpuType, u32val); +} + +/** + * @brief Clear CPU lockstep monitor + * + * @param eEimCpuType EIM_CPU0_LOCKSTEP or EIM_CPU1_LOCKSTEP + * @param eMonitorType EIM_MONITOR0 or EIM_MONITOR1 + */ +void EIM_CpuLockStepMonitorSet_MonClr(const EIM_CPU_ChnType eEimCpuType,const EIM_MONType eMonitorType) +{ + uint32_t u32val = 0U; + + u32val = EIM_HWA_Get_CPULockstep((uint8_t)eEimCpuType); + + if(eMonitorType == EIM_MONITOR0) + { + u32val |= EIM_CPU0_LOCKSTEP_LOCKSTEP_MON0_CLR(1U); + } + if(eMonitorType == EIM_MONITOR1) + { + u32val |= EIM_CPU0_LOCKSTEP_LOCKSTEP_MON1_CLR(1U); + } + + EIM_HWA_Set_CPULockstep((uint8_t)eEimCpuType, u32val); +} + +/** + * @brief Clean CPU lockstep monitor bit + * + * @param eEimCpuType EIM_CPU0_LOCKSTEP or EIM_CPU1_LOCKSTEP + * @param eMonitorType EIM_MONITOR0 or EIM_MONITOR1 + */ +void EIM_CpuLockStepMonitorClr(const EIM_CPU_ChnType eEimCpuType, const EIM_MONType eMonitorType) +{ + uint32_t u32val = 0U; + + u32val = EIM_HWA_Get_CPULockstep((uint8_t)eEimCpuType); + + if(eMonitorType == EIM_MONITOR0) + { + u32val &= 0xFFFFFFF5;//clear mon0 clr + } + + if(eMonitorType == EIM_MONITOR1) + { + u32val &= 0xFFFFFFFA;//clear mon1 clr + } + + EIM_HWA_Set_CPULockstep((uint8_t)eEimCpuType, u32val); +} + +/** + * @brief Deinin EIM function + * + */ +void Eim_Deinit(void) +{ + uint8_t u8loop; + EIM_HWA_DisableGlobalErrorInjection(); + for (u8loop = 0U; u8loop < EIM_CTRL_REG_COUNT; u8loop++) + { + EIM_HWA_Set_CtrlRegn(u8loop, 0U); + } + + EIM_HWA_Set_CPULockstep(EIM_CPU0_LOCKSTEP, 0U); + EIM_HWA_Set_CPULockstep(EIM_DMA0_LOCKSTEP, 0U); + + for (u8loop = 0U; u8loop < EIM_BUS_REG_COUNT; u8loop++) + { + EIM_HWA_Set_BUSRegn(u8loop, 0U); + } +} + diff --git a/Src/fc7xxx_driver_erm.c b/Src/fc7xxx_driver_erm.c new file mode 100644 index 0000000..432356b --- /dev/null +++ b/Src/fc7xxx_driver_erm.c @@ -0,0 +1,175 @@ +/** + * @file fc7xxx_driver_erm.c + * @author Flagchip + * @brief FC7xxx ERM driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-14 qxw0100 N/A First version for FC7240 +********************************************************************************/ + +#include "fc7xxx_driver_erm.h" +#include "fc7xxx_driver_pcc.h" +#include "interrupt_manager.h" + +/* ############################## Local Variables ################################ */ +/** + * @brief Erm user defined interrupt function + * */ +static ERM_InterruptCallBackType s_pErmNotifyPtr = NULL; + +/* ################################################################################## */ +/* ########################### Global Prototype Functions ########################### */ + +void ERM_fault_IRQHandler(void); + +/* ################################################################################## */ +/* ################################ Local Functions ################################# */ +/** + * @brief Initialize ERM function + * + * @param pErmInt_cfg Initialization structure of ERM + * @return return 0: initialize successful. 1: invalid parameter + */ + +ERM_RetType Erm_Init(const ERM_MemorytInitType *pErmInt_cfg) +{ + ERM_RetType eRet = ERM_STATUS_SUCCESS; + uint32_t u32ErmCrVal = 0U; + ERM_ClearSRnRegister(); + + if (NULL == pErmInt_cfg) + { + eRet = ERM_STATUS_PARAM_INVALID; + } + else + { + if(pErmInt_cfg->u8ErmEnable != 0U) + { + if ((uint32_t)pErmInt_cfg->eChannel < 8U) + { + u32ErmCrVal |= (uint32_t)((uint32_t)pErmInt_cfg->eInt << (30UL - (uint32)pErmInt_cfg->eChannel*4U)); + ERM_HWA_Set_CRn(0, u32ErmCrVal); + } + else if (((uint32_t)pErmInt_cfg->eChannel >= 8U) && ((uint32_t)pErmInt_cfg->eChannel < 16U)) + { + u32ErmCrVal |= (uint32_t)((uint32_t)pErmInt_cfg->eInt << (62UL - (uint32)pErmInt_cfg->eChannel*4U)); + ERM_HWA_Set_CRn(1, u32ErmCrVal); + } + else if (((uint32_t)pErmInt_cfg->eChannel >= 16U) && ((uint32_t)pErmInt_cfg->eChannel < 24U)) + { + u32ErmCrVal |= (uint32_t)((uint32_t)pErmInt_cfg->eInt << (94UL - (uint32)pErmInt_cfg->eChannel*4U)); + ERM_HWA_Set_CRn(2, u32ErmCrVal); + } + else if (((uint32_t)pErmInt_cfg->eChannel >= 24U) && ((uint32_t)pErmInt_cfg->eChannel < 32U)) + { + u32ErmCrVal |= (uint32_t)((uint32_t)pErmInt_cfg->eInt << (126UL - (uint32)pErmInt_cfg->eChannel*4U)); + ERM_HWA_Set_CRn(3, u32ErmCrVal); + } + else + { + eRet = ERM_STATUS_PARAM_INVALID; + } + if(eRet == ERM_STATUS_SUCCESS) + { + s_pErmNotifyPtr = pErmInt_cfg->pIsrNotify; + } + } + + } + return eRet; +} +/** + * @brief De-initialize ERM function + * Restore the ERM instance to its reset state + */ +void Erm_DeInit(void) +{ + uint8_t u8loop; + for (u8loop = 0U; u8loop < 4U; u8loop++) + { + ERM_HWA_Set_CRn(u8loop, 0x0U); + ERM_HWA_Set_SRn(u8loop, 0x0U); + } +} +/** + * @brief ERM Clear SR0 register. + * + * This function Clear ERM SR0 register. + */ +void ERM_ClearSRnRegister(void) +{ + uint8_t u8loop; + for (u8loop = 0U; u8loop < 4U; u8loop++) + { + ERM_HWA_Set_SRn(u8loop, ERM_SR_MASK); + } +} + +/** + * @brief ERM read SRn register. + * + * This function Clear ERM SRn register. + * @param u8Index the SRn channel + */ +uint32_t ERM_ReadSRnVal(uint8_t u8Index) +{ + uint32_t u32Val; + u32Val = ERM_HWA_Get_SRn(u8Index); + return u32Val; +} +/** + * @brief ERM clear CRn register. + * + * This function Clear ERM CRn register. + * @param u8Index of the CRn channel + */ +void ERM_ClearCRnVal(uint8_t u8Index) +{ + ERM_HWA_Set_CRn(u8Index, 0UL); +} + +/** + * @brief ERM clear SRn register. + * + * This function Clear ERM SR0 register. + * @param u8Index the SRn channel + */ +uint32_t ERM_ClearSRnVal(uint8_t u8Index) +{ + uint32_t u32Val; + u32Val = ERM_HWA_Get_SRn(u8Index); + ERM_HWA_Set_SRn(u8Index, u32Val); + return u32Val; +} +/** + * @brief ERM interrupt function + */ +void ERM_fault_IRQHandler(void) +{ + if(s_pErmNotifyPtr != NULL) + { + s_pErmNotifyPtr(); + } +} +/** + * @brief ERM Read EARn address. + * @param eChannel The channel type + * @return u32Address The error address + */ +/* +uint32_t ERM_ReadAddress(ERM_channelType eChannel) +{ + uint32_t u32Address = 0U; + u32Address = ERM_HWA_GetEARn(eChannel); + return u32Address; +}*/ + diff --git a/Src/fc7xxx_driver_fciic.c b/Src/fc7xxx_driver_fciic.c new file mode 100644 index 0000000..d56136f --- /dev/null +++ b/Src/fc7xxx_driver_fciic.c @@ -0,0 +1,817 @@ +/** + * @file fc7xxx_driver_fciic.c + * @author Flagchip + * @brief FC7xxx FCIIC driver type definition and API + * @version 0.1.0 + * @date 2022-12-31 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ + +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024/1/10 qxw0095 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_fciic.h" +#include "interrupt_manager.h" + +#include "stdarg.h" +#include "stdio.h" +#include "string.h" +#include "stdlib.h" + +/* #define FCIIC_RX_FIFO */ + + +/* iic instance value */ +static FCIIC_Type *const s_aFCIIC_InstanceTable[FCIIC_INSTANCE_COUNT] = FCIIC_BASE_PTRS; + +/* store notify callback function point */ +static FCIIC_ErrorInterrupt_CallBackType s_aFCIIC_ErrorNotifyTable[FCIIC_INSTANCE_COUNT] = {NULL}; +static FCIIC_RxInterrupt_CallBackType s_aFCIIC_RxNotifyTable[FCIIC_INSTANCE_COUNT] = {NULL}; + +#ifdef FCIIC_RX_ALL_POLLING + /* check every pFciic instance whether is used */ + static uint8_t s_aFCIIC_IicMasterUsed[FCIIC_INSTANCE_COUNT]; + static uint8_t s_aFCIIC_IicSlaveUsed[FCIIC_INSTANCE_COUNT]; +#endif + + +/* ################################################################################## */ +/* ########################### Local Prototype Functions ############################ */ +#if 0 +static void CheckAndClear(FCIIC_Type *pFciic); +#endif +static void FCIIC_LL_MasterIRQnHandler(uint8_t u8IicIndex); +static void FCIIC_LL_SlaveIRQnHandler(uint8_t u8IicIndex); +static uint8_t FCIIC_Init_Master(uint8_t u8IicIndex, FCIIC_InitType *pInitCfg); +static uint8_t FCIIC_Init_Slave(uint8_t u8IicIndex, FCIIC_InitType *pInitCfg); + + +/* ################################################################################## */ +/* ########################### Global Prototype Functions ########################### */ + +void FCIIC0_IRQHandler(void); +void FCIIC1_IRQHandler(void); + +/* ################################################################################## */ +/* ################################ Local Functions ################################# */ + + +#if 0 +static void CheckAndClear(FCIIC_Type *pFciic) +{ + FCIIC_Master_HwA_CheckClearStatus(pFciic, FCIIC_MSR_EPF_STATUS); + FCIIC_Master_HwA_CheckClearStatus(pFciic, FCIIC_MSR_SDF_STATUS); + FCIIC_Master_HwA_CheckClearStatus(pFciic, FCIIC_MSR_NDF_STATUS); + FCIIC_Master_HwA_CheckClearStatus(pFciic, FCIIC_MSR_FEF_STATUS); + FCIIC_Master_HwA_CheckClearStatus(pFciic, FCIIC_MSR_ALF_STATUS); +} +#endif + + + +/*************************************************** + * FCIIC_LL_MasterIRQnHandler + * @detail: Iic n interrupt process + * + * param in : u8IicIndex, 0,1,2,3 + * param out: none + * + * return : none + * ************************************************/ +static void FCIIC_LL_MasterIRQnHandler(uint8_t u8IicIndex) +{ + /* uint8_t iic_status; */ + uint8_t u8RetVal; + FCIIC_RxDataType pRxData; + uint32_t u32ErrorValue; + + /* check pFciic receive data */ + u8RetVal = FCIIC_Master_Receive(u8IicIndex, &pRxData); + + if ((s_aFCIIC_RxNotifyTable[u8IicIndex] != NULL) && (u8RetVal == 0U)) + { + s_aFCIIC_RxNotifyTable[u8IicIndex](u8IicIndex, &pRxData); + } + + /* check error */ + u32ErrorValue = FCIIC_Master_GetError(u8IicIndex); + if ((u32ErrorValue != 0U) && (s_aFCIIC_ErrorNotifyTable[u8IicIndex] != NULL)) + { + s_aFCIIC_ErrorNotifyTable[u8IicIndex](u8IicIndex, 1U, u32ErrorValue); + FCIIC_Master_ClrError(u8IicIndex); + } + +} + + +/*************************************************** + * FCIIC_LL_SlaveIRQnHandler + * @detail: Iic n interrupt process + * + * param in : u8IicIndex, 0,1,2,3 + * param out: none + * + * return : none + * ************************************************/ +static void FCIIC_LL_SlaveIRQnHandler(uint8_t u8IicIndex) +{ + /* uint8_t iic_status; */ + uint8_t u8RetVal; + FCIIC_RxDataType pRxData; + uint32_t u32ErrorValue; + + /* check pFciic receive data */ + u8RetVal = FCIIC_Slave_Receive(u8IicIndex, &pRxData); + + if ((s_aFCIIC_RxNotifyTable[u8IicIndex] != NULL) && (u8RetVal == 0U)) + { + s_aFCIIC_RxNotifyTable[u8IicIndex](u8IicIndex, &pRxData); + } + + /* check error */ + u32ErrorValue = FCIIC_Slave_GetError(u8IicIndex); + if ((u32ErrorValue != 0U) && (s_aFCIIC_ErrorNotifyTable[u8IicIndex] != NULL)) + { + s_aFCIIC_ErrorNotifyTable[u8IicIndex](u8IicIndex, 0U, u32ErrorValue); + FCIIC_Slave_ClrError(u8IicIndex); + } + +} + + + + + +/*************************************************** + * FCIIC_Init_Master + * @detail: Iic device master mode initial + * + * param in : pInitCfg, pFciic initial config parameters + * structure address + * param out: none + * + * return : 0 is ok, others are not ok + * ************************************************/ +static uint8_t FCIIC_Init_Master(uint8_t u8IicIndex, FCIIC_InitType *pInitCfg) +{ + uint32_t u32TempMcr, u32TempMder, u32TempMcfgr0, u32TempMcfgr1, u32TempMcfgr2, u32TempMcfgr3, u32TempMccr0; + uint32_t u32TempMFCR; + + FCIIC_Type *pFciic; + uint32_t u32ClkSrcHz; + uint32_t u32FreqDeltaCur, u32FreqDeltaOld; + uint32_t u32FreqDesired, u32FreqCur; + uint32_t u32Prescale, u8PrescaleTemp; + uint32_t u32CLKHI, u32CLKHITemp; + uint32_t u32CLKLO, u32CLKLOTemp; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + u32ClkSrcHz = pInitCfg->u32ClkSrcHz; + u32FreqDesired = pInitCfg->u32Frequency; + u32FreqDeltaOld = u32FreqDesired; + + /* SCL_LATENCY is defined as ROUNDDOWN ((2 + FILTSCL + SCL_RISETIME) / (2 ^ PRESCALE)) */ + /* CLKLO: Minimum value is 0x3 */ + /* CLKHI: Minimum value is 0x1 */ + /* SCL clock period: (CLKHI + CLKLO + 2 + SCL_LATENCY) �� (2 ^ PRESCALE) �� function clock period */ + for(u32CLKHITemp=1U; (u32CLKHITemp < 63U); u32CLKHITemp++) + { + for(u32CLKLOTemp=3U; (u32CLKLOTemp < 63U); u32CLKLOTemp++) + { + /* get the linear prescale */ + for (u8PrescaleTemp = 0U; u8PrescaleTemp < 8U; u8PrescaleTemp++) + { + u32FreqCur = u32ClkSrcHz / Fc_Power(2U, (uint32_t)u8PrescaleTemp)/(u32CLKHITemp+u32CLKLOTemp+2U); + /* If the current frequency is less than the desired frequency, + * compare the delta with the previous one and select the parameter with the smallest delta + * */ + if(u32FreqCur <= u32FreqDesired) + { + u32FreqDeltaCur = u32FreqDesired - u32FreqCur; + if (u32FreqDeltaCur < u32FreqDeltaOld) + { + u32FreqDeltaOld = u32FreqDeltaCur; + u32Prescale = u8PrescaleTemp; + u32CLKHI = u32CLKHITemp; + u32CLKLO = u32CLKLOTemp; + } + break; + } + } + + if(u32FreqDeltaOld == 0U) + { + break; + } + } + + if(u32FreqDeltaOld==0U) + { + break; + } + } + + u32TempMcr = FCIIC_MCR_RRF(0U) | + FCIIC_MCR_RTF(0U) | + FCIIC_MCR_DBGEN(0U) | + FCIIC_MCR_RST(0U) | + FCIIC_MCR_MEN(1U); /* master enable */ + + + u32TempMder = FCIIC_MDER_RDDE(pInitCfg->bEnDma) | /* enable receive dma */ + FCIIC_MDER_TDDE(pInitCfg->bEnDma); /* enable transmit dma */ + + u32TempMcfgr0 = FCIIC_MCFGR0_RDMO(0U) | + FCIIC_MCFGR0_TRGEN(0U); + + u32TempMcfgr1 = FCIIC_MCFGR1_PINCFG(0U) | /* 0=open drain; 1=push-pull mode */ + FCIIC_MCFGR1_MATCFG(0U) | + FCIIC_MCFGR1_TIMECFG(0U) | + FCIIC_MCFGR1_IGNACK(1U) | + FCIIC_MCFGR1_AUTOSTOP(0U) | + FCIIC_MCFGR1_PRESCALE(u32Prescale); /* Prescaler = 2^n */ + + u32TempMcfgr2 = FCIIC_MCFGR2_FILTSDA(0U) | + FCIIC_MCFGR2_FILTSCL(0U) | + FCIIC_MCFGR2_BUSIDLE(0U); + + u32TempMcfgr3 = FCIIC_MCFGR3_PINLOW(0U); + + + u32TempMccr0 = FCIIC_MCCR_DATAVD(0x09U) | + FCIIC_MCCR_SETHOLD(0x13U) | + FCIIC_MCCR_CLKHI(u32CLKHI) | + FCIIC_MCCR_CLKLO(u32CLKLO); /* 0x09131327; */ + + u32TempMFCR = FCIIC_MFCR_TXWATER(pInitCfg->bTxFifoWMrk) | FCIIC_MFCR_RXWATER(pInitCfg->bRxFifoWMrk); + + FCIIC_HWA_SetMder(pFciic, u32TempMder); + FCIIC_HWA_SetMCFGR0(pFciic, u32TempMcfgr0); + FCIIC_HWA_SetMCFGR1(pFciic, u32TempMcfgr1); + FCIIC_HWA_SetMCFGR2(pFciic, u32TempMcfgr2); + FCIIC_HWA_SetMCFGR3(pFciic, u32TempMcfgr3); + FCIIC_HWA_SetMCCR(pFciic, u32TempMccr0); + FCIIC_HWA_SetMFCR(pFciic, u32TempMFCR); + + FCIIC_HWA_SetMcr(pFciic, u32TempMcr); /* | FCIIC_MCR_RRF_MASK | FCIIC_MCR_RTF_MASK | FCIIC_MCR_DBGEN_MASK | FCIIC_MCR_RST_MASK; */ + + #ifdef FCIIC_INIT_WAITRESET + u8RetVal = 1; + + while (u8RetVal) + { + u8RetVal = (pFciic->MCR & FCIIC_MCR_RST_MASK) >> FCIIC_MCR_RST_SHIFT; + pFciic->MCR = u32TempMcr; + } + #endif + return 0U; +} + + + +/*************************************************** + * FCIIC_DeInit_Master + * @detail: Iic device master mode de-initial + * + * param in : u8IicIndex + * param out: none + * + * return : 0 is ok, others are not ok + * ************************************************/ +static uint8_t FCIIC_DeInit_Master(uint8_t u8IicIndex) +{ + uint32_t u32TempMcr, u32TempMder; + + FCIIC_Type *pFciic; + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + + u32TempMcr = FCIIC_MCR_RRF(0U) | + FCIIC_MCR_RTF(0U) | + FCIIC_MCR_DBGEN(0U) | + FCIIC_MCR_RST(0U) | + FCIIC_MCR_MEN(0U); /* master enable */ + + + u32TempMder = FCIIC_MDER_RDDE(0U) | /* disable receive dma */ + FCIIC_MDER_TDDE(0U); /* disable transmit dma */ + + + + + FCIIC_HWA_SetMder(pFciic, u32TempMder); + + FCIIC_HWA_SetMcr(pFciic, u32TempMcr); /* | FCIIC_MCR_RRF_MASK | FCIIC_MCR_RTF_MASK | FCIIC_MCR_DBGEN_MASK | FCIIC_MCR_RST_MASK; */ + + + return 0U; +} + + + +/*************************************************** + * FCIIC_Init_Slave + * @detail: Iic device master mode initial + * + * param in : u8IicIndex + * param out: none + * + * return : 0 is ok, others are not ok + * ************************************************/ +static uint8_t FCIIC_Init_Slave(uint8_t u8IicIndex, FCIIC_InitType *pInitCfg) +{ + uint32_t u32TempScr, u32TempSder, u32TempScfgr1, u32TempScfgr2, u32TempSamr; + + FCIIC_Type *pFciic; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + + u32TempScr = FCIIC_SCR_FILTEN(0U) | + FCIIC_SCR_RST(0U) | + FCIIC_SCR_SEN(1U); /* slave enable */ + + + u32TempSder = FCIIC_SDER_AVDE(pInitCfg->bEnDma) | + FCIIC_SDER_RDDE(pInitCfg->bEnDma) | /* enable receive dma */ + FCIIC_SDER_TDDE(pInitCfg->bEnDma); /* enable transmit dma */ + + + + u32TempScfgr1 = FCIIC_SCFGR1_ADDRCFG(0U) | /* Address Configuration, 7bit */ + FCIIC_SCFGR1_HSMEN(0U) | + FCIIC_SCFGR1_IGNACK(1U) | + FCIIC_SCFGR1_RXCFG(0U) | + FCIIC_SCFGR1_TXCFG(0U) | + FCIIC_SCFGR1_SAEN(0U) | + FCIIC_SCFGR1_GCEN(0U) | + FCIIC_SCFGR1_ACKSTALL(0U) | + FCIIC_SCFGR1_TXDSTALL(0U) | + FCIIC_SCFGR1_RXSTALL(0U) | + FCIIC_SCFGR1_ADRSTALL(0U); + + u32TempScfgr2 = FCIIC_SCFGR2_FILTSDA(0U) | + FCIIC_SCFGR2_FILTSCL(0U) | + FCIIC_SCFGR2_DATAVD(0x09U) | + FCIIC_SCFGR2_CLKHOLD(1U); + + + + + u32TempSamr = FCIIC_SAMR_ADDR1(0U) | + FCIIC_SAMR_ADDR0(pInitCfg->u8SlaveAddr); + + + + FCIIC_HWA_SetSDER(pFciic, u32TempSder); + FCIIC_HWA_SetSCFGR1(pFciic, u32TempScfgr1); + FCIIC_HWA_SetSCFGR2(pFciic, u32TempScfgr2); + FCIIC_HWA_SetSAMR(pFciic, u32TempSamr); + + + FCIIC_HWA_SetSCR(pFciic, u32TempScr); + + return 0U; +} + + +/*************************************************** + * FCIIC_DeInit_Slave + * @detail: Iic device master mode de-initial + * + * param in : pInitCfg, pFciic initial config parameters + * structure address + * param out: none + * + * return : 0 is ok, others are not ok + * ************************************************/ +static uint8_t FCIIC_DeInit_Slave(uint8_t u8IicIndex) +{ + uint32_t u32TempScr, u32TempSder; + + FCIIC_Type *pFciic; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + u32TempScr = FCIIC_SCR_FILTEN(0U) | + FCIIC_SCR_RST(0U) | + FCIIC_SCR_SEN(0U); /* slave enable */ + + + u32TempSder = FCIIC_SDER_AVDE(0U) | + FCIIC_SDER_RDDE(0U) | /* disable receive dma */ + FCIIC_SDER_TDDE(0U); /* disable transmit dma */ + + FCIIC_HWA_SetSDER(pFciic, u32TempSder); + + + FCIIC_HWA_SetSCR(pFciic, u32TempScr); + + return 0U; + +} + + +/* ################################################################################## */ +/* ################################ Global Functions ################################ */ + + + +/** + * \brief This Function is used to initial IIC instance + * + * \param u8IicIndex Iic Index, 0,1 + * \param pInitCfg is the structure address of IIC initial configuration parameters, and it contains IIC instance + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Init(uint8_t u8IicIndex, FCIIC_InitType *pInitCfg) +{ + /* master mode */ + if (pInitCfg->bMasterMode != 0U) + { + FCIIC_Init_Master(u8IicIndex, pInitCfg); + #ifdef FCIIC_RX_ALL_POLLING + s_aFCIIC_IicMasterUsed[u8IicIndex] = 1U; + s_aFCIIC_IicSlaveUsed[u8IicIndex] = 0U; + #endif + } + else /* slave mode */ + { + FCIIC_Init_Slave(u8IicIndex, pInitCfg); + #ifdef FCIIC_RX_ALL_POLLING + s_aFCIIC_IicMasterUsed[u8IicIndex] = 0U; + s_aFCIIC_IicSlaveUsed[u8IicIndex] = 1U; + #endif + } + #if (defined(__ICCARM__)) + u8IicIndex = u8IicIndex; + #elif defined __GNUC__ + (void)u8IicIndex; + #endif + + return 0U; +} + + +/** + * \brief This Function is used to de-initial IIC instance + * + * \param u8IicIndex Iic Index, 0,1 + * \param pInitCfg is the structure address of IIC initial configuration parameters, bMaster should be set + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_DeInit(uint8_t u8IicIndex, FCIIC_InitType *pInitCfg) +{ + + /* master mode */ + if (pInitCfg->bMasterMode != 0U) + { + FCIIC_DeInit_Master(u8IicIndex); + #ifdef FCIIC_RX_ALL_POLLING + s_aFCIIC_IicMasterUsed[u8IicIndex] = 0U; + s_aFCIIC_IicSlaveUsed[u8IicIndex] = 0U; + #endif + } + else /* slave mode */ + { + FCIIC_DeInit_Slave(u8IicIndex); + #ifdef FCIIC_RX_ALL_POLLING + s_aFCIIC_IicMasterUsed[u8IicIndex] = 0U; + s_aFCIIC_IicSlaveUsed[u8IicIndex] = 0U; + #endif + } + + + #if (defined(__ICCARM__)) + u8IicIndex = u8IicIndex; + #elif defined __GNUC__ + (void)u8IicIndex; + #endif + + return 0U; +} + + +/** + * \brief This Function is used to configure IIC master interrupt + * + * \param u8IicIndex Iic Index, 0,1 + * \param pIntCfg contains IIC instance and interrupt callback functions + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Master_SetInterrupt(uint8_t u8IicIndex, FCIIC_InterruptType *pIntCfg) +{ + FCIIC_Type *pFciic; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + if ((pIntCfg->bEnErrorInterrupt != 0U) || (pIntCfg->bEnRxInterrupt != 0U)) + { + /* enable global interrupt for pFciic */ + IntMgr_EnableInterrupt((IRQn_Type)((uint8_t)((uint8_t)FCIIC0_IRQn + u8IicIndex))); + /* IntMag_ReplaceHandler(FCIIC0_IRQn+u8IicIndex,u8IicIndex==0?FCIIC0_IRQHandler:FCIIC1_IRQHandler); */ + } + + if (pIntCfg->bEnErrorInterrupt != 0U) + { + FCIIC_Master_HWA_EnableErrorInterrupt(pFciic); + s_aFCIIC_ErrorNotifyTable[u8IicIndex] = pIntCfg->pErrorNotify; + } + + if (pIntCfg->bEnRxInterrupt != 0U) + { + /* pFciic->MIER |= FCIIC_MIER_RDIE_MASK; */ + FCIIC_Master_HWA_EnableReceiveInterrupt(pFciic); + s_aFCIIC_RxNotifyTable[u8IicIndex] = pIntCfg->pRxNotify; + } + + return 0U; +} + + + + +/** + * \brief This Function is used to transmit data in master mode + * + * \param u8IicIndex Iic Index, 0,1 + * \param pTxData contains IIC instance and buffer address + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Master_Transmit(uint8_t u8IicIndex, FCIIC_TxDataType *pTxData) +{ + uint8_t u8RetVal; + FCIIC_Type *pFciic; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + /* clear error flag */ + /* CheckAndClear(pFciic); */ + + /* check tx data flag */ + u8RetVal = FCIIC_Master_HWA_GetStatus(pFciic, FCIIC_MSR_TDF_STATUS); + + /* pFciic->MSR |= FCIIC_MSR_FEF_MASK; */ /* clear fifo error error */ + if (u8RetVal == 1U) + { + FCIIC_Master_HWA_Transmit(pFciic, pTxData->eCmd, pTxData->u8Data); + } + + return (uint8_t)(1U >> u8RetVal); +} + + + +/** + * \brief This Function is used to get master status + * + * \param u8IicIndex is IIC instance + * \param eStatus is status type enumeration + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Master_GetStatus(uint8_t u8IicIndex, FCIIC_MasterStatusType eStatus) +{ + FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + return (uint8_t)(1U >> FCIIC_Master_HWA_GetStatus(pFciic, eStatus)); +} + + +/** + * \brief This Function is used to receive data when polling (not used when rx interrupt enabled) in master mode + * + * \param u8IicIndex Iic Index, 0,1 + * \param pRxData contains IIC instance + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Master_Receive(uint8_t u8IicIndex, FCIIC_RxDataType *pRxData) +{ + FCIIC_Type *pFciic; + uint8_t u8RetVal; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + /* CheckAndClear(pFciic); */ + + + /* check receive flag */ + u8RetVal = FCIIC_Master_HWA_GetStatus(pFciic, FCIIC_MSR_RDF_STATUS); + + /* u8RetVal = (pFciic->MRDR & FCIIC_MRDR_RXEMPTY_MASK)>>FCIIC_MRDR_RXEMPTY_SHIFT; */ + + if (u8RetVal == 1U) + { + /* copy data */ + pRxData->u8Data = FCIIC_Master_HWA_Receive(pFciic); + } + + return (uint8_t)(1U >> u8RetVal); +} + +/** + * \brief This Function is used to get master error value + * + * \param u8IicIndex Iic Index, 0,1 + * \return error value + */ +uint32_t FCIIC_Master_GetError(uint8_t u8IicIndex) +{ + FCIIC_Type *pFciic; + uint32_t u32RetVal; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + /* check receive flag */ + u32RetVal = FCIIC_Master_HWA_GetErrorFlag(pFciic); + + return u32RetVal; +} + +/** + * \brief This Function is used to clear master error value + * + * \param u8IicIndex Iic Index, 0,1 + */ +void FCIIC_Master_ClrError(uint8_t u8IicIndex) +{ + FCIIC_Type *pFciic; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + /* clear receive flag */ + FCIIC_Master_HWA_ClrErrorFlag(pFciic); + +} + +/** + * \brief This Function is used to configure IIC slave interrupt + * + * \param u8IicIndex Iic Index, 0,1 + * \param pIntCfg contains IIC instance and interrupt callback functions + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Slave_SetInterrupt(uint8_t u8IicIndex, FCIIC_InterruptType *pIntCfg) +{ + FCIIC_Type *pFciic; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + if ((pIntCfg->bEnErrorInterrupt != 0U) || (pIntCfg->bEnRxInterrupt != 0U)) + { + /* enable global interrupt for pFciic */ + IntMgr_EnableInterrupt((IRQn_Type)((uint8_t)((uint8_t)FCIIC0_IRQn + u8IicIndex))); + /* IntMag_ReplaceHandler(FCIIC0_IRQn+u8IicIndex,u8IicIndex==0?FCIIC0_IRQHandler:FCIIC1_IRQHandler); */ + } + + + if (pIntCfg->bEnErrorInterrupt != 0U) + { + FCIIC_Slave_HWA_EnableErrorInterrupt(pFciic); + s_aFCIIC_ErrorNotifyTable[u8IicIndex] = pIntCfg->pErrorNotify; + } + + if (pIntCfg->bEnRxInterrupt != 0U) + { + FCIIC_Slave_HWA_EnableReceiveInterrupt(pFciic); + + s_aFCIIC_RxNotifyTable[u8IicIndex] = pIntCfg->pRxNotify; + } + + return 0U; +} + + +/** + * \brief This Function is used to transmit data in slave mode + * + * \param u8IicIndex Iic Index, 0,1 + * \param pTxData contains IIC instance and buffer address + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Slave_Transmit(uint8_t u8IicIndex, FCIIC_TxDataType *pTxData) +{ + #ifdef FCIIC_TX_CHECK + uint8_t u8RetVal; + uint32_t u32TryTick; + uint32_t u32TryCount; + #endif + FCIIC_Type *pFciic; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + #ifdef FCIIC_TX_CHECK + /* u8RetVal = (pFciic->SSR & FCIIC_SSR_TDF_MASK)>> FCIIC_SSR_TDF_SHIFT; */ + + /* pFciic->SSR |= FCIIC_SSR_TREF_MASK; */ /* clear receive & transmit error error */ + /* if(u8RetVal) */ + { + #endif + FCIIC_Slave_HWA_Transmit(pFciic, pTxData->u8Data); + #ifdef FCIIC_TX_CHECK + /* after transmit completed, close TE */ + /* u8RetVal = 0; */ + /* u32TryCount = 0; */ + /* while(u8RetVal==0 && u32TryCount++<100) */ + /* { */ + /* u8RetVal = (pFciic->SSR & FCIIC_SSR_TDF_MASK)>> FCIIC_SSR_TDF_SHIFT; */ + /* u32TryTick = 0; */ + /* while(u32TryTick++<100){} */ + + /* } */ + } + #endif + + return 0U; +} + + + +/** + * \brief This Function is used to receive data when polling (not used when rx interrupt enabled) in slave mode + * + * \param u8IicIndex Iic Index, 0,1 + * \param pRxData contains IIC instance and buffer address + * \return 0 is ok, others are not ok + */ +uint8_t FCIIC_Slave_Receive(uint8_t u8IicIndex, FCIIC_RxDataType *pRxData) +{ + FCIIC_Type *pFciic; + uint8_t u8RetVal; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + + /* check slave receive flag */ + u8RetVal = FCIIC_Slave_HWA_GetStatus(pFciic, FCIIC_SSR_RDF_STATUS); + + /* u8RetVal = (pFciic->MRDR & FCIIC_MRDR_RXEMPTY_MASK)>>FCIIC_MRDR_RXEMPTY_SHIFT; */ + + if (u8RetVal != 0U) + { + /* get received data */ + pRxData->u8Data = FCIIC_Slave_HWA_Receive(pFciic); + } + + return (uint8_t)(1U >> u8RetVal); +} + + +/** + * \brief This Function is used to get slave error value + * + * \param u8IicIndex Iic Index, 0,1 + * \return error value + */ +uint32_t FCIIC_Slave_GetError(uint8_t u8IicIndex) +{ + FCIIC_Type *pFciic; + uint32_t u32RetVal; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + /* check receive flag */ + u32RetVal = FCIIC_Slave_HWA_GetErrorFlag(pFciic); + + return u32RetVal; +} + +/** + * \brief This Function is used to clear slave error value + * + * \param u8IicIndex Iic Index, 0,1 + */ +void FCIIC_Slave_ClrError(uint8_t u8IicIndex) +{ + FCIIC_Type *pFciic; + + pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[u8IicIndex]; + + /* clear receive flag */ + FCIIC_Slave_HWA_ClrErrorFlag(pFciic); +} + + +/* ################################################################################## */ +/* ############################## Interrupt Services ################################ */ + + +void FCIIC0_IRQHandler(void) +{ + FCIIC_LL_MasterIRQnHandler(0U); + FCIIC_LL_SlaveIRQnHandler(0U); +} + +void FCIIC1_IRQHandler(void) +{ + FCIIC_LL_MasterIRQnHandler(1U); + FCIIC_LL_SlaveIRQnHandler(1U); +} + + diff --git a/Src/fc7xxx_driver_fcpit.c b/Src/fc7xxx_driver_fcpit.c new file mode 100644 index 0000000..5c6bd51 --- /dev/null +++ b/Src/fc7xxx_driver_fcpit.c @@ -0,0 +1,524 @@ +/** + * @file fc7xxx_driver_fcpit.h + * @author Flagchip + * @brief FC7xxx FCPIT driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-10 Flagchip0076 N/A First version for FC7240 +********************************************************************************/ +#include "fc7xxx_driver_fcpit.h" +#include "interrupt_manager.h" + + +/********* Local Variables ************/ +/** @brief FCPIT instance list */ +static FCPIT_Type *s_pFcpitInstanceTable[FCPIT_INSTANCE_COUNT] = FCPIT_BASE_PTRS; + +/** @brief Fcpit user defined interrupt function */ +static FCPIT_InterruptCallBackType s_aFcpitIntNotifyTab[FCPIT_INSTANCE_COUNT][MAX_FCPIT_CHANNEL_NUM] = {0}; + + + + +/** @brief Fcpit interrupt entry */ +void FCPIT0_IRQHandler(void); + +/** @brief Fcpit common interrupt handle function */ +static void Fcpit_CommonProcessInterrupt(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel); + + +/** + * @brief Initialize Fcpit instance. + * @param eFcpit instance + * @param pInitStruct Fcpit initialization structure + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_Init(const FCPIT_InstanceType eFcpit, const FCPIT_InitType *const pInitStruct) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + + if ( ((uint32_t)eFcpit >= FCPIT_INSTANCE_COUNT) || (NULL == pInitStruct) ) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + pFcpit = s_pFcpitInstanceTable[eFcpit]; + /*Enable module clock*/ + FCPIT_HWA_EnableModule(pFcpit); + if (pInitStruct->bDebugEn) + { + FCPIT_HWA_SetChannelRunOnDebug(pFcpit); + } + else + { + FCPIT_HWA_SetChannelStopOnDebug(pFcpit); + } + + if (pInitStruct->bLowPowerModeEn) + { + FCPIT_HWA_SetChannelRunOnLpm(pFcpit); + } + else + { + FCPIT_HWA_SetChannelStopOnLpm(pFcpit); + } + /* w1c , clear channel interrupt flag*/ + FCPIT_HWA_ClearChannelsInterruptFlag(pFcpit, (uint32_t)1U << (uint32_t)pInitStruct->eFcpitChannel); + + FCPIT_HWA_ConfigChannel(pFcpit, pInitStruct->eFcpitChannel, (uint32_t)0U); + FCPIT_HWA_ConfigChannelMode(pFcpit, pInitStruct->eFcpitChannel, pInitStruct->eMode); + + if (pInitStruct->bChainModeEn) + { + if (pInitStruct->eFcpitChannel > FCPIT_CHANNEL_0) + { + FCPIT_HWA_EnableChannelChainMode(pFcpit, pInitStruct->eFcpitChannel); + } + else + { + /* channel 0 is the first channel can not be chained to last channel */ + eRet = FCPIT_STATUS_PARAM_INVALID; + } + } + else + { + /*Chain mode is not enabled, no operation */ + } + + FCPIT_HWA_SetChannelValue(pFcpit, pInitStruct->eFcpitChannel, pInitStruct->u32TimerValue); + } + + return eRet; +} + +/** + * @brief Initialize Fcpit trigger configuration + * @param eFcpit instance + * @param pTrgStruct Fcpit trigger structure + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_InitTrigger(const FCPIT_InstanceType eFcpit, const FCPIT_TrggerType *const pTrgStruct) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + + if ( ((uint32_t)eFcpit >= FCPIT_INSTANCE_COUNT) || (NULL == pTrgStruct) ) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + pFcpit = s_pFcpitInstanceTable[eFcpit]; + if ( (uint32_t)0U == FCPIT_HWA_ReadModuleEnable(pFcpit) ) + { + eRet = FCPIT_STATUS_FUNCTION_ERROR; + } + else + { + if (pTrgStruct->bStartOnTrigger) + { + FCPIT_HWA_SetChannelStartOnTrig(pFcpit, pTrgStruct->eFcpitChannel); + } + else + { + FCPIT_HWA_ClearChannelStartOnTrig(pFcpit, pTrgStruct->eFcpitChannel); + } + + if (pTrgStruct->bStopOnInterrupt) + { + FCPIT_HWA_SetChannelStopOnInterrupt(pFcpit, pTrgStruct->eFcpitChannel); + } + else + { + FCPIT_HWA_ClearChannelStopOnInterrupt(pFcpit, pTrgStruct->eFcpitChannel); + } + + if (pTrgStruct->bReloadOnTrigger) + { + FCPIT_HWA_SetChannelReloadOnTrig(pFcpit, pTrgStruct->eFcpitChannel); + } + else + { + FCPIT_HWA_ClearChannelReloadOnTrig(pFcpit, pTrgStruct->eFcpitChannel); + } + + if (FCPIT_TRIGGER_EXTERNAL != pTrgStruct->eTriggerSel) + { + FCPIT_HWA_SetChannelTriggerSrc(pFcpit, pTrgStruct->eFcpitChannel); + FCPIT_HWA_SelectChannelTrigger(pFcpit, pTrgStruct->eFcpitChannel, (uint8_t)pTrgStruct->eTriggerSel); + } + else + { + FCPIT_HWA_ClearChannelTriggerSrc(pFcpit, pTrgStruct->eFcpitChannel); + FCPIT_HWA_SelectChannelTrigger(pFcpit, pTrgStruct->eFcpitChannel, (uint8_t)pTrgStruct->eFcpitChannel); + } + + } + + } + + return eRet; +} + +/** + * @brief De-initialize Fcpit instance. + * @param eFcpit instance + */ +FCPIT_StatusType FCPIT_Deinit(const FCPIT_InstanceType eFcpit) +{ + uint8_t u8Index; + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + + if ((uint32_t)eFcpit >= FCPIT_INSTANCE_COUNT) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + pFcpit = s_pFcpitInstanceTable[eFcpit]; + FCPIT_HWA_ConfigModule(pFcpit, (uint32_t)FCPIT_MCR_M_CEN_MASK); + FCPIT_HWA_ClearChannelsInterruptFlag(pFcpit, (uint32_t)(FCPIT_MSR_TIF3_MASK | FCPIT_MSR_TIF2_MASK | FCPIT_MSR_TIF1_MASK | + FCPIT_MSR_TIF0_MASK)); + FCPIT_HWA_DisableChannelsInterrupt(pFcpit, (uint32_t)0U); + for (u8Index = 0U; u8Index < MAX_FCPIT_CHANNEL_NUM; u8Index++) + { + FCPIT_HWA_ConfigChannel(pFcpit, (FCPIT_ChannelType)u8Index, (uint32_t)0U); + FCPIT_HWA_SetChannelValue(pFcpit, (FCPIT_ChannelType)u8Index, (uint32_t)0U); + s_aFcpitIntNotifyTab[eFcpit][u8Index] = NULL; + } + FCPIT_HWA_ConfigModule(pFcpit, (uint32_t)0U); + } + + return eRet; +} + +/** + * @brief Initialize Fcpit interrupt functionality + * @param eFcpit instance + * @param pIntStruct Fcpit interrupt structure + * @return Fcpit return type + * @note this function will stop timer + */ +FCPIT_StatusType FCPIT_InitInterrupt(const FCPIT_InstanceType eFcpit, const FCPIT_IntType *const pIntStruct) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + + if ( ((uint8_t)eFcpit >= FCPIT_INSTANCE_COUNT) || (NULL == pIntStruct) ) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + pFcpit = s_pFcpitInstanceTable[eFcpit]; + if ((uint32_t)0U == (uint32_t)FCPIT_HWA_ReadModuleEnable(pFcpit)) + { + eRet = FCPIT_STATUS_FUNCTION_ERROR; + } + else + { + FCPIT_HWA_DisableChannel(pFcpit, pIntStruct->eFcpitChannel); + /* w1c , clear channel interrupt flag*/ + FCPIT_HWA_ClearChannelsInterruptFlag(pFcpit, (uint32_t)1U << (uint32_t)pIntStruct->eFcpitChannel); + if (pIntStruct->bChannelIsrEn) + { + FCPIT_HWA_EnableChannelsInterrupt(pFcpit, (uint32_t)1U << (uint32_t)pIntStruct->eFcpitChannel); + s_aFcpitIntNotifyTab[eFcpit][pIntStruct->eFcpitChannel] = pIntStruct->pIsrNotify; + } + else + { + FCPIT_HWA_DisableChannelsInterrupt(pFcpit, (uint32_t)1U << (uint32_t)pIntStruct->eFcpitChannel); + s_aFcpitIntNotifyTab[eFcpit][pIntStruct->eFcpitChannel] = pIntStruct->pIsrNotify; + } + } + } + + return eRet; +} + +/** + * @brief Enable Fcpit interrupt + * @param eFcpit instance + * @param eChannel Fcpit channel + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_EnableInterrupt(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + + if ( ((uint32_t)eFcpit >= FCPIT_INSTANCE_COUNT) || ((uint32_t)eChannel >= MAX_FCPIT_CHANNEL_NUM)) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + pFcpit = s_pFcpitInstanceTable[eFcpit]; + + if ((uint32_t)0U == (uint32_t)FCPIT_HWA_ReadModuleEnable(pFcpit)) + { + eRet = FCPIT_STATUS_FUNCTION_ERROR; + } + else + { + FCPIT_HWA_DisableChannel(pFcpit, eChannel); + /* w1c , clear channel interrupt flag*/ + FCPIT_HWA_ClearChannelsInterruptFlag(pFcpit, (uint32_t)1U << (uint32_t)eChannel); + FCPIT_HWA_EnableChannelsInterrupt(pFcpit, (uint32_t)1U << (uint32_t)eChannel); + FCPIT_HWA_EnableChannel(pFcpit, eChannel); + } + + } + + return eRet; +} + +/** + * @brief Disable Fcpit interrupt + * @param eFcpit instance + * @param eChannel Fcpit channel + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_DisableInterrupt(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + + if ( ((uint32_t)eFcpit >= FCPIT_INSTANCE_COUNT) || ((uint32_t)eChannel >= MAX_FCPIT_CHANNEL_NUM) ) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + pFcpit = s_pFcpitInstanceTable[eFcpit]; + + if ((uint32_t)0U == (uint32_t)FCPIT_HWA_ReadModuleEnable(pFcpit)) + { + eRet = FCPIT_STATUS_FUNCTION_ERROR; + } + else + { + FCPIT_HWA_DisableChannel(pFcpit, eChannel); + /* w1c , clear channel interrupt flag*/ + FCPIT_HWA_ClearChannelsInterruptFlag(pFcpit, (uint32_t)1U << (uint32_t)eChannel); + FCPIT_HWA_DisableChannelsInterrupt(pFcpit, (uint32_t)1U << (uint32_t)eChannel); + FCPIT_HWA_EnableChannel(pFcpit, eChannel); + } + } + + return eRet; +} + +/** + * @brief Fcpit start timer + * @param eFcpit instance + * @param eChannel Fcpit channel + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_Start(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + if ( ((uint32_t)eFcpit >= FCPIT_INSTANCE_COUNT) || ((uint32_t)eChannel >= MAX_FCPIT_CHANNEL_NUM) ) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + pFcpit = s_pFcpitInstanceTable[eFcpit]; + if ((uint32_t)0U == (uint32_t)FCPIT_HWA_ReadModuleEnable(pFcpit)) + { + eRet = FCPIT_STATUS_FUNCTION_ERROR; + } + + if (FCPIT_STATUS_SUCCESS == eRet) + { + FCPIT_HWA_EnableChannel(pFcpit, eChannel); + } + } + + return eRet; +} + +/** + * @brief Fcpit stop + * @param eFcpit instance + * @param eChannel Fcpit channel + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_Stop(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + + if ( ((uint32_t)eFcpit >= FCPIT_INSTANCE_COUNT) || ((uint32_t)eChannel >= MAX_FCPIT_CHANNEL_NUM) ) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + pFcpit = s_pFcpitInstanceTable[eFcpit]; + if ((uint32_t)0U == (uint32_t)FCPIT_HWA_ReadModuleEnable(pFcpit)) + { + eRet = FCPIT_STATUS_FUNCTION_ERROR; + } + else + { + FCPIT_HWA_DisableChannel(pFcpit, eChannel); + } + } + + return eRet; +} + +/** + * @brief Immediately update Fcpit channel value + * @param eFcpit instance + * @param eChannel Fcpit channel + * @param u32ChannelValue in/Out value + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_ImmediateUpdateChannelValue(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel, const uint32_t u32ChannelValue) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet; + + pFcpit = s_pFcpitInstanceTable[eFcpit]; + + eRet = FCPIT_Stop(eFcpit, eChannel); + + if (FCPIT_STATUS_SUCCESS == eRet) + { + FCPIT_HWA_SetChannelValue(pFcpit, eChannel, u32ChannelValue); + eRet = FCPIT_Start(eFcpit, eChannel); + } + else + { + return eRet; + } + + return eRet; +} + +/** + * @brief Update Fcpit channel value + * @param eFcpit instance + * @param eChannel Fcpit channel + * @param u32ChannelValue in/Out value + * @return Fcpit return type + */ +FCPIT_StatusType FCPIT_UpdateChannelValue(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel, const uint32_t u32ChannelValue) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + + if ( ((uint32_t)eFcpit >= FCPIT_INSTANCE_COUNT) || ((uint32_t)eChannel >= MAX_FCPIT_CHANNEL_NUM) ) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + pFcpit = s_pFcpitInstanceTable[eFcpit]; + if ((uint32_t)0U == (uint32_t)FCPIT_HWA_ReadModuleEnable(pFcpit)) + { + eRet = FCPIT_STATUS_FUNCTION_ERROR; + } + + if (FCPIT_STATUS_SUCCESS == eRet) + { + FCPIT_HWA_SetChannelValue(pFcpit, eChannel, u32ChannelValue); + } + } + + return eRet; +} + +/** + * @brief read Fcpit channel time stamps. + * #param eFcpit Fcpit instance + * @param eChannel Fcpit channel + * @param *u32timeStampValue value + * @return Fcpit return type + */ + +FCPIT_StatusType FCPIT_ReadTimstamp(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel,uint32_t *u32timeStampValue) +{ + FCPIT_Type *pFcpit; + FCPIT_StatusType eRet = FCPIT_STATUS_SUCCESS; + if ( ((uint32_t)eFcpit >= FCPIT_INSTANCE_COUNT) || ((uint32_t)eChannel >= MAX_FCPIT_CHANNEL_NUM) ) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + pFcpit = s_pFcpitInstanceTable[eFcpit]; + + if((uint32_t)0x3u != FCPIT_HWA_ReadChannelMode(pFcpit,eChannel)) + { + eRet = FCPIT_STATUS_PARAM_INVALID; + } + else + { + + *u32timeStampValue = FCPIT_HWA_ReadChannelValue(pFcpit,eChannel); + } + return eRet; +} + + + +/** + * @brief Fcpit common interrupt handle function + * @param eFcpit instance + * @param eChannel Fcpit interrupt channel + */ +static void Fcpit_CommonProcessInterrupt(const FCPIT_InstanceType eFcpit, const FCPIT_ChannelType eChannel) +{ + if (NULL != s_aFcpitIntNotifyTab[eFcpit][eChannel]) + { + s_aFcpitIntNotifyTab[eFcpit][eChannel](); + } +} + +/** + * @brief Fcpit_0 interrupt handler entry + * + */ +void FCPIT0_IRQHandler(void) +{ + uint32_t u32TifValue = FCPIT_HWA_ReadEnableInterruptFlag(FCPIT) & FCPIT_HWA_ReadInterruptFlag(FCPIT); + + if ((u32TifValue & FCPIT_MSR_TIF0_MASK) != 0u) + { + Fcpit_CommonProcessInterrupt(FCPIT_0, FCPIT_CHANNEL_0); + FCPIT_HWA_ClearChannelsInterruptFlag(FCPIT, (uint32_t)FCPIT_MSR_TIF0_MASK); + } + if ((u32TifValue & FCPIT_MSR_TIF1_MASK) != 0u) + { + Fcpit_CommonProcessInterrupt(FCPIT_0, FCPIT_CHANNEL_1); + FCPIT_HWA_ClearChannelsInterruptFlag(FCPIT, (uint32_t)FCPIT_MSR_TIF1_MASK); + } + if ((u32TifValue & FCPIT_MSR_TIF2_MASK) != 0u) + { + Fcpit_CommonProcessInterrupt(FCPIT_0, FCPIT_CHANNEL_2); + FCPIT_HWA_ClearChannelsInterruptFlag(FCPIT, (uint32_t)FCPIT_MSR_TIF2_MASK); + } + if ((u32TifValue & FCPIT_MSR_TIF3_MASK) != 0u) + { + Fcpit_CommonProcessInterrupt(FCPIT_0, FCPIT_CHANNEL_3); + FCPIT_HWA_ClearChannelsInterruptFlag(FCPIT, (uint32_t)FCPIT_MSR_TIF3_MASK); + } + +} + diff --git a/Src/fc7xxx_driver_fcsmu.c b/Src/fc7xxx_driver_fcsmu.c new file mode 100644 index 0000000..61df4e6 --- /dev/null +++ b/Src/fc7xxx_driver_fcsmu.c @@ -0,0 +1,408 @@ +/** + * @file fc7xxx_driver_fcsmu.c + * @author Flagchip + * @brief FC7xxx FCSMU driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-14 qxw0100 N/A First version for FC7240 + ******************************************************************************** */ +#include "fc7xxx_driver_fcsmu.h" +#include "HwA_csc.h" + +/* ################################################################################## */ +/* ####################################### Macro #################################### */ + +#define FCSMU_FST_UNLOCK_KEY 0x951413CFU +#define FCSMU_OPC1_UNLOCK_KEY 0xFC2020CFU +#define FCSMU_OPC2_UNLOCK_KEY 0x20FCCF20U +#define FCSMU_CONFIG_TMEP_UNLOCK_KEY 0xFCU + +/* ################################################################################## */ +/* ################################### Type define ################################## */ + +/* ################################################################################## */ +/* ################################ Local Variables ################################# */ +static FCSMU_Type *const s_apFcsmuBase[FCSMU_INSTANCE_COUNT] = FCSMU_BASE_PTRS; +static FCSMU_ISRCallbackType s_apFcsmuISRCallback = NULL; + +/* ################################################################################## */ +/* ########################### Local Prototype Functions ############################ */ + +/* ################################################################################## */ +/* ######################### Global prototype Functions ############################ */ +void FCSMU0_IRQHandler(void); +/* ################################################################################## */ +/* ################################ Local Functions ################################ */ + +/* ################################################################################## */ +/* ################################ Global Functions ################################ */ + +FCSMU_StatusType FCSMU_init(const FCSMU_InitCfgType *pInitConfig) +{ + DEV_ASSERT(pInitConfig != NULL); + FCSMU_StatusType eRet; + + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + + eRet = FCSMU_TransStateNTC(); + + if (eRet != FCSMU_STATUS_SUCCESS) + { + return eRet; + } + + if (pInitConfig->u32WarnTo > 432000U) + { + FCSMU_HWA_SetWaringTo(pFcsmu, 432000U); + } + else + { + FCSMU_HWA_SetWaringTo(pFcsmu, pInitConfig->u32WarnTo); + } + FCSMU_HWA_ClearCfgToIrq(pFcsmu); + FCSMU_HWA_SetWarningEn0(pFcsmu, pInitConfig->u32WarnChannel); + FCSMU_HWA_SetWarningIen(pFcsmu, pInitConfig->u32WarnInterruptChannel); + FCSMU_HWA_SetFaultIen(pFcsmu, pInitConfig->u32FaultInterruptChannel); + FCSMU_HWA_SetFRST0(pFcsmu, pInitConfig->u32FaultResetChannel); + FCSMU_HWA_SetFe0(pFcsmu, pInitConfig->u32FaultChannel); + FCSMU_HWA_SetFccr0(pFcsmu, pInitConfig->u32SoftwareClearedChannel); + + eRet = FCSMU_TransStateCTN(); + FCSMU_HWA_SetTempUnlk(pFcsmu, 0xFFU); + + s_apFcsmuISRCallback = pInitConfig->pISRCallback; + + return eRet; +} + +FCSMU_StatusType FCSMU_ConfigStatusOutput(FCSMU_StatusOutputConfigType *pInitConfig) +{ + + DEV_ASSERT(pInitConfig != NULL); + + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + uint32_t u32TempValue; + FCSMU_StatusType eRet; + + if (pInitConfig->eFastMode == true) + { + if (pInitConfig->eProtocal != FCSMU_SOUT_PROTOCOL_DUAL_RAIL && pInitConfig->eProtocal != FCSMU_SOUT_PROTOCOL_TIME_SWITCH) + { + return FCSMU_STATUS_ERROR; + } + } + + u32TempValue = FCSMU_SOCTRL_SOUT_PEN(pInitConfig->bEnable) | + FCSMU_SOCTRL_FASTEN(pInitConfig->eFastMode) | + FCSMU_SOCTRL_POLSW(pInitConfig->ePolarity) | + FCSMU_SOCTRL_SOUT_PTC(pInitConfig->eProtocal) | + FCSMU_SOCTRL_DIVEX(pInitConfig->bDivex) | + FCSMU_SOCTRL_SOUT_CTRL(pInitConfig->eSoutCtrl) | + FCSMU_SOCTRL_SOUT_DIV(pInitConfig->u32Divder) | + FCSMU_SOCTRL_SMRDT(pInitConfig->u32Delaytimer); + + eRet = FCSMU_TransStateNTC(); + + if (eRet != FCSMU_STATUS_SUCCESS) + { + return eRet; + } + + FCSMU_HWA_SetSoctrl(pFcsmu, u32TempValue); + FCSMU_HWA_SetSoutEn(pFcsmu, pInitConfig->u32SoutChannel); + + eRet = FCSMU_TransStateCTN(); + + return eRet; +} + +void FCSMU_CrcGen(void) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + FCSMU_HWA_GenerateCrc(pFcsmu); +} + +bool FCSMU_IsCrcBusy(void) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + return FCSMU_HWA_GetCrcBusy(pFcsmu); +} + +FCSMU_StatusType FCSMU_CrcConfig(FCSMU_CrcModeType eMode) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + uint32_t u32TimeoutTimes = 65535U; + FCSMU_StatusType eRet = FCSMU_STATUS_SUCCESS; + + FCSMU_HWA_GenerateCrc(pFcsmu); + while (FCSMU_HWA_GetCrcBusy(pFcsmu) == FCSMU_Crc_STATE_BUSY) + { + u32TimeoutTimes--; + if (u32TimeoutTimes == 0U) + { + eRet = FCSMU_STATUS_ERROR; + break; + } + } + + if (eRet == FCSMU_STATUS_SUCCESS) + { + if (eMode == FCSMU_CRC_TRIGGER_MODE) + { + FCSMU_HWA_EnableTrigger(pFcsmu, true); + } + else + { + + } + + CSC0_HWA_CTRL4_EnableReqToSMU(CSC_SMU_SCF_IRQ); + FCSMU_HWA_EnableErrorOutput(pFcsmu, true); + FCSMU_HWA_EnableCrcChecker(pFcsmu, true); + } + + return eRet; + +} + +FCSMU_StatusType FCSMU_ClearFaultFlag(uint32_t u32FaultChannel) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + uint32_t u32TimeoutTimes = 65535U; + FCSMU_StatusType eRet = FCSMU_STATUS_SUCCESS; + + FCSMU_HWA_SetFunlk(pFcsmu, FCSMU_FST_UNLOCK_KEY); + FCSMU_HWA_SetFst0(pFcsmu, u32FaultChannel); + + while (FCSMU_HWA_GetCtrlOps(pFcsmu) != (uint32_t)FCSMU_OP_STATE_SUCCESSFUL) + { + u32TimeoutTimes--; + if (u32TimeoutTimes == 0U) + { + eRet = FCSMU_STATUS_ERROR; + break; + } + } + + return eRet; +} + +FCSMU_StatusType FCSMU_TransStateCTN(void) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + uint32_t u32TimeoutTimes; + uint32_t u32RetryTimes = 65535U; + uint32_t u32Temp; + FCSMU_StatusType eRet = FCSMU_STATUS_ERROR; + + while (u32RetryTimes != 0U) + { + u32TimeoutTimes = 65535U; + u32Temp = (uint32_t)FCSMU_HWA_GetCtrl(pFcsmu); + u32Temp |= (uint32_t)FCSMU_OPC_MOVE_TO_NORMAL; + + FCSMU_HWA_SetOprk(pFcsmu, FCSMU_OPC2_UNLOCK_KEY); + FCSMU_HWA_SetCrtl(pFcsmu, u32Temp); + + while (FCSMU_HWA_GetCtrlOps(pFcsmu) != (uint32_t)FCSMU_OP_STATE_SUCCESSFUL) + { + u32TimeoutTimes--; + if (u32TimeoutTimes == 0U) + { + break; + } + } + + if (u32TimeoutTimes != 0U) + { + if (FCSMU_HWA_GetState(pFcsmu) == (uint32_t)FCSMU_STATE_NORMAL) + { + break; + } + } + + u32RetryTimes--; + } + + if (u32RetryTimes != 0U) + { + eRet = FCSMU_STATUS_SUCCESS; + } + + return eRet; +} + +FCSMU_StatusType FCSMU_TransStateNTC(void) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + uint32_t u32TimeoutTimes; + uint32_t u32RetryTimes = 65535U; + FCSMU_StatusType eRet = FCSMU_STATUS_ERROR; + uint32_t u32Temp; + + while (u32RetryTimes != 0U) + { + u32TimeoutTimes = 65535U; + u32Temp = FCSMU_HWA_GetCtrl(pFcsmu); + u32Temp |= (uint32_t)FCSMU_OPC_MOVE_TO_CONFIG; + FCSMU_HWA_SetTempUnlk(pFcsmu, FCSMU_CONFIG_TMEP_UNLOCK_KEY); + FCSMU_HWA_SetOprk(pFcsmu, FCSMU_OPC1_UNLOCK_KEY); + FCSMU_HWA_SetCrtl(pFcsmu, u32Temp); + + while (FCSMU_HWA_GetCtrlOps(pFcsmu) != (uint32_t)FCSMU_OP_STATE_SUCCESSFUL) + { + if (FCSMU_HWA_GetCtrlOps(pFcsmu) == (uint32_t)FCSMU_OP_STATE_BUSY) + { + u32TimeoutTimes--; + if (u32TimeoutTimes == 0U) + { + break; + } + } + else + { + break; + } + } + + if (u32TimeoutTimes != 0U) + { + if (FCSMU_HWA_GetState(pFcsmu) == (uint32_t)FCSMU_STATE_CONGIG) + { + break; + } + } + + u32RetryTimes--; + } + + if (u32RetryTimes != 0U) + { + eRet = FCSMU_STATUS_SUCCESS; + } + + return eRet; +} + +void FCSMU_InjectionFault(uint32_t u32ChannelIndex) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + + FCSMU_HWA_SetInject(pFcsmu, u32ChannelIndex); +} + +uint32_t FCSMU_GetFaultChannel(void) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + + return FCSMU_HWA_GetFst0(pFcsmu); +} + +uint32_t FCSMU_GetIrqState(void) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + + return FCSMU_HWA_GetIrqStat(pFcsmu); +} + +uint32_t FCSMU_GetNtfFlag(void) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + + return FCSMU_HWA_GetNtf(pFcsmu); +} + +uint32_t FCSMU_GetWtfFlag(void) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + + return FCSMU_HWA_GetWtf(pFcsmu); +} + +uint32_t FCSMU_GetNtwFlag(void) +{ + FCSMU_Type *const pFcsmu = s_apFcsmuBase[FCSMU_INSTANCE_0]; + + return FCSMU_HWA_GetNtw(pFcsmu); +} + +static void FCSMUn_IRQHandler(void) +{ + uint32_t u32TempValue = FCSMU_GetIrqState(); + uint32_t u32IrqChannel; + + if ((FCSMU_IRQ_STAT_FAULT_IRQ_MASK & u32TempValue) == FCSMU_IRQ_STAT_FAULT_IRQ_MASK) + { + if ((FCSMU_GetNtfFlag() & FCSMU_NTF_FLAG_MASK) == FCSMU_NTF_FLAG_MASK) + { + u32IrqChannel = FCSMU_GetNtfFlag() & 0xFFU; + } + else + { + u32IrqChannel = FCSMU_GetWtfFlag() & 0xFFU; + } + + if (u32IrqChannel == 0xFFU) + { + u32IrqChannel = FCSMU_GetFaultChannel(); + } + else + { + if (u32IrqChannel > 0U && u32IrqChannel <= 32U) + { + u32IrqChannel = (uint32_t)1U << (u32IrqChannel - (uint32_t)1U); + } + else + { + u32IrqChannel = 0U; + } + } + + s_apFcsmuISRCallback(FCSMU_FAULT_IRQ, u32IrqChannel); + } + else if ((FCSMU_IRQ_STAT_WARNING_IRQ_MASK & u32TempValue) == FCSMU_IRQ_STAT_WARNING_IRQ_MASK) + { + u32IrqChannel = FCSMU_GetNtwFlag() & 0xFFU; + + if (u32IrqChannel == 0xFFU) + { + u32IrqChannel = FCSMU_GetFaultChannel(); + } + else + { + if (u32IrqChannel > 0U && u32IrqChannel <= 32U) + { + u32IrqChannel = (uint32_t)1U << (u32IrqChannel - (uint32_t)1U); + } + else + { + u32IrqChannel = 0U; + } + } + + s_apFcsmuISRCallback(FCSMU_WARNING_IRQ, u32IrqChannel); + + } + else if ((FCSMU_IRQ_STAT_CFG_TO_IRQ_MASK & u32TempValue) == FCSMU_IRQ_STAT_CFG_TO_IRQ_MASK) + { + s_apFcsmuISRCallback(FCSMU_CFG_TIMEOUT, 0); + } + else + { + + } +} + +void FCSMU0_IRQHandler(void) +{ + FCSMUn_IRQHandler(); +} diff --git a/Src/fc7xxx_driver_fcspi.c b/Src/fc7xxx_driver_fcspi.c new file mode 100644 index 0000000..3bb82e8 --- /dev/null +++ b/Src/fc7xxx_driver_fcspi.c @@ -0,0 +1,3229 @@ +/** + * @file fc7xxx_driver_fcspi.c + * @author Flagchip + * @brief FC7xxx FCSPI driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024/01/12 Flagchip071 N/A First version for FC240 + ******************************************************************************** */ + +#include "interrupt_manager.h" +#include "fc7xxx_driver_fcspi.h" +#define FCSPI_DRV_STATUS_REG_W1C_U32 ((uint32_t)( FCSPI_STATUS_DMF(1) | \ + FCSPI_STATUS_RX_FO(1) | \ + FCSPI_STATUS_TX_FU(1) | \ + FCSPI_STATUS_TCF(1) | \ + FCSPI_STATUS_FEF(1) | \ + FCSPI_STATUS_RX_WF(1))) + +#define FCSPI_DRV_STATUS_REG_W1C_MASK_U32 ((uint32_t)(FCSPI_STATUS_DMF_MASK | \ + FCSPI_STATUS_RX_FO_MASK | \ + FCSPI_STATUS_TX_FU_MASK | \ + FCSPI_STATUS_TCF_MASK | \ + FCSPI_STATUS_FEF_MASK | \ + FCSPI_STATUS_RX_WF_MASK)) + +#define FCSPI_DRV_INT_EN_REG_ALL_U32 ((uint32_t)(FCSPI_INT_EN_DMIE(1) | \ + FCSPI_INT_EN_RFOIE(1) | \ + FCSPI_INT_EN_TFUIE(1) | \ + FCSPI_INT_EN_TCIE(1) | \ + FCSPI_INT_EN_FEIE(1) | \ + FCSPI_INT_EN_RWIE(1) | \ + FCSPI_INT_EN_RX_PEIE(1) | \ + FCSPI_INT_EN_TX_PEIE(1) | \ + FCSPI_INT_EN_RFIE(1) | \ + FCSPI_INT_EN_TFIE(1))) + +#define FCSPI_DRV_RX_FIFO_WORD_CNT (8) + +#define FCSPI_DRV_TX_FIFO_WORD_CNT (8) + +#define FCSPI_CFGR1_PCS23_PCS_MODE_U32 FCSPI_CFG1_PCS_CFG(0) /* PCS[3:2] as PCS feature */ +#define FCSPI_CFGR1_PCS23_DATABUS_IN_4BIT_MODE_U32 FCSPI_CFG1_PCS_CFG(1) /* PCS[3:2] as data bus in 4-bit mode */ + +#define FCSPI_CFGR1_OUTCFG_RETAIN_LAST_WHEN_NEGATE_U32 FCSPI_CFG1_OUT_CFG(0) +#define FCSPI_CFGR1_OUTCFG_TRISTATE_WHEN_NEGATE_U32 FCSPI_CFG1_OUT_CFG(1) + +#define FCSPI_CFGR1_PINCFG_SIN_INPUT_SOUT_OUTPUT_U32 FCSPI_CFG1_PIN_CFG(0) /* SIN is used for input data and SOUT for output data */ +#define FCSPI_CFGR1_PINCFG_SIN_INPUT_OUTPUT_U32 FCSPI_CFG1_PIN_CFG(1) /* SIN is used for both input and output data */ +#define FCSPI_CFGR1_PINCFG_SOUT_INPUT_OUTPUT_U32 FCSPI_CFG1_PIN_CFG(2) /* SOUT is used for both input and output data */ +#define FCSPI_CFGR1_PINCFG_SOUT_INPUT_SIN_OUTPUT_U32 FCSPI_CFG1_PIN_CFG(3) /* SOUT is used for input data and SIN for output data */ + +#define FCSPI_CFGR1_PCS0_ACTIVE_HIGH_U32 FCSPI_CFG1_PCS_POL(1) /* Peripheral Chip Select Polarity - Active High */ +#define FCSPI_CFGR1_PCS0_POL_MASK_U32 FCSPI_CFG1_PCS_POL(1) +#define FCSPI_CFGR1_PCS1_ACTIVE_HIGH_U32 FCSPI_CFG1_PCS_POL(2) /* Peripheral Chip Select Polarity - Active High */ +#define FCSPI_CFGR1_PCS1_POL_MASK_U32 FCSPI_CFG1_PCS_POL(2) +#define FCSPI_CFGR1_PCS2_ACTIVE_HIGH_U32 FCSPI_CFG1_PCS_POL(4) /* Peripheral Chip Select Polarity - Active High */ +#define FCSPI_CFGR1_PCS2_POL_MASK_U32 FCSPI_CFG1_PCS_POL(4) +#define FCSPI_CFGR1_PCS3_ACTIVE_HIGH_U32 FCSPI_CFG1_PCS_POL(8) /* Peripheral Chip Select Polarity - Active High */ +#define FCSPI_CFGR1_PCS3_POL_MASK_U32 FCSPI_CFG1_PCS_POL(8) + +#define FCSPI_TRCR_SCKPOL_ACTIVE_HIGH_U32 FCSPI_TR_CTRL_SCK_POL(0) /* When inactive, SCK is low */ +#define FCSPI_TRCR_SCKPOL_ACTIVE_LOW_U32 FCSPI_TR_CTRL_SCK_POL(1) /* When inactive, SCK is high */ + +#define FCSPI_TRCR_SCKPHA_CAP_LEADING_U32 FCSPI_TR_CTRL_SCK_PHA(0) /* Data is changed on the leading edge of SCK and captured on the following edge */ +#define FCSPI_TRCR_SCKPHA_CAP_TRAILING_U32 FCSPI_TR_CTRL_SCK_PHA(1) /* Data is captured on the leading edge of SCK and changed on the following edge */ + +#define FCSPI_TRCR_PRESCALE_1_U32 FCSPI_TR_CTRL_PRESCALE(0) /* Divide by 1 */ +#define FCSPI_TRCR_PRESCALE_2_U32 FCSPI_TR_CTRL_PRESCALE(1) /* Divide by 2 */ +#define FCSPI_TRCR_PRESCALE_4_U32 FCSPI_TR_CTRL_PRESCALE(2) /* Divide by 4 */ +#define FCSPI_TRCR_PRESCALE_8_U32 FCSPI_TR_CTRL_PRESCALE(3) /* Divide by 8 */ +#define FCSPI_TRCR_PRESCALE_16_U32 FCSPI_TR_CTRL_PRESCALE(4) /* Divide by 16 */ +#define FCSPI_TRCR_PRESCALE_32_U32 FCSPI_TR_CTRL_PRESCALE(5) /* Divide by 32 */ +#define FCSPI_TRCR_PRESCALE_64_U32 FCSPI_TR_CTRL_PRESCALE(6) /* Divide by 64 */ +#define FCSPI_TRCR_PRESCALE_128_U32 FCSPI_TR_CTRL_PRESCALE(7) /* Divide by 128 */ + +#define FCSPI_TRCR_PCS0_EN_U32 FCSPI_TR_CTRL_PCS(0) /* Transfer using FCSPI_PCS[0] */ +#define FCSPI_TRCR_PCS1_EN_U32 FCSPI_TR_CTRL_PCS(1) /* Transfer using FCSPI_PCS[1] */ +#define FCSPI_TRCR_PCS2_EN_U32 FCSPI_TR_CTRL_PCS(2) /* Transfer using FCSPI_PCS[2] */ +#define FCSPI_TRCR_PCS3_EN_U32 FCSPI_TR_CTRL_PCS(3) /* Transfer using FCSPI_PCS[3] */ + +#define FCSPI_TRCR_MSB_U32 FCSPI_TR_CTRL_LSBF(0) /* Data is transferred MSB first */ +#define FCSPI_TRCR_LSB_U32 FCSPI_TR_CTRL_LSBF(1) /* Data is transferred LSB first */ + +#define FCSPI_TRCR_BYSW_EN_U32 FCSPI_TR_CTRL_BYSW(1) /* Byte swap enabled */ +#define FCSPI_TRCR_BYSW_DIS_U32 FCSPI_TR_CTRL_BYSW(0) /* Byte swap disable */ + +#define FCSPI_TRCR_CONT_EN_U32 FCSPI_TR_CTRL_CT_EN(1) /* Continuous transfer enabled */ +#define FCSPI_TRCR_CONT_DIS_U32 FCSPI_TR_CTRL_CT_EN(0) /* Continuous transfer disabled */ + +#define FCSPI_TRCR_CONTC_EN_U32 FCSPI_TR_CTRL_CT_GO(1) /* Command word for continuing transfer */ + +#define FCSPI_TRCR_WIDTH_1_U32 FCSPI_TR_CTRL_WIDTH(0) /* Single bit transfer */ +#define FCSPI_TRCR_WIDTH_2_U32 FCSPI_TR_CTRL_WIDTH(1) /* Two bita transfer */ +#define FCSPI_TRCR_WIDTH_4_U32 FCSPI_TR_CTRL_WIDTH(2) /* Four bits transfer */ + +#define ITCM_START_ADDRESS 0x0u +#define ITCM_END_ADDRESS 0xFFFFu +#define DTCM_START_ADDRESS 0x20000000u +#define DTCM_END_ADDRESS 0x2001FFFFu +#define ITCM_TO_BACKDOOR_OFFSET 0x24000000u +#define DTCM_TO_BACKDOOR_OFFSET 0x02000000u + + + +typedef enum { + SIN_INPUT_SOUT_OUTPUT = 0, + SIN_INPUT_OUTPUT = 1, + SOUT_INPUT_OUTPUT = 2, + SOUT_INPUT_SIN_OUTPUT = 3 +} FCSPI_PinModeType; + +typedef enum { + FCSPI_PRESCALE_1 = 0, + FCSPI_PRESCALE_2 = 1, + FCSPI_PRESCALE_4 = 2, + FCSPI_PRESCALE_8 = 3, + FCSPI_PRESCALE_16 = 4, + FCSPI_PRESCALE_32 = 5, + FCSPI_PRESCALE_64 = 6, + FCSPI_PRESCALE_128 = 7, + FCSPI_PRESCALE_MAX = 8 +} FCSPI_PrescaleValueType; + +typedef enum { + FCSPI_TRANSFER_1_BIT = 0, /* 1-bit shift at a time, data out on SDO, in on SDI (normal mode) */ + FCSPI_TRANSFER_2_BIT = 1, /* 2-bits shift out on SDO/SDI and in on SDO/SDI */ + FCSPI_TRANSFER_4_BIT = 2 /* 4-bits shift out on SDO/SDI/PCS[3:2] and in on SDO/SDI/PCS[3:2] */ +} FCSPI_TransferWidthType; + +typedef enum { + PINOUT_RETAIN_LAST = 0, + PINOUT_TRISTATE = 1 +} FCSPI_NegatedPinOutStatType; + +typedef enum { + PCS2_3_PCS = 0, + PCS2_3_DATA_BUS_IN_4BIT_MODE = 1 +} FCSPI_PCS2_3ModeType; + +typedef struct { + FCSPI_SckPolarityType eSckPolarity; + FCSPI_SckSamplePhaseType eSckPhase; + FCSPI_PrescaleValueType ePrescalerValue; + FCSPI_PCSType ePCSSelect; + FCSPI_BitFirstOrderType eBitFirstOrder; + FCSPI_AtomicBoolType eByteSwap; + FCSPI_AtomicBoolType eContTransEnable; + FCSPI_AtomicBoolType eContCmdEnable; + FCSPI_AtomicBoolType eRxDisable; + FCSPI_AtomicBoolType eTxDisable; + FCSPI_TransferWidthType eTransferWidth; + uint16_t u16FrameBitCnt; +} FCSPI_TxRxCtrlType; + +typedef enum { + FCSPI_TRANSFER_OK = 0U, /* Transfer OK */ + FCSPI_TRANSFER_TX_FAIL, /* Error during transmission */ + FCSPI_TRANSFER_RX_FAIL, /* Error during reception */ + FCSPI_TRANSFER_ABORT, /* Transfer is aborted */ +} FCSPI_TransferStatusType; + +typedef struct { + uint16_t u16BitsPerFrame; /* count of bits per frame: 8-4096bits */ + uint16_t u16BytesCntFrameNeed; /* count of bytes per frame: 1-512bytes for external buffer passed into driver */ + FCSPI_BitFirstOrderType eBitFirstOrder; /* MSB/LSB first to send/receive */ + uint8_t u8TxFifoSize; /* Tx fifo size */ + uint8_t u8RxFifoSize; /* Rx fifo size */ + FCSPI_TriggerDmaInfType tTriggerDmaInf; + FCSPI_TriggerSrcType eTransferTriggerSrc; /* Type of transfer */ + FCSPI_StopCbType pStopNotifyCb; /* callback to transfer stop, transfer successfully or aborted */ + FCSPI_SemaphoreResetCbType pSemaResetCb; /* synchronous send need, reset the semaphore */ + FCSPI_SemaphoreTakeCbType pSemaTakeCb; /* synchronous send need, acquire the semaphore */ + FCSPI_SemaphorePostCbType pSemaPostCb; /* synchronous send need, release the semaphore outside of the interrupt */ + uint32_t u32DmaDummyData; /* DMA mode, TX is NULL, just send this data, RX is NULL, just store in this var */ + + FCSPI_SckSamplePhaseType eSckSamplePhase; /* select which edge of active sck clock to capture data */ + FCSPI_SckPolarityType eSckPolarity; /* select output sclk clock polarity */ + + FCSPI_PCSType ePcs; /* chip select pin */ + FCSPI_PcsPolarityType ePcsPolarity; /* chip select pin polarity */ + + /* only master mode use, slave not */ + FCSPI_AtomicBoolType eIsPcsContinuous; /* Option to keep chip select asserted until transfer complete; needed for TCR programming */ + uint32_t u32FCSpiSrcClk; /* Module source clock */ + uint32_t u32Baundrate; /* the bit per second of current transmission */ + + /* dynamic state */ + volatile uint8_t u8WaitSemaphore; + const uint8_t *pbyTxBuff; /* The buffer from which transmitted bytes are taken */ + uint8_t *pbyRxBuff; /* The buffer into which received bytes are placed */ + volatile uint16_t u16TxIndex; + volatile uint16_t u16RxIndex; + + volatile uint16_t u16TxByteCntRemainToSend; /* Number of bytes remaining to send */ + volatile uint16_t u16RxByteCntRemainToGet; /* Number of bytes remaining to receive */ + volatile uint16_t u16TxSendByteCntOfCurFrame; /* Number of bytes from current frame which were already sent */ + volatile uint16_t u16RxGetByteCntOfCurFrame; /* Number of bytes from current frame which were already received */ + volatile FCSPI_TransferStatusType eTransferStat; /* The status of the current */ + volatile FCSPI_AtomicBoolType eIsInTransfer; /* True if there is an active transfer */ +} FCSPI_DrvStateType; + +typedef struct +{ + FCSPI_MemMapPtr tFCSpiInstance; + FCSPI_DrvStateType tFCSpiStat; + IRQn_Type eFCSpiIrq; +} FCSPI_DriverInfoType; + +static FCSPI_DriverInfoType s_atFCSpiInfo[FCSPI_INSTANCE_COUNT] = { + {FCSPI0, {0} ,FCSPI0_IRQn}, + {FCSPI1, {0} ,FCSPI1_IRQn}, + {FCSPI2, {0} ,FCSPI2_IRQn}, + {FCSPI3, {0} ,FCSPI3_IRQn}, + {FCSPI4, {0} ,FCSPI4_IRQn}, + {FCSPI5, {0} ,FCSPI5_IRQn} + }; + + +/* soft reset just reset the logic and registers except CTRL */ +static void FCSpi_Hw_Reset(FCSPI_InstanceType eInst, + FCSPI_AtomicBoolType eRxFifo, + FCSPI_AtomicBoolType eTxFifo, + FCSPI_AtomicBoolType eSoftRst); +static FCSPI_StatusType FCSpi_Hw_Disable(FCSPI_InstanceType eInst); + +/* get status value and check using macro */ +#define FCSpi_Hw_ChkBusy(status) (((status) & FCSPI_STATUS_BF_MASK) != 0U) +#define FCSpi_Hw_ChkDataMatch(status) (((status) & FCSPI_STATUS_DMF_MASK) != 0U) +#define FCSpi_Hw_ChkRxFifoOverflow(status) (((status) & FCSPI_STATUS_RX_FO_MASK) != 0U) +#define FCSpi_Hw_ChkTxFifoUnderrun(status) (((status) & FCSPI_STATUS_TX_FU_MASK) != 0U) +#define FCSpi_Hw_ChkTransferComplete(status) (((status) & FCSPI_STATUS_TCF_MASK) != 0U) +#define FCSpi_Hw_ChkFrameEndDetected(status) (((status) & FCSPI_STATUS_FEF_MASK) != 0U) +#define FCSpi_Hw_ChkReceiveWordComplete(status) (((status) & FCSPI_STATUS_RX_WF_MASK) != 0U) +#define FCSpi_Hw_ChkRxGreaterThanWater(status) (((status) & FCSPI_STATUS_RX_FF_MASK) != 0U) +#define FCSpi_Hw_ChkTxEqualOrLessThanWater(status) (((status) & FCSPI_STATUS_TX_FF_MASK) != 0U) + +static void FCSpi_Hw_ClearSomeStatusW1CFlag(FCSPI_InstanceType eInst, uint32_t u32FlagBitSet); /* refer to FCSPI_DRV_STATUS_REG_W1C_U32 */ +static void FCSpi_Hw_EnableMoreInterrupts(FCSPI_InstanceType eInst, uint32_t u32Interrupts); /* refer to FCSPI_INT_EN_DMIE(1) */ +static void FCSpi_Hw_DisableSomeInterrupts(FCSPI_InstanceType eInst, uint32_t u32Interrupts); /* refer to FCSPI_INT_EN_DMIE(1) */ +#define FCSpi_Hw_EnableTransmitDataInterrupt(eInst) FCSpi_Hw_EnableMoreInterrupts((eInst), FCSPI_INT_EN_TFIE_MASK) +#define FCSpi_Hw_DisableTransmitDataInterrupt(eInst) FCSpi_Hw_DisableSomeInterrupts((eInst), FCSPI_INT_EN_TFIE_MASK) +#define FCSpi_Hw_EnableReceiveDataInterrupt(eInst) FCSpi_Hw_EnableMoreInterrupts((eInst), FCSPI_INT_EN_RFIE_MASK) +#define FCSpi_Hw_DisableReceiveDataInterrupt(eInst) FCSpi_Hw_DisableSomeInterrupts((eInst), FCSPI_INT_EN_RFIE_MASK) +#define FCSpi_Hw_EnableTransmitCompleteInterrupt(eInst) FCSpi_Hw_EnableMoreInterrupts((eInst), FCSPI_INT_EN_TCIE_MASK) +#define FCSpi_Hw_DisableTransmitCompleteInterrupt(eInst) FCSpi_Hw_DisableSomeInterrupts((eInst), FCSPI_INT_EN_TCIE_MASK) + +static void FCSpi_Hw_SetPcs_2_3_Mode(FCSPI_InstanceType eInst, FCSPI_PCS2_3ModeType eMode); +static void FCSpi_Hw_SetPin(FCSPI_InstanceType eInst, FCSPI_PinModeType eMode, FCSPI_NegatedPinOutStatType eStat); + +static void FCSpi_Hw_SetOnePcsPolarity(FCSPI_InstanceType eInst, + FCSPI_PCSType ePcs, FCSPI_PcsPolarityType ePolarity); + +static void FCSpi_Hw_Master_SetSckLoopbackSample(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType eEnable); + +#define FCSpi_Hw_PrescalerRegToActualVal(eVal) (((uint32_t)1) << ((uint8_t)(eVal))) +static void FCSpi_Hw_SetContinuousCommand(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType eEnable); + +static void FCSpi_Hw_SelectUsePcs(FCSPI_InstanceType eInst, FCSPI_PCSType ePCS); +static uint32_t FCSpi_Hw_Master_CalcBaudRate(const FCSPI_MasterCfgType *pCfg, uint32_t *pdwPrescaleRegVal, uint32_t *pdwActualSckDiv); + +static FCSPI_StatusType FCSpi_Hw_SetTRCR(FCSPI_InstanceType eInst, FCSPI_TxRxCtrlType *ptCtrl); +static FCSPI_PrescaleValueType FCSpi_Hw_GetRegPrescalerVal(FCSPI_InstanceType eInst); + +static void FCSpi_Hw_Get_SCK_PCS_DIV_Hold(FCSPI_InstanceType eInst, uint8_t *pbySCKPCS, uint8_t *pbyPCSSCK, uint8_t *pbyPCSPCS, uint8_t *pbySCKDIV); +static void FCSpi_Hw_Set_SCK_PCS_DIV_Hold(FCSPI_InstanceType eInst, uint8_t u8SCKPCS, uint8_t u8PCSSCK, uint8_t u8PCSPCS, uint8_t u8SCKDIV); +static void FCSpi_Hw_Set_SCK_PCS_Hold(FCSPI_InstanceType eInst, uint8_t u8SCKPCS, uint8_t u8PCSSCK, uint8_t u8PCSPCS); +static void FCSpi_Hw_SetRxTxDmaEnableStatus(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType eRxEnable, FCSPI_AtomicBoolType eTxEnable); +static void fcspi_read_rx_fifo(FCSPI_InstanceType eInst); +static void fcspi_write_tx_fifo(FCSPI_InstanceType eInst); +static void fcspi_master_clean_transfer(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInInterrupt); +static void fcspi_master_abort_transfer(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInISR); +static void fcspi_master_dma_rx_err_interrupt(FCSPI_InstanceType eInst); +static void fcspi_0_master_dma_rx_err_interrupt(void); +static void fcspi_1_master_dma_rx_err_interrupt(void); +static void fcspi_2_master_dma_rx_err_interrupt(void); +static void fcspi_3_master_dma_rx_err_interrupt(void); +static void fcspi_4_master_dma_rx_err_interrupt(void); +static void fcspi_5_master_dma_rx_err_interrupt(void); +static void fcspi_master_dma_rx_finish_interrupt(void); +static void fcspi_master_dma_tx_err_interrupt(FCSPI_InstanceType eInst); +static void fcspi_0_master_dma_tx_err_interrupt(void); +static void fcspi_1_master_dma_tx_err_interrupt(void); +static void fcspi_2_master_dma_tx_err_interrupt(void); +static void fcspi_3_master_dma_tx_err_interrupt(void); +static void fcspi_4_master_dma_tx_err_interrupt(void); +static void fcspi_5_master_dma_tx_err_interrupt(void); +static void fcspi_master_dma_tx_finish_interrupt(FCSPI_InstanceType eInst); +static void fcspi_0_master_dma_tx_finish_interrupt(void); +static void fcspi_1_master_dma_tx_finish_interrupt(void); +static void fcspi_2_master_dma_tx_finish_interrupt(void); +static void fcspi_3_master_dma_tx_finish_interrupt(void); +static void fcspi_4_master_dma_tx_finish_interrupt(void); +static void fcspi_5_master_dma_tx_finish_interrupt(void); +static FCSPI_StatusType fcspi_master_async_transfer_bytes(FCSPI_InstanceType eInst, + const uint8_t *pSendBuffer, uint8_t *pReceiveBuffer, + uint16_t u16TransferByteCnt); +static FCSPI_StatusType fcspi_master_trigger(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInIsr); +static void fcspi_slave_clean_transfer(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInInterrupt); +static void fcspi_slave_abort_transfer(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInInterrupt); +static void fcspi_slave_dma_rx_err_interrupt(FCSPI_InstanceType eInst); +static void fcspi_0_slave_dma_rx_err_interrupt(void); +static void fcspi_1_slave_dma_rx_err_interrupt(void); +static void fcspi_2_slave_dma_rx_err_interrupt(void); +static void fcspi_3_slave_dma_rx_err_interrupt(void); +static void fcspi_4_slave_dma_rx_err_interrupt(void); +static void fcspi_5_slave_dma_rx_err_interrupt(void); +static void fcspi_slave_dma_rx_finish_interrupt(FCSPI_InstanceType eInst); +static void fcspi_0_slave_dma_rx_finish_interrupt(void); +static void fcspi_1_slave_dma_rx_finish_interrupt(void); +static void fcspi_2_slave_dma_rx_finish_interrupt(void); +static void fcspi_3_slave_dma_rx_finish_interrupt(void); +static void fcspi_4_slave_dma_rx_finish_interrupt(void); +static void fcspi_5_slave_dma_rx_finish_interrupt(void); +static void fcspi_slave_dma_tx_err_interrupt(FCSPI_InstanceType eInst); +static void fcspi_0_slave_dma_tx_err_interrupt(void); +static void fcspi_1_slave_dma_tx_err_interrupt(void); +static void fcspi_2_slave_dma_tx_err_interrupt(void); +static void fcspi_3_slave_dma_tx_err_interrupt(void); +static void fcspi_4_slave_dma_tx_err_interrupt(void); +static void fcspi_5_slave_dma_tx_err_interrupt(void); +static void fcspi_slave_dma_tx_finish_interrupt(FCSPI_InstanceType eInst); +static void fcspi_0_slave_dma_tx_finish_interrupt(void); +static void fcspi_1_slave_dma_tx_finish_interrupt(void); +static void fcspi_2_slave_dma_tx_finish_interrupt(void); +static void fcspi_3_slave_dma_tx_finish_interrupt(void); +static void fcspi_4_slave_dma_tx_finish_interrupt(void); +static void fcspi_5_slave_dma_tx_finish_interrupt(void); + +static FCSPI_StatusType fcspi_slave_async_transfer_bytes(FCSPI_InstanceType eInst, + const uint8_t *pSendBuffer, uint8_t *pReceiveBuffer, uint16_t u16TransferByteCnt); +static FCSPI_StatusType fcspi_slave_trigger(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInISR); +static void fcspi_irq_handler(FCSPI_InstanceType eInst); + +static void FCSpi_Hw_Reset(FCSPI_InstanceType eInst, + FCSPI_AtomicBoolType eRxFifo, FCSPI_AtomicBoolType eTxFifo, FCSPI_AtomicBoolType eSoftRst) +{ + uint32_t u32Flag = 0U; + uint32_t u32OldFlag = FCSPI_HWA_GetCtrlValue(s_atFCSpiInfo[eInst].tFCSpiInstance); + uint32_t u32Mask = FCSPI_CTRL_MASK; + + if (eRxFifo) + { + u32Flag |= FCSPI_CTRL_RST_RF(1); + } + + if (eTxFifo) + { + u32Flag |= FCSPI_CTRL_RST_TF(1); + } + + if (FCSPI_TRUE == eSoftRst) + { + u32Flag |= FCSPI_CTRL_SW_RST(1); + } + + u32Flag |= u32OldFlag; + FCSPI_HWA_SetCtrlValue(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); + + /* no need delay */ + if (FCSPI_TRUE == eSoftRst) + { + FCSPI_HWA_SetCtrlValue(s_atFCSpiInfo[eInst].tFCSpiInstance, 0U); + } + else + { + FCSPI_HWA_SetCtrlValue(s_atFCSpiInfo[eInst].tFCSpiInstance, (u32OldFlag & u32Mask)); + } +} + +#ifdef FCSPI_DRV_INTERNAL_FUNC_EN +static FCSPI_AtomicBoolType FCSpi_Hw_ChkEnabled(FCSPI_InstanceType eInst) +{ + return (FCSPI_AtomicBoolType)((FCSPI_HWA_GetCtrlValue(s_atFCSpiInfo[eInst].tFCSpiInstance) & + FCSPI_CTRL_M_EN_MASK) >> FCSPI_CTRL_M_EN_SHIFT); +} +#endif + +static FCSPI_StatusType FCSpi_Hw_Disable(FCSPI_InstanceType eInst) +{ + FCSPI_StatusType eStatus = FCSPI_STATUS_SUCCESS; + + if (0U != (FCSPI_HWA_GetStatus(s_atFCSpiInfo[eInst].tFCSpiInstance) & FCSPI_STATUS_BF_MASK)) + { + eStatus = FCSPI_STATUS_BUSY; + } + else + { + FCSPI_HWA_ModuleDisable(s_atFCSpiInfo[eInst].tFCSpiInstance); + } + + return eStatus; +} + +static void FCSpi_Hw_ClearSomeStatusW1CFlag( + FCSPI_InstanceType eInst, uint32_t u32FlagBitSet) /* refer to FCSPI_DRV_STATUS_REG_W1C_U32 */ +{ + FCSPI_HWA_ClearStatus(s_atFCSpiInfo[eInst].tFCSpiInstance, (u32FlagBitSet & FCSPI_DRV_STATUS_REG_W1C_MASK_U32)); +} + +#ifdef FCSPI_DRV_INTERNAL_FUNC_EN +static void FCSpi_Hw_SetAllInterruptEnableStatus( + FCSPI_InstanceType eInst, uint32_t u32Interrupts) /* refer to FCSPI_DRV_INT_EN_REG_ALL_U32 */ +{ + FCSPI_HWA_SetInterruptEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance, (u32Interrupts & FCSPI_INT_EN_MASK)); +} + +static uint32_t FCSpi_Hw_GetAllInterruptEnableStatus(FCSPI_InstanceType eInst) +{ + return FCSPI_HWA_GetIntrruptEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance); +} +#endif + +static void FCSpi_Hw_EnableMoreInterrupts(FCSPI_InstanceType eInst, uint32_t u32Interrupts) +{ + uint32_t u32RegVal = FCSPI_HWA_GetIntrruptEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance); + u32RegVal |= (u32Interrupts & FCSPI_INT_EN_MASK); + + FCSPI_HWA_SetInterruptEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32RegVal); +} + +static void FCSpi_Hw_DisableSomeInterrupts(FCSPI_InstanceType eInst, uint32_t u32Interrupts) +{ + uint32_t u32RegVal = FCSPI_HWA_GetIntrruptEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance); + u32RegVal &= (~(u32Interrupts & FCSPI_INT_EN_MASK)); + + FCSPI_HWA_SetInterruptEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32RegVal); +} + +static void FCSpi_Hw_SetRxTxDmaEnableStatus( + FCSPI_InstanceType eInst, FCSPI_AtomicBoolType eRxEnable, FCSPI_AtomicBoolType eTxEnable) +{ + uint32_t u32Flag = 0U; + + if (eRxEnable) + { + u32Flag |= FCSPI_DMA_EN_RFDE(1); + } + + if (eTxEnable) + { + u32Flag |= FCSPI_DMA_EN_TFDE(1); + } + + FCSPI_HWA_SetDMAEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); +} + +#ifdef FCSPI_DRV_INTERNAL_FUNC_EN +static void FCSpi_Hw_SetRxDmaEnableStatus(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType eEnable) +{ + uint32_t u32RegVal = FCSPI_HWA_GetDMAEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance); + + if (eEnable) + { + u32RegVal |= FCSPI_DMA_EN_RFDE(1); + } + else + { + u32RegVal &= (~(FCSPI_DMA_EN_RFDE_MASK)); + } + + FCSPI_HWA_SetDMAEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32RegVal); +} + +static void FCSpi_Hw_SetTxDmaEnableStatus(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType eEnable) +{ + uint32_t u32RegVal = FCSPI_HWA_GetDMAEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance); + + if (FCSPI_TRUE == eEnable) + { + u32RegVal |= FCSPI_DMA_EN_TFDE(1); + } + else + { + u32RegVal &= (~(FCSPI_DMA_EN_TFDE_MASK)); + } + + FCSPI_HWA_SetDMAEnableReg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32RegVal); +} +#endif + +static void FCSpi_Hw_SetPcs_2_3_Mode(FCSPI_InstanceType eInst, FCSPI_PCS2_3ModeType eMode) +{ + uint32_t u32RegVal = FCSPI_HWA_GetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance); + + if (PCS2_3_PCS == eMode) + { + u32RegVal &= (~(FCSPI_CFG1_PCS_CFG_MASK)); + } + else + { + u32RegVal |= (FCSPI_CFGR1_PCS23_DATABUS_IN_4BIT_MODE_U32); + } + + FCSPI_HWA_SetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32RegVal); +} + +static void FCSpi_Hw_SetPin(FCSPI_InstanceType eInst, + FCSPI_PinModeType eMode, FCSPI_NegatedPinOutStatType eStat) +{ + uint32_t u32Flag = FCSPI_HWA_GetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance); + + u32Flag &= (~(FCSPI_CFG1_PIN_CFG_MASK)); + u32Flag &= (~(FCSPI_CFG1_OUT_CFG_MASK)); + + switch (eMode) + { + case SIN_INPUT_OUTPUT: + u32Flag |= FCSPI_CFGR1_PINCFG_SIN_INPUT_OUTPUT_U32; + break; + case SOUT_INPUT_OUTPUT: + u32Flag |= FCSPI_CFGR1_PINCFG_SOUT_INPUT_OUTPUT_U32; + break; + case SOUT_INPUT_SIN_OUTPUT: + u32Flag |= FCSPI_CFGR1_PINCFG_SOUT_INPUT_SIN_OUTPUT_U32; + break; + case SIN_INPUT_SOUT_OUTPUT: + u32Flag |= FCSPI_CFGR1_PINCFG_SIN_INPUT_SOUT_OUTPUT_U32; + break; + default: + u32Flag |= FCSPI_CFGR1_PINCFG_SIN_INPUT_SOUT_OUTPUT_U32; + break; + } + + if (PINOUT_RETAIN_LAST == eStat) + { + u32Flag |= FCSPI_CFGR1_OUTCFG_RETAIN_LAST_WHEN_NEGATE_U32; + } + else + { + u32Flag |= FCSPI_CFGR1_OUTCFG_TRISTATE_WHEN_NEGATE_U32; + } + + FCSPI_HWA_SetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); +} + +#ifdef FCSPI_DRV_INTERNAL_FUNC_EN +static void FCSpi_Hw_SetPcsPolarity(FCSPI_InstanceType eInst, + FCSPI_AtomicBoolType eSetPCS0, FCSPI_PcsPolarityType ePCS0Polarity, + FCSPI_AtomicBoolType eSetPCS1, FCSPI_PcsPolarityType ePCS1Polarity, + FCSPI_AtomicBoolType eSetPCS2, FCSPI_PcsPolarityType ePCS2Polarity, + FCSPI_AtomicBoolType eSetPCS3, FCSPI_PcsPolarityType ePCS3Polarity) +{ + uint32_t u32Flag = FCSPI_HWA_GetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance); + + if (eSetPCS0) + { + if (FCSPI_PCS_POL_ACTIVE_HIGH == ePCS0Polarity) + u32Flag |= FCSPI_CFGR1_PCS0_ACTIVE_HIGH_U32; + else + u32Flag &= (~(FCSPI_CFGR1_PCS0_POL_MASK_U32)); + } + + if (eSetPCS1) + { + if (FCSPI_PCS_POL_ACTIVE_HIGH == ePCS1Polarity) + u32Flag |= FCSPI_CFGR1_PCS1_ACTIVE_HIGH_U32; + else + u32Flag &= (~(FCSPI_CFGR1_PCS1_POL_MASK_U32)); + } + + if (eSetPCS2) + { + if (FCSPI_PCS_POL_ACTIVE_HIGH == ePCS2Polarity) + u32Flag |= FCSPI_CFGR1_PCS2_ACTIVE_HIGH_U32; + else + u32Flag &= (~(FCSPI_CFGR1_PCS2_POL_MASK_U32)); + } + + if (eSetPCS3) + { + if (FCSPI_PCS_POL_ACTIVE_HIGH == ePCS3Polarity) + u32Flag |= FCSPI_CFGR1_PCS3_ACTIVE_HIGH_U32; + else + u32Flag &= (~(FCSPI_CFGR1_PCS3_POL_MASK_U32)); + } + + FCSPI_HWA_SetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); +} +#endif + +static void FCSpi_Hw_SetOnePcsPolarity(FCSPI_InstanceType eInst, + FCSPI_PCSType ePcs, FCSPI_PcsPolarityType ePolarity) +{ + uint32_t u32Flag = FCSPI_HWA_GetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance); + + if (FCSPI_PCS_POL_ACTIVE_HIGH == ePolarity) + { + if (0U == ((((uint32_t)0x1) << (FCSPI_CFG1_PCS_POL_SHIFT + (uint32_t)ePcs)) & u32Flag)) + { + u32Flag |= (((uint32_t)0x1) << (FCSPI_CFG1_PCS_POL_SHIFT + (uint32_t)ePcs)); + } + } + else /* active low */ + { + if (0U != ((((uint32_t)0x1) << (FCSPI_CFG1_PCS_POL_SHIFT + (uint32_t)ePcs)) & u32Flag)) + { + u32Flag &= (~(((uint32_t)0x1) << (FCSPI_CFG1_PCS_POL_SHIFT + (uint32_t)ePcs))); + } + } + + FCSPI_HWA_SetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); +} + +/* before call this function, ensure in master mode */ +static void FCSpi_Hw_Master_SetSckLoopbackSample( + FCSPI_InstanceType eInst, FCSPI_AtomicBoolType eEnable) +{ + uint32_t u32Flag = FCSPI_HWA_GetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance); + + if (FCSPI_TRUE == eEnable) + { + if (FCSPI_CFG1_SCK_LB(1) != (u32Flag & FCSPI_CFG1_SCK_LB_MASK)) + { + u32Flag |= FCSPI_CFG1_SCK_LB(1); + } + } + else + { + if (FCSPI_CFG1_SCK_LB(0) != (u32Flag & FCSPI_CFG1_SCK_LB_MASK)) + { + u32Flag &= (~(FCSPI_CFG1_SCK_LB_MASK)); + } + } + + FCSPI_HWA_SetCFG1Reg(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); +} + +static void FCSpi_Hw_Set_SCK_PCS_DIV_Hold(FCSPI_InstanceType eInst, + uint8_t u8SCKPCS, uint8_t u8PCSSCK, uint8_t u8PCSPCS, uint8_t u8SCKDIV) +{ + uint32_t u32Flag = FCSPI_HWA_GetClockConfig(s_atFCSpiInfo[eInst].tFCSpiInstance); + uint32_t u32Val; + + { + u32Val = u8SCKPCS; + u32Flag &= (~(FCSPI_CLK_CFG_SCKPCS_MASK)); + u32Flag |= (u32Val << FCSPI_CLK_CFG_SCKPCS_SHIFT); + } + + { + u32Val = u8PCSSCK; + u32Flag &= (~(FCSPI_CLK_CFG_PCSSCK_MASK)); + u32Flag |= (u32Val << FCSPI_CLK_CFG_PCSSCK_SHIFT); + } + + { + u32Val = u8PCSPCS; + u32Flag &= (~(FCSPI_CLK_CFG_PCSPCS_MASK)); + u32Flag |= (u32Val << FCSPI_CLK_CFG_PCSPCS_SHIFT); + } + + { + u32Val = u8SCKDIV; + u32Flag &= (~(FCSPI_CLK_CFG_SCKDIV_MASK)); + u32Flag |= (u32Val << FCSPI_CLK_CFG_SCKDIV_SHIFT); + } + + { + FCSPI_HWA_SetClockConfig(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); + } +} + +static void FCSpi_Hw_Set_SCK_PCS_Hold(FCSPI_InstanceType eInst, + uint8_t u8SCKPCS, uint8_t u8PCSSCK, uint8_t u8PCSPCS) +{ + uint32_t u32Flag = FCSPI_HWA_GetClockConfig(s_atFCSpiInfo[eInst].tFCSpiInstance); + uint32_t u32Val; + + { + u32Val = u8SCKPCS; + u32Flag &= (~(FCSPI_CLK_CFG_SCKPCS_MASK)); + u32Flag |= (u32Val << FCSPI_CLK_CFG_SCKPCS_SHIFT); + } + + { + u32Val = u8PCSSCK; + u32Flag &= (~(FCSPI_CLK_CFG_PCSSCK_MASK)); + u32Flag |= (u32Val << FCSPI_CLK_CFG_PCSSCK_SHIFT); + } + + { + u32Val = u8PCSPCS; + u32Flag &= (~(FCSPI_CLK_CFG_PCSPCS_MASK)); + u32Flag |= (u32Val << FCSPI_CLK_CFG_PCSPCS_SHIFT); + } + + { + FCSPI_HWA_SetClockConfig(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); + } +} + +static void FCSpi_Hw_Get_SCK_PCS_DIV_Hold(FCSPI_InstanceType eInst, + uint8_t *pbySCKPCS, + uint8_t *pbyPCSSCK, + uint8_t *pbyPCSPCS, + uint8_t *pbySCKDIV) +{ + uint32_t u32Flag = FCSPI_HWA_GetClockConfig(s_atFCSpiInfo[eInst].tFCSpiInstance); + + if (pbySCKPCS != NULL) + { + *pbySCKPCS = (uint8_t)((u32Flag & FCSPI_CLK_CFG_SCKPCS_MASK) >> FCSPI_CLK_CFG_SCKPCS_SHIFT); + } + + if (pbyPCSSCK != NULL) + { + *pbyPCSSCK = (uint8_t)((u32Flag & FCSPI_CLK_CFG_PCSSCK_MASK) >> FCSPI_CLK_CFG_PCSSCK_SHIFT); + } + + if (pbyPCSPCS != NULL) + { + *pbyPCSPCS = (uint8_t)((u32Flag & FCSPI_CLK_CFG_PCSPCS_MASK) >> FCSPI_CLK_CFG_PCSPCS_SHIFT); + } + + if (pbySCKDIV != NULL) + { + *pbySCKDIV = ((uint8_t)(u32Flag & FCSPI_CLK_CFG_SCKDIV_MASK) >> FCSPI_CLK_CFG_SCKDIV_SHIFT); + } +} + +#ifdef FCSPI_DRV_INTERNAL_FUNC_EN +static void FCSpi_Hw_GetTRCR(FCSPI_InstanceType eInst, FCSPI_TxRxCtrlType *ptCtrl) +{ + uint32_t u32Flag = FCSPI_HWA_GetTxRxControl(s_atFCSpiInfo[eInst].tFCSpiInstance); + + ptCtrl->eSckPolarity = (FCSPI_SckPolarityType) + ((u32Flag & FCSPI_TR_CTRL_SCK_POL_MASK) >> FCSPI_TR_CTRL_SCK_POL_SHIFT); + ptCtrl->eSckPhase = (FCSPI_SckSamplePhaseType) + ((u32Flag & FCSPI_TR_CTRL_SCK_PHA_MASK) >> FCSPI_TR_CTRL_SCK_PHA_SHIFT); + ptCtrl->ePrescalerValue = (FCSPI_PrescaleValueType) + ((u32Flag & FCSPI_TR_CTRL_PRESCALE_MASK) >> FCSPI_TR_CTRL_PRESCALE_SHIFT); + ptCtrl->ePCSSelect = (FCSPI_PCSType) + ((u32Flag & FCSPI_TR_CTRL_PCS_MASK) >> FCSPI_TR_CTRL_PCS_SHIFT); + ptCtrl->eBitFirstOrder = (FCSPI_BitFirstOrderType) + ((u32Flag & FCSPI_TR_CTRL_LSBF_MASK) >> FCSPI_TR_CTRL_LSBF_SHIFT); + ptCtrl->eByteSwap = (FCSPI_AtomicBoolType) + ((u32Flag & FCSPI_TR_CTRL_BYSW_MASK) >> FCSPI_TR_CTRL_BYSW_SHIFT); + ptCtrl->eContTransEnable = (FCSPI_AtomicBoolType) + ((u32Flag & FCSPI_TR_CTRL_CT_EN_MASK) >> FCSPI_TR_CTRL_CT_EN_SHIFT); + + ptCtrl->eContCmdEnable = (FCSPI_AtomicBoolType) + ((u32Flag & FCSPI_TR_CTRL_CT_GO_MASK) >> FCSPI_TR_CTRL_CT_GO_SHIFT); + ptCtrl->eRxDisable = (FCSPI_AtomicBoolType) + ((u32Flag & FCSPI_TR_CTRL_RX_MSK_MASK) >> FCSPI_TR_CTRL_RX_MSK_SHIFT); + ptCtrl->eTxDisable = (FCSPI_AtomicBoolType) + ((u32Flag & FCSPI_TR_CTRL_TX_MSK_MASK) >> FCSPI_TR_CTRL_TX_MSK_SHIFT); + ptCtrl->eTransferWidth = (FCSPI_TransferWidthType) + ((u32Flag & FCSPI_TR_CTRL_WIDTH_MASK) >> FCSPI_TR_CTRL_WIDTH_SHIFT); + ptCtrl->u16FrameBitCnt = (uint16_t) + (((u32Flag & FCSPI_TR_CTRL_FRM_SZ_MASK) >> FCSPI_TR_CTRL_FRM_SZ_SHIFT)+1); +} +#endif + +static FCSPI_StatusType FCSpi_Hw_SetTRCR(FCSPI_InstanceType eInst, FCSPI_TxRxCtrlType *ptCtrl) +{ + uint32_t u32Flag = 0U; + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + + if ((ptCtrl->u16FrameBitCnt < ((uint16_t)8)) || + (((uint16_t)0) != (ptCtrl->u16FrameBitCnt & ((uint16_t)0x1)))) + { + eRet = FCSPI_STATUS_PARAM_ERR; + } + else + { + u32Flag |= (((uint32_t)(ptCtrl->eSckPolarity)) << FCSPI_TR_CTRL_SCK_POL_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->eSckPhase)) << FCSPI_TR_CTRL_SCK_PHA_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->ePrescalerValue)) << FCSPI_TR_CTRL_PRESCALE_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->ePCSSelect)) << FCSPI_TR_CTRL_PCS_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->eBitFirstOrder)) << FCSPI_TR_CTRL_LSBF_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->eByteSwap)) << FCSPI_TR_CTRL_BYSW_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->eContTransEnable)) << FCSPI_TR_CTRL_CT_EN_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->eContCmdEnable)) << FCSPI_TR_CTRL_CT_GO_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->eRxDisable)) << FCSPI_TR_CTRL_RX_MSK_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->eTxDisable)) << FCSPI_TR_CTRL_TX_MSK_SHIFT); + u32Flag |= (((uint32_t)(ptCtrl->eTransferWidth)) << FCSPI_TR_CTRL_WIDTH_SHIFT); + u32Flag |= (((uint32_t)((uint16_t)(ptCtrl->u16FrameBitCnt - (uint16_t)1))) << FCSPI_TR_CTRL_FRM_SZ_SHIFT); + + FCSPI_HWA_SetTxRxControl(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); + } + + return eRet; +} + +/* caution:write TR_CTRL */ +static void FCSpi_Hw_SelectUsePcs(FCSPI_InstanceType eInst, FCSPI_PCSType ePCS) +{ + uint32_t u32Flag = FCSPI_HWA_GetTxRxControl(s_atFCSpiInfo[eInst].tFCSpiInstance); + + u32Flag &= (~(FCSPI_TR_CTRL_PCS_MASK)); + u32Flag |= (((uint32_t)ePCS) << FCSPI_TR_CTRL_PCS_SHIFT); + + FCSPI_HWA_SetTxRxControl(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); +} + +static FCSPI_PrescaleValueType FCSpi_Hw_GetRegPrescalerVal(FCSPI_InstanceType eInst) +{ + return (FCSPI_PrescaleValueType)((FCSPI_HWA_GetTxRxControl(s_atFCSpiInfo[eInst].tFCSpiInstance) & + FCSPI_TR_CTRL_PRESCALE_MASK) >> FCSPI_TR_CTRL_PRESCALE_SHIFT); +} + +/* caution:write TR_CTRL */ +static void FCSpi_Hw_SetContinuousCommand(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType eEnable) +{ + uint32_t u32Flag = FCSPI_HWA_GetTxRxControl(s_atFCSpiInfo[eInst].tFCSpiInstance); + + u32Flag &= (~(FCSPI_TR_CTRL_CT_GO_MASK)); + u32Flag |= (((uint32_t)eEnable) << FCSPI_TR_CTRL_CT_GO_SHIFT); + + FCSPI_HWA_SetTxRxControl(s_atFCSpiInfo[eInst].tFCSpiInstance, u32Flag); +} + +#ifdef FCSPI_DRV_INTERNAL_FUNC_EN +static uint32_t FCSpi_Hw_ReadRxFifoFirstEntry(FCSPI_InstanceType eInst) +{ + return FCSPI_HWA_ReadData(s_atFCSpiInfo[eInst].tFCSpiInstance); +} +#endif + +#ifdef FCSPI_DRV_INTERNAL_FUNC_EN +static void FCSpi_Hw_WriteDataToTxFifo(FCSPI_InstanceType eInst, uint32_t u32TxData) +{ + FCSPI_HWA_WriteData(s_atFCSpiInfo[eInst].tFCSpiInstance, u32TxData); +} +#endif + +/* + * Before call this function, ensure the FCSPI is disabled and in MASTER mode. + * Src Clk -> Prescaler -> sck divider -> SCLK + */ +#define FCSPI_CAL_DISTANCE(x, y) ((x) > (y) ? ((x) - (y)) : ((y) - (x))) +typedef struct { + uint32_t u32CacheTargetBps; + uint32_t u32CacheSrcClkHz; + uint32_t u32CachePrescaleRegVal; + uint32_t u32CacheBps; + uint32_t u32CacheSckDiv; +} FCSPI_BaundrateCacheType; +#define FCSPI_PCS_CLK_CACHE_CNT ((uint8_t)2) + +/* Often use case, just set the same baundrate for specific external device linked with one FCSPI PCS */ +static uint32_t FCSpi_Hw_Master_CalcBaudRate(const FCSPI_MasterCfgType *pCfg, + uint32_t *pdwPrescaleRegVal, uint32_t *pdwActualSckDiv) +{ + uint32_t u32TargetBps = pCfg->u32BitCntPerSecond; + uint32_t u32SrcClkHz = pCfg->u32FCSpiSrcClk; + uint32_t u32TestFreq = 0U; + int16_t s16TestSckDivRegVal = (int16_t)0; + uint8_t u8PrescalerRegVal = (uint8_t)0; + int16_t s16SckDivLow, s16SckDivHigh; + uint32_t u32Prescale = 0U; + uint32_t u32ActualBps = 0U; + uint32_t u32ActualSckDiv = 0U; + uint32_t u32ActualPrescaleRegVal = 0U; + uint32_t u32ThisPrescaleBestBps = 0U; + uint32_t u32ThisPrescaleBestSckDiv = 0U; + uint32_t u32AbsDistance1, u32AbsDistance2; + uint8_t u8Find = (uint8_t)0; + uint32_t u32Ret = 0U; + + if (u32SrcClkHz < (u32TargetBps * 2U)) + { + u32Ret = 0U; + } + else + { + if ((uint8_t)0 == u8Find) + { + u32ActualSckDiv = 0U; + u32ActualPrescaleRegVal = 0U; + u32ActualBps = (uint32_t)(u32SrcClkHz / ((uint32_t)((((uint32_t)1) << + u32ActualPrescaleRegVal) * (u32ActualSckDiv + (uint32_t)2U)))); + + for (u8PrescalerRegVal = (uint8_t)0; u8PrescalerRegVal < FCSPI_PRESCALE_MAX; ++u8PrescalerRegVal) + { + s16SckDivLow = (int16_t)0; + + if ((FCSPI_SCK_SAMPLE_SECOND_EDGE == pCfg->eSckSamplePhase) && /* sample the 2nd edge */ + (FCSPI_FALSE != pCfg->eIsPcsContinuous)) /* continuous pcs */ + { + /* hw bug fix, sck must be 0 */ + s16SckDivHigh = (int16_t)0; + } + else + { + s16SckDivHigh = (int16_t)255; + } + + u32Prescale = ((uint32_t)1) << u8PrescalerRegVal; + u32ThisPrescaleBestSckDiv = 0U; + u32ThisPrescaleBestBps = (uint32_t)(u32SrcClkHz / ((uint32_t)(u32Prescale * + (u32ThisPrescaleBestSckDiv + (uint32_t)2U)))); + + while(s16SckDivHigh > s16SckDivLow) + { + s16TestSckDivRegVal = s16SckDivLow + s16SckDivHigh; + s16TestSckDivRegVal = (s16TestSckDivRegVal / (int16_t)2); + u32TestFreq = (uint32_t)(u32SrcClkHz / + ((uint32_t)(u32Prescale * ((uint32_t)s16TestSckDivRegVal + (uint32_t)2U)))); + + u32AbsDistance1 = FCSPI_CAL_DISTANCE(u32TargetBps, u32ThisPrescaleBestBps); + u32AbsDistance2 = FCSPI_CAL_DISTANCE(u32TargetBps, u32TestFreq); + if (u32AbsDistance1 > u32AbsDistance2) + { + u32ThisPrescaleBestBps = u32TestFreq; + u32ThisPrescaleBestSckDiv = (uint32_t)s16TestSckDivRegVal; + } + + if (u32TestFreq == u32TargetBps) + { + break; + } + else if (u32TestFreq < u32TargetBps) + { + s16SckDivHigh = s16TestSckDivRegVal - 1; + } + else + { + s16SckDivLow = s16TestSckDivRegVal + 1; + } + } + + u32AbsDistance1 = FCSPI_CAL_DISTANCE(u32TargetBps, u32ActualBps); + u32AbsDistance2 = FCSPI_CAL_DISTANCE(u32TargetBps, u32ThisPrescaleBestBps); + if (u32AbsDistance1 > u32AbsDistance2) + { + u32ActualBps = u32ThisPrescaleBestBps; + u32ActualSckDiv = u32ThisPrescaleBestSckDiv; + u32ActualPrescaleRegVal = u8PrescalerRegVal; + } + + if(u32ThisPrescaleBestBps == u32TargetBps) + { + break; + } + } + + if (0U != u32ActualBps) + { + if (NULL != pdwActualSckDiv) + { + *pdwActualSckDiv = u32ActualSckDiv; + } + + if (NULL != pdwPrescaleRegVal) + { + *pdwPrescaleRegVal = u32ActualPrescaleRegVal; + } + } + + /* return the actual calculated baud rate */ + u32Ret = u32ActualBps; + } + } + + return u32Ret; +} + +/* Master/Slave side all use */ + +static void fcspi_read_rx_fifo(FCSPI_InstanceType eInst) +{ + uint32_t u32RxWordData = 0U; + uint16_t u16ByteCount = (uint16_t)0; + uint8_t u8ByteIndex = (uint8_t)0; + uint8_t u8WordCntInRxFifo = FCSPI_HWA_GetRxFifoStoredCount(s_atFCSpiInfo[eInst].tFCSpiInstance); + + while (u8WordCntInRxFifo > (uint8_t)0) + { + u32RxWordData = FCSPI_HWA_ReadData(s_atFCSpiInfo[eInst].tFCSpiInstance); + /* Get the number of bytes which can be read from this 32 bites */ + if (s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed <= + (s_atFCSpiInfo[eInst].tFCSpiStat.u16RxGetByteCntOfCurFrame + (uint16_t)4)) + { + u16ByteCount = (uint16_t)(s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed - + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxGetByteCntOfCurFrame); + } + else + { + u16ByteCount = (uint16_t)4; + } + + /* Generate the word which will be write in buffer. */ + for (u8ByteIndex = (uint8_t)0; u8ByteIndex < u16ByteCount; ++u8ByteIndex) + { + (s_atFCSpiInfo[eInst].tFCSpiStat.pbyRxBuff)[s_atFCSpiInfo[eInst].tFCSpiStat.u16RxIndex] = + (uint8_t)((u32RxWordData >> (uint32_t)((uint32_t)u8ByteIndex * (uint32_t)8)) & (uint8_t)0xFF); + (s_atFCSpiInfo[eInst].tFCSpiStat.u16RxIndex)++; + } + + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxGetByteCntOfCurFrame = + (uint16_t)((s_atFCSpiInfo[eInst].tFCSpiStat.u16RxGetByteCntOfCurFrame + + u16ByteCount) % s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed); + + /* Update internal variable used in transmission. */ + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet = + (uint16_t)(s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet - u16ByteCount); + /* Verify if all bytes were sent. */ + if ((uint16_t)0 == s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet) + { + break; + } + + u8WordCntInRxFifo--; + } +} + +static void fcspi_write_tx_fifo(FCSPI_InstanceType eInst) +{ + uint32_t u32DataToSend = 0U; + uint16_t u16ThisSendByteCnt = (uint16_t)0; + uint8_t u8TxFifoFreeWordCnt = (uint8_t)(s_atFCSpiInfo[eInst].tFCSpiStat.u8TxFifoSize - + (uint8_t)FCSPI_HWA_GetTxFifoStoredCount(s_atFCSpiInfo[eInst].tFCSpiInstance)); + uint16_t u16BytesTxLeft = s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend; + + while ((u8TxFifoFreeWordCnt != (uint8_t)0) && ((uint16_t)0 != u16BytesTxLeft)) + { + if (FCSPI_TRUE == s_atFCSpiInfo[eInst].tFCSpiStat.eIsPcsContinuous) + { + if((uint16_t)1 == s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend) + { + /* Disable continuous PCS */ + FCSpi_Hw_SetContinuousCommand(eInst, FCSPI_FALSE); + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend = (uint16_t)0; + u16BytesTxLeft = (uint16_t)0; + break; + } + } + + /* Get the number of bytes which can be written in a single 32 bits word. */ + if ((s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed - + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxSendByteCntOfCurFrame) <= (uint16_t)4) + { + u16ThisSendByteCnt = (uint16_t)(s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed - + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxSendByteCntOfCurFrame); + } + else + { + u16ThisSendByteCnt = (uint16_t)4; + } + + u32DataToSend = 0U; + + if (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pbyTxBuff) + { + switch(s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed) + { + case 1: + u32DataToSend = *((const uint8_t *)&(s_atFCSpiInfo[eInst].tFCSpiStat.pbyTxBuff[s_atFCSpiInfo[eInst].tFCSpiStat.u16TxIndex])); + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxIndex += sizeof(uint8_t); + break; + + case 2: + u32DataToSend = *((const uint16_t *)&(s_atFCSpiInfo[eInst].tFCSpiStat.pbyTxBuff[s_atFCSpiInfo[eInst].tFCSpiStat.u16TxIndex])); + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxIndex += sizeof(uint16_t); + break; + + default: + u32DataToSend = *((const uint32_t *)&(s_atFCSpiInfo[eInst].tFCSpiStat.pbyTxBuff[s_atFCSpiInfo[eInst].tFCSpiStat.u16TxIndex])); + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxIndex += sizeof(uint32_t); + break; + } + + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxSendByteCntOfCurFrame = + (uint16_t)((s_atFCSpiInfo[eInst].tFCSpiStat.u16TxSendByteCntOfCurFrame + u16ThisSendByteCnt) % + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed); + } + + FCSPI_HWA_WriteData(s_atFCSpiInfo[eInst].tFCSpiInstance, u32DataToSend); + /* Update internal variable used in transmission. */ + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend -= u16ThisSendByteCnt; + u16BytesTxLeft = s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend; + u8TxFifoFreeWordCnt -= (uint8_t)1; + } +} + +/* MASTER side API */ +/*----------------------------------------------------------------------------*/ +/** + * @brief Init the FCSpi instance as spi master side + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Configuration of the FCSpi, MUST NOT NULL + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, some error occur. + */ +FCSPI_StatusType FCSPI_Master_Init(const FCSPI_InstanceType eInst, const FCSPI_MasterCfgType *pCfg) +{ + uint32_t u32BaudRate = 0U; + uint32_t u32PrescaleRegVal = 0U; + uint32_t u32SckDiv = 0U; + FCSPI_TxRxCtrlType tTxRxCtrlCfg; + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + + if (NULL != pCfg) + { + if ((pCfg->u16BitCountPerFrame >= (uint16_t)8) && + (pCfg->u16BitCountPerFrame <= (uint16_t)4096)) /* TR_CTRL[FRM_SZ] 12bits */ + { + u32BaudRate = FCSpi_Hw_Master_CalcBaudRate(pCfg, &u32PrescaleRegVal, &u32SckDiv); + if (0U != u32BaudRate) + { + FCSpi_Hw_Reset(eInst, FCSPI_FALSE, FCSPI_FALSE, FCSPI_TRUE); + FCSPI_HWA_SetMasterMode(s_atFCSpiInfo[eInst].tFCSpiInstance); + FCSpi_Hw_SetPcs_2_3_Mode(eInst, PCS2_3_PCS); + FCSpi_Hw_SetPin(eInst, SIN_INPUT_SOUT_OUTPUT, PINOUT_RETAIN_LAST); + + /* set internal state parameters for spi */ + s_atFCSpiInfo[eInst].tFCSpiStat.u8TxFifoSize = (uint8_t)FCSPI_DRV_TX_FIFO_WORD_CNT; + s_atFCSpiInfo[eInst].tFCSpiStat.u8RxFifoSize = (uint8_t)FCSPI_DRV_RX_FIFO_WORD_CNT; + s_atFCSpiInfo[eInst].tFCSpiStat.u32DmaDummyData = 0U; + s_atFCSpiInfo[eInst].tFCSpiStat.u16BitsPerFrame = pCfg->u16BitCountPerFrame; + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed = (uint16_t)(((pCfg->u16BitCountPerFrame + (uint16_t)7)) >> (uint16_t)3); + s_atFCSpiInfo[eInst].tFCSpiStat.eIsPcsContinuous = pCfg->eIsPcsContinuous; + s_atFCSpiInfo[eInst].tFCSpiStat.u32FCSpiSrcClk = pCfg->u32FCSpiSrcClk; + s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer = FCSPI_FALSE; + s_atFCSpiInfo[eInst].tFCSpiStat.eBitFirstOrder = pCfg->eBitFirstOrder; + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc = pCfg->eTransferTriggerSrc; + s_atFCSpiInfo[eInst].tFCSpiStat.eSckPolarity = pCfg->eSckPolarity; + s_atFCSpiInfo[eInst].tFCSpiStat.eSckSamplePhase = pCfg->eSckSamplePhase; + s_atFCSpiInfo[eInst].tFCSpiStat.ePcs = pCfg->ePcs; + s_atFCSpiInfo[eInst].tFCSpiStat.ePcsPolarity = pCfg->ePcsPolarity; + s_atFCSpiInfo[eInst].tFCSpiStat.u32Baundrate = u32BaudRate; + + /* DMA require frames of 3 bytes per frame handled as 4 bytes per frame. */ + if (s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed == (uint16_t)3) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed = (uint16_t)4; + } + /* 4 bytes align requirement when > 32bits */ + if (s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed > (uint16_t)4) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed = + ((((s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed + (uint16_t)3)) >> (uint16_t)2)) << (uint16_t)2; + } + + s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf = pCfg->tTriggerDmaInf; + s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb = pCfg->pStopNotifyCb; + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaResetCb = pCfg->pSemaResetCb; + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaTakeCb = pCfg->pSemaTakeCb; + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaPostCb = pCfg->pSemaPostCb; + + /* Configure the desired PCS polarity */ + FCSpi_Hw_SetOnePcsPolarity(eInst, pCfg->ePcs, pCfg->ePcsPolarity); + + /* enable sample delay */ + FCSpi_Hw_Master_SetSckLoopbackSample(eInst, FCSPI_TRUE); + + /* set up the baudrate */ + FCSpi_Hw_Set_SCK_PCS_DIV_Hold(eInst, + (uint8_t)(u32SckDiv >> 2U), + (uint8_t)(u32SckDiv >> 2U), + (uint8_t)(u32SckDiv >> 2U), + (uint8_t)u32SckDiv); /* write best baudrate scaler to SCKDIV */ + + /* Write the TCR for this transfer. */ + tTxRxCtrlCfg.eSckPolarity = pCfg->eSckPolarity; + tTxRxCtrlCfg.eSckPhase = pCfg->eSckSamplePhase; + tTxRxCtrlCfg.ePrescalerValue = (FCSPI_PrescaleValueType)u32PrescaleRegVal; + tTxRxCtrlCfg.ePCSSelect = pCfg->ePcs; + tTxRxCtrlCfg.eBitFirstOrder = pCfg->eBitFirstOrder; + tTxRxCtrlCfg.eByteSwap = FCSPI_FALSE; + tTxRxCtrlCfg.eContTransEnable = pCfg->eIsPcsContinuous; + tTxRxCtrlCfg.eContCmdEnable = FCSPI_FALSE; + tTxRxCtrlCfg.eRxDisable = FCSPI_FALSE; + tTxRxCtrlCfg.eTxDisable = FCSPI_FALSE; + tTxRxCtrlCfg.eTransferWidth = FCSPI_TRANSFER_1_BIT; + tTxRxCtrlCfg.u16FrameBitCnt = pCfg->u16BitCountPerFrame; + eRet = FCSpi_Hw_SetTRCR(eInst, &tTxRxCtrlCfg); + + if (FCSPI_STATUS_SUCCESS == eRet) + { + if (FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL != pCfg->eTransferTriggerSrc) + { + IntMgr_EnableInterrupt(s_atFCSpiInfo[eInst].eFCSpiIrq); + } + + FCSPI_HWA_ModuleEnable(s_atFCSpiInfo[eInst].tFCSpiInstance); + } + else + { + eRet = FCSPI_STATUS_ERROR; + } + } + else + { + eRet = FCSPI_STATUS_ERROR; + } + } + else + { + eRet = FCSPI_STATUS_PARAM_ERR; + } + } + else + { + eRet = FCSPI_STATUS_PARAM_ERR; + } + + return eRet; +} + +/** + * @brief Deinit the FCSpi + * + * @param eInst Which FCSpi Hardware instance + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when deinit the FCSpi successfully. Others, the hardware is busy now. + */ +FCSPI_StatusType FCSPI_Deinit(const FCSPI_InstanceType eInst) +{ + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + + if (FCSPI_TRUE != s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer) + { + /* reset registers, disabling spi module */ + FCSpi_Hw_Reset(eInst, FCSPI_FALSE, FCSPI_FALSE, FCSPI_TRUE); + } + else + { + eRet = FCSPI_STATUS_BUSY; + } + + return eRet; +} + +/** + * @brief Configure the holding time (in us) between PCS and SCK + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Configure the delay parameters between PCS and SCK, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, the hardware is busy now. + */ +FCSPI_StatusType FCSPI_Master_SetSckPcsHoldTime(const FCSPI_InstanceType eInst, + const FCSPI_MasterSckPcsHoldTimeType *pCfg) +{ + FCSPI_StatusType eStat = FCSPI_STATUS_SUCCESS; + uint32_t u32PCSPCSCycle, + u32SCKPCSCycle, + u32PCSSCKCycle; + FCSPI_PrescaleValueType ePrescaler; + uint32_t u32PrescaleValue; + uint32_t u32ClkAfterScalePerUs; + + if (NULL != pCfg) + { + /* disable FCSPI first */ + eStat = FCSpi_Hw_Disable(eInst); + if (FCSPI_STATUS_SUCCESS == eStat) + { + ePrescaler = FCSpi_Hw_GetRegPrescalerVal(eInst); + u32PrescaleValue = FCSpi_Hw_PrescalerRegToActualVal(ePrescaler); + if (0U != u32PrescaleValue) /* actually unreachable */ + { + u32ClkAfterScalePerUs = (uint32_t)(s_atFCSpiInfo[eInst].tFCSpiStat.u32FCSpiSrcClk / + u32PrescaleValue / (uint32_t)1000000); + u32PCSPCSCycle = pCfg->u32PCStoPCSHoldUs * u32ClkAfterScalePerUs; + u32SCKPCSCycle = pCfg->u32SCKtoPCSHoldUs * u32ClkAfterScalePerUs; + u32PCSSCKCycle = pCfg->u32PCStoSCKHoldUs * u32ClkAfterScalePerUs; + + if (u32PCSPCSCycle > (uint32_t)257U) + { + u32PCSPCSCycle = (uint32_t)257U; + } + + if(u32SCKPCSCycle > (uint32_t)256U) + { + u32SCKPCSCycle = (uint32_t)256U; + } + + if(u32PCSSCKCycle > (uint32_t)256U) + { + u32PCSSCKCycle = (uint32_t)256U; + } + + if (u32PCSPCSCycle < (uint32_t)2U) + { + u32PCSPCSCycle = (uint32_t)2U; + } + + if(u32SCKPCSCycle == (uint32_t)0) + { + u32SCKPCSCycle = (uint32_t)1U; + } + + if(u32PCSSCKCycle == (uint32_t)0U) + { + u32PCSSCKCycle = (uint32_t)1U; + } + + FCSpi_Hw_Set_SCK_PCS_Hold(eInst, + (uint8_t)(u32SCKPCSCycle - 1U), + (uint8_t)(u32PCSSCKCycle - 1U), + (uint8_t)(u32PCSPCSCycle - 2U)); + /* Enable module */ + FCSPI_HWA_ModuleEnable(s_atFCSpiInfo[eInst].tFCSpiInstance); + } + else + { + eStat = FCSPI_STATUS_ERROR; + } + } + else + { + eStat = FCSPI_STATUS_BUSY; + } + } + else + { + eStat = FCSPI_STATUS_PARAM_ERR; + } + + return eStat; +} + +/** + * @brief Configure the holding time (in SCK/100) between PCS and SCK + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Configure the delay parameters between PCS and SCK, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, the hardware is busy now. + */ +FCSPI_StatusType FCSPI_Master_SetSckPcsHoldSckPercentage( + const FCSPI_InstanceType eInst, const FCSPI_MasterSckPcsHoldSckCycleType *pCfg) +{ + uint8_t u8PCSPCSCycle; + uint8_t u8SCKPCSCycle; + uint8_t u8PCSSCKCycle; + uint8_t u8SckDiv; + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + + if (NULL != pCfg) + { + /* disable FCSPI first */ + eRet = FCSpi_Hw_Disable(eInst); + if (FCSPI_STATUS_SUCCESS == eRet) + { + FCSpi_Hw_Get_SCK_PCS_DIV_Hold(eInst, NULL, NULL, NULL, &u8SckDiv); + + u8PCSPCSCycle = (uint8_t)((uint32_t)pCfg->u32PCStoPCSHoldPercentage * + (uint32_t)u8SckDiv / (uint32_t)100); + u8SCKPCSCycle = (uint8_t)((uint32_t)pCfg->u32SCKtoPCSHoldPercentage * + (uint32_t)u8SckDiv / (uint32_t)100); + u8PCSSCKCycle = (uint8_t)((uint32_t)pCfg->u32PCStoSCKHoldPercentage * + (uint32_t)u8SckDiv / (uint32_t)100); + + if (u8PCSPCSCycle < (uint8_t)2) + { + u8PCSPCSCycle = (uint8_t)2; + } + + if(u8SCKPCSCycle == (uint8_t)0) + { + u8SCKPCSCycle = (uint8_t)1; + } + + if(u8PCSSCKCycle == (uint8_t)0) + { + u8PCSSCKCycle = (uint8_t)1; + } + + FCSpi_Hw_Set_SCK_PCS_Hold(eInst, + (uint8_t)(u8SCKPCSCycle - (uint8_t)1), + (uint8_t)(u8PCSSCKCycle - (uint8_t)1), + (uint8_t)(u8PCSPCSCycle - (uint8_t)2)); + /* Enable module */ + FCSPI_HWA_ModuleEnable(s_atFCSpiInfo[eInst].tFCSpiInstance); + } + else + { + eRet = FCSPI_STATUS_BUSY; + } + } + else + { + eRet = FCSPI_STATUS_PARAM_ERR; + } + + return eRet; +} + +/** + * @brief Select the PCS to use and configure + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Parameters about PCS configuration, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, the hardware is busy now. + */ +FCSPI_StatusType FCSPI_Master_SelectPcs( + const FCSPI_InstanceType eInst, const FCSPI_MasterPcsConfType *pCfg) +{ + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + + if (pCfg) + { + eRet = FCSpi_Hw_Disable(eInst); + if (FCSPI_STATUS_SUCCESS == eRet) + { + FCSpi_Hw_SetOnePcsPolarity(eInst, pCfg->ePcs, pCfg->ePolarity); + FCSPI_HWA_ModuleEnable(s_atFCSpiInfo[eInst].tFCSpiInstance); + FCSpi_Hw_SelectUsePcs(eInst, pCfg->ePcs); + } + else + { + eRet = FCSPI_STATUS_BUSY; + } + } + else + { + eRet = FCSPI_STATUS_PARAM_ERR; + } + + return eRet; +} + +static void fcspi_master_clean_transfer(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInInterrupt) +{ + s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer = FCSPI_FALSE; + + if (FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc) + { + FCSpi_Hw_SetRxTxDmaEnableStatus(eInst, FCSPI_FALSE, FCSPI_FALSE); + } + else + { + FCSpi_Hw_DisableSomeInterrupts(eInst, + FCSPI_INT_EN_RFIE(1) | FCSPI_INT_EN_TFIE(1)); + } + + FCSpi_Hw_DisableSomeInterrupts(eInst, + FCSPI_INT_EN_RFOIE(1) | FCSPI_INT_EN_TFUIE(1) | FCSPI_INT_EN_TCIE(1)); + FCSpi_Hw_ClearSomeStatusW1CFlag(eInst, + FCSPI_STATUS_RX_FO(1) | FCSPI_STATUS_TX_FU(1) | FCSPI_STATUS_TCF(1)); + + if (FCSPI_TRUE == bIsInInterrupt) + { + if (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb(eInst, FCSPI_TRUE); + } + + if (s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaPostCb(eInst, FCSPI_TRUE); + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)0; + } + } + else + { + if (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb(eInst, FCSPI_FALSE); + } + + if (s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaPostCb(eInst, FCSPI_FALSE); + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)0; + } + } +} + +static void fcspi_master_abort_transfer(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInISR) +{ + fcspi_master_clean_transfer(eInst, bIsInISR); + + /* clean the fifo */ + FCSpi_Hw_Reset(eInst, FCSPI_TRUE, FCSPI_TRUE, FCSPI_FALSE); + FCSpi_Hw_Reset(eInst, FCSPI_TRUE, FCSPI_TRUE, FCSPI_FALSE); /* for shifter */ +} + +static void fcspi_master_dma_rx_err_interrupt(FCSPI_InstanceType eInst) +{ + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_RX_FAIL; + fcspi_master_abort_transfer(eInst, FCSPI_TRUE); +} + +static void fcspi_0_master_dma_rx_err_interrupt(void) +{ + fcspi_master_dma_rx_err_interrupt(FCSPI_0); +} + +static void fcspi_1_master_dma_rx_err_interrupt(void) +{ + fcspi_master_dma_rx_err_interrupt(FCSPI_1); +} + +static void fcspi_2_master_dma_rx_err_interrupt(void) +{ + fcspi_master_dma_rx_err_interrupt(FCSPI_2); +} + +static void fcspi_3_master_dma_rx_err_interrupt(void) +{ + fcspi_master_dma_rx_err_interrupt(FCSPI_3); +} + +static void fcspi_4_master_dma_rx_err_interrupt(void) +{ + fcspi_master_dma_rx_err_interrupt(FCSPI_4); +} + +static void fcspi_5_master_dma_rx_err_interrupt(void) +{ + fcspi_master_dma_rx_err_interrupt(FCSPI_5); +} + +static void fcspi_master_dma_rx_finish_interrupt(void) +{ + ; /* in master mode, the tx trigger the sclk output, so when rx finish, ignore. */ +} + +static void fcspi_master_dma_tx_err_interrupt(FCSPI_InstanceType eInst) +{ + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_TX_FAIL; + fcspi_master_abort_transfer(eInst, FCSPI_TRUE); +} + +static void fcspi_0_master_dma_tx_err_interrupt(void) +{ + fcspi_master_dma_tx_err_interrupt(FCSPI_0); +} + +static void fcspi_1_master_dma_tx_err_interrupt(void) +{ + fcspi_master_dma_tx_err_interrupt(FCSPI_1); +} + +static void fcspi_2_master_dma_tx_err_interrupt(void) +{ + fcspi_master_dma_tx_err_interrupt(FCSPI_2); +} + +static void fcspi_3_master_dma_tx_err_interrupt(void) +{ + fcspi_master_dma_tx_err_interrupt(FCSPI_3); +} + +static void fcspi_4_master_dma_tx_err_interrupt(void) +{ + fcspi_master_dma_tx_err_interrupt(FCSPI_4); +} + +static void fcspi_5_master_dma_tx_err_interrupt(void) +{ + fcspi_master_dma_tx_err_interrupt(FCSPI_5); +} + +static void fcspi_master_dma_tx_finish_interrupt(FCSPI_InstanceType eInst) +{ + if (FCSPI_TRUE == s_atFCSpiInfo[eInst].tFCSpiStat.eIsPcsContinuous) + { + FCSpi_Hw_SetContinuousCommand(eInst, FCSPI_FALSE); + } + + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend = (uint16_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet = (uint16_t)0; + + /* DMA -> TX FIFO -> PIN, DMA send to tx fifo finish, enable tx fifo finish interrupt */ + FCSpi_Hw_EnableTransmitCompleteInterrupt(eInst); +} + +static void fcspi_0_master_dma_tx_finish_interrupt(void) +{ + fcspi_master_dma_tx_finish_interrupt(FCSPI_0); +} + +static void fcspi_1_master_dma_tx_finish_interrupt(void) +{ + fcspi_master_dma_tx_finish_interrupt(FCSPI_1); +} + +static void fcspi_2_master_dma_tx_finish_interrupt(void) +{ + fcspi_master_dma_tx_finish_interrupt(FCSPI_2); +} + +static void fcspi_3_master_dma_tx_finish_interrupt(void) +{ + fcspi_master_dma_tx_finish_interrupt(FCSPI_3); +} + +static void fcspi_4_master_dma_tx_finish_interrupt(void) +{ + fcspi_master_dma_tx_finish_interrupt(FCSPI_4); +} + +static void fcspi_5_master_dma_tx_finish_interrupt(void) +{ + fcspi_master_dma_tx_finish_interrupt(FCSPI_5); +} + +/* if enter transfer state, return success, others, not start tranfer */ +static FCSPI_StatusType fcspi_master_async_transfer_bytes(FCSPI_InstanceType eInst, + const uint8_t *pSendBuffer, uint8_t *pReceiveBuffer, + uint16_t u16TransferByteCnt) +{ + DMA_InterruptCfgType tDmaTxInterruptCfg = {0}; + DMA_ChannelCfgType tDmaTxChnlCfg = {0}; + uint8_t u8DmaTxBlkByteCnt = (uint8_t)1; + DMA_InterruptCfgType tDmaRxInterruptCfg = {0}; + DMA_ChannelCfgType tDmaRxChnlCfg = {0}; + uint8_t u8DmaRxBlkByteCnt = (uint8_t)1; + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + uint32_t u32StatRegVal = 0u; + + if ((uint16_t)0 != s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed) + { + if ((uint16_t)0 != u16TransferByteCnt) + { + if ((u16TransferByteCnt % s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed) == (uint16_t)0) + { + u32StatRegVal = FCSPI_HWA_GetStatus(s_atFCSpiInfo[eInst].tFCSpiInstance); + if ((FCSPI_TRUE != s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer) && + (!FCSpi_Hw_ChkBusy(u32StatRegVal))) + { + if (!FCSpi_Hw_ChkBusy(FCSPI_HWA_GetStatus(s_atFCSpiInfo[eInst].tFCSpiInstance))) + { + FCSpi_Hw_Reset(eInst, FCSPI_TRUE, FCSPI_TRUE, FCSPI_FALSE); + FCSpi_Hw_Reset(eInst, FCSPI_TRUE, FCSPI_TRUE, FCSPI_FALSE); /* ensure clear data in shifter */ + + /* if pcs need continuous, set command continuous bit */ + if (s_atFCSpiInfo[eInst].tFCSpiStat.eIsPcsContinuous) + { + FCSpi_Hw_SetContinuousCommand(eInst, FCSPI_TRUE); + } + + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_OK; + + FCSPI_HWA_SetWatermark(s_atFCSpiInfo[eInst].tFCSpiInstance, (uint8_t)0, (uint8_t)2); + + FCSpi_Hw_ClearSomeStatusW1CFlag(eInst, FCSPI_DRV_STATUS_REG_W1C_U32); + FCSpi_Hw_EnableMoreInterrupts(eInst, FCSPI_INT_EN_TFUIE(1)); + + /* if rx needed, enable overflow interrupt and rx */ + if (NULL != pReceiveBuffer) + { + FCSpi_Hw_EnableMoreInterrupts(eInst, FCSPI_INT_EN_RFOIE(1)); + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet = u16TransferByteCnt; + FCSPI_HWA_EnableRxDataMask(s_atFCSpiInfo[eInst].tFCSpiInstance, FCSPI_TRUE); + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet = (uint16_t)0; + FCSPI_HWA_EnableRxDataMask(s_atFCSpiInfo[eInst].tFCSpiInstance, FCSPI_FALSE); + } + + if (FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc) + { + /* TX */ + tDmaTxChnlCfg.u8ChannelPriority = s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8TxDMAChannelPriority; + tDmaTxChnlCfg.bDestAddrLoopbackEn = false; + tDmaTxChnlCfg.bSrcAddrLoopbackEn = false; + tDmaTxChnlCfg.bAutoStop = true; /* auto stop dma after send finish */ + tDmaTxChnlCfg.bSrcCircularBufferEn = false; + tDmaTxChnlCfg.bDestCircularBufferEn = false; + + switch (s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed) + { + case 1: + tDmaTxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_1B; + tDmaTxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_1B; + tDmaTxChnlCfg.bSrcBlockOffsetEn = true; + tDmaTxChnlCfg.s32BlockOffset = (int32_t)1; + u8DmaTxBlkByteCnt = (uint8_t)1; + break; + + case 2: + tDmaTxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_2B; + tDmaTxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_2B; + tDmaTxChnlCfg.bSrcBlockOffsetEn = true; + tDmaTxChnlCfg.s32BlockOffset = (int32_t)2; + u8DmaTxBlkByteCnt = (uint8_t)2; + break; + + default: + tDmaTxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B; + tDmaTxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_4B; + tDmaTxChnlCfg.bSrcBlockOffsetEn = true; + tDmaTxChnlCfg.s32BlockOffset = (int32_t)4; + u8DmaTxBlkByteCnt = (uint8_t)4; + break; + } + + tDmaTxChnlCfg.u16BlockCount = u16TransferByteCnt / u8DmaTxBlkByteCnt; + tDmaTxChnlCfg.bDestBlockOffsetEn = false; + + tDmaTxInterruptCfg.bTransferCompleteIntEn = true; + tDmaTxInterruptCfg.bTransferErrorIntEn = true; + switch (eInst) + { + case FCSPI_0: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI0_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_0_master_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_0_master_dma_tx_err_interrupt; + break; + + case FCSPI_1: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI1_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_1_master_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_1_master_dma_tx_err_interrupt; + break; + + case FCSPI_2: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI2_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_2_master_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_2_master_dma_tx_err_interrupt; + break; + + case FCSPI_3: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI3_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_3_master_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_3_master_dma_tx_err_interrupt; + break; + + case FCSPI_4: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI4_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_4_master_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_4_master_dma_tx_err_interrupt; + break; + + case FCSPI_5: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI5_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_5_master_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_5_master_dma_tx_err_interrupt; + break; + + default: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI3_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_3_master_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_3_master_dma_tx_err_interrupt; + break; + } + + tDmaTxChnlCfg.eDestIncMode = DMA_INCREMENT_DISABLE; + tDmaTxChnlCfg.eSrcIncMode = DMA_INCREMENT_DISABLE; + tDmaTxChnlCfg.pDestBuffer = FCSPI_HWA_GetTxDataAddr(s_atFCSpiInfo[eInst].tFCSpiInstance); + tDmaTxChnlCfg.u32BlockSize = (uint32_t)u8DmaTxBlkByteCnt; + + if (NULL != pSendBuffer) + { + tDmaTxChnlCfg.pSrcBuffer = pSendBuffer; + } + else + { + tDmaTxChnlCfg.pSrcBuffer = &(s_atFCSpiInfo[eInst].tFCSpiStat.u32DmaDummyData); + tDmaTxChnlCfg.bSrcBlockOffsetEn = false; /* if send buffer is NULL, just send dummy data, MUST fix the source to the dummy variable */ + tDmaTxChnlCfg.s32BlockOffset = (int32_t)0; + } + + DMA_InitChannel(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8TxDMAChannel, &tDmaTxChnlCfg); + + /* RX */ + /* if needed, configure the DMA Rx function */ + if (NULL != pReceiveBuffer) + { + tDmaRxChnlCfg.u8ChannelPriority = s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8RxDMAChannelPriority; + tDmaRxChnlCfg.bDestAddrLoopbackEn = false; + tDmaRxChnlCfg.bSrcAddrLoopbackEn = false; + tDmaRxChnlCfg.bAutoStop = true; /* auto stop dma after send finish */ + tDmaRxChnlCfg.bSrcCircularBufferEn = false; + tDmaRxChnlCfg.bDestCircularBufferEn = false; + + switch (s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed) + { + case 1: + tDmaRxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_1B; + tDmaRxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_1B; + tDmaRxChnlCfg.bDestBlockOffsetEn = true; + tDmaRxChnlCfg.s32BlockOffset = (int32_t)1; + u8DmaRxBlkByteCnt = (uint8_t)1; + break; + + case 2: + tDmaRxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_2B; + tDmaRxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_2B; + tDmaRxChnlCfg.bDestBlockOffsetEn = true; + tDmaRxChnlCfg.s32BlockOffset = (int32_t)2; + u8DmaRxBlkByteCnt = (uint8_t)2; + break; + + default: + tDmaRxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_4B; + tDmaRxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B; + tDmaRxChnlCfg.bDestBlockOffsetEn = true; + tDmaRxChnlCfg.s32BlockOffset = (int32_t)4; + u8DmaRxBlkByteCnt = (uint8_t)4; + break; + } + + tDmaRxChnlCfg.u16BlockCount = u16TransferByteCnt / u8DmaRxBlkByteCnt; + tDmaRxChnlCfg.bSrcBlockOffsetEn = false; + + tDmaRxInterruptCfg.bTransferCompleteIntEn = true; + tDmaRxInterruptCfg.bTransferErrorIntEn = true; + switch (eInst) + { + case FCSPI_0: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI0_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_master_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_0_master_dma_rx_err_interrupt; + break; + + case FCSPI_1: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI1_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_master_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_1_master_dma_rx_err_interrupt; + break; + + case FCSPI_2: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI2_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_master_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_2_master_dma_rx_err_interrupt; + break; + + case FCSPI_3: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI3_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_master_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_3_master_dma_rx_err_interrupt; + break; + + case FCSPI_4: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI4_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_master_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_4_master_dma_rx_err_interrupt; + break; + + case FCSPI_5: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI5_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_master_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_5_master_dma_rx_err_interrupt; + break; + + default: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI3_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_master_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_3_master_dma_rx_err_interrupt; + break; + } + + tDmaRxChnlCfg.eDestIncMode = DMA_INCREMENT_DISABLE; + tDmaRxChnlCfg.eSrcIncMode = DMA_INCREMENT_DISABLE; + tDmaRxChnlCfg.pSrcBuffer = FCSPI_HWA_GetRxDataAddr(s_atFCSpiInfo[eInst].tFCSpiInstance); + tDmaRxChnlCfg.u32BlockSize = (uint32_t)u8DmaRxBlkByteCnt; + tDmaRxChnlCfg.pDestBuffer = pReceiveBuffer; + + DMA_InitChannel(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8RxDMAChannel, &tDmaRxChnlCfg); + DMA_InitChannelInterrupt(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8RxDMAChannel, &tDmaRxInterruptCfg); + DMA_StartChannel(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8RxDMAChannel); + } + + DMA_InitChannelInterrupt(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8TxDMAChannel, &tDmaTxInterruptCfg); + + DMA_StartChannel(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8TxDMAChannel); + + s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer = FCSPI_TRUE; + + if (pReceiveBuffer) + { + FCSpi_Hw_SetRxTxDmaEnableStatus(eInst, FCSPI_TRUE, FCSPI_TRUE); + } + else + { + /* only enable TX DMA */ + FCSpi_Hw_SetRxTxDmaEnableStatus(eInst, FCSPI_FALSE, FCSPI_TRUE); + } + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.pbyTxBuff = pSendBuffer; + s_atFCSpiInfo[eInst].tFCSpiStat.pbyRxBuff = pReceiveBuffer; + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxIndex = (uint16_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxIndex = (uint16_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxSendByteCntOfCurFrame = (uint16_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxGetByteCntOfCurFrame = (uint16_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend = u16TransferByteCnt; + if (FCSPI_TRUE == s_atFCSpiInfo[eInst].tFCSpiStat.eIsPcsContinuous) + { + /* continuous transfer need an extra word to negate PCS */ + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend++; + } + s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer = FCSPI_TRUE; + + if (NULL != pReceiveBuffer) /* need rx fifo */ + { + FCSpi_Hw_EnableMoreInterrupts(eInst, FCSPI_INT_EN_RFIE(1) | FCSPI_INT_EN_TFIE(1)); + } + else + { + FCSpi_Hw_EnableMoreInterrupts(eInst, FCSPI_INT_EN_TFIE(1)); + } + } + eRet = FCSPI_STATUS_SUCCESS; + } + else + { + eRet = FCSPI_STATUS_BUSY; + } + } + else + { + eRet = FCSPI_STATUS_BUSY; + } + } + else + { + eRet = FCSPI_STATUS_ERROR; + } + } + else + { + eRet = FCSPI_STATUS_NO_DATA; + } + } + else + { + eRet = FCSPI_STATUS_ERROR; + } + + return eRet; +} + +/** + * @brief Send and receive asynchronously + * 1) If the trigger source is driver user poll, this api not support this mode. + * 2) If the trigger source is interrupt or DMA, this api will start the transmission, then return immediately. + * After transmission stop, it will trigger an interrupt. + * During the transmission, the send data buffer and receive data buffer + * should keep valid until the transmission stop. + * @param eInst Which FCSpi Hardware instance + * @param pCfg the data information, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when start transfer successfully. Others, some error occur. + */ +FCSPI_StatusType FCSPI_AsyncTransfer(const FCSPI_InstanceType eInst, const FCSPI_AsyncDataInfType *pCfg) +{ + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + + if (NULL != pCfg) + { + if (FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL != s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc) + { + if (FCSPI_MODE_MASTER == FCSPI_HWA_CheckMode(s_atFCSpiInfo[eInst].tFCSpiInstance)) + { + eRet = fcspi_master_async_transfer_bytes(eInst, + pCfg->pSendBuffer, pCfg->pReceiveBuffer, + pCfg->u16FrameCount * s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed); + } + else + { + eRet = fcspi_slave_async_transfer_bytes(eInst, pCfg->pSendBuffer, pCfg->pReceiveBuffer, + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed * pCfg->u16FrameCount); + } + } + else + { + eRet = FCSPI_STATUS_ERROR; + } + } + else + { + eRet = FCSPI_STATUS_PARAM_ERR; + } + + return eRet; +} + +/** + * @brief Send and receive synchronously + * 1) If the semaphore callbacks are configured, + * and the driver is configured transmitting triggered by interrupt, or by DMA, + * the driver will use semaphore to wait the transmission stopped. + * In this case, the timeout value is passed to semaphore callback directly. + * 2) If the semaphore callbacks are not configured, + * this api will poll the status when triggered by interrupt or DMA, + * or poll to trigger the transmission when the mode is "FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL". + * In this case, the timeout value has different meaning for different trigger mode. + * Read the source code for detail. + * @param eInst Which FCSpi Hardware instance + * @param pCfg the data information, MUST NOT null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when transfer successfully. Others, some error occur. + */ +FCSPI_StatusType FCSPI_SyncTransfer(const FCSPI_InstanceType eInst, const FCSPI_SyncDataInfType *pCfg) +{ + FCSPI_StatusType tStatus; + FCSPI_SemaphoreStatType tSemaStat; + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + FCSPI_AtomicBoolType bIsMaster; + uint32_t u32MonitorTimeout = 0xFFFFFFFFu; + uint16_t u16RxRemain = (uint16_t)0; + uint16_t u16TxRemain = (uint16_t)0; + uint16_t u16PreRxRemain = (uint16_t)0; + uint16_t u16PreTxRemain = (uint16_t)0; + uint32_t u32TryTimeout = 0xFFFFFFFFu; + FCSPI_AtomicBoolType bIsBlockType = FCSPI_TRUE; + bIsMaster = (FCSPI_MODE_MASTER == FCSPI_HWA_CheckMode(s_atFCSpiInfo[eInst].tFCSpiInstance)) ? FCSPI_TRUE : FCSPI_FALSE; + FCSPI_AtomicBoolType bNeedExitLoop = FCSPI_FALSE; + + if (NULL != pCfg) + { + if ((uint16_t)0 != pCfg->u16FrameCount) + { + if ((NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pSemaResetCb) && + (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pSemaTakeCb) && + (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pSemaPostCb) && + ((FCSPI_TRANSFER_TRIGGER_SRC_ISR == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc) || + (FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc))) + { + if (FCSPI_SEMAPHORE_SUCCESS == s_atFCSpiInfo[eInst].tFCSpiStat.pSemaResetCb(eInst)) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)1; + + if (FCSPI_TRUE == bIsMaster) + { + tStatus = fcspi_master_async_transfer_bytes(eInst, pCfg->pSendBuffer, pCfg->pReceiveBuffer, + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed * pCfg->u16FrameCount); + } + else + { + tStatus = fcspi_slave_async_transfer_bytes(eInst, pCfg->pSendBuffer, pCfg->pReceiveBuffer, + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed * pCfg->u16FrameCount); + } + + if (FCSPI_STATUS_SUCCESS == tStatus) + { + tSemaStat = s_atFCSpiInfo[eInst].tFCSpiStat.pSemaTakeCb(eInst, pCfg->u32Timeout); + if (FCSPI_SEMAPHORE_FAIL == tSemaStat) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_ABORT; + if (FCSPI_TRUE == bIsMaster) + { + fcspi_master_abort_transfer(eInst, FCSPI_FALSE); + } + else + { + fcspi_slave_abort_transfer(eInst, FCSPI_FALSE); + } + + eRet = FCSPI_STATUS_ERROR; + } + else if (FCSPI_SEMAPHORE_TIMEOUT == tSemaStat) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_ABORT; + if (FCSPI_TRUE == bIsMaster) + { + fcspi_master_abort_transfer(eInst, FCSPI_FALSE); + } + else + { + fcspi_slave_abort_transfer(eInst, FCSPI_FALSE); + } + eRet = FCSPI_STATUS_SYNC_TIMEOUT; + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)0; + if (FCSPI_TRANSFER_OK != s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat) + { + eRet = FCSPI_STATUS_TRANSFER_FAIL; + } + else + { + eRet = FCSPI_STATUS_SUCCESS; + } + } + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)0; + eRet = tStatus; + } + } + else + { + eRet = FCSPI_STATUS_ERROR; + } + } + else + { + if (FCSPI_TRUE == bIsMaster) + { + tStatus = fcspi_master_async_transfer_bytes(eInst, pCfg->pSendBuffer, pCfg->pReceiveBuffer, + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed * pCfg->u16FrameCount); + } + else + { + tStatus = fcspi_slave_async_transfer_bytes(eInst, pCfg->pSendBuffer, pCfg->pReceiveBuffer, + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed * pCfg->u16FrameCount); + } + + if (FCSPI_STATUS_SUCCESS == tStatus) + { + if (pCfg->u32Timeout > 0u) + { + u32TryTimeout = pCfg->u32Timeout; + bIsBlockType = FCSPI_FALSE; + } + else + { + bIsBlockType = FCSPI_TRUE; + } + + if (FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc) + { + if (FCSPI_TRUE == bIsMaster) + { + do { + eRet = fcspi_master_trigger(eInst, FCSPI_FALSE); + if (FCSPI_FALSE == bIsBlockType) + { + u32TryTimeout--; + if (0u == u32TryTimeout) + { + break; + } + } + } while (FCSPI_STATUS_TRIGGER_OK == eRet); + } + else + { + do { + eRet = fcspi_slave_trigger(eInst, FCSPI_FALSE); + + if (FCSPI_FALSE == bIsBlockType) + { + u32TryTimeout--; + if (0u == u32TryTimeout) + { + break; + } + } + } while (FCSPI_STATUS_TRIGGER_OK == eRet); + } + + if (FCSPI_STATUS_TRIGGER_FINISH == eRet) + { + eRet = FCSPI_STATUS_SUCCESS; + } + else if ((FCSPI_FALSE == bIsBlockType) && (0u == u32TryTimeout)) + { + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_ABORT; + if (FCSPI_TRUE == bIsMaster) + { + fcspi_master_abort_transfer(eInst, FCSPI_FALSE); + } + else + { + fcspi_slave_abort_transfer(eInst, FCSPI_FALSE); + } + eRet = FCSPI_STATUS_SYNC_TIMEOUT; + } + else + { + eRet = FCSPI_STATUS_TRANSFER_FAIL; + } + } + else if ((FCSPI_TRANSFER_TRIGGER_SRC_ISR == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc) || + (FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc)) + { + u32MonitorTimeout = 0xfffff00u; /* ensure 1s */ + + u16PreRxRemain = s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet; + u16PreTxRemain = s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend; + + while (FCSPI_TRUE == s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer) + { + u32MonitorTimeout--; + if (0u == u32MonitorTimeout) + { + bNeedExitLoop = FCSPI_FALSE; + u16RxRemain = s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet; + u16TxRemain = s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend; + if (((u16PreRxRemain == u16RxRemain) && ((uint16_t)0 != u16RxRemain)) || + ((u16PreTxRemain == u16TxRemain) && ((uint16_t)0 != u16TxRemain))) + { + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_ABORT; + if (FCSPI_TRUE == bIsMaster) + { + fcspi_master_abort_transfer(eInst, FCSPI_FALSE); + } + else + { + fcspi_slave_abort_transfer(eInst, FCSPI_FALSE); + } + + bNeedExitLoop = FCSPI_TRUE; + } + else + { + u16PreRxRemain = u16RxRemain; + u16PreTxRemain = u16TxRemain; + u32MonitorTimeout = 0xfffff00u; + + if (FCSPI_FALSE == bIsBlockType) + { + u32TryTimeout--; + if (0u == u32TryTimeout) + { + bNeedExitLoop = FCSPI_TRUE; + } + } + } + + if (FCSPI_TRUE == bNeedExitLoop) + { + break; + } + } + } + + if ((FCSPI_FALSE == bIsBlockType) && (0u == u32TryTimeout)) + { + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_ABORT; + if (FCSPI_TRUE == bIsMaster) + { + fcspi_master_abort_transfer(eInst, FCSPI_FALSE); + } + else + { + fcspi_slave_abort_transfer(eInst, FCSPI_FALSE); + } + eRet = FCSPI_STATUS_SYNC_TIMEOUT; + } + else if (FCSPI_TRANSFER_OK == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat) + { + eRet = FCSPI_STATUS_SUCCESS; + } + else + { + eRet = FCSPI_STATUS_TRANSFER_FAIL; + } + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_ABORT; + if (FCSPI_TRUE == bIsMaster) + { + fcspi_master_abort_transfer(eInst, FCSPI_FALSE); + } + else + { + fcspi_slave_abort_transfer(eInst, FCSPI_FALSE); + } + + eRet = FCSPI_STATUS_TRANSFER_FAIL; + } + } + else + { + eRet = tStatus; + } + } + } + else + { + eRet = FCSPI_STATUS_SUCCESS; + } + } + else + { + eRet = FCSPI_STATUS_PARAM_ERR; + } + + return eRet; +} + +static FCSPI_StatusType fcspi_master_trigger( + FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInIsr) +{ + uint32_t u32StatusRegValue; + FCSPI_StatusType eRet = FCSPI_STATUS_TRIGGER_OK; + + /* if an error is detected the transfer will be aborted */ + u32StatusRegValue = FCSPI_HWA_GetStatus(s_atFCSpiInfo[eInst].tFCSpiInstance); + + /* if tx need more data but hungry, and has data, sth wrong */ + if (FCSpi_Hw_ChkTxFifoUnderrun(u32StatusRegValue) && + (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pbyTxBuff)) + { + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_TX_FAIL; + fcspi_master_abort_transfer(eInst, bIsInIsr); + eRet = FCSPI_STATUS_TRIGGER_ABORT_TX_FAIL; + } + /* if rx need more space but overflow, and has space to store, sth wrong */ + else if (FCSpi_Hw_ChkRxFifoOverflow(u32StatusRegValue) && + (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pbyRxBuff)) + { + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_RX_FAIL; + fcspi_master_abort_transfer(eInst, bIsInIsr); + eRet = FCSPI_STATUS_TRIGGER_ABORT_RX_FAIL; + } + /* rx data ready */ + else + { + if (FCSpi_Hw_ChkRxGreaterThanWater(u32StatusRegValue)) + { + if ((uint16_t)0 != s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet) + { + fcspi_read_rx_fifo(eInst); + } + } + + /* transmit some, need add more */ + if (FCSpi_Hw_ChkTxEqualOrLessThanWater(u32StatusRegValue)) + { + if ((uint16_t)0 != s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend) + { + fcspi_write_tx_fifo(eInst); + } + } + + if ((uint16_t)0 == s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend) + { + /* disable tx interrupt. enable tx completion interrupt.*/ + FCSpi_Hw_DisableTransmitDataInterrupt(eInst); + FCSpi_Hw_EnableTransmitCompleteInterrupt(eInst); + + /* tx finish first, if rx also finish, just check completion */ + if ((uint16_t)0 == s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet) + { + u32StatusRegValue = FCSPI_HWA_GetStatus(s_atFCSpiInfo[eInst].tFCSpiInstance); + if (FCSpi_Hw_ChkTransferComplete(u32StatusRegValue)) + { + fcspi_master_clean_transfer(eInst, bIsInIsr); + eRet = FCSPI_STATUS_TRIGGER_FINISH; + } + } + } + } + return eRet; +} + +/******************************************************************************/ + +static void fcspi_slave_clean_transfer(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInInterrupt) +{ + s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer = FCSPI_FALSE; + + if (FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc) + { + FCSpi_Hw_SetRxTxDmaEnableStatus(eInst, FCSPI_FALSE, FCSPI_FALSE); + } + else + { + FCSpi_Hw_DisableSomeInterrupts(eInst, FCSPI_INT_EN_RFIE(1) | FCSPI_INT_EN_TFIE(1)); + } + + FCSpi_Hw_DisableSomeInterrupts(eInst, FCSPI_INT_EN_RFOIE(1) | FCSPI_INT_EN_TFUIE(1)); + FCSpi_Hw_ClearSomeStatusW1CFlag(eInst, FCSPI_STATUS_RX_FO(1) | FCSPI_STATUS_TX_FU(1)); + + if (FCSPI_TRUE == bIsInInterrupt) + { + if (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb(eInst, FCSPI_TRUE); + } + + if (s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaPostCb(eInst, FCSPI_TRUE); + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)0; + } + } + else + { + if (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb(eInst, FCSPI_FALSE); + } + + if (s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaPostCb(eInst, FCSPI_FALSE); + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)0; + } + } +} + +static void fcspi_slave_abort_transfer(FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInInterrupt) +{ + fcspi_slave_clean_transfer(eInst, bIsInInterrupt); + FCSpi_Hw_Reset(eInst, FCSPI_TRUE, FCSPI_TRUE, FCSPI_FALSE); + FCSpi_Hw_Reset(eInst, FCSPI_TRUE, FCSPI_TRUE, FCSPI_FALSE); /* for shifter */ +} + +/** + * @brief Init the FCSpi instance as spi slave side + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg Configuration of the FCSpi + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when configure successfully. Others, some error occur. + */ +FCSPI_StatusType FCSPI_Slave_Init(const FCSPI_InstanceType eInst, const FCSPI_SlaveCfgType * pCfg) +{ + FCSPI_TxRxCtrlType tTxRxCtrlCfg; + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + + s_atFCSpiInfo[eInst].tFCSpiStat.eBitFirstOrder = pCfg->eBitFirstOrder; + s_atFCSpiInfo[eInst].tFCSpiStat.u16BitsPerFrame = pCfg->u16BitCountPerFrame; + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc = pCfg->eTransferTriggerSrc; + s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf = pCfg->tTriggerDmaInf; + s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb = pCfg->pStopNotifyCb; + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaResetCb = pCfg->pSemaResetCb; + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaTakeCb = pCfg->pSemaTakeCb; + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaPostCb = pCfg->pSemaPostCb; + s_atFCSpiInfo[eInst].tFCSpiStat.eSckPolarity = pCfg->eSckPolarity; + s_atFCSpiInfo[eInst].tFCSpiStat.eSckSamplePhase = pCfg->eSckSamplePhase; + s_atFCSpiInfo[eInst].tFCSpiStat.ePcs = pCfg->ePcs; + s_atFCSpiInfo[eInst].tFCSpiStat.ePcsPolarity = pCfg->ePcsPolarity; + + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed = + (uint16_t)((s_atFCSpiInfo[eInst].tFCSpiStat.u16BitsPerFrame + (uint16_t)7) >> (uint16_t)3); + + /* DMA use 4 bytes/frame. */ + if ((uint16_t)3 == s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed = (uint16_t)4; + } + + /* FCSPI require 4 bytes align when > 32bits. */ + if (s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed > (uint16_t)4) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed = (uint16_t) + ((((s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed + (uint16_t)3)) >> (uint16_t)2) << (uint16_t)2); + } + + s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer = FCSPI_FALSE; + + FCSpi_Hw_Reset(eInst, FCSPI_FALSE, FCSPI_FALSE, FCSPI_TRUE); + FCSPI_HWA_SetSlaveMode(s_atFCSpiInfo[eInst].tFCSpiInstance); + FCSpi_Hw_SetPcs_2_3_Mode(eInst, PCS2_3_PCS); + FCSpi_Hw_SetPin(eInst, SIN_INPUT_SOUT_OUTPUT, PINOUT_RETAIN_LAST); + /* set fifo size param */ + s_atFCSpiInfo[eInst].tFCSpiStat.u8TxFifoSize = (uint8_t)FCSPI_DRV_TX_FIFO_WORD_CNT; + s_atFCSpiInfo[eInst].tFCSpiStat.u8RxFifoSize = (uint8_t)FCSPI_DRV_RX_FIFO_WORD_CNT; + s_atFCSpiInfo[eInst].tFCSpiStat.u32DmaDummyData = 0xFFu; + + /* Set polarity */ + FCSpi_Hw_SetOnePcsPolarity(eInst, pCfg->ePcs, pCfg->ePcsPolarity); + + /* Write the TCR for this transfer */ + tTxRxCtrlCfg.eSckPolarity = pCfg->eSckPolarity; + tTxRxCtrlCfg.eSckPhase = pCfg->eSckSamplePhase; + tTxRxCtrlCfg.ePrescalerValue = FCSPI_PRESCALE_1; /* not use */ + tTxRxCtrlCfg.ePCSSelect = pCfg->ePcs; + tTxRxCtrlCfg.eBitFirstOrder = pCfg->eBitFirstOrder; + tTxRxCtrlCfg.eByteSwap = FCSPI_FALSE; + tTxRxCtrlCfg.eContTransEnable = FCSPI_FALSE; /* not use */ + tTxRxCtrlCfg.eContCmdEnable = FCSPI_FALSE; /* not use */ + tTxRxCtrlCfg.eRxDisable = FCSPI_FALSE; + tTxRxCtrlCfg.eTxDisable = FCSPI_FALSE; + tTxRxCtrlCfg.eTransferWidth = FCSPI_TRANSFER_1_BIT; + tTxRxCtrlCfg.u16FrameBitCnt = pCfg->u16BitCountPerFrame; + + eRet = FCSpi_Hw_SetTRCR(eInst, &tTxRxCtrlCfg); + if (FCSPI_STATUS_SUCCESS == eRet) + { + FCSPI_HWA_ModuleEnable(s_atFCSpiInfo[eInst].tFCSpiInstance); + + if (FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL != pCfg->eTransferTriggerSrc) + { + IntMgr_EnableInterrupt(s_atFCSpiInfo[eInst].eFCSpiIrq); + } + } + else + { + eRet = FCSPI_STATUS_ERROR; + } + + return eRet; +} + +static void fcspi_slave_dma_rx_err_interrupt(FCSPI_InstanceType eInst) +{ + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_RX_FAIL; + fcspi_slave_abort_transfer(eInst, FCSPI_TRUE); +} + +static void fcspi_0_slave_dma_rx_err_interrupt(void) +{ + fcspi_slave_dma_rx_err_interrupt(FCSPI_0); +} + +static void fcspi_1_slave_dma_rx_err_interrupt(void) +{ + fcspi_slave_dma_rx_err_interrupt(FCSPI_1); +} + +static void fcspi_2_slave_dma_rx_err_interrupt(void) +{ + fcspi_slave_dma_rx_err_interrupt(FCSPI_2); +} + +static void fcspi_3_slave_dma_rx_err_interrupt(void) +{ + fcspi_slave_dma_rx_err_interrupt(FCSPI_3); +} + +static void fcspi_4_slave_dma_rx_err_interrupt(void) +{ + fcspi_slave_dma_rx_err_interrupt(FCSPI_4); +} + +static void fcspi_5_slave_dma_rx_err_interrupt(void) +{ + fcspi_slave_dma_rx_err_interrupt(FCSPI_5); +} + +static void fcspi_slave_dma_rx_finish_interrupt(FCSPI_InstanceType eInst) +{ + fcspi_slave_abort_transfer(eInst, FCSPI_TRUE); +} + +static void fcspi_0_slave_dma_rx_finish_interrupt(void) +{ + fcspi_slave_dma_rx_finish_interrupt(FCSPI_0); +} + +static void fcspi_1_slave_dma_rx_finish_interrupt(void) +{ + fcspi_slave_dma_rx_finish_interrupt(FCSPI_1); +} + +static void fcspi_2_slave_dma_rx_finish_interrupt(void) +{ + fcspi_slave_dma_rx_finish_interrupt(FCSPI_2); +} + +static void fcspi_3_slave_dma_rx_finish_interrupt(void) +{ + fcspi_slave_dma_rx_finish_interrupt(FCSPI_3); +} + +static void fcspi_4_slave_dma_rx_finish_interrupt(void) +{ + fcspi_slave_dma_rx_finish_interrupt(FCSPI_4); +} + +static void fcspi_5_slave_dma_rx_finish_interrupt(void) +{ + fcspi_slave_dma_rx_finish_interrupt(FCSPI_5); +} + +static void fcspi_slave_dma_tx_err_interrupt(FCSPI_InstanceType eInst) +{ + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_TX_FAIL; + fcspi_slave_abort_transfer(eInst, FCSPI_TRUE); +} + +static void fcspi_0_slave_dma_tx_err_interrupt(void) +{ + fcspi_slave_dma_tx_err_interrupt(FCSPI_0); +} + +static void fcspi_1_slave_dma_tx_err_interrupt(void) +{ + fcspi_slave_dma_tx_err_interrupt(FCSPI_1); +} + +static void fcspi_2_slave_dma_tx_err_interrupt(void) +{ + fcspi_slave_dma_tx_err_interrupt(FCSPI_2); +} + +static void fcspi_3_slave_dma_tx_err_interrupt(void) +{ + fcspi_slave_dma_tx_err_interrupt(FCSPI_3); +} + +static void fcspi_4_slave_dma_tx_err_interrupt(void) +{ + fcspi_slave_dma_tx_err_interrupt(FCSPI_4); +} + +static void fcspi_5_slave_dma_tx_err_interrupt(void) +{ + fcspi_slave_dma_tx_err_interrupt(FCSPI_5); +} + +static void fcspi_slave_dma_tx_finish_interrupt(FCSPI_InstanceType eInst) +{ + fcspi_slave_abort_transfer(eInst, FCSPI_TRUE); +} + +static void fcspi_0_slave_dma_tx_finish_interrupt(void) +{ + fcspi_slave_dma_tx_finish_interrupt(FCSPI_0); +} + +static void fcspi_1_slave_dma_tx_finish_interrupt(void) +{ + fcspi_slave_dma_tx_finish_interrupt(FCSPI_1); +} + +static void fcspi_2_slave_dma_tx_finish_interrupt(void) +{ + fcspi_slave_dma_tx_finish_interrupt(FCSPI_2); +} + +static void fcspi_3_slave_dma_tx_finish_interrupt(void) +{ + fcspi_slave_dma_tx_finish_interrupt(FCSPI_3); +} + +static void fcspi_4_slave_dma_tx_finish_interrupt(void) +{ + fcspi_slave_dma_tx_finish_interrupt(FCSPI_4); +} + +static void fcspi_5_slave_dma_tx_finish_interrupt(void) +{ + fcspi_slave_dma_tx_finish_interrupt(FCSPI_5); +} + +static FCSPI_StatusType fcspi_slave_async_transfer_bytes(FCSPI_InstanceType eInst, + const uint8_t *pSendBuffer, uint8_t *pReceiveBuffer, uint16_t u16TransferByteCnt) +{ + DMA_InterruptCfgType tDmaTxInterruptCfg = {0}; + DMA_ChannelCfgType tDmaTxChnlCfg = {0}; + uint8_t u8DmaTxBlkByteCnt = (uint8_t)1; + DMA_InterruptCfgType tDmaRxInterruptCfg = {0}; + DMA_ChannelCfgType tDmaRxChnlCfg = {0}; + uint8_t u8DmaRxBlkByteCnt = (uint8_t)1; + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + + if ((NULL == pSendBuffer) && (NULL == pReceiveBuffer)) + { + eRet = FCSPI_STATUS_ERROR; + } + else if ((uint16_t)0 == s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed) + { + eRet = FCSPI_STATUS_ERROR; + } + else if ((uint16_t)0 == u16TransferByteCnt) + { + eRet = FCSPI_STATUS_NO_DATA; + } + else if ((uint16_t)0 != (u16TransferByteCnt % s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed)) + { + eRet = FCSPI_STATUS_ERROR; + } + else if (FCSPI_TRUE == s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer) + { + eRet = FCSPI_STATUS_BUSY; + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_OK; + FCSpi_Hw_Reset(eInst, FCSPI_TRUE, FCSPI_TRUE, FCSPI_FALSE); + FCSpi_Hw_Reset(eInst, FCSPI_TRUE, FCSPI_TRUE, FCSPI_FALSE); /* for shifter */ + + FCSpi_Hw_ClearSomeStatusW1CFlag(eInst, FCSPI_DRV_STATUS_REG_W1C_U32); + + /* in slave mode, rx and tx all enabled */ + FCSpi_Hw_EnableMoreInterrupts(eInst, FCSPI_INT_EN_TFUIE(1) | FCSPI_INT_EN_RFOIE(1)); + + s_atFCSpiInfo[eInst].tFCSpiStat.pbyTxBuff = pSendBuffer; + s_atFCSpiInfo[eInst].tFCSpiStat.pbyRxBuff = pReceiveBuffer; + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxIndex = (uint16_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxIndex = (uint16_t)0; + + if (FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc) + { + FCSPI_HWA_SetWatermark(s_atFCSpiInfo[eInst].tFCSpiInstance, (uint8_t)0, (uint8_t)3); + + /* TX */ + tDmaTxChnlCfg.u8ChannelPriority = s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8TxDMAChannelPriority; + tDmaTxChnlCfg.bDestAddrLoopbackEn = false; + tDmaTxChnlCfg.bSrcAddrLoopbackEn = false; + tDmaTxChnlCfg.bAutoStop = true; /* auto stop dma after send finish */ + tDmaTxChnlCfg.bSrcCircularBufferEn = false; + tDmaTxChnlCfg.bDestCircularBufferEn = false; + + switch (s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed) + { + case 1: + tDmaTxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_1B; + tDmaTxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_1B; + tDmaTxChnlCfg.bSrcBlockOffsetEn = true; + tDmaTxChnlCfg.s32BlockOffset = (int32_t)1; + u8DmaTxBlkByteCnt = (uint8_t)1; + break; + + case 2: + tDmaTxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_2B; + tDmaTxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_2B; + tDmaTxChnlCfg.bSrcBlockOffsetEn = true; + tDmaTxChnlCfg.s32BlockOffset = (int32_t)2; + u8DmaTxBlkByteCnt = (uint8_t)2; + break; + + default: + tDmaTxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B; + tDmaTxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_4B; + tDmaTxChnlCfg.bSrcBlockOffsetEn = true; + tDmaTxChnlCfg.s32BlockOffset = (int32_t)4; + u8DmaTxBlkByteCnt = (uint8_t)4; + break; + } + + tDmaTxChnlCfg.u16BlockCount = u16TransferByteCnt / u8DmaTxBlkByteCnt; + tDmaTxChnlCfg.bDestBlockOffsetEn = false; + tDmaTxInterruptCfg.bTransferCompleteIntEn = true; + tDmaTxInterruptCfg.bTransferErrorIntEn = true; + switch (eInst) + { + case FCSPI_0: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI0_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_0_slave_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_0_slave_dma_tx_err_interrupt; + break; + + case FCSPI_1: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI1_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_1_slave_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_1_slave_dma_tx_err_interrupt; + break; + + case FCSPI_2: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI2_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_2_slave_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_2_slave_dma_tx_err_interrupt; + break; + + case FCSPI_3: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI3_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_3_slave_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_3_slave_dma_tx_err_interrupt; + break; + + case FCSPI_4: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI4_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_4_slave_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_4_slave_dma_tx_err_interrupt; + break; + + case FCSPI_5: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI5_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_5_slave_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_5_slave_dma_tx_err_interrupt; + break; + + default: + tDmaTxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI3_TX; + tDmaTxInterruptCfg.pTransferCompleteNotify = fcspi_3_slave_dma_tx_finish_interrupt; + tDmaTxInterruptCfg.pTransferErrorNotify = fcspi_3_slave_dma_tx_err_interrupt; + break; + } + + tDmaTxChnlCfg.eDestIncMode = DMA_INCREMENT_DISABLE; + tDmaTxChnlCfg.eSrcIncMode = DMA_INCREMENT_DISABLE; + tDmaTxChnlCfg.pDestBuffer = FCSPI_HWA_GetTxDataAddr(s_atFCSpiInfo[eInst].tFCSpiInstance); + tDmaTxChnlCfg.u32BlockSize = (uint32_t)u8DmaTxBlkByteCnt; + + if (NULL != pSendBuffer) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend = u16TransferByteCnt; + tDmaTxChnlCfg.pSrcBuffer = pSendBuffer; + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend = (uint16_t)0; + tDmaTxChnlCfg.bSrcBlockOffsetEn = false; /* if send buffer is NULL, just send dummy data, MUST fix the source to the dummy variable */ + tDmaTxChnlCfg.s32BlockOffset = (int32_t)0; + tDmaTxChnlCfg.pSrcBuffer = &(s_atFCSpiInfo[eInst].tFCSpiStat.u32DmaDummyData); + } + + DMA_InitChannel(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8TxDMAChannel, &tDmaTxChnlCfg); + + /* RX */ + tDmaRxChnlCfg.u8ChannelPriority = s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8RxDMAChannelPriority; + tDmaRxChnlCfg.bDestAddrLoopbackEn = false; + tDmaRxChnlCfg.bSrcAddrLoopbackEn = false; + tDmaRxChnlCfg.bAutoStop = true; /* auto stop dma after send finish */ + tDmaRxChnlCfg.bSrcCircularBufferEn = false; + tDmaRxChnlCfg.bDestCircularBufferEn = false; + + switch (s_atFCSpiInfo[eInst].tFCSpiStat.u16BytesCntFrameNeed) + { + case 1: + tDmaRxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_1B; + tDmaRxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_1B; + tDmaRxChnlCfg.bDestBlockOffsetEn = true; + tDmaRxChnlCfg.s32BlockOffset = (int32_t)1; + u8DmaRxBlkByteCnt = (uint8_t)1; + break; + + case 2: + tDmaRxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_2B; + tDmaRxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_2B; + tDmaRxChnlCfg.bDestBlockOffsetEn = true; + tDmaRxChnlCfg.s32BlockOffset = (int32_t)2; + u8DmaRxBlkByteCnt = (uint8_t)2; + break; + + default: + tDmaRxChnlCfg.eDestDataSize = DMA_TRANSFER_SIZE_4B; + tDmaRxChnlCfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B; + tDmaRxChnlCfg.bDestBlockOffsetEn = true; + tDmaRxChnlCfg.s32BlockOffset = (int32_t)4; + u8DmaRxBlkByteCnt = (uint8_t)4; + break; + } + + tDmaRxChnlCfg.u16BlockCount = u16TransferByteCnt / u8DmaRxBlkByteCnt; + tDmaRxChnlCfg.bSrcBlockOffsetEn = false; + tDmaRxInterruptCfg.bTransferCompleteIntEn = true; + tDmaRxInterruptCfg.bTransferErrorIntEn = true; + switch (eInst) + { + case FCSPI_0: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI0_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_0_slave_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_0_slave_dma_rx_err_interrupt; + break; + + case FCSPI_1: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI1_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_1_slave_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_1_slave_dma_rx_err_interrupt; + break; + + case FCSPI_2: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI2_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_2_slave_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_2_slave_dma_rx_err_interrupt; + break; + + case FCSPI_3: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI3_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_3_slave_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_3_slave_dma_rx_err_interrupt; + break; + + case FCSPI_4: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI4_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_4_slave_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_4_slave_dma_rx_err_interrupt; + break; + + case FCSPI_5: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI5_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_5_slave_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_5_slave_dma_rx_err_interrupt; + break; + + default: + tDmaRxChnlCfg.eTriggerSrc = DMA_REQ_FCSPI3_RX; + tDmaRxInterruptCfg.pTransferCompleteNotify = fcspi_3_slave_dma_rx_finish_interrupt; + tDmaRxInterruptCfg.pTransferErrorNotify = fcspi_3_slave_dma_rx_err_interrupt; + break; + } + + tDmaRxChnlCfg.eSrcIncMode = DMA_INCREMENT_DISABLE; + tDmaRxChnlCfg.eDestIncMode = DMA_INCREMENT_DISABLE; + tDmaRxChnlCfg.pSrcBuffer = FCSPI_HWA_GetRxDataAddr(s_atFCSpiInfo[eInst].tFCSpiInstance); + tDmaRxChnlCfg.u32BlockSize = (uint32_t)u8DmaRxBlkByteCnt; + + if (NULL != pReceiveBuffer) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet = u16TransferByteCnt; + tDmaRxChnlCfg.pDestBuffer = pReceiveBuffer; + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet = (uint16_t)0; + tDmaRxChnlCfg.bDestBlockOffsetEn = false; + tDmaRxChnlCfg.s32BlockOffset = (int32_t)0; + tDmaRxChnlCfg.pDestBuffer = &(s_atFCSpiInfo[eInst].tFCSpiStat.u32DmaDummyData); + } + + DMA_InitChannel(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8RxDMAChannel, &tDmaRxChnlCfg); + + s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer = FCSPI_TRUE; + + DMA_InitChannelInterrupt(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8RxDMAChannel, &tDmaRxInterruptCfg); + DMA_InitChannelInterrupt(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8TxDMAChannel, &tDmaTxInterruptCfg); + DMA_StartChannel(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8RxDMAChannel); + DMA_StartChannel(s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.eDMAInstance, + (DMA_ChannelType)s_atFCSpiInfo[eInst].tFCSpiStat.tTriggerDmaInf.u8TxDMAChannel); + FCSpi_Hw_SetRxTxDmaEnableStatus(eInst, FCSPI_TRUE, FCSPI_TRUE); + } + else + { + FCSPI_HWA_SetWatermark(s_atFCSpiInfo[eInst].tFCSpiInstance, (uint8_t)0, (uint8_t)2); + + if (NULL == s_atFCSpiInfo[eInst].tFCSpiStat.pbyTxBuff) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend = (uint16_t)0; + FCSPI_HWA_EnableTxDataMask(s_atFCSpiInfo[eInst].tFCSpiInstance, FCSPI_FALSE); + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend = u16TransferByteCnt; + FCSPI_HWA_EnableTxDataMask(s_atFCSpiInfo[eInst].tFCSpiInstance, FCSPI_TRUE); + } + + if (NULL == s_atFCSpiInfo[eInst].tFCSpiStat.pbyRxBuff) + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet = (uint16_t)0; + FCSPI_HWA_EnableRxDataMask(s_atFCSpiInfo[eInst].tFCSpiInstance, FCSPI_FALSE); + } + else + { + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet = u16TransferByteCnt; + FCSPI_HWA_EnableRxDataMask(s_atFCSpiInfo[eInst].tFCSpiInstance, FCSPI_TRUE); + } + + s_atFCSpiInfo[eInst].tFCSpiStat.u16RxGetByteCntOfCurFrame = (uint16_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.u16TxSendByteCntOfCurFrame = (uint16_t)0; + s_atFCSpiInfo[eInst].tFCSpiStat.eIsPcsContinuous = FCSPI_FALSE; + s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer = FCSPI_TRUE; + + if (NULL != pReceiveBuffer) /* need rx fifo */ + { + FCSpi_Hw_EnableMoreInterrupts(eInst, FCSPI_INT_EN_RFIE(1)); + } + + if (NULL != pSendBuffer) + { + FCSpi_Hw_EnableMoreInterrupts(eInst, FCSPI_INT_EN_TFIE(1)); + } + } + } + + return eRet; +} + +static FCSPI_StatusType fcspi_slave_trigger( + FCSPI_InstanceType eInst, FCSPI_AtomicBoolType bIsInISR) +{ + uint32_t u32StatusRegValue; + uint16_t u16RemainTx = (uint16_t)0; + uint16_t u16RemainRx = (uint16_t)0; + FCSPI_StatusType eRet = FCSPI_STATUS_TRIGGER_OK; + + /* If an error is detected the transfer will be aborted */ + u32StatusRegValue = FCSPI_HWA_GetStatus(s_atFCSpiInfo[eInst].tFCSpiInstance); + if (FCSpi_Hw_ChkTxFifoUnderrun(u32StatusRegValue) && + (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pbyTxBuff)) + { + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_TX_FAIL; + fcspi_slave_abort_transfer(eInst, bIsInISR); + eRet = FCSPI_STATUS_TRIGGER_ABORT_TX_FAIL; + } + else if (FCSpi_Hw_ChkRxFifoOverflow(u32StatusRegValue) && + (NULL != s_atFCSpiInfo[eInst].tFCSpiStat.pbyRxBuff)) + { + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_RX_FAIL; + fcspi_slave_abort_transfer(eInst, bIsInISR); + eRet = FCSPI_STATUS_TRIGGER_ABORT_RX_FAIL; + } + /* rx data ready */ + else + { + if (FCSpi_Hw_ChkRxGreaterThanWater(u32StatusRegValue)) + { + if ((uint16_t)0 != s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet) + { + fcspi_read_rx_fifo(eInst); + } + } + + /* transmit some, need add more */ + if (FCSpi_Hw_ChkTxEqualOrLessThanWater(u32StatusRegValue)) + { + if ((uint16_t)0 != s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend) + { + fcspi_write_tx_fifo(eInst); + } + } + + if ((uint16_t)0 == s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend) + { + /* Disable TX flag. Software buffer is empty.*/ + FCSpi_Hw_DisableTransmitDataInterrupt(eInst); + } + + if ((uint16_t)0 == s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet) + { + FCSpi_Hw_DisableReceiveDataInterrupt(eInst); + } + + u16RemainTx = s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend; + u16RemainRx = s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet; + if (((uint16_t)0 == u16RemainTx) && ((uint16_t)0 == u16RemainRx)) + { + FCSpi_Hw_DisableSomeInterrupts(eInst, FCSPI_INT_EN_RFOIE(1) | FCSPI_INT_EN_TFUIE(1)); + + if (s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pStopNotifyCb(eInst, bIsInISR); + } + + if (s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore) + { + s_atFCSpiInfo[eInst].tFCSpiStat.pSemaPostCb(eInst, bIsInISR); + s_atFCSpiInfo[eInst].tFCSpiStat.u8WaitSemaphore = (uint8_t)0; + } + + s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer = FCSPI_FALSE; + eRet = FCSPI_STATUS_TRIGGER_FINISH; + } + } + + return eRet; +} + +/*----------------------------------------------------------------------------*/ +/** + * @brief If it's in transfer, get its stat, or get the last transfer's stat. + * + * @param eInst Which FCSpi Hardware instance + * @param pCfg the transfer information, can be null + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when the last transfer is finish successfully. Others, busy or error occur. + */ +FCSPI_StatusType FCSPI_GetLatestTransferStat(const FCSPI_InstanceType eInst, FCSPI_TransferRemainInfType *pCfg) +{ + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + + if (NULL != pCfg) + { + pCfg->u32ByteCountReceiveRemained = s_atFCSpiInfo[eInst].tFCSpiStat.u16RxByteCntRemainToGet; + pCfg->u32ByteCountSendRemained = s_atFCSpiInfo[eInst].tFCSpiStat.u16TxByteCntRemainToSend; + } + + if (FCSPI_TRANSFER_OK != s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat) + { + eRet = FCSPI_STATUS_ERROR; + } + else if (FCSPI_TRUE == s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer) + { + eRet = FCSPI_STATUS_BUSY; + } + else + { + eRet = FCSPI_STATUS_SUCCESS; + } + + return eRet; +} + +#ifdef FCSPI_DRV_INTERNAL_FUNC_EN +/** + * @brief Trigger the driver to transfer data when select FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL + * + * @param eInst Which FCSpi Hardware instance + * @return FCSPI_StatusType FCSPI_STATUS_TRIGGER_OK when api trigger successfully, FCSPI_STATUS_TRIGGER_FINISH when all data transfer finish. Others, error happen. + */ +FCSPI_StatusType FCSPI_PollTrigger(FCSPI_InstanceType eInst) +{ + FCSPI_StatusType eRet = FCSPI_STATUS_TRIGGER_OK; + + if (FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL == s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc) + { + if (FCSPI_TRUE == s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer) + { + if (FCSPI_MODE_MASTER == FCSPI_HWA_CheckMode(s_atFCSpiInfo[eInst].tFCSpiInstance)) + { + eRet = fcspi_master_trigger(eInst, FCSPI_FALSE); + } + else + { + eRet = fcspi_slave_trigger(eInst, FCSPI_FALSE); + } + } + else + { + eRet = FCSPI_STATUS_ERROR; + } + } + else + { + eRet = FCSPI_STATUS_ERROR; + } + + return eRet; +} +#endif + +/** + * @brief Select the trigger source(DMA with interrupt / interrupt / user poll) + * + * @param eInst Which FCSpi Hardware instance + * @param eSrc three source, 1) DMA move data between memory and registers, notified when finish by interrupt; 2) purely by interrupt; 3) purely by user poll. + * @return FCSPI_StatusType FCSPI_STATUS_SUCCESS when successfully. Others, error. + */ +FCSPI_StatusType FCSPI_SelectTriggerSrc( + FCSPI_InstanceType eInst, FCSPI_TriggerSrcType eSrc) +{ + FCSPI_StatusType eRet = FCSPI_STATUS_SUCCESS; + uint32_t u32StatRegVal = 0u; + + u32StatRegVal = FCSPI_HWA_GetStatus(s_atFCSpiInfo[eInst].tFCSpiInstance); + if ((FCSPI_TRUE != s_atFCSpiInfo[eInst].tFCSpiStat.eIsInTransfer) && + (!FCSpi_Hw_ChkBusy(u32StatRegVal))) + { + switch (eSrc) + { + case FCSPI_TRANSFER_TRIGGER_SRC_ISR: + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc = eSrc; + break; + case FCSPI_TRANSFER_TRIGGER_SRC_DMA_ISR: + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc = eSrc; + break; + case FCSPI_TRANSFER_TRIGGER_SRC_USER_POLL: + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc = eSrc; + break; + default: + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferTriggerSrc = eSrc; + break; + } + } + else + { + eRet = FCSPI_STATUS_BUSY; + } + + return eRet; +} + +/** + * @brief Abort current transfer if exist, or just recovery the hardware. + * + * @param eInst Which FCSpi Hardware instance + */ +void FCSPI_AbortTransfer(const FCSPI_InstanceType eInst) +{ + s_atFCSpiInfo[eInst].tFCSpiStat.eTransferStat = FCSPI_TRANSFER_ABORT; + + if (FCSPI_MODE_MASTER == FCSPI_HWA_CheckMode(s_atFCSpiInfo[eInst].tFCSpiInstance)) + { + fcspi_master_abort_transfer(eInst, FCSPI_FALSE); + } + else + { + fcspi_slave_abort_transfer(eInst, FCSPI_FALSE); + } +} + +static void fcspi_irq_handler(FCSPI_InstanceType eInst) +{ + if (FCSPI_MODE_MASTER == FCSPI_HWA_CheckMode(s_atFCSpiInfo[eInst].tFCSpiInstance)) + { + fcspi_master_trigger(eInst, FCSPI_TRUE); + } + else + { + fcspi_slave_trigger(eInst, FCSPI_TRUE); + } +} + +/** + * @brief fcspi 0 interrupt handler + * + * @note This function should be called as/in FCSPI 0 interrupt handler + */ +void FCSPI0_IRQHandler(void) +{ + fcspi_irq_handler(FCSPI_0); +} + +/** + * @brief fcspi 1 interrupt handler + * + * @note This function should be called as/in FCSPI 1 interrupt handler + */ +void FCSPI1_IRQHandler(void) +{ + fcspi_irq_handler(FCSPI_1); +} + +/** + * @brief fcspi 2 interrupt handler + * + * @note This function should be called as/in FCSPI 2 interrupt handler + */ +void FCSPI2_IRQHandler(void) +{ + fcspi_irq_handler(FCSPI_2); +} + +/** + * @brief fcspi 3 interrupt handler + * + * @note This function should be called as/in FCSPI 3 interrupt handler + */ +void FCSPI3_IRQHandler(void) +{ + fcspi_irq_handler(FCSPI_3); +} + +/** + * @brief fcspi 4 interrupt handler + * + * @note This function should be called as/in FCSPI 4 interrupt handler + */ +void FCSPI4_IRQHandler(void) +{ + fcspi_irq_handler(FCSPI_4); +} + +/** + * @brief fcspi 5 interrupt handler + * + * @note This function should be called as/in FCSPI 5 interrupt handler + */ +void FCSPI5_IRQHandler(void) +{ + fcspi_irq_handler(FCSPI_5); +} diff --git a/Src/fc7xxx_driver_fcuart.c b/Src/fc7xxx_driver_fcuart.c new file mode 100644 index 0000000..88a775b --- /dev/null +++ b/Src/fc7xxx_driver_fcuart.c @@ -0,0 +1,1946 @@ +/** + * @file fc7xxx_driver_fcuart.c + * @author Flagchip + * @brief FC7xxx FCUart driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + */ + +/******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-14 Flagchip0122 N/A FC7xxx internal release version + ********************************************************************************/ + +#include "fc7xxx_driver_fcuart.h" + + + + +/********* Macro ************/ + +/********* Local typedef ************/ + +typedef enum +{ + UART_PRINT_RADIX_BIN = 2U, + UART_PRINT_RADIX_OCT = 8U, + UART_PRINT_RADIX_DEC = 10U, + UART_PRINT_RADIX_HEX = 16U +} UART_PrintIntType; + +/** + * @brief FCUART Operation Sequence + * + */ +typedef enum +{ + FCUART_SEQUENCE_VAR_NOINIT, /**< FCUART_SEQUENCE_DEINIT means fcuart variables data is not initialed */ + FCUART_SEQUENCE_DEINIT, /**< FCUART_SEQUENCE_DEINIT means fcuart driver is not initialed */ + FCUART_SEQUENCE_NOTSTART_RECEIVE, /**< FCUART_SEQUENCE_NOTSTART_RECEIVE means fcuart driver initialed and write/erase is allowed */ + FCUART_SEQUENCE_START_RECEIVE /**< FCUART_SEQUENCE_START_RECEIVE means fcuart driver started received */ +} FCUART_SequenceType; + +/********* Local Variables ************/ +/* UART instance array */ +static FCUART_Type *const s_aFCUART_InstanceTable[FCUART_INSTANCE_COUNT] = FCUART_BASE_PTRS; + +/* sequence table */ +static FCUART_SequenceType s_aCurrentSequence[FCUART_INSTANCE_COUNT] = {FCUART_SEQUENCE_VAR_NOINIT}; + +/* error notify callback function point */ +static FCUART_ErrorInterrupt_CallBackType s_aFCUART_ErrorNotifyTable[FCUART_INSTANCE_COUNT]; + +/* receive notify callback function point */ +static FCUART_TxRxInterrupt_CallBackType s_aFCUART_RxNotifyTable[FCUART_INSTANCE_COUNT]; + +/* Transfer empty notify callback function point */ +static FCUART_TxRxInterrupt_CallBackType s_aFCUART_TxEmptyNotifyTable[FCUART_INSTANCE_COUNT]; + +/* Transfer complete notify callback function point */ +static FCUART_TxRxInterrupt_CallBackType s_aFCUART_TxCompleteNotifyTable[FCUART_INSTANCE_COUNT]; + +/* Idle notify callback function point */ +static FCUART_IdleInterrupt_CallBackType s_aFCUART_IdleNotifyTable[FCUART_INSTANCE_COUNT]; + +/* check every pUart instance whether is used */ +static uint8_t s_aFCUART_UartUsed[FCUART_INSTANCE_COUNT]; + +/* check every pUart instance transmit timeout */ +static uint32_t s_aFCUART_TransmitTimeout[FCUART_INSTANCE_COUNT]; + +/* pUart instance receive buffer */ +static FCUART_DataType *s_aFCUART_RxMsg[FCUART_INSTANCE_COUNT]; + +/* pUart instance transfer buffer */ +static FCUART_DataType *s_aFCUART_TxMsg[FCUART_INSTANCE_COUNT]; + +/********* Local Prototype Functions ************/ + +static FCUART_ErrorType FCUART_LL_CheckInstance(uint8_t u8UartIndex); + +static uint32_t FCUART_LL_Error(uint8_t u8UartIndex); + +static FCUART_ErrorType FCUART_LL_ProcessBaud(uint32_t u32Smb, uint32_t *u32OverSamp, uint32_t *u32Sbr); + +static FCUART_ErrorType FCUART_LL_Transmit_Char(FCUART_Type *pUart, uint8_t u8Data, uint32_t u32TimeoutTick); + +static FCUART_ErrorType FCUART_LL_Receive(uint8_t u8UartIndex, FCUART_DataType *pUartData); + +static FCUART_ErrorType FCUART_LL_Transmit_Empty(uint8_t u8UartIndex, FCUART_DataType *pUartData); + +static FCUART_ErrorType FCUART_LL_Transmit_Complete(uint8_t u8UartIndex); + +static FCUART_ErrorType FCUART_LL_Idle(uint8_t u8UartIndex); + +static uint8_t FCUART_Float2Char(double Value, char *pOutStr, uint32_t u32Eps); + +static uint8_t FCUART_Int2Char(int i32Value, char *pOutStr, UART_PrintIntType eRadix, bool bHexUpper); + +/********* Global Prototype Functions ************/ + +/********* Local Functions ************/ +/** + * @brief Check UART instance + * + * @param u8UartIndex UART instance number + * @return + */ +static FCUART_ErrorType FCUART_LL_CheckInstance(uint8_t u8UartIndex) +{ + FCUART_ErrorType tRetVal; + + if (u8UartIndex < FCUART_INSTANCE_COUNT) + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + return tRetVal; +} + +/** + * @brief Process get OverSamp and SBR + * + * @param u32Smb the value OverSame*SBR + * @param u32OverSamp out OverSampe + * @param u32Sbr out + * @return FCUART_ERROR_OK is ok, others are not ok + */ +static FCUART_ErrorType FCUART_LL_ProcessBaud(uint32_t u32Smb, uint32_t *u32OverSamp, uint32_t *u32Sbr) +{ + FCUART_ErrorType tRetVal; + uint32_t u32SbrTemp; + uint32_t u32OverSampTemp; + uint32_t u32TempSmbDiff; + uint32_t u32SmbDiff; + uint32_t u32CalcSmb; + uint32_t u32OverSamp1; + uint32_t u32Sbr1; + uint32_t u32OriginDiff; + + u32OverSamp1 = 4U; /* 4..32 */ + + /* sbr = smb / oversamp */ + u32Sbr1 = (uint16_t)(u32Smb / (u32OverSamp1)); + u32CalcSmb = (u32OverSamp1) * (u32Sbr1); + + if (u32CalcSmb > u32Smb) + { + u32SmbDiff = u32CalcSmb - u32Smb; + } + else + { + u32SmbDiff = u32Smb - u32CalcSmb; + } + u32OriginDiff = u32SmbDiff; + + if (u32SmbDiff != 0U) + { + + /* loop to find the best u32OverSamp1 value possible, one that generates minimum u32SmbDiff + * iterate through the rest of the supported values of u32OverSamp */ + for (u32OverSampTemp = 5U; u32OverSampTemp <= 32U; u32OverSampTemp++) + { + /* calculate the temporary u32Sbr value */ + u32SbrTemp = (uint32_t)(u32Smb / u32OverSampTemp); + /* calculate the baud rate based on the temporary u32OverSamp and u32Sbr values */ + u32CalcSmb = (uint32_t)(u32OverSampTemp * u32SbrTemp); + + if (u32CalcSmb > u32Smb) + { + u32TempSmbDiff = u32CalcSmb - u32Smb; + } + else + { + u32TempSmbDiff = u32Smb - u32CalcSmb; + } + + if (u32TempSmbDiff < u32SmbDiff) + { + u32SmbDiff = u32TempSmbDiff; + u32OverSamp1 = u32OverSampTemp; /* update and store the best u32OverSamp value calculated */ + u32Sbr1 = u32SbrTemp; /* update store the best u32Sbr value calculated */ + } + + /* when differ is 0U, break */ + if (u32SmbDiff == 0U) + { + break; + } + } + } + + /* check differ */ + if (u32SmbDiff <= u32OriginDiff) + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + + /* out the calculated value */ + *u32Sbr = u32Sbr1; + *u32OverSamp = u32OverSamp1; + } + else + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_FAILED; + } + + return tRetVal; +} + +/** + * @brief Function to Transmit single Char + * + * @param pUart UART Instance point + * @param u8Data UART data + * @return FCUART_ERROR_OK is ok, others are not ok + */ +static FCUART_ErrorType FCUART_LL_Transmit_Char(FCUART_Type *pUart, uint8_t u8Data, uint32_t u32TimeoutTick) +{ + uint32_t u32Result; + uint32_t u32TryCount; + + /* check transmit ready flag */ + u32Result = FCUART_HWA_GetStatus(pUart, FCUART_STAT_TDREF); + + if (u32Result != 0U) + { + FCUART_HWA_SetData(pUart, (uint32_t)u8Data); /* Send data */ + FCUART_HWA_SetTxTransfer(pUart, true); /* start transmit */ + + u32Result = 0U; + u32TryCount = 0U; + + while ((u32Result == 0U) && (u32TryCount < u32TimeoutTick)) + { + /* check transmit flag */ + u32Result = FCUART_HWA_GetStatus(pUart, FCUART_STAT_TCF); + u32TryCount++; + } + + /* after transmit completed, close TE */ + FCUART_HWA_SetTxTransfer(pUart, false); + } + + return (u32Result == 0U) ? (FCUART_ErrorType)FCUART_ERROR_FAILED : (FCUART_ErrorType)FCUART_ERROR_OK; +} + +/** + * @brief Function to Transmit single Char by interrupt + * + * @param u8UartIndex UART Instance + * @param pUartData UART receive buffer + * @return FCUART_ERROR_OK is ok, others are not ok + */ +static FCUART_ErrorType FCUART_LL_Transmit_Empty(uint8_t u8UartIndex, FCUART_DataType *pUartData) +{ + FCUART_ErrorType tRetVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + FCUART_Type *pUart; + uint32_t u32TempStats; + uint32_t u32Index; + uint8_t u8Index; + uint8_t u8TxWaterMark; + + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + if ((pUartData != NULL) && (pUartData->pDatas != NULL)) + { + /* get and clear receive flag */ + u32TempStats = FCUART_HWA_GetStatus(pUart, FCUART_STAT_TDREF); + if (u32TempStats > 0U) + { + /* TDRFF Flag has been got */ + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + if(pUartData->u32DataLen > 0U) + { + if(true == FCUART_HWA_GetEnStatusTxFifo(pUart)) + { + /* Tx fifo enable */ + u8TxWaterMark = FCUART_HWA_GetTxWaterMark(pUart); + + if(((pUartData->u32DataLen) >= (uint32_t)(FCUART_FIFO_DEPTH - u8TxWaterMark) )) + { + for(u8Index=0U; u8Index<(FCUART_FIFO_DEPTH - u8TxWaterMark); u8Index++) + { + FCUART_HWA_SetData(pUart, (uint8_t)(pUartData->pDatas[0U])); /* Send data */ + + /* Update pointer position */ + (pUartData->pDatas)++; + (pUartData->u32DataLen)--; + } + } + else + { + for(u32Index=0U; u32Index<(pUartData->u32DataLen); u32Index++) + { + FCUART_HWA_SetData(pUart, (uint8_t)(pUartData->pDatas[0U])); /* Send data */ + + /* Update pointer position */ + (pUartData->pDatas)++; + (pUartData->u32DataLen)--; + } + } + } + else + { + /* Tx fifo disable */ + FCUART_HWA_SetData(pUart, (uint8_t)(pUartData->pDatas[0U])); /* Send data */ + + /* Update pointer position */ + (pUartData->pDatas)++; + (pUartData->u32DataLen)--; + } + + if(0U == pUartData->u32DataLen) + { + /* There's no new data, disable transmit empty interrupt and enable transmit complete interrupt */ + FCUART_HWA_DisableInterrupt(pUart, (uint32_t)FCUART_INT_CTRL_TIE); + FCUART_HWA_EnableInterrupt(pUart, (uint32_t)FCUART_INT_CTRL_TCIE); + } + } + } + } + + return tRetVal; +} + +/** + * @brief Function to deal transmit complete + * + * @param u8UartIndex UART Instance + * @return FCUART_ERROR_OK is ok, others are not ok + */ +static FCUART_ErrorType FCUART_LL_Transmit_Complete(uint8_t u8UartIndex) +{ + FCUART_ErrorType tRetVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + FCUART_Type *pUart; + uint32_t u32TempStats; + + /* No need to check instance */ + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + /* get and clear receive flag */ + u32TempStats = FCUART_HWA_GetStatus(pUart, FCUART_STAT_TCF); + + if (u32TempStats > 0U) + { + /* TCF Flag has been got */ + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + + FCUART_HWA_DisableInterrupt(pUart, (uint32_t)(FCUART_INT_CTRL_TE | FCUART_INT_CTRL_TCIE)); + } + return tRetVal; +} + +/** + * @brief Function to deal idle line + * + * @param u8UartIndex UART Instance + * @return FCUART_ERROR_OK is ok, others are not ok + */ +static FCUART_ErrorType FCUART_LL_Idle(uint8_t u8UartIndex) +{ + FCUART_ErrorType tRetVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + FCUART_Type *pUart; + uint32_t u32TempStats; + + /* get and clear receive flag */ + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + /* No need to check instance */ + u32TempStats = FCUART_HWA_GetStatus(pUart, FCUART_STAT_IDLEF); + + if (u32TempStats > 0U) + { + /* IDLF Flag has been got */ + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + FCUART_HWA_ClearStatus(pUart, (uint32_t)FCUART_STAT_IDLEF); + } + return tRetVal; +} + +/** + * @brief Receive UART data + * + * @param u8UartIndex UART Instance + * @param pUartData UART receive buffer + * @return FCUART_ERROR_OK is ok, others are not ok + */ +static FCUART_ErrorType FCUART_LL_Receive(uint8_t u8UartIndex, FCUART_DataType *pUartData) +{ + FCUART_ErrorType tRetVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + FCUART_Type *pUart; + uint8_t u8ReadData; + uint32_t u32TempStats; + uint8_t u8RxCount; + uint8_t u8Index; + + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + if ((pUartData != NULL) && (pUartData->pDatas != NULL)) + { + /* get and clear receive flag */ + u32TempStats = FCUART_HWA_GetStatus(pUart, FCUART_STAT_RDRFF); + + if (u32TempStats > 0U) + { + /* RDRFF Flag has been got */ + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + + pUartData->u32DataLen = 0U; + if( true == FCUART_HWA_GetEnStatusRxFifo(pUart)) + { + /* Rx fifo enable */ + u8RxCount = FCUART_HWA_GetFifoRxCount(pUart); + for(u8Index = 0U; u8Index < u8RxCount; u8Index++) + { + u8ReadData = FCUART_HWA_GetData(pUart); + pUartData->pDatas[u8Index] = u8ReadData; + pUartData->u32DataLen++; + } + } + else + { + /* Rx fifo disable */ + u8ReadData = FCUART_HWA_GetData(pUart); + pUartData->pDatas[0U] = u8ReadData; + pUartData->u32DataLen++; + } + } + } + + return tRetVal; +} + +/** + * @brief Get Error Status + * + * @param u8UartIndex + * @return All Error Combine, 0U is no error + */ +static uint32_t FCUART_LL_Error(uint8_t u8UartIndex) +{ + uint32_t u32RetVal; + uint32_t u32ErrorValue; + FCUART_Type *pUart; + + u32ErrorValue = 0U; + + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + /* receive overrun */ + u32RetVal = FCUART_HWA_GetStatus(pUart, FCUART_STAT_RORF); + + /* FCUART_HWA_ClearStatus(pUart, FCUART_STAT_RORF); */ + if (u32RetVal != 0U) + { + u32ErrorValue = (uint32_t)FCUART_ERROR_RORF; + } + + /* noise flag */ + u32RetVal = FCUART_HWA_GetStatus(pUart, FCUART_STAT_NF); + + /*FCUART_HWA_ClearStatus(pUart, FCUART_STAT_NF);*/ + if (u32RetVal != 0U) + { + u32ErrorValue |= (uint32_t)FCUART_ERROR_NF; + } + + /* Frame Error flag */ + u32RetVal = FCUART_HWA_GetStatus(pUart, FCUART_STAT_FEF); + + /*FCUART_HWA_ClearStatus(pUart, FCUART_STAT_FEF);*/ + if (u32RetVal != 0U) + { + u32ErrorValue |= (uint32_t)FCUART_ERROR_FEF; + } + + /* Parity Error Flag */ + u32RetVal = FCUART_HWA_GetStatus(pUart, FCUART_STAT_PEF); + + /*FCUART_HWA_ClearStatus(pUart, FCUART_STAT_PEF);*/ + if (u32RetVal != 0U) + { + u32ErrorValue |= (uint32_t)FCUART_ERROR_PEF; + } + + /* Receive Data Parity Error Flag */ + u32RetVal = FCUART_HWA_GetStatus(pUart, FCUART_STAT_RPEF); + + /*FCUART_HWA_ClearStatus(pUart, FCUART_STAT_RPEF);*/ + if (u32RetVal != 0U) + { + u32ErrorValue |= (uint32_t)FCUART_ERROR_RPEF; + } + + /* Transmit Data Parity Error Flag */ + u32RetVal = FCUART_HWA_GetStatus(pUart, FCUART_STAT_TPEF); + + /*FCUART_HWA_ClearStatus(pUart, FCUART_STAT_TPEF);*/ + if (u32RetVal != 0U) + { + u32ErrorValue |= (uint32_t)FCUART_ERROR_TPEF; + } + + /* clear error flags */ + FCUART_HWA_ClearStatus(pUart, u32ErrorValue); + + return u32ErrorValue; +} + +/********************* Global Functions *********************/ + +/** + * @brief Initial UART variables Memory + * + */ +void FCUART_InitMemory(uint8_t u8UartIndex) +{ + + s_aFCUART_ErrorNotifyTable[u8UartIndex] = NULL; + + s_aFCUART_RxNotifyTable[u8UartIndex] = NULL; + + s_aFCUART_TxEmptyNotifyTable[u8UartIndex] = NULL; + + s_aFCUART_TxCompleteNotifyTable[u8UartIndex] = NULL; + + s_aFCUART_IdleNotifyTable[u8UartIndex] = NULL; + + s_aFCUART_UartUsed[u8UartIndex] = 0U; + + /* set first state */ + s_aCurrentSequence[u8UartIndex] = FCUART_SEQUENCE_DEINIT; + +} + +/** + * @brief This Function is used to initial UART instance + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pInitCfg contains clock, baud-rate, Bit Mode, parity and so on. + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Init(uint8_t u8UartIndex, FCUART_InitType *pInitCfg) +{ + FCUART_ErrorType tRetVal; + uint32_t u32TempBaudReg; + uint32_t u32TempCtrlReg; + uint32_t u32TempFifoReg; + uint32_t u32TempWatermarkReg; + uint32_t u32TempStat; + uint32_t u32TempModir; + FCUART_Type *pUart; + uint32_t u32Sbr = 0U; + uint32_t u32OverSamp = 0U; + uint32_t u32Smb = 0U; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if ((tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_DEINIT)) + { + + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + + if (pInitCfg != NULL) + { + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + + /* set not start state */ + s_aCurrentSequence[u8UartIndex] = FCUART_SEQUENCE_NOTSTART_RECEIVE; + + if(0U != pInitCfg->u32Baudrate) + { + u32Smb = pInitCfg->u32ClkSrcHz / pInitCfg->u32Baudrate; + } + else + { + u32Smb = 0; + tRetVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + /* process for baud-rate */ + if ((FCUART_ErrorType)FCUART_ERROR_OK == FCUART_LL_ProcessBaud(u32Smb, &u32OverSamp, &u32Sbr)) + { + /* temporary BAUD register */ + u32TempBaudReg = (uint32_t)0U | /* initial value */ + FCUART_BAUD_MAEN0(0U) | /* Match mode enable 0 */ + FCUART_BAUD_MAEN1(0U) | /* Match mode enable 1 */ + FCUART_BAUD_10BIT_MODE(0U) | /* 10bit mode select */ + FCUART_BAUD_OVR_SAMP(u32OverSamp - 1U) | /* Over sampling Ratio, n+1 */ + FCUART_BAUD_TDMAEN(pInitCfg->bEnTxEmptyDma) | /* Transmitter DMA Enable */ + FCUART_BAUD_RDMAEN(pInitCfg->bEnRxFullDma) | /* Receiver Full DMA Enable */ + FCUART_BAUD_RIDMAEN(0U) | /* Receiver Idle DMA Enable */ + FCUART_BAUD_MATCH_CFG(0U) | /* Match Configuration */ + FCUART_BAUD_BEDGE_SAMP(1U) | /* Both Edge Sampling */ + FCUART_BAUD_RESYNC_DIS(0U) | /* Re-synchronization Disable */ + FCUART_BAUD_LBKDIE(0U) | /* LIN Break Detect Interrupt Enable */ + FCUART_BAUD_RIAEIE(0U) | /* RX Input Active Edge Interrupt Enable */ + FCUART_BAUD_SBNS(pInitCfg->eStopBit) | /* Stop Bit Number Select */ + FCUART_BAUD_SBR(u32Sbr); /* Baud Rate Modulo Divisor. baud-rate = baud clock / ((OVR_SAMP+1) * SBR) */ + + /* temporary CTRL register */ + u32TempCtrlReg = (uint32_t)0U | /* initial value */ + FCUART_CTRL_R8T9(0U) | /* Receive Bit 8 / Transmit Bit 9 */ + FCUART_CTRL_R9T8(0U) | /* Receive Bit 9 / Transmit Bit 8 */ + FCUART_CTRL_TXDIR(0U) | /* TXD Pin Direction in Single-Wire Mode */ + FCUART_CTRL_TXINV(0U) | /* Transmit Data Inversion */ + FCUART_CTRL_ORIE(0U) | /* Overrun Interrupt Enable */ + FCUART_CTRL_NEIE(0U) | /* Noise Error Interrupt Enable */ + FCUART_CTRL_FEIE(0U) | /* Frame Error Interrupt Enable */ + FCUART_CTRL_PEIE(0U) | /* Parity Error Interrupt Enable */ + FCUART_CTRL_TIE(0U) | /* Transmit Interrupt Enable */ + FCUART_CTRL_TCIE(0U) | /* Transmission Complete Interrupt Enable */ + FCUART_CTRL_RIE(0U) | /* Receiver Interrupt Enable */ + FCUART_CTRL_IIE(0U) | /* Idle Line Interrupt Enable */ + FCUART_CTRL_TE(0U) | /* Transmitter Enable */ + FCUART_CTRL_RE(0U) | /* Receiver Enable */ + FCUART_CTRL_RWC(0U) | /* Receiver WakeUp Control */ + FCUART_CTRL_SBK(0U) | /* Send Break */ + FCUART_CTRL_M0IE(0U) | /* Match address 0 Interrupt Enable */ + FCUART_CTRL_M1IE(0U) | /* Match address 1 Interrupt Enable */ + FCUART_CTRL_7BMS(0U) | /* 7-Bit Mode Select */ + FCUART_CTRL_IDLECFG(pInitCfg->eIdleCharNum) | /* Idle Configuration 2^n bytes time no data entry IDLE */ + FCUART_CTRL_LOOPMS(0U) | /* Loop Mode Select */ + FCUART_CTRL_WAITEN(0U) | /* WAIT Enable */ + FCUART_CTRL_RXSRC(0U) | /* Receiver Source Select */ + FCUART_CTRL_BMSEL(pInitCfg->eBitMode) | /* 9-Bit or 8-Bit Mode Select */ + FCUART_CTRL_RSWMS(0U) | /* Receiver WakeUp Method Select */ + FCUART_CTRL_ITS(pInitCfg->eIdleStart) | /* Idle Line Type Select */ + FCUART_CTRL_PE(pInitCfg->bParityEnable) | /* Parity Enable */ + FCUART_CTRL_PT(pInitCfg->eParityType); /* Parity Type */ + + /* temporary FIFO register */ + u32TempFifoReg = (uint32_t)0U | /* initial value */ + FCUART_FIFO_TXEMPTY(0U) | /* Transmit Buffer/FIFO Empty */ + FCUART_FIFO_RXEMPTY(0U) | /* Receive Buffer/FIFO Empty */ + FCUART_FIFO_TXOF(0U) | /* Transmitter Buffer Overflow Flag */ + FCUART_FIFO_RXUF(0U) | /* Receiver Buffer Underflow Flag */ + FCUART_FIFO_TXFLUSH(1U) | /* Transmit FIFO/Buffer Flush */ + FCUART_FIFO_RXFLUSH(1U) | /* Receive FIFO/Buffer Flush */ + FCUART_FIFO_RXIDEN(pInitCfg->eFifoRxIdleCharNum) | /* Receiver Idle Empty Enable */ + FCUART_FIFO_TXOFIE(0U) | /* Transmit FIFO Overflow Interrupt Enable */ + FCUART_FIFO_RXUFIE(0U) | /* Receive FIFO Underflow Interrupt Enable */ + FCUART_FIFO_TXFEN(pInitCfg->bEnTxFifo) | /* Transmit FIFO Enable */ + FCUART_FIFO_TXFIFODEP(1U) | /* Transmit FIFO Buffer Depth */ + FCUART_FIFO_RXFEN(pInitCfg->bEnRxFifo) | /* Receive FIFO Enable, enable RX FIFO */ + FCUART_FIFO_RXFIFODEP(1U); /* Receive FIFO Buffer Depth */ + + /* temporary WATERMARK register */ + u32TempWatermarkReg = (uint32_t)0U | /* initial value */ + FCUART_WATERMARK_RXCOUNT(0U) | /* Receive Counter */ + FCUART_WATERMARK_RXWATER(pInitCfg->u8RxFifoWaterMark) | /* Receive WaterMark, receive n-1 request interrupt or DMA */ + FCUART_WATERMARK_TXCOUNT(0U) | /* Transmit Counter */ + FCUART_WATERMARK_TXWATER(pInitCfg->u8TxFifoWaterMark); /* Transmit WaterMark */ + + /* temporary MODIR register */ + u32TempModir = (uint32_t)0U | /* initial value */ + FCUART_MODIR_RXRTSCFG(0U) | /* Receive RTS Configuration */ + FCUART_MODIR_TXCTSSRC(0U) | /* Transmit CTS Source */ + FCUART_MODIR_TXCTSCFG(0U) | /* Transmit CTS Configuration */ + FCUART_MODIR_RXRTSEN(0U) | /* Receiver Request-to-Send Enable */ + FCUART_MODIR_TXRTSPOL(0U) | /* Transmitter Request-to-Send Polarity */ + FCUART_MODIR_TXRTSEN(0U) | /* Transmitter Request-to-Send Enable */ + FCUART_MODIR_TXCTSEN(0U); /* Transmitter Clear-to-Send Enable */ + + /* write register with temporary data */ + FCUART_HWA_SetBaud(pUart, u32TempBaudReg); /* 0x19000008; */ + FCUART_HWA_SetFifo(pUart, u32TempFifoReg); + FCUART_HWA_SetWaterMark(pUart, u32TempWatermarkReg); + FCUART_HWA_SetModir(pUart, u32TempModir); + + FCUART_HWA_SetCtrl(pUart, u32TempCtrlReg); + + /* clear all status */ + u32TempStat = FCUART_HWA_GetSTAT(pUart); + FCUART_HWA_WriteClearSTAT(pUart, u32TempStat); + FCUART_HWA_ClearFIFOErrorFlag(pUart); + + /* instance used */ + s_aFCUART_UartUsed[u8UartIndex] = 1U; + s_aFCUART_TransmitTimeout[u8UartIndex] = pInitCfg->u32TransmitTimeout > 0U ? pInitCfg->u32TransmitTimeout : 3000U; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_FAILED; + } + } + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + return tRetVal; +} + +/** + * @brief This Function is used to de-initial UART instance + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_DeInit(uint8_t u8UartIndex) +{ + FCUART_ErrorType tRetVal; + FCUART_Type *pUart; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if ((tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (s_aCurrentSequence[u8UartIndex] > FCUART_SEQUENCE_DEINIT)) + { + + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + /* set deinit state */ + s_aCurrentSequence[u8UartIndex] = FCUART_SEQUENCE_DEINIT; + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + FCUART_HWA_SetSoftWareReset(pUart); + } + + return tRetVal; +} + +/** + * @brief This Function is used to set UART interrupt + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pIntCfg contains callback functions + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_SetInterrupt(uint8_t u8UartIndex, FCUART_InterruptType *pInterruptCfg) +{ + FCUART_ErrorType tRetVal; + FCUART_Type *pUart; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if ((tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_NOTSTART_RECEIVE)) + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + if (pInterruptCfg != NULL) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + /* error interrupt */ + if (true == pInterruptCfg->bEnErrorInterrupt) + { + FCUART_HWA_EnableInterrupt(pUart, (uint32_t)(FCUART_INT_CTRL_ORIE |FCUART_INT_CTRL_NEIE |FCUART_INT_CTRL_FEIE |FCUART_INT_CTRL_PEIE)); + + s_aFCUART_ErrorNotifyTable[u8UartIndex] = pInterruptCfg->pErrorNotify; + } + else + { + FCUART_HWA_DisableInterrupt(pUart, (uint32_t)(FCUART_INT_CTRL_ORIE |FCUART_INT_CTRL_NEIE |FCUART_INT_CTRL_FEIE |FCUART_INT_CTRL_PEIE)); + } + + /* receive interrupt */ + if (true == pInterruptCfg->bEnRxInterrupt) + { + /* check buffer point if it is null */ + if (pInterruptCfg->pRxBuf != NULL) + { + FCUART_HWA_EnableInterrupt(pUart, (uint32_t)FCUART_INT_CTRL_RIE); + + s_aFCUART_RxMsg[u8UartIndex] = pInterruptCfg->pRxBuf; + s_aFCUART_RxNotifyTable[u8UartIndex] = pInterruptCfg->pRxNotify; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + } + else + { + FCUART_HWA_DisableInterrupt(pUart, (uint32_t)FCUART_INT_CTRL_RIE); + } + + /* Transfer interrupt */ + if (true == pInterruptCfg->bEnTxInterrupt) + { + /* check buffer point if it is null */ + if (pInterruptCfg->pTxBuf != NULL) + { + FCUART_HWA_EnableInterrupt(pUart, (uint32_t)FCUART_INT_CTRL_TIE); + s_aFCUART_TxMsg[u8UartIndex] = pInterruptCfg->pTxBuf; + s_aFCUART_TxEmptyNotifyTable[u8UartIndex] = pInterruptCfg->pTxEmptyNotify; + s_aFCUART_TxCompleteNotifyTable[u8UartIndex] = pInterruptCfg->pTxCompleteNotify; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + } + else + { + FCUART_HWA_DisableInterrupt(pUart, (uint32_t)FCUART_INT_CTRL_TIE); + } + + /* Idle interrupt */ + if (true == pInterruptCfg->bEnIdleInterrupt) + { + FCUART_HWA_EnableInterrupt(pUart, (uint32_t)FCUART_INT_CTRL_IIE); + s_aFCUART_IdleNotifyTable[u8UartIndex] = pInterruptCfg->pIdleNotify; + } + else + { + FCUART_HWA_DisableInterrupt(pUart, (uint32_t)FCUART_INT_CTRL_IIE); + } + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + } + else + { + /* No deal with */ + } + + return tRetVal; +} + +/** + * @brief This Function is used to set UART WakeUp + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pWakeupCfg contains UART wake-up parameters + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_SetWakeup(uint8_t u8UartIndex, FCUART_WakeupType *pWakeupCfg) +{ + FCUART_ErrorType tRetVal; + FCUART_Type *pUart; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if ((tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_NOTSTART_RECEIVE)) + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + + if (pWakeupCfg != NULL) + { + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + /* + * RWC MATCH0|MATCH1 MATCH_CFG [RSWMS,RWUID] Receiver Wakeup + 0 0 X X Normal operation + 1 0 00 00 Receiver wakeup on idle line, IDLE flag not set + 1 0 00 01 Receiver wakeup on idle line, IDLE flag set + 1 0 00 10 Receiver wakeup on address mark + 1 1 11 10 Receiver wakeup on address match + 0 1 00 X0 Address mark address match, IDLE flag not set for discarded characters + 0 1 00 X1 Address mark address match, IDLE flag set for discarded characters + 0 1 01 X0 Idle line address match + 0 1 10 X0 Address match on and address match off, IDLE flag not set for discarded characters + 0 1 10 X1 Address match on and address match off, IDLE flag set for discarded characters + * + */ + + FCUART_HWA_AttachCtrl(pUart, FCUART_CTRL_RWC_MASK | FCUART_CTRL_RSWMS_MASK); /* WakeUp enable and method select address-mark */ + FCUART_HWA_AttachBaud(pUart, FCUART_BAUD_MATCH_CFG(3U) | FCUART_BAUD_MAEN0(1U)); /* match0 data */ + FCUART_HWA_AttachMatch(pUart, FCUART_MATCH_MATCH0(pWakeupCfg->u32WakeUpData)); /* set wake-up data*/ + } + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + return tRetVal; +} + +/** + * @brief This Function is used to start receiving + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_StartReceive(uint8_t u8UartIndex) +{ + FCUART_ErrorType tRetVal; + FCUART_Type *pUart; + + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if((FCUART_ErrorType)FCUART_ERROR_OK == tRetVal) + { + if (s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_NOTSTART_RECEIVE) + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + /* set started receive state */ + s_aCurrentSequence[u8UartIndex] = FCUART_SEQUENCE_START_RECEIVE; + + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + /* start receive */ + FCUART_HWA_SetRxTransfer(pUart, true); + } + else + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + } + else + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + return tRetVal; +} + +/** + * @brief This Function is used to stop receiving + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_StopReceive(uint8_t u8UartIndex) +{ + FCUART_ErrorType tRetVal; + FCUART_Type *pUart; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if ((tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) && ((s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_START_RECEIVE) || (s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_NOTSTART_RECEIVE))) + { + + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + /* set stop state */ + s_aCurrentSequence[u8UartIndex] = FCUART_SEQUENCE_NOTSTART_RECEIVE; + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + /* stop receive */ + FCUART_HWA_SetRxTransfer(pUart, false); + } + + return tRetVal; +} + +/** + * @brief This Function is used to start transmit through interrupt + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_StartTransmit(uint8_t u8UartIndex) +{ + FCUART_ErrorType tRetVal; + FCUART_Type *pUart; + + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if((FCUART_ErrorType)FCUART_ERROR_OK == tRetVal) + { + + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + /* start transmit */ + FCUART_HWA_SetTxTransfer(pUart, true); + + if(false == FCUART_GetInterruptMode(u8UartIndex, (uint32_t)FCUART_INT_CTRL_TIE)) + { + FCUART_HWA_EnableInterrupt(pUart, (uint32_t)FCUART_INT_CTRL_TIE); + } + } + else + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + return tRetVal; +} + +/** + * @brief This Function is used to stop transmitting + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_StopTransmit(uint8_t u8UartIndex) +{ + FCUART_ErrorType tRetVal; + FCUART_Type *pUart; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + /* stop receive */ + FCUART_HWA_SetTxTransfer(pUart, false); + } + else + { + /* No deal with */ + } + + return tRetVal; +} + +/** + * @brief This Function is used to transmit UART data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pUartData contains UART data and length + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Transmit(uint8_t u8UartIndex, FCUART_DataType *pUartData) +{ + FCUART_ErrorType tRetVal; + + FCUART_Type *pUart; + uint8_t *pData; + uint32_t u32DataLen; + uint8_t u8Index; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if ((tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) &&((s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_START_RECEIVE) || (s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_NOTSTART_RECEIVE))) + { + + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + + if (pUartData != NULL) + { + if (pUartData->pDatas != NULL) + { + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pData = pUartData->pDatas; + u32DataLen = pUartData->u32DataLen; + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + for (u8Index = 0U; u8Index < u32DataLen; u8Index++) + { + tRetVal |= FCUART_LL_Transmit_Char(pUart, pData[u8Index], s_aFCUART_TransmitTimeout[u8UartIndex]); + + if (tRetVal != (FCUART_ErrorType)FCUART_ERROR_OK) + { + break; + } + } + } + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + return tRetVal; +} + +/** + * @brief Get Stat Flag + * + * @param u8UartIndex UART instance + * @param eStatusType stat type + * @return FCUART STAT status flag + */ +uint32_t FCUART_GetStatus(uint8_t u8UartIndex, FCUART_StatType eStatusType) +{ + FCUART_ErrorType tRetVal; + FCUART_Type *pUart; + uint32_t u32RetVal; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + u32RetVal = FCUART_HWA_GetStatus(pUart, eStatusType); + } + else + { + u32RetVal = 0U; + } + + return u32RetVal; +} + +/** + * @brief This Function is used to receive data when polling (not used when rx interrupt enabled) + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pRxMsg is data buffer address, and pDatas need to be initialed with external buffer + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Receive_Polling(uint8_t u8UartIndex, FCUART_DataType *pRxMsg) +{ + FCUART_ErrorType tRetVal; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if ((tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_START_RECEIVE)) + { + + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + + if (pRxMsg != NULL) + { + if (pRxMsg->pDatas != NULL) + { + if (s_aFCUART_UartUsed[u8UartIndex] == 1U) + { + tRetVal = FCUART_LL_Receive(u8UartIndex, pRxMsg); + } + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + + return tRetVal; +} + +/** + * @brief This Function is used to get error when polling (not used when error interrupt enabled) + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pErrorValue is error value + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Error_Polling(uint8_t u8UartIndex, uint32_t *pErrorValue) +{ + FCUART_ErrorType tRetVal; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if ((tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (s_aCurrentSequence[u8UartIndex] >= FCUART_SEQUENCE_NOTSTART_RECEIVE)) + { + + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + if (s_aFCUART_UartUsed[u8UartIndex] == 1U) + { + /* check error */ + *pErrorValue = FCUART_LL_Error(u8UartIndex); + } + else + { + tRetVal = (FCUART_ErrorType)FCUART_ERROR_FAILED; + } + } + + return tRetVal; +} + +/** + * @brief This Function is used to enable fcuart loop mode + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param bStatus enable/disable status of loop mode + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_SetLoopMode(uint8_t u8UartIndex, bool bStatus) +{ + FCUART_Type *pUart; + FCUART_ErrorType tRetVal; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + if (true == bStatus) + { + FCUART_HWA_EnableLoopMode(pUart); + } + else + { + FCUART_HWA_DisableLoopMode(pUart); + } + } + else + { + /* No deal with */ + } + return tRetVal; +} + +/** + * @brief This Function is used to send 9 bits data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param u16Data data to send + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_SendData_9Bits(uint8_t u8UartIndex, uint16_t u16Data) +{ + FCUART_Type *pUart; + FCUART_ErrorType tRetVal; + uint8_t u8SingleBit_8; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + u8SingleBit_8 = (uint8_t)((u16Data >> 8U) & 1U); + + /* Set bit8 */ + FCUART_HWA_SetR9T8(pUart, u8SingleBit_8); + /* Set 0 ~ 7 bits */ + FCUART_HWA_SetData(pUart, (uint8_t)u16Data); + } + else + { + /* No deal with */ + } + return tRetVal; + +} + +/** + * @brief This Function is used to Get 9 bits data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pData pointer to data + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_GetData_9Bits(uint8_t u8UartIndex, uint16_t *pData) +{ + FCUART_Type *pUart; + FCUART_ErrorType tRetVal; + uint8_t u8SingleBit_8; + uint8_t u8Temp; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + /* Get bit8 */ + u8SingleBit_8 = FCUART_HWA_GetR8T9(pUart); + /* Get 0 ~ 7 bits */ + u8Temp = FCUART_HWA_GetData(pUart); + /* Get 0 ~ 8 bits */ + *pData = (((uint16_t)u8SingleBit_8 << 8U) | (uint16_t)u8Temp); + } + else + { + /* No deal with */ + } + return tRetVal; + +} + +/** + * @brief This Function is used to send 10 bits data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param u16Data data to send + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_SendData_10Bits(uint8_t u8UartIndex, uint16_t u16Data) +{ + FCUART_Type *pUart; + FCUART_ErrorType tRetVal; + uint8_t u8SingleBit_8; + uint8_t u8SingleBit_9; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + u8SingleBit_8 = (uint8_t)((u16Data >> 8U) & 1U); + u8SingleBit_9 = (uint8_t)((u16Data >> 9U) & 1U); + + /* Set bit8 */ + FCUART_HWA_SetR9T8(pUart, u8SingleBit_8); + /* Set bit9 */ + FCUART_HWA_SetR8T9(pUart, u8SingleBit_9); + /* Set 0 ~ 7 bits */ + FCUART_HWA_SetData(pUart, (uint8_t)u16Data); + } + else + { + /* No deal with */ + } + return tRetVal; + +} + +/** + * @brief This Function is used to Get 10 bits data + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pData pointer to data + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_GetData_10Bits(uint8_t u8UartIndex, uint16_t *pData) +{ + FCUART_Type *pUart; + FCUART_ErrorType tRetVal; + uint8_t u8SingleBit_8; + uint8_t u8SingleBit_9; + uint8_t u8Temp; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + /* Get bit8 */ + u8SingleBit_8 = FCUART_HWA_GetR8T9(pUart); + /* Get bit9 */ + u8SingleBit_9 = FCUART_HWA_GetR9T8(pUart); + /* Get 0 ~ 7 bits */ + u8Temp = FCUART_HWA_GetData(pUart); + /* Get 0 ~ 9 bits */ + *pData = (((uint16_t)u8SingleBit_8 << 8U) | ((uint16_t)u8SingleBit_9 << 9U) | (uint16_t)u8Temp); + } + else + { + /* No deal with */ + } + return tRetVal; + +} + +/** + * @brief This Function is used to set bit mode,parity and stop bit + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pData pointer to data + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_SetBitModeAndParity( uint8_t u8UartIndex, + FCUART_BitModeType eBitMode, + FCUART_StopBitNumType eStopBit, + FCUART_ParityType eParityType, + bool bParityEnable + ) +{ + FCUART_Type *pUart; + FCUART_ErrorType tRetVal; + + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + FCUART_HWA_SetBitMode(pUart, eBitMode); + FCUART_HWA_SetStopBit(pUart, eStopBit); + FCUART_HWA_SetParity(pUart, eParityType, bParityEnable); + } + else + { + /* No deal with */ + } + return tRetVal; +} + +/** + * @brief This Function is used to Get current interrupt mode + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param u32Data Interrupt type to get + * @return true/false + * + */ +bool FCUART_GetInterruptMode(uint8_t u8UartIndex, uint32_t u32Data) +{ + FCUART_ErrorType tTempVal; + bool bRetVal; + FCUART_Type *pUart; + uint32_t u32CtrlRegData; + + /* check parameter */ + tTempVal = FCUART_LL_CheckInstance(u8UartIndex); + if (tTempVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + u32CtrlRegData = FCUART_HWA_GetCtrl(pUart); + bRetVal = ((u32CtrlRegData & u32Data) > 0U ) ? true : false; + } + else + { + bRetVal = false; + } + + return bRetVal; +} + +/** + * @brief This Function is used to assign data to send through interrupt + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param pData data pointer + * @param u32Length data length to send + * @return FCUART_ERROR_OK is ok, others are not ok + * + */ +FCUART_ErrorType FCUART_AssignTxInterruptData(uint8_t u8UartIndex, uint8_t * pData, uint32_t u32Length) +{ + FCUART_ErrorType tTempVal; + /* check parameter */ + tTempVal = FCUART_LL_CheckInstance(u8UartIndex); + if (tTempVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + if(pData != NULL) + { + s_aFCUART_TxMsg[u8UartIndex]->pDatas = pData; + s_aFCUART_TxMsg[u8UartIndex]->u32DataLen = u32Length; + } + else + { + tTempVal = (FCUART_ErrorType)FCUART_ERROR_INVALID_PARAM; + } + } + else + { + /* No deal with */ + } + + return tTempVal; +} + + +/* ################################################################################## */ +/* ############################## Interrupt Services ################################ */ +/** + * @brief This Function is used to deal with FCUART TxRx interrupt + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * + */ +void FCUARTN_RxTx_IRQHandler(uint8_t u8UartIndex) +{ + FCUART_ErrorType tTempVal; + FCUART_DataType *pRxMsgList; + FCUART_DataType *pTxMsgList; + uint32_t u32ErrorValue; + uint32_t u32CtrlRegData; + + //Do not check instance because it should be checked before + u32CtrlRegData = FCUART_HWA_GetCtrl((FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]); + + /* Handle receive interrupt */ + if(((uint32_t)FCUART_INT_CTRL_RIE) == (u32CtrlRegData & ((uint32_t)FCUART_INT_CTRL_RIE))) + { + /* get buffer point and it stored when called SetInterrupt */ + pRxMsgList = s_aFCUART_RxMsg[u8UartIndex]; + /* check pUart receive data */ + tTempVal = FCUART_LL_Receive(u8UartIndex, pRxMsgList); + + /* check buffer valid */ + if ( (tTempVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (pRxMsgList != NULL)) + { + if (s_aFCUART_RxNotifyTable[u8UartIndex] != NULL) + { + s_aFCUART_RxNotifyTable[u8UartIndex](u8UartIndex, pRxMsgList); + } + } + } + + /* Handle transmit interrupt */ + if(((uint32_t)FCUART_INT_CTRL_TIE) == (u32CtrlRegData & ((uint32_t)FCUART_INT_CTRL_TIE))) + { + /* get buffer point and it stored when called SetInterrupt */ + pTxMsgList = s_aFCUART_TxMsg[u8UartIndex]; + /* transfer data */ + tTempVal = FCUART_LL_Transmit_Empty(u8UartIndex, pTxMsgList); + + if((tTempVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (pTxMsgList != NULL)) + { + if (s_aFCUART_TxEmptyNotifyTable[u8UartIndex] != NULL) + { + s_aFCUART_TxEmptyNotifyTable[u8UartIndex](u8UartIndex, pTxMsgList); + } + } + } + + /* Handle transmit complete interrupt */ + if(((uint32_t)FCUART_INT_CTRL_TCIE) == (u32CtrlRegData & ((uint32_t)FCUART_INT_CTRL_TCIE))) + { + tTempVal = FCUART_LL_Transmit_Complete(u8UartIndex); + + if ((tTempVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (s_aFCUART_TxCompleteNotifyTable[u8UartIndex] != NULL)) + { + s_aFCUART_TxCompleteNotifyTable[u8UartIndex](u8UartIndex, NULL); + } + } + + /* Handle idle interrupt */ + if(((uint32_t)FCUART_INT_CTRL_IIE) == (u32CtrlRegData & ((uint32_t)FCUART_INT_CTRL_IIE))) + { + tTempVal = FCUART_LL_Idle(u8UartIndex); + if ((tTempVal == (FCUART_ErrorType)FCUART_ERROR_OK) && (s_aFCUART_IdleNotifyTable[u8UartIndex] != NULL)) + { + s_aFCUART_IdleNotifyTable[u8UartIndex](u8UartIndex); + } + } + + /* Handle error interrupt */ + if(0U != (u32CtrlRegData & ((uint32_t)(FCUART_INT_CTRL_ORIE | FCUART_INT_CTRL_NEIE | FCUART_INT_CTRL_FEIE | FCUART_INT_CTRL_PEIE)))) + { + /* check error */ + u32ErrorValue = FCUART_LL_Error(u8UartIndex); + + if ((u32ErrorValue != 0U) && (s_aFCUART_ErrorNotifyTable[u8UartIndex] != NULL)) + { + s_aFCUART_ErrorNotifyTable[u8UartIndex](u8UartIndex, u32ErrorValue); + } + + PROCESS_UNUSED_VAR(u32ErrorValue) + } +} + +/************************ Uart Print Library ************************/ + +/** + * @brief This Function is used to print ASCII char from UART + * + * @param u8UartIndex is UART instance, 0U..(FCUART_INSTANCE_COUNT-1U) + * @param fmt is char format + * @return FCUART_ERROR_OK is ok, others are not ok + */ +FCUART_ErrorType FCUART_Printf(uint8_t u8UartIndex, char *fmt, ...) +{ + FCUART_Type *pUart; + FCUART_ErrorType tRetVal; + const char *pStr; + int i32Temp; + unsigned char TxData; + uint8_t u8Number; + uint8_t u8LenthNumber = 4U; + char TempBuffer[16]; + va_list ap; + + va_start(ap, fmt); + /* check parameter */ + tRetVal = FCUART_LL_CheckInstance(u8UartIndex); + + if ((tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) && ((s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_START_RECEIVE) || (s_aCurrentSequence[u8UartIndex] == FCUART_SEQUENCE_NOTSTART_RECEIVE))) + { + + tRetVal = (FCUART_ErrorType)FCUART_ERROR_OK; + } + else + { + tRetVal |= (FCUART_ErrorType)FCUART_ERROR_INVALID_SEQUENCE; + } + + if (tRetVal == (FCUART_ErrorType)FCUART_ERROR_OK) + { + pUart = (FCUART_Type *)s_aFCUART_InstanceTable[u8UartIndex]; + + while (*fmt != (char)0) + { + /* Escape character */ + if ((*fmt) == ESCAPE_CHARACTER) + { + switch (*(++fmt)) + { + case 'r': + { + TxData = ENTER; + tRetVal = FCUART_LL_Transmit_Char(pUart, TxData, s_aFCUART_TransmitTimeout[u8UartIndex]); + fmt++; + } + break; + + case 'n': + { + TxData = NEW_LINE; + tRetVal = FCUART_LL_Transmit_Char(pUart, TxData, s_aFCUART_TransmitTimeout[u8UartIndex]); + fmt++; + } + break; + + default: + fmt++; + break; + } + } + else if ((*fmt) == (char)'%') + { + switch (*(++fmt)) + { + case 's': + { + pStr = va_arg(ap, const char *); + for (; *pStr; pStr++) + { + tRetVal = FCUART_LL_Transmit_Char(pUart, *((unsigned char *)pStr), s_aFCUART_TransmitTimeout[u8UartIndex]); + } + fmt++; + } + break; + + case 'd': + { + i32Temp = va_arg(ap, int); + if (0U == FCUART_Int2Char(i32Temp, TempBuffer, UART_PRINT_RADIX_DEC, false)) + { + for (pStr = TempBuffer; *pStr; pStr++) + { + tRetVal = FCUART_LL_Transmit_Char(pUart, *((unsigned char *)pStr), s_aFCUART_TransmitTimeout[u8UartIndex]); + } + } + fmt++; + } + break; + + case 'x': + { + i32Temp = va_arg(ap, int); + if (0U == FCUART_Int2Char(i32Temp, TempBuffer, UART_PRINT_RADIX_HEX, false)) + { + for (pStr = TempBuffer; *pStr; pStr++) + { + tRetVal = FCUART_LL_Transmit_Char(pUart, *((unsigned char *)pStr), s_aFCUART_TransmitTimeout[u8UartIndex]); + } + } + fmt++; + } + break; + + case 'X': + { + i32Temp = va_arg(ap, int); + if (0U == FCUART_Int2Char(i32Temp, TempBuffer, UART_PRINT_RADIX_HEX, true)) + { + for (pStr = TempBuffer; *pStr; pStr++) + { + tRetVal = FCUART_LL_Transmit_Char(pUart, *((unsigned char *)pStr), s_aFCUART_TransmitTimeout[u8UartIndex]); + } + } + fmt++; + } + break; + + case '.': + { + u8Number = (uint8_t)(*(++fmt) - '0'); + if ((*(++fmt)) == 'f') + { + double num = va_arg(ap, double); + if (0U == FCUART_Float2Char(num, TempBuffer, u8Number)) + { + for (pStr = TempBuffer; *pStr; pStr++) + { + tRetVal = FCUART_LL_Transmit_Char(pUart, *((unsigned char *)pStr), s_aFCUART_TransmitTimeout[u8UartIndex]); + } + } + fmt++; + } + } + break; + + case 'f': + { + double num = va_arg(ap, double); + if (0U == FCUART_Float2Char(num, TempBuffer, u8LenthNumber)) + { + for (pStr = TempBuffer; *pStr; pStr++) + { + tRetVal = FCUART_LL_Transmit_Char(pUart, *((unsigned char *)pStr), s_aFCUART_TransmitTimeout[u8UartIndex]); + } + } + fmt++; + } + break; + + default: + fmt++; + break; + } + } + else + { + tRetVal = FCUART_LL_Transmit_Char(pUart, *((unsigned char *)fmt), s_aFCUART_TransmitTimeout[u8UartIndex]); + + if (tRetVal != FCUART_ERROR_OK) + { + break; + } + + fmt++; + } + } + } + + va_end(ap); + + return tRetVal; +} + +/** + * @brief Convert integer to char + * + * @param i32Value + * @param pOutStr + * @param eRadix + * @return 0 is ok + */ +static uint8_t FCUART_Int2Char(int i32Value, char *pOutStr, UART_PrintIntType eRadix, bool bHexUpper) +{ + uint8_t u8Retval; + char aCharListUpper[] = "0123456789ABCDEF"; + char aCharListLower[] = "0123456789abcdef"; + char aNumList[] = "0123456789"; + char *pCharList; + uint32_t u32Temp; + uint8_t u8Index = 0U; + uint8_t u8ValueStart = 0U; + char Temp = 0; + uint32_t j; + + if (NULL == pOutStr) + { + u8Retval = 1U; + } + else + { + u8Retval = 0U; + if ((UART_PRINT_RADIX_DEC == eRadix) && (i32Value < 0)) + { + // Decimal and negative + u32Temp = (uint32_t)(0 - i32Value); + pOutStr[u8Index++] = '-'; + u8ValueStart = 1U; + pCharList = aNumList; + } + else + { + if (true == bHexUpper) + { + pCharList = aCharListUpper; + } + else + { + pCharList = aCharListLower; + } + u32Temp = (uint32_t)i32Value; + } + + // Data is converted to a string and stored in reverse order + do + { + pOutStr[u8Index++] = pCharList[u32Temp % (uint8_t)eRadix]; + u32Temp /= (uint8_t)eRadix; + } while (u32Temp); + + pOutStr[u8Index] = '\0'; + + // Convert the string with reverse order to positive + for (j = u8ValueStart; j < (u8Index + u8ValueStart) / 2U; j++) + { + Temp = pOutStr[j]; + pOutStr[j] = pOutStr[u8Index - j - 1U + u8ValueStart]; + pOutStr[u8Index - j - 1U + u8ValueStart] = Temp; + } + } + return u8Retval; +} + +/** + * @brief Convert float to char + * + * @param Value + * @param pOutStr + * @param U32Eps + * @return 0 is ok + */ +static uint8_t FCUART_Float2Char(double Value, char *pOutStr, uint32_t u32Eps) +{ + uint32_t u32Integer; + double Decimal; + char aCharList[] = "0123456789"; + uint8_t u8ValueStart = 0U; + uint32_t u32TempCnt = 1U; + char Temp = 0; + double TempFactor = 0.1; + uint8_t u8Index = 0U; + uint32_t u32TempDecimal; + uint8_t u8Retval; + uint32_t j; + + if (NULL == pOutStr) + { + u8Retval = 1U; + } + else + { + u8Retval = 0U; + // Extract integer and decimal from the input number + if (Value < FLOAT_ZERO) + { + Decimal = (double)((int32_t)Value - Value); + u32Integer = (uint32_t)(0.0 - Value); + pOutStr[u8Index++] = '-'; + u8ValueStart = 1U; + } + else + { + u32Integer = (uint32_t)Value; + Decimal = (double)(Value - u32Integer); + } + // The integer part of the data is converted into a string and stored in reverse order + do + { + pOutStr[u8Index++] = aCharList[u32Integer % 10U]; + u32Integer /= 10U; + } while (0U != u32Integer); + + pOutStr[u8Index] = '\0'; + + // Convert the string with reverse order to positive + for (j = u8ValueStart; j < (u8Index + u8ValueStart) / 2U; j++) + { + Temp = pOutStr[j]; + pOutStr[j] = pOutStr[u8Index - j - 1U + u8ValueStart]; + pOutStr[u8Index - j - 1U + u8ValueStart] = Temp; + } + + // Accuracy problem, preventing input 1.2 and output 1.19 + for (j = 0U; j <= u32Eps; j++) + { + TempFactor *= 0.1; + } + Decimal += TempFactor; + + for (j = 0; j < u32Eps; j++) + { + Decimal *= (double)10.0; + u32TempCnt *= 10U; + } + + u32TempDecimal = (uint32_t)Decimal; + pOutStr[u8Index++] = '.'; + for (j = 0; j < u32Eps; j++) + { + u32TempCnt /= 10U; + if (0U != u32TempCnt) + { + pOutStr[u8Index++] = u32TempDecimal / u32TempCnt + '0'; + u32TempDecimal %= u32TempCnt; + } + } + pOutStr[u8Index] = '\0'; + } + return u8Retval; +} diff --git a/Src/fc7xxx_driver_flash.c b/Src/fc7xxx_driver_flash.c new file mode 100644 index 0000000..355ed08 --- /dev/null +++ b/Src/fc7xxx_driver_flash.c @@ -0,0 +1,998 @@ +/** + * @file fc7xxx_driver_flash.c + * @author Flagchip + * @brief FC7xxx Flash driver source code + * @version 0.1.0 + * @date 2024-01-11 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-11 Flagchip054 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_flash.h" + +/* ################################################################################## */ +/* ####################################### Macro #################################### */ + +#define STATUS_SUCCESS 0x001UL +#define STATUS_HVOP 0x8001UL +#define FLASH_API_DISABLE 0x0UL +#define FLASH_API_ENABLE 0x1UL +#define FLASH_API_SIZE_8M 0x0UL +#define WDG_TUNE_DISABLE 0x1u +#define FLASH_AUTO_HOLD_ENABLE 0x1UL +#define FLASH_AUTO_HOLD_DISABLE 0x0UL +#define FLASH_REG_BIT_CFG_DISABLE 0x0UL +#define FLASH_REG_BIT_CFG_ENABLE 0x1UL +#define FLASH_REG_BIT_CFG_HOLD 0x2UL + +#define INVAILD_ADDR ((void*)0xFFFFFFFFU) + +#define FLS_MAX_ERASE_BLANK_CHECK (256U) + +#define FLS_ABT_TIMEOUT_VALUE (1000000U) +#define FLS_ASYNC_WRITE_TIMEOUT_VALUE (1000U) +#define FLS_ASYNC_ERASE_TIMEOUT_VALUE (500000U) +/*================================================================================================= +* LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS) +=================================================================================================*/ + +typedef uint32_t status_t; + +typedef struct { + uint32_t blk_sel; + uint32_t dest; +} FLASH_DRV_ERASESECTOR_CFG_T; + +typedef struct { + uint32_t dest; + uint32_t size; + uint32_t *pData; + uint32_t wdg_tune; + uint32_t pgff; +} FLASH_DRV_PRGM_CFG_T; + + +typedef struct +{ + uint16 u16FlashRomApiMajorVersion; + uint16 u16FlashRomApiMinorVersion; + + status_t (*FLASH_DRV_EraseBlock)(FLASH_API_BLOCK_SELECT_TYPE blk_se, uint32_t int_en, uint32_t type); + status_t (*FLASH_DRV_EraseBlock_Clear)(void); + status_t (*FLASH_DRV_EraseSector)(FLASH_DRV_ERASESECTOR_CFG_T * flash_api_cfg, uint32_t int_en, uint32_t type); + status_t (*FLASH_DRV_EraseSector_Clear)(void); + uint32_t RESERVED2[2U]; + status_t (*FLASH_DRV_Program)(FLASH_DRV_PRGM_CFG_T * flash_api_cfg, uint32_t int_en, uint32_t type); + status_t (*FLASH_DRV_Program_Clear)(void); + uint32_t RESERVED3[6U]; + status_t (*FLASH_DRV_HV_Status_Check)(void); + uint32_t RESERVED4[8U]; + status_t (*FLASH_DRV_ENABLE_HOLD_CFG)(uint32_t flash_api_cfg); +}FLASH_ROM_API_ENTRY_T; + + +/** flash driver header for finding function in special address */ +#define FLASHAPI_IN_ROM_ADDR 0x04810200U /* flash api address in rom */ +const FLASH_ROM_API_ENTRY_T *s_pFlashDriver_RomApiHeader; + +/* ################################################################################## */ +/* ################################ Local Variables ################################# */ + + +/* ################################################################################## */ +/* ########################### Local Prototype Functions ############################ */ + + +/* ################################################################################## */ +/* ########################### Global Prototype Functions ########################### */ + + + + +/* ################################################################################## */ +/* ################################ Local Functions ################################# */ + + +/** + * \brief PFlash Driver Function for Erasing Address Check + * + * \param pFlashParam flash driver erase parameter + */ +static FLASH_StatusType FLASHDRIVER_LL_PFlashEraseCheck(FLASH_DRIVER_ParamType *pFlashParam) +{ + FLASH_StatusType tRetVal; + + if (s_pFlashDriver_RomApiHeader != (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR) + { + tRetVal = FLASH_ERROR_NO_INIT; + } + else + { + tRetVal = FLASH_ERROR_OK; + /* check address align */ + if (pFlashParam->u32Address & (PFLASH_ERASE_SECTOR_SIZE - 1U)) + { + tRetVal = FLASH_ERROR_INVALID_ADDR; + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + + } + else + { + /* check length align */ + if (pFlashParam->u32Length & (PFLASH_ERASE_SECTOR_SIZE - 1U)) + { + tRetVal = FLASH_ERROR_INVALID_SIZE; + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + } + + } + } + return tRetVal; +} + +/** + * \brief DFlash Driver Function for Erasing Address Check + * + * \param pFlashParam flash driver erase parameter + */ +static FLASH_StatusType FLASHDRIVER_LL_DFlashEraseCheck(FLASH_DRIVER_ParamType *pFlashParam) +{ + FLASH_StatusType tRetVal; + + if (s_pFlashDriver_RomApiHeader != (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR) + { + tRetVal = FLASH_ERROR_NO_INIT; + } + else + { + + tRetVal = FLASH_ERROR_OK; + + /* check address align */ + if (pFlashParam->u32Address & (DFLASH_ERASE_SECTOR_SIZE - 1U)) + { + tRetVal = FLASH_ERROR_INVALID_ADDR; + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + + } + else + { + /* check length align */ + if (pFlashParam->u32Length & (DFLASH_ERASE_SECTOR_SIZE - 1U)) + { + tRetVal = FLASH_ERROR_INVALID_SIZE; + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + } + + } + + } + return tRetVal; +} + +/** + * \brief PFlash Driver Function for Writing address Check + * + * \param pFlashParam flash driver write parameter + */ +static FLASH_StatusType FLASHDRIVER_PFlashWriteCheck(FLASH_DRIVER_ParamType *pFlashParam) +{ + FLASH_StatusType tRetVal; + + if (s_pFlashDriver_RomApiHeader != (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR) + { + tRetVal = FLASH_ERROR_NO_INIT; + } + else + { + tRetVal = FLASH_ERROR_OK; + + /* check address align */ + if (pFlashParam->u32Address & (PFLASH_PROGRAM_PAGE_MIN_SIZE - 1U)) + { + tRetVal = FLASH_ERROR_INVALID_ADDR; + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + } + + else + { + /* check length align */ + if (pFlashParam->u32Length & (PFLASH_PROGRAM_PAGE_MIN_SIZE - 1U)) + { + tRetVal = FLASH_ERROR_INVALID_SIZE; + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + } + } + } + return tRetVal; +} + +/** + * \brief DFlash Driver Function for Writing address Check + * + * \param pFlashParam flash driver write parameter + */ +static FLASH_StatusType FLASHDRIVER_DFlashWriteCheck(FLASH_DRIVER_ParamType *pFlashParam) +{ + FLASH_StatusType tRetVal; + + if (s_pFlashDriver_RomApiHeader != (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR) + { + tRetVal = FLASH_ERROR_NO_INIT; + } + else + { + tRetVal = FLASH_ERROR_OK; + + /* check address align */ + if (pFlashParam->u32Address & (DFLASH_PROGRAM_PAGE_MIN_SIZE - 1U)) + { + tRetVal = FLASH_ERROR_INVALID_ADDR; + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + } + + else + { + /* check length align */ + if (pFlashParam->u32Length & (DFLASH_PROGRAM_PAGE_MIN_SIZE - 1U)) + { + tRetVal = FLASH_ERROR_INVALID_SIZE; + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + } + } + } + return tRetVal; +} + +/** + * \brief PFlash Driver Function for lock/unlock sector + * + * \param u32Address sector address + * \param bLock 0U-unlock, 1U-lock + */ +static void FLASHDRIVER_PFlashLockBlock(FLASH_API_BLOCK_SELECT_TYPE blk_sel, uint8_t bLock) +{ + uint32_t u32Index; + uint32_t u32Temp; + + u32Index = (uint32_t)blk_sel; + /* 1 bank contains more than 256KB, used FB_CPELCK for first and last 256KB used FB_FPELCK */ + /* PFLASH bank index */ + u32Temp = bLock ? 0xFFFFFFFFUL : 0x0UL; + if(blk_sel < FLASH_DATA_BLOCK_SELECT0) + { + FMC1->FB_CPELCK[u32Index] = u32Temp; + FMC1->FB_FPELCK[u32Index] = u32Temp; + } + else + { + FMC1->FB_FPELCK[u32Index] = u32Temp; + } +} + +/** + * \brief PFlash Driver Function for lock/unlock sector + * + * \param u32Address sector address + * \param bLock 0U-unlock, 1U-lock + */ +static FLASH_StatusType FLASHDRIVER_PFlashLockSector(uint32_t u32Address, uint8_t bLock) +{ + FLASH_StatusType tRetVal; + uint32_t u32Index; + uint32_t u32Length; + uint32_t u32Temp; + + tRetVal = FLASH_ERROR_OK; + + /* 1 bank contains more than 256KB, used FB_CPELCK for first and last 256KB used FB_FPELCK */ + if ((u32Address >= PFLASH_ADDR_START) && (u32Address <= PFLASH_ADDR_END)) + { + /* PFLASH bank index */ + u32Index = (u32Address - PFLASH_ADDR_START) / PFLASH_BANK_SIZE; + u32Length = ((u32Address - PFLASH_ADDR_START) % PFLASH_BANK_SIZE) ; + if (u32Length < (PFLASH_BANK_SIZE - FLASH_256KB_SIZE)) /* first 1792KB */ + { + u32Temp = ((uint32_t)1UL << ((u32Address - PFLASH_ADDR_START - PFLASH_BANK_SIZE * u32Index) >> 16)); + u32Temp = bLock ? 0xFFFFFFFFUL : (0xFFFFFFFFUL ^ u32Temp); + FMC1->FB_CPELCK[u32Index] = u32Temp; + } + else /* last 256KB */ + { + u32Temp = ((u32Address - PFLASH_ADDR_START - PFLASH_BANK_SIZE * u32Index - PFLASH_LAST256K_OFFSET) >> 13); + u32Temp = ((uint32_t)1UL << u32Temp); + u32Temp = bLock ? 0xFFFFFFFFUL : (0xFFFFFFFFUL ^ u32Temp); + /* 0x1C0000UL */ + FMC1->FB_FPELCK[u32Index] = u32Temp; + } + } + else + { + tRetVal = FLASH_ERROR_INVALID_ADDR; + } + return tRetVal; +} + +/** + * \brief DFlash Driver Function for lock/unlock sector + * + * \param u32Address sector address + * \param bLock 0U-unlock, 1U-lock + */ +static FLASH_StatusType FLASHDRIVER_DFlashLockSector(uint32_t u32Address, uint8_t bLock) +{ + FLASH_StatusType tRetVal; + uint32_t u32Index; + uint32_t u32Temp; + tRetVal = FLASH_ERROR_OK; + + /* 1 bank contains only 256KB, only used FB_FPELCK */ + u32Index = 2U; + if ((u32Address >= DFLASH_ADDR_START) && (u32Address <= DFLASH_ADDR_END)) + { + u32Temp = 0xFFFFFFFFUL ^ (1UL << ((u32Address - DFLASH_ADDR_START - DFLASH_BANK0_SIZE * (u32Index - 2U)) >> 13)); + FMC1->FB_FPELCK[u32Index] = bLock ? 0xFFFFFFFFUL : u32Temp ; + } + else + { + tRetVal = FLASH_ERROR_INVALID_ADDR; + } + return tRetVal; +} + +/** + * \brief Get Flash Configuration + * + * \param u32Address the flash address + * \param pFlash_api_cfg out flash parameter + */ +static FLASH_StatusType FLASHDRIVER_GetFlashConfig(uint32_t u32Address, FLASH_DRV_ERASESECTOR_CFG_T *pFlash_api_cfg) +{ + FLASH_StatusType tRetVal; + tRetVal = FLASH_ERROR_OK; + + if ((u32Address >= PFLASH_ADDR_START) && (u32Address < PFLASH_ADDR_START + PFLASH_BANK_SIZE)) + { + pFlash_api_cfg->blk_sel = FLASH_BLOCK_SELECT0; + pFlash_api_cfg->dest = u32Address; + + } + else if ((u32Address >= PFLASH_ADDR_START) && (u32Address < PFLASH_ADDR_START + PFLASH_BANK_SIZE*2U)) + { + pFlash_api_cfg->blk_sel = FLASH_BLOCK_SELECT1; + pFlash_api_cfg->dest = u32Address; + } + else if ((u32Address >= DFLASH_ADDR_START) && (u32Address < DFLASH_ADDR_START + DFLASH_BANK0_SIZE)) + { + pFlash_api_cfg->blk_sel = FLASH_DATA_BLOCK_SELECT0; + pFlash_api_cfg->dest = u32Address; + } + else + { + tRetVal = FLASH_ERROR_INVALID_ADDR; + } + return tRetVal; +} + +/* ################################################################################## */ +/* ################################# Global Functions ############################### */ + +void FLASHDRIVER_Init(void) +{ + s_pFlashDriver_RomApiHeader = (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR; +} + +/** + * \brief PFlash Driver Function for Erasing + * + * \param pFlashParam flash driver erase parameter + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_FlashEraseBlock(FLASH_API_BLOCK_SELECT_TYPE blk_sel) +{ + uint32_t u32TryCount; + + FLASH_StatusType tRetVal; + uint32_t u32Temp; + + tRetVal = FLASH_ERROR_OK; + + if(blk_sel > FLASH_DATA_BLOCK_SELECT0) + { + tRetVal = FLASH_ERROR_INVALID_PARAM; + } + else + { + s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE); + FLASHDRIVER_PFlashLockBlock(blk_sel, 0); + __asm(" cpsid i"); + u32Temp = s_pFlashDriver_RomApiHeader-> FLASH_DRV_EraseBlock(blk_sel, FLASH_API_DISABLE, 0); + __asm(" cpsie i"); + tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + /* check erase operation valid */ + if (tRetVal != FLASH_ERROR_OK) + { + + } + else + { + /* check erasing still in progress */ + tRetVal = FLASH_ERROR_FAILED; + u32TryCount = 0; + while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 1000000)) + { + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check(); + /* check if finished */ + if (u32Temp == STATUS_HVOP) + { + tRetVal = FLASH_ERROR_FAILED; + } + else + { + tRetVal = FLASH_ERROR_OK; + } + } + + if (tRetVal != FLASH_ERROR_OK) + { + /* erasing timeout, exit */ + *(uint32_t*)(0x00000014U) = *((uint32_t*)0x40020004U); + } + else + { + /* check erasing result */ + u32Temp = s_pFlashDriver_RomApiHeader-> FLASH_DRV_EraseBlock_Clear(); + tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + } + } + } + return tRetVal; +} + +/** + * \brief PFlash Driver Function for Erasing + * + * \param pFlashParam flash driver erase parameter + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_PFlashEraseSector(FLASH_DRIVER_ParamType *pFlashParam) +{ + uint32_t u32Addr, u32Length; + uint32_t u32TryCount; + FLASH_DRV_ERASESECTOR_CFG_T tFlash_api_cfg; + + FLASH_StatusType tRetVal; + uint32_t u32Temp; + + tRetVal = FLASH_ERROR_OK; + + /* FLASH_DRV_WDG_CFG_T tFlash_wdg_cfg; */ + + u32Addr = pFlashParam->u32Address; + u32Length = pFlashParam->u32Length; + + tRetVal = FLASH_ERROR_OK; + pFlashParam->u32ErrorAddress = 0x0U; + + tRetVal = FLASHDRIVER_LL_PFlashEraseCheck(pFlashParam); + + if (tRetVal == FLASH_ERROR_OK) + { + /* config flash wdog */ + //ConfigFlashWdog(); + + s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE); + + + pFlashParam->u32Length = PFLASH_ERASE_SECTOR_SIZE; + + /* loop erase */ + for (pFlashParam->u32Address = u32Addr; pFlashParam->u32Address < u32Addr + u32Length; + pFlashParam->u32Address += PFLASH_ERASE_SECTOR_SIZE) + { + + FLASHDRIVER_PFlashLockSector(pFlashParam->u32Address, 0U); + FLASHDRIVER_GetFlashConfig(pFlashParam->u32Address, &tFlash_api_cfg); + /* start erase */ + __asm(" cpsid i"); + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_EraseSector(&tFlash_api_cfg, FLASH_API_DISABLE, 0); + __asm(" cpsie i"); + tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + + + /* check erase operation valid */ + if (tRetVal != FLASH_ERROR_OK) + { + /* erase operation failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + /* check erasing still in progress */ + tRetVal = FLASH_ERROR_FAILED; + u32TryCount = 0; + while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 100000)) + { + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check(); + /* check if finished */ + if (u32Temp == STATUS_HVOP) + { + tRetVal = FLASH_ERROR_FAILED; + } + else + { + tRetVal = FLASH_ERROR_OK; + } + } + + if (tRetVal != FLASH_ERROR_OK) + { + /* erasing timeout, exit */ + *(uint32_t*)(0x00000014U) = *((uint32_t*)0x40020004U); + break; + } + else + { + /* check erasing result */ + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_EraseSector_Clear(); + tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + + if (tRetVal != FLASH_ERROR_OK) + { + /* erasing failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + + if (tRetVal != FLASH_ERROR_OK) + { + /* erasing failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + + /* trigger watchdog function */ + if (pFlashParam->wdTriggerFct != ((void *)0)) + { + pFlashParam->wdTriggerFct(); + } + } + + + } + } + } + /* lock sector */ + FLASHDRIVER_PFlashLockSector(pFlashParam->u32Address, 1U); + } + } + return tRetVal; +} + +/** + * \brief PFlash Driver Function for Writing + * + * \param pFlashParam flash driver write parameter + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_PFlashWrite(FLASH_DRIVER_ParamType *pFlashParam) +{ + uint32_t u32Addr, u32Length, u32DataAddr, u32AlignLen, u32TempLen; + /* uint8_t *pTempBuf; */ + uint32_t u32AlignOffset, u32Index, u32Count; + uint32_t u32TryCount; + FLASH_DRV_PRGM_CFG_T tFlash_api_cfg; + + FLASH_StatusType tRetVal; + uint32_t u32Temp; + + + tRetVal = FLASH_ERROR_OK; + + u32Addr = pFlashParam->u32Address; + u32Length = pFlashParam->u32Length; + + pFlashParam->u32ErrorAddress = 0x0U; + + + tRetVal = FLASHDRIVER_PFlashWriteCheck(pFlashParam); + + if (tRetVal == FLASH_ERROR_OK) + { + /* config flash wdog */ + //ConfigFlashWdog(); + + s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE); + + /* align address, write must align to FLASH_PROGRAM_PAGE_MAX_SIZE */ + u32AlignOffset = u32Addr & (PFLASH_PROGRAM_PAGE_MAX_SIZE - 1U); + u32AlignLen = u32Length + u32AlignOffset; + + u32Count = u32AlignLen & (PFLASH_PROGRAM_PAGE_MAX_SIZE - 1U); + + u32Count = u32Count > 0U ? 1U : 0U; + + u32Count += u32AlignLen / PFLASH_PROGRAM_PAGE_MAX_SIZE; + + u32DataAddr = (uint32_t)pFlashParam->pData; + u32TempLen = u32AlignLen; + + for (u32Index = 0U; u32Index < u32Count; u32Index++) + { + /* real write length in this cycle */ + u32TempLen = u32Length + u32AlignOffset; + u32TempLen = u32TempLen >= PFLASH_PROGRAM_PAGE_MAX_SIZE ? PFLASH_PROGRAM_PAGE_MAX_SIZE : u32TempLen; + u32TempLen -= u32AlignOffset; + + pFlashParam->u32Address = u32Addr; + pFlashParam->u32Length = u32TempLen; + + /* unlock sector */ + FLASHDRIVER_PFlashLockSector(pFlashParam->u32Address, 0U); + tFlash_api_cfg.pgff = FLASH_REG_BIT_CFG_DISABLE; + tFlash_api_cfg.dest = pFlashParam->u32Address; + tFlash_api_cfg.size = (pFlashParam->u32Length / 4); /* one data is 4 bytes */ + tFlash_api_cfg.pData = (uint32_t *)u32DataAddr; + tFlash_api_cfg.wdg_tune = WDG_TUNE_DISABLE; + + /* next address and length */ + u32Addr += u32TempLen; + u32DataAddr += u32TempLen; + u32Length -= u32TempLen; + + u32AlignOffset = 0U; + + /* start write */ + __asm(" cpsid i"); + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_Program(&tFlash_api_cfg, FLASH_API_DISABLE, 0); + __asm(" cpsie i"); + tRetVal = u32Temp == STATUS_SUCCESS ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + + /* check erase operation valid */ + if (tRetVal != FLASH_ERROR_OK) + { + /* write operation failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + /* FLASHDRIVER_LL_Delay(); */ + + /* check write still in progress */ + tRetVal = FLASH_ERROR_FAILED; + u32TryCount = 0; + while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 10000)) + { + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check(); + /* check if finished */ + if (u32Temp == STATUS_HVOP) + { + tRetVal = FLASH_ERROR_FAILED; + } + else + { + tRetVal = FLASH_ERROR_OK; + } + } + + + if (tRetVal != FLASH_ERROR_OK) + { + /* erasing timeout, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + + /* check write result */ + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_Program_Clear(); + tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + + if (tRetVal != FLASH_ERROR_OK) + { + /* write failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + /* trigger watchdog function */ + if (pFlashParam->wdTriggerFct != ((void *)0)) + { + pFlashParam->wdTriggerFct(); + } + + } + } + } + + /* lock sector */ + FLASHDRIVER_PFlashLockSector(pFlashParam->u32Address, 1U); + } + } + return tRetVal; +} + +/** + * \brief DFlash Driver Function for Erasing + * + * \param pFlashParam flash driver erase parameter + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_DFlashEraseSector(FLASH_DRIVER_ParamType *pFlashParam) +{ + uint32_t u32Addr, u32Length; + uint32_t u32TryCount; + FLASH_DRV_ERASESECTOR_CFG_T tFlash_api_cfg; + FLASH_StatusType tRetVal; + uint32_t u32Temp; + + tRetVal = FLASH_ERROR_OK; + + + u32Addr = pFlashParam->u32Address; + u32Length = pFlashParam->u32Length; + + tRetVal = FLASH_ERROR_OK; + pFlashParam->u32ErrorAddress = 0x0U; + + tRetVal = FLASHDRIVER_LL_DFlashEraseCheck(pFlashParam); + + if (tRetVal == FLASH_ERROR_OK) + { + /* config flash wdog */ + //ConfigFlashWdog(); + + s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE); + + + pFlashParam->u32Length = DFLASH_ERASE_SECTOR_SIZE; + + /* loop erase */ + for (pFlashParam->u32Address = u32Addr; pFlashParam->u32Address < u32Addr + u32Length; + pFlashParam->u32Address += DFLASH_ERASE_SECTOR_SIZE) + { + /* unlock data flash */ + FLASHDRIVER_DFlashLockSector(pFlashParam->u32Address, 0U); + + FLASHDRIVER_GetFlashConfig(pFlashParam->u32Address, &tFlash_api_cfg); + /* start erase */ + __asm(" cpsid i"); + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_EraseSector(&tFlash_api_cfg, FLASH_API_DISABLE, 0); + __asm(" cpsie i"); + tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + + + /* check erase operation valid */ + if (tRetVal != FLASH_ERROR_OK) + { + /* erase operation failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + /* check erasing still in progress */ + tRetVal = FLASH_ERROR_FAILED; + u32TryCount = 0; + while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 100000)) + { + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check(); + /* check if finished */ + if (u32Temp == STATUS_HVOP) + { + tRetVal = FLASH_ERROR_FAILED; + } + else + { + tRetVal = FLASH_ERROR_OK; + } + } + + if (tRetVal != FLASH_ERROR_OK) + { + /* erasing timeout, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + /* check erasing result */ + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_EraseSector_Clear(); + tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + + if (tRetVal != FLASH_ERROR_OK) + { + /* erasing failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + + if (tRetVal != FLASH_ERROR_OK) + { + /* erasing failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + + /* trigger watchdog function */ + if (pFlashParam->wdTriggerFct != ((void *)0)) + { + pFlashParam->wdTriggerFct(); + } + } + + + } + } + } + + /* lock data flash */ + FLASHDRIVER_DFlashLockSector(pFlashParam->u32Address, 1U); + } + } + return tRetVal; +} + +/** + * \brief DFlash Driver Function for Writing + * + * \param pFlashParam flash driver write parameter + * \return ErrorType + */ +FLASH_StatusType FLASHDRIVER_DFlashWrite(FLASH_DRIVER_ParamType *pFlashParam) +{ + uint32_t u32Addr, u32Length, u32DataAddr, u32AlignLen, u32TempLen; + /* uint8_t *pTempBuf; */ + uint32_t u32AlignOffset, u32Index, u32Count; + uint32_t u32TryCount; + FLASH_DRV_PRGM_CFG_T tFlash_api_cfg; + + FLASH_StatusType tRetVal; + uint32_t u32Temp; + + tRetVal = FLASH_ERROR_OK; + + u32Addr = pFlashParam->u32Address; + u32Length = pFlashParam->u32Length; + + pFlashParam->u32ErrorAddress = 0x0U; + + + tRetVal = FLASHDRIVER_DFlashWriteCheck(pFlashParam); + + if (tRetVal == FLASH_ERROR_OK) + { + /* config flash wdog */ + //ConfigFlashWdog(); + + s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE); + + /* align address, write must align to FLASH_PROGRAM_PAGE_MAX_SIZE */ + u32AlignOffset = u32Addr & (DFLASH_PROGRAM_PAGE_MAX_SIZE - 1U); + u32AlignLen = u32Length + u32AlignOffset; + + u32Count = u32AlignLen & (DFLASH_PROGRAM_PAGE_MAX_SIZE - 1U); + + u32Count = u32Count > 0U ? 1U : 0U; + + u32Count += u32AlignLen / DFLASH_PROGRAM_PAGE_MAX_SIZE; + + u32DataAddr = (uint32_t)pFlashParam->pData; + u32TempLen = u32AlignLen; + + for (u32Index = 0U; u32Index < u32Count; u32Index++) + { + /* real write length in this cycle */ + u32TempLen = u32Length + u32AlignOffset; + u32TempLen = u32TempLen >= DFLASH_PROGRAM_PAGE_MAX_SIZE ? DFLASH_PROGRAM_PAGE_MAX_SIZE : u32TempLen; + u32TempLen -= u32AlignOffset; + + pFlashParam->u32Address = u32Addr; + pFlashParam->u32Length = u32TempLen; + + /* unlock sector */ + FLASHDRIVER_DFlashLockSector(pFlashParam->u32Address, 0U); + tFlash_api_cfg.pgff = FLASH_REG_BIT_CFG_DISABLE; + tFlash_api_cfg.dest = pFlashParam->u32Address; + tFlash_api_cfg.size = (pFlashParam->u32Length / 4); /* one data is 4 bytes */ + tFlash_api_cfg.pData = (uint32_t *)u32DataAddr; + tFlash_api_cfg.wdg_tune = WDG_TUNE_DISABLE; + + /* next address and length */ + u32Addr += u32TempLen; + u32DataAddr += u32TempLen; + u32Length -= u32TempLen; + + u32AlignOffset = 0U; + + /* start write */ + __asm(" cpsid i"); + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_Program(&tFlash_api_cfg, FLASH_API_DISABLE, 0); + __asm(" cpsie i"); + tRetVal = u32Temp == STATUS_SUCCESS ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + + /* check erase operation valid */ + if (tRetVal != FLASH_ERROR_OK) + { + /* write operation failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + /* FLASHDRIVER_LL_Delay(); */ + + /* check write still in progress */ + tRetVal = FLASH_ERROR_FAILED; + u32TryCount = 0; + while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 10000)) + { + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check(); + /* check if finished */ + if (u32Temp == STATUS_HVOP) + { + tRetVal = FLASH_ERROR_FAILED; + } + else + { + tRetVal = FLASH_ERROR_OK; + } + } + + + if (tRetVal != FLASH_ERROR_OK) + { + /* erasing timeout, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + /* check write result */ + u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_Program_Clear(); + tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED; + + if (tRetVal != FLASH_ERROR_OK) + { + /* write failed, exit */ + pFlashParam->u32ErrorAddress = pFlashParam->u32Address; + break; + } + else + { + /* trigger watchdog function */ + if (pFlashParam->wdTriggerFct != ((void *)0)) + { + pFlashParam->wdTriggerFct(); + } + + } + } + } + /* lock data flash */ + FLASHDRIVER_DFlashLockSector(pFlashParam->u32Address, 1U); + + } + } + return tRetVal; +} diff --git a/Src/fc7xxx_driver_flexcan.c b/Src/fc7xxx_driver_flexcan.c new file mode 100644 index 0000000..500dcfd --- /dev/null +++ b/Src/fc7xxx_driver_flexcan.c @@ -0,0 +1,2810 @@ +/** + * @file fc7xxx_driver_flexcan.h + * @author Flagchip + * @brief FC7xxx CAN driver type definition and API + * @version 0.1.0 + * @date 2022-02-20 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ + +/* ******************************************************************************** + * Revision History: + * + * Version Date Author Descriptions + * --------- ---------- ------------ --------------- + * 0.1.0 2024-1-13 Flagchip0112 First version for FC7240 + ******************************************************************************** */ + + + +#include "fc7xxx_driver_flexcan.h" /* include peripheral declarations */ + +#include "interrupt_manager.h" + + +/* ################################################################################## */ +/* ####################################### Macro #################################### */ + + +#ifndef NULL + #define NULL ((void *)0) +#endif + +#define FLEXCAN_FD_INSTANCE_COUNT FLEXCAN_INSTANCE_COUNT /** all support can fd */ + +#define FLEXCAN_MB_NUM 32U /** Every CAN contains message buffer number */ + + +#define FLEXCAN_RX_FIFO_ENABLE STD_OFF +#define FLEXCAN_DMA_ENABLE STD_OFF + +#define FLEXCAN_DET_ERROR_REPORT STD_OFF + + +#define FLEXCAN_DET_ERROR_ID_FUNC_INIT 0x01U +#define FLEXCAN_DET_ERROR_ID_FUNC_MSGCFG 0x02U +#define FLEXCAN_DET_ERROR_ID_FUNC_SETINTERRUPT 0x03U +#define FLEXCAN_DET_ERROR_ID_FUNC_START 0x04U +#define FLEXCAN_DET_ERROR_ID_FUNC_STOP 0x05U +#define FLEXCAN_DET_ERROR_ID_FUNC_TRANSMIT 0x06U +#define FLEXCAN_DET_ERROR_ID_FUNC_RECEIVE 0x07U + + +#define FLEXCAN_DET_ERROR_ID_PARAM_POINTCHECK 0x01U +#define FLEXCAN_DET_ERROR_ID_PARAM_INDEXCHECK 0x02U + + + +/* register word num */ +#define FLEXCAN_MEM_WORD_LEN 0x04U + + +#define MB_RAM_OFFSET 0x80U +#define RXIMR_OFFSET 0x880U +#define RXFIR_TEST_OFFSET 0xA80U +#define MASK_OFFSET 0xAA0U +#define SMBTX_OFFSET 0xAB0U +#define SMBRX0_OFFSET 0xAC0U +#define SMBRX1_OFFSET 0xAD0U +#define FD_SMBTX_OFFSET 0xF28U +#define FD_SMBRX0_OFFSET 0xF70U +#define FD_SMBRX1_OFFSET 0xFB8U +#define ERX_FIFO_OFFSET 0x2000U +#define ERFFEL_OFFSET 0x3000U + + +#define MB_RAM_WORD_NUM 128U +#define RXIMR_WORD_NUM 32U +#define RXFIR_TEST_WORD_NUM 8U +#define MASK_WORD_NUM 4U +#define SMBTX_WORD_NUM 4U +#define SMBRX0_WORD_NUM 4U +#define SMBRX1_WORD_NUM 4U +#define FD_SMBTX_WORD_NUM 18U +#define FD_SMBRX0_WORD_NUM 18U +#define FD_SMBRX1_WORD_NUM 18U +#define ERX_FIFO_WORD_NUM 240U +#define ERFFEL_WORD_NUM 32U + + + +#define USE_CBT_NORMAL + + + +#define TQ_NUM_IPT 2U + +#define TQ_SYNC_NUM 1U + +/* Ctrl1 */ +#define TQ_NUM_CTRL1_MAX 25U +#define TQ_NUM_CTRL1_MIN 8U + +#define CTRL1_PRESDIV_MAX 256U +#define CTRL1_PRESDIV_MIN 1U + +#define CTRL1_RJW_MAX 4U +#define CTRL1_RJW_MIN 1U + +#define CTRL1_PROPSEG_MAX 8U +#define CTRL1_PROPSEG_MIN 1U + +#define CTRL1_PSEG1_MAX 8U +#define CTRL1_PSEG1_MIN 1U + +#define CTRL1_TIMERSEGMENT1_MAX 16U +#define CTRL1_TIMERSEGMENT1_MIN 2U + +#define CTRL1_PSEG2_MAX 8U +#define CTRL1_PSEG2_MIN 2U + + +/* CBT */ +#define TQ_NUM_CBT_MAX 25U /* 80U */ +#define TQ_NUM_CBT_MIN 8U + +#define CBT_PRESDIV_MAX 1024U +#define CBT_PRESDIV_MIN 1U + +#define CBT_RJW_MAX 32U +#define CBT_RJW_MIN 1U + +#define CBT_PROPSEG_MAX 64U +#define CBT_PROPSEG_MIN 1U + +#define CBT_PSEG1_MAX 32U +#define CBT_PSEG1_MIN 1U + +#define CBT_TIMERSEGMENT1_MAX 96U +#define CBT_TIMERSEGMENT1_MIN 2U + +#define CBT_PSEG2_MAX 32U +#define CBT_PSEG2_MIN 2U + + +/* FDCBT */ +#define TQ_NUM_FDCBT_MAX 25U +#define TQ_NUM_FDCBT_MIN 5U + +#define FDCBT_PRESDIV_MAX 1024U +#define FDCBT_PRESDIV_MIN 1U + +#define FDCBT_RJW_MAX 8U +#define FDCBT_RJW_MIN 1U + +#define FDCBT_PROPSEG_MAX 31U +#define FDCBT_PROPSEG_MIN 0U + +#define FDCBT_PSEG1_MAX 8U +#define FDCBT_PSEG1_MIN 1U + +#define FDCBT_TIMERSEGMENT1_MAX 39U +#define FDCBT_TIMERSEGMENT1_MIN 2U + +#define FDCBT_PSEG2_MAX 8U +#define FDCBT_PSEG2_MIN 2U + + + +/* ################################################################################## */ +/* ################################### Type define ################################## */ + + + + + + + +typedef enum +{ + /* RXIDA=0: bitIDE=29-19,EXT=29-1; */ + RXFIFO_FILTERFORMATA = 0, + /* RXIDB_0: bitIDE=29-19,EXT=29-16; RXIDB_1: bitIDE=13-3,EXT=13-0; */ + RXFIFO_FILTERFORMATB = 1, + /* RXIDC_0: bitIDE/EXT=31-24; RXIDC_1: bitIDE/EXT=23-16; RXIDC_2: bitIDE/EXT=15-8; RXIDC_3: bitIDE/EXT=7-0 */ + RXFIFO_FILTERFORMATC = 2 + +} FLEXCAN_RxFifoFilterFormatType; + +typedef struct +{ + FLEXCAN_RxFifoFilterFormatType eFilterFormat; + uint32_t u32RxElementNum; + uint32_t *pRxElementList; +} FLEXCAN_RxFifoFilterType; + + + +/** + * @brief CAN Baudrate setting + * + */ +typedef struct +{ + uint8_t bEnFd; /**< if enable can FD, set 1U */ + uint8_t bEnBrs; /**< if enable can BRS, set 1U */ + FLEXCAN_DataWidthType eMbDataWidth; /**< Message Buffer Data Width */ + + FLEXCAN_BaudClkType eClkSrcHz; /**< clock source HZ */ + FLEXCAN_BaudType eBaudrate; /**< normal bit rate */ + FLEXCAN_BaudType eDataBaud; /**< can fd data bit rate */ + + uint32_t u32Ctrl1; /**< ctrl1 register value */ + uint32_t u32Cbt; /**< cbt register value */ + uint32_t u32FdCtrl; /**< fdctrl register value */ + uint32_t u32FdCbt; /**< fdcbt register value */ + +} FLEXCAN_BaudCfgType; + + + +/** + * @brief CAN setting configuration + * + */ +typedef struct +{ + uint8_t bEnableFd; /**< if enable can FD, set 1U */ + uint8_t bEnableFifo; /**< if enable can fifo, set 1U */ + uint8_t bEnableDMA; /**< if enable can dma, set 1U */ + uint8_t bEnableErrInt; /**< if enable can error interrupt, set 1U */ + uint8_t bEnableFifoInt; /**< if enable can fifo interrupt, set 1U */ + uint8_t bEnableTxMBInt; /**< if enable can Tx MB interrupt, set 1U */ + uint8_t bEnableRxMBInt; /**< if enable can Rx MB interrupt, set 1U */ + uint8_t u8EnhancedFifoDmaWM;/**< The watermark for DMA in CANFD FIFO mode */ + uint8_t u8RxFifoCnt; /**< can receive start message buffer index */ + uint8_t u8RxMbStart1; /**< can receive start message buffer index */ + uint8_t u8RxMbCnt1; /**< can receive message buffer count */ + uint8_t u8TxMbStart1; /**< can transmit start message buffer index */ + uint8_t u8TxMbCnt1; /**< can receive message buffer count */ + FLEXCAN_DataWidthType eMbDataWidth; /**< Message Buffer Data Width */ + FLEXCAN_RxMsgType *pRxBuf; /**< receive buffer address, length same to u8RxFilterCnt, must global array */ +} FLEXCAN_SettingType; + +/** + * @brief CAN Operation Sequence + * + */ +typedef enum +{ + FLEXCAN_SEQUENCE_VAR_NOINIT, /**< FLEXCAN_SEQUENCE_DEINIT means CAN variables data is not initialed */ + FLEXCAN_SEQUENCE_DEINIT, /**< FLEXCAN_SEQUENCE_DEINIT means CAN driver is not initialed */ + FLEXCAN_SEQUENCE_NOTSTART, /**< FLEXCAN_SEQUENCE_NOTSTART means can driver initialed and not start */ + FLEXCAN_SEQUENCE_STARTED /**< FLEXCAN_SEQUENCE_STARTED means can driver started */ +} FLEXCAN_SequenceType; + + +/** + * @brief Baud-rate clock and divider + * + */ +typedef struct +{ + FLEXCAN_BaudClkType eClkHz; /**< Clock Hz for baudrate */ + FLEXCAN_BaudType eBaudrate; /**< Normal bit baudrate */ + uint32_t u32Presdiv; /**< Presdiv for can */ + uint32_t u32Propseg; /**< Propseg for can */ + uint32_t u32Pseg1; /**< Pseg1 for can */ + uint32_t u32Pseg2; /**< Pseg2 for can */ + uint32_t u32Rjw; /**< RJW for can */ +} FLEXCAN_BaudRegType; + + +/* ################################################################################## */ +/* ############################# Local Const Variables ############################## */ + +/* CAN Instance */ +static FLEXCAN_Type *const s_aFlexCan_InstanceTable[FLEXCAN_INSTANCE_COUNT] = +{ + FLEXCAN0, + FLEXCAN1, + FLEXCAN2, + FLEXCAN3 +}; + +/* Normal bit table */ +static const FLEXCAN_BaudRegType s_aFlexCan_NormalBaudDividerTable[] = +{ + /* clock source hz baudrate presdiv propseg pseg1 pseg2 rjw */ + { FLEXCAN_BAUDCLK_HZ_16M, FLEXCAN_BAUD_500K, 2, 8, 4, 3, 2 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_100K, 12, 7, 6, 6, 1 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_125K, 12, 5, 5, 5, 1 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_250K, 8, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_500K, 4, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_800K, 3, 5, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_1M, 2, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_2M, 1, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_100K, 32, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_125K, 24, 7, 4, 4, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_250K, 24, 3, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_500K, 6, 7, 4, 4, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_800K, 4, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_1M, 3, 7, 4, 4, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_2M, 2, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_100K, 80, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_125K, 64, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_250K, 32, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_500K, 16, 8, 3, 3, 3 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_800K, 15, 5, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_1M, 8, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_2M, 4, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_150M, FLEXCAN_BAUD_500K, 20, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_150M, FLEXCAN_BAUD_1M, 10, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_150M, FLEXCAN_BAUD_2M, 5, 8, 3, 3, 1 }, + +}; + +/* Data bit table */ +static const FLEXCAN_BaudRegType s_aFlexCan_DataBaudDividerTable[] = +{ + /* clock source hz baudrate presdiv propseg pseg1 pseg2 rjw */ + { FLEXCAN_BAUDCLK_HZ_16M, FLEXCAN_BAUD_2M, 1, 3, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_1M, 2, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_2M, 1, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_24M, FLEXCAN_BAUD_3M, 1, 3, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_1M, 3, 7, 4, 4, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_2M, 2, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_3M, 1, 7, 4, 4, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_4M, 1, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_48M, FLEXCAN_BAUD_6M, 1, 3, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_1M, 8, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_2M, 4, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_3M, 4, 5, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_4M, 3, 5, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_5M, 2, 5, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_6M, 2, 5, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_120M, FLEXCAN_BAUD_8M, 1, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_150M, FLEXCAN_BAUD_1M, 10, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_150M, FLEXCAN_BAUD_2M, 5, 8, 3, 3, 1 }, + { FLEXCAN_BAUDCLK_HZ_150M, FLEXCAN_BAUD_3M, 5, 5, 2, 2, 1 }, + { FLEXCAN_BAUDCLK_HZ_150M, FLEXCAN_BAUD_5M, 2, 8, 3, 3, 1 } + +}; + + +/* ################################################################################## */ +/* ################################ Local Variables ################################# */ + + +/* sequence var */ +static FLEXCAN_SequenceType s_aCurrentSequence[FLEXCAN_INSTANCE_COUNT] = {FLEXCAN_SEQUENCE_VAR_NOINIT}; + + +/* message buffer word length, default pCan is 16bytes, 4words */ +/* static uint8_t s_aFlexCan_DataLen[FLEXCAN_INSTANCE_COUNT]; */ + +/* pCan message buffer used count stored */ +/* static FLEXCAN_MBConfigType s_aFlexCan_MBCfg_Table[FLEXCAN_INSTANCE_COUNT]; */ + +/* can setting */ +static FLEXCAN_SettingType s_aFlexCan_Setting_Table[FLEXCAN_INSTANCE_COUNT]; + + +/* store notify callback function point */ +static FLEXCAN_ErrorInterruptCallBackType s_aFlexCan_ErrorNotifyTable[FLEXCAN_INSTANCE_COUNT]; +static FLEXCAN_TxInterruptCallBackType s_aFlexCan_TxNotifyTable[FLEXCAN_INSTANCE_COUNT]; +static FLEXCAN_RxInterruptCallBackType s_aFlexCan_RxNotifyTable[FLEXCAN_INSTANCE_COUNT]; +static FLEXCAN_RxInterruptCallBackType s_aFlexCan_RxFifoNotifyTable[FLEXCAN_INSTANCE_COUNT]; + +/* check every pCan instance whether is used */ +/* static FLEXCAN_RxMsgType const * s_aFlexCan_RxBufList[FLEXCAN_INSTANCE_COUNT]; */ + +/* check every pCan instance whether is used */ +static uint8_t s_aFlexCan_CanUsed[FLEXCAN_INSTANCE_COUNT]; + +#if FLEXCAN_DET_ERROR_REPORT == STD_ON +typedef struct +{ + uint8_t u8FunctionID; + uint8_t u8ParameterID; +} FLEXCAN_DetErrorType; + +static FLEXCAN_DetErrorType s_tFlexCan_DetErrorId; +#endif + + +/* ################################################################################## */ +/* ########################### Local Prototype Functions ############################ */ + + + + +/* ################################################################################## */ +/* ########################### Global Prototype Functions ########################### */ + + +/* ################################################################################## */ +/* ################################ Local Functions ################################# */ + +#if FLEXCAN_DET_ERROR_REPORT == STD_ON +static void FLEXCAN_ReportDet(uint8_t funcId, uint8_t paramId) +{ + s_tFlexCan_DetErrorId.u8FunctionID = funcId; + s_tFlexCan_DetErrorId.u8ParameterID = paramId; + + while (1) + { + + } + +} + +#endif + + +#if FLEXCAN_CHECK_PARAMETERS == STD_ON +/** + * @brief Check FLEXCAN instance + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @return FLEXCAN_ERROR_OK is OK + */ +LOCAL_INLINE FLEXCAN_ErrorType FLEXCAN_LL_CheckInstance(uint8_t u8CanIndex) +{ + FLEXCAN_ErrorType tRetVal; + + if (u8CanIndex < FLEXCAN_INSTANCE_COUNT) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal = FLEXCAN_ERROR_INVALID_PARAM; + } + + return tRetVal; +} + +#endif + +/** + * @brief Check FLEXCAN Fd Support instance + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @return FLEXCAN_ERROR_OK is OK + */ +LOCAL_INLINE FLEXCAN_ErrorType FLEXCAN_LL_CheckFdInstance(uint8_t u8CanIndex) +{ + FLEXCAN_ErrorType tRetVal; + + if (u8CanIndex < FLEXCAN_FD_INSTANCE_COUNT) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal = FLEXCAN_ERROR_INVALID_PARAM; + } + + return tRetVal; +} + + +/** + * @brief Initial embedded can ram area + * + * @param u8CanIndex CanIndex, Must less than FLEXCAN_INSTANCE_COUNT + */ +static void FLEXCAN_LL_EmbededRam_Init(uint8_t u8CanIndex) +{ + volatile uint32_t u8Index ; + volatile uint32_t ramAddr; + FLEXCAN_Type *pCan; + + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + for (u8Index = 0U; u8Index < MB_RAM_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, MB_RAM_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + for (u8Index = 0U; u8Index < RXIMR_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, RXIMR_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + for (u8Index = 0U; u8Index < RXFIR_TEST_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, RXFIR_TEST_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + for (u8Index = 0U; u8Index < MASK_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, MASK_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + for (u8Index = 0U; u8Index < SMBTX_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, SMBTX_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + for (u8Index = 0U; u8Index < SMBRX0_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, SMBRX0_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + for (u8Index = 0U; u8Index < SMBRX1_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, SMBRX1_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + /* can fd only */ + if (FLEXCAN_LL_CheckFdInstance(u8CanIndex) == FLEXCAN_ERROR_OK) + { + for (u8Index = 0U; u8Index < FD_SMBTX_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FD_SMBTX_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + for (u8Index = 0U; u8Index < FD_SMBRX0_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FD_SMBRX0_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + for (u8Index = 0U; u8Index < FD_SMBRX1_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, FD_SMBRX1_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + + /** initial rx fifo */ + for (u8Index = 0U; u8Index < ERX_FIFO_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, ERX_FIFO_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + for (u8Index = 0U; u8Index < ERFFEL_WORD_NUM; u8Index++) + { + ramAddr = FLEXCAN_REGISTER_WITHOFFSET(pCan, ERFFEL_OFFSET, u8Index * FLEXCAN_MEM_WORD_LEN); + FLEXCAN_REG32_CONTENT(ramAddr) = 0U; + } + + } + +} + + + +/** + * @brief This Function is used to receive Special Message Buffer data + * + * @param u8CanIndex Can Index, Must less than FLEXCAN_INSTANCE_COUNT + * @param u8RealMbIndex, message buffer index 0...31, if fifo enable, always 0 + * @param u8MbDataLen, message buffer data length + * @param pRxMsg, received data buffer + * @return 0 means no data, others means received data + */ +static uint8_t FLEXCAN_LL_ReceiveMb(uint8_t u8CanIndex, uint8_t u8RealMbIndex, uint8 bEnFifo, uint8_t u8MbDataLen, FLEXCAN_RxMsgType *const pRxMsg) +{ + + FLEXCAN_Type *pCan; + uint32_t u32Status; + + uint32_t *pSrc; + uint32_t *pDest; + uint8_t u8Index; + + uint32_t u32TempAddr; + uint32_t u32WordLen; + uint8 u8IflagIndex; + + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + if (bEnFifo != 0U) + { + u8IflagIndex = 5U; /* IFLAG1[BIT5] (Frames available in Rx FIFO) is asserted when there is at least one frame available to be read from the FIFO */ + u8RealMbIndex = 0U; /* fifo received always in MB0 */ + } + else + { + u8IflagIndex = u8RealMbIndex; + } + + pRxMsg->u32DataLen = 0U; + + u32Status = FLEXCAN_HWA_GetFlag1NoFifoFlag(pCan, (uint32_t)u8IflagIndex); + + if (u32Status != 0U) + { + pRxMsg->u8CanIndex = u8CanIndex; + pRxMsg->u8MbIndex = u8RealMbIndex; + + /* message buffer 1th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8RealMbIndex, u8MbDataLen, 0U); + + pRxMsg->bEnFd = (uint8_t)((FLEXCAN_MB_EDL_GET(u32TempAddr) == 0U) ? 0U : 1U); + pRxMsg->bEnBrs = (uint8_t)((FLEXCAN_MB_BRS_GET(u32TempAddr) == 0U) ? 0U : 1U); + + + pRxMsg->u32DataLen = FLEXCAN_MB_DLC_GET(u32TempAddr); + pRxMsg->u32DataLen = FLEXCAN_DlcToDataLen(pRxMsg->u32DataLen); + pRxMsg->eFrameType = (FLEXCAN_IdType)(FLEXCAN_MB_IDE_GET(u32TempAddr)); + + /* message buffer 2th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8RealMbIndex, u8MbDataLen, 4U); + + if (pRxMsg->eFrameType) + { + pRxMsg->u32CanId = FLEXCAN_MB_EXTID_GET(u32TempAddr); + } + else + { + pRxMsg->u32CanId = FLEXCAN_MB_STDID_GET(u32TempAddr); + } + + + + pDest = (uint32_t *)pRxMsg->aData; + /* message buffer 3th word */ + pSrc = (uint32_t *)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8RealMbIndex, u8MbDataLen, 8U); + + + u32WordLen = pRxMsg->u32DataLen / 4U + (pRxMsg->u32DataLen % 4U > 0U ? 1U : 0U); + + for (u8Index = 0U; u8Index < u32WordLen; u8Index++) + { + /* big endian to little endian */ + REV_BYTES_32(pSrc[u8Index], pDest[u8Index]); + } + + FLEXCAN_HWA_UnlockMbNoFifoFlag(pCan, (uint32_t)u8IflagIndex); + + } + else + { + } + + return pRxMsg->u32DataLen > 0U; +} + + +/** + * @brief This Function is used to receive Enhance FIFO Buffer data + * + * @param u8CanIndex Can Index, Must less than FLEXCAN_INSTANCE_COUNT + * @param pRxMsg, received data buffer + * @return 0 means no data, others means received data + */ +static uint8_t FLEXCAN_LL_ReceiveEnhanceFifo(uint8_t u8CanIndex, FLEXCAN_RxMsgType *const pRxMsg) +{ + uint32_t u32Status; + + volatile uint32_t *pSrc; + volatile uint32_t *pDest; + uint8_t u8Index; + FLEXCAN_Type *pCan; + + pRxMsg->u32DataLen = 0U; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + if (FLEXCAN_LL_CheckFdInstance(u8CanIndex) == FLEXCAN_ERROR_OK) + { + #endif + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + /* The enhanced Rx FIFO has a watermark that is configured by setting EFRCR[ERFWM]. + * If EFRCR[ERFWM] is set, the CPU is notified only if a minimum number of messages is stored in the FIFO. + * When the number of stored messages is greater than the value in EFRCR[ERFWM], ERFSR[ERFWMI] is set by the hardware. */ + + /* check fd fifo data available */ + u32Status = FLEXCAN_HWA_ERFSRGetEnhancedFifoFlag(pCan, FLEXCAN_ERFSR_ERFDA_SHIFT, FLEXCAN_ERFSR_ERFDA_MASK); + + if (u32Status != 0U) + { + + pRxMsg->u8CanIndex = u8CanIndex; + pRxMsg->u8MbIndex = 0U; + + pRxMsg->bEnFd = (uint8_t)(FLEXCAN_EFIFOMB_EDL_GET()); + pRxMsg->bEnBrs = (uint8_t)(FLEXCAN_EFIFOMB_BRS_GET()); + + + pRxMsg->u32DataLen = FLEXCAN_EFIFOMB_DLC_GET(); + pRxMsg->u32DataLen = (uint8_t)(FLEXCAN_DlcToDataLen(pRxMsg->u32DataLen)); + pRxMsg->eFrameType = (FLEXCAN_IdType)(FLEXCAN_EFIFOMB_IDE_GET()); + + + if (pRxMsg->eFrameType) + { + pRxMsg->u32CanId = FLEXCAN_EFIFOMB_EXTID_GET(); + } + else + { + pRxMsg->u32CanId = FLEXCAN_EFIFOMB_STDID_GET(); + } + + pDest = (uint32_t *)pRxMsg->aData; + /* message buffer 3th word */ + pSrc = (volatile uint32_t *)FLEXCAN_EFIFOMB_DATAADDR_GET(0U); + + + //u32WordLen = pRxMsg->u32DataLen / 4U + (pRxMsg->u32DataLen % 4U > 0U ? 1U : 0U); + + for (u8Index = 0U; u8Index < 18U; u8Index++) + { + /* big endian to little endian */ + REV_BYTES_32(pSrc[u8Index], pDest[u8Index]); + } + + //u32WordLen = FLEXCAN_EFIFOMB_HRTIMESTAMP_GET(u32WordLen); /* Read TIMER to unlock message buffers */ + + /* clear fifo data available status */ + FLEXCAN_HWA_ERFSRClearEnhancedFifoFlag(pCan, FLEXCAN_ERFSR_ERFDA_MASK); + + /* get fifo data available status */ + u32Status = FLEXCAN_HWA_ERFSRGetEnhancedFifoFlag(pCan, FLEXCAN_ERFSR_ERFDA_SHIFT, FLEXCAN_ERFSR_ERFDA_MASK); + + } + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return pRxMsg->u32DataLen > 0U; +} + + +/** + * @brief Polling Message Buffer Received Data + * + * @param u8CanIndex Can Index, Must less than FLEXCAN_INSTANCE_COUNT + * @param pRxMsgList Message Stored buffer point + * @return Received message count + */ +static uint8_t FLEXCAN_LL_PollingMb(uint8_t u8CanIndex, FLEXCAN_RxMsgType *const pRxMsgList) +{ + uint8_t u8MsgNum; + uint32_t u32Status; + uint8_t u8RealMbIndex; + + FLEXCAN_SettingType *pCurSetting; + + uint8_t u8MBindex; + uint8_t u8MbDataWidth; + + pCurSetting = &s_aFlexCan_Setting_Table[u8CanIndex]; + + u8MsgNum = 0U; + + /* loop check all receive message buffer */ + for (u8MBindex = 0U; u8MBindex < pCurSetting->u8RxMbCnt1; u8MBindex++) + { + u8RealMbIndex = (uint8_t)(pCurSetting->u8RxMbStart1 + u8MBindex); + u8MbDataWidth = pCurSetting->eMbDataWidth; + + u32Status = FLEXCAN_LL_ReceiveMb(u8CanIndex, u8RealMbIndex, 0U, u8MbDataWidth, &pRxMsgList[u8MsgNum]); + + if (u32Status != 0U) + { + u8MsgNum ++; + } + else + { + } + } + + return u8MsgNum; +} + +/** + * @brief Polling Legacy Rx FIFO + * + * @param u8CanIndex CanIndex, Must less than FLEXCAN_INSTANCE_COUNT + * @param u8MbDataWidth Message Buffer Data Width + * @param pRxMsgList received data buffer + * @return receive message count + */ +static uint8_t FLEXCAN_LL_PollingLegacyFifo(uint8_t u8CanIndex, uint8_t u8MbDataWidth, FLEXCAN_RxMsgType *pRxMsgList) +{ + uint8_t u8MsgNum; + uint32_t u32Status; + uint8_t u8MBindex; + + u8MsgNum = 0U; + pRxMsgList[u8MsgNum].u32DataLen = 0U; + + /* legacy fifo only receive in MB 0 */ + u8MBindex = 0U; + + /* IFLAG1[BIT5] (Frames available in Rx FIFO) is asserted when there is at least one frame available to be read from the FIFO. */ + u32Status = 1U; + + while (u32Status != 0U) + { + u32Status = FLEXCAN_LL_ReceiveMb(u8CanIndex, u8MBindex, 1U, u8MbDataWidth, &pRxMsgList[u8MsgNum]); + + if (u32Status != 0U) + { + u8MsgNum ++; + } + else + { + } + + } + + return u8MsgNum; +} + +/** + * @brief Polling Enhanced Rx FIFO Data + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pRxMsgList received data buffer + * @return receive message count + */ +static uint8_t FLEXCAN_LL_PollingEnhancedFifo(uint8_t u8CanIndex, FLEXCAN_RxMsgType *pRxMsgList) +{ + uint8_t u8MsgNum; + uint32_t u32Status; + + /* The enhanced Rx FIFO has a watermark that is configured by setting EFRCR[ERFWM]. + * If EFRCR[ERFWM] is set, the CPU is notified only if a minimum number of messages is stored in the FIFO. + * When the number of stored messages is greater than the value in EFRCR[ERFWM], ERFSR[ERFWMI] is set by the hardware. */ + + /* check fd fifo data available */ + u8MsgNum = 0U; + u32Status = 1U; + while (u32Status != 0U) + { + u32Status = FLEXCAN_LL_ReceiveEnhanceFifo(u8CanIndex, &pRxMsgList[u8MsgNum]); + if (u32Status > 0U) + { + u8MsgNum ++; + } + } + + return u8MsgNum; +} + + +/** + * @brief Receive Can FIFO Data + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param bEnableFd if it is CAN FD Fifo + * @param pRxMsgList received data buffer + * @return receive message count + */ +static uint8_t FLEXCAN_LL_ReceiveFifo(uint8_t u8CanIndex, uint8_t bEnableFd, FLEXCAN_RxMsgType *pRxMsgList) +{ + + uint8_t u8MsgNum; + + FLEXCAN_SettingType *pCurSetting; + + pCurSetting = &s_aFlexCan_Setting_Table[u8CanIndex]; + + + if (bEnableFd) /* can fd fifo receive */ + { + u8MsgNum = FLEXCAN_LL_PollingEnhancedFifo(u8CanIndex, pRxMsgList); + + } + else /* legacy fifo receive */ + { + u8MsgNum = FLEXCAN_LL_PollingLegacyFifo(u8CanIndex, pCurSetting->eMbDataWidth, pRxMsgList); + + } + + return u8MsgNum; +} + + +/** + * @brief Process CAN Baudrate from table + * + * @param pBaudCfg baudrate configuration + * @return 0 is ok + */ +static uint8_t FLEXCAN_LL_ProcessBaud(FLEXCAN_BaudCfgType *pBaudCfg) +{ + uint32_t u32Mod; + uint8_t u8RetVal; + uint32_t u32Index; + + + u8RetVal = 1U; + + if (pBaudCfg->bEnFd) + { + u32Mod = (uint32_t)pBaudCfg->eClkSrcHz % (uint32_t)pBaudCfg->eBaudrate; + if (u32Mod != 0U) + { + u8RetVal = 1U; + } + else + { + + /* loop check for normal bit rate */ + for (u32Index = 0U; u32Index < sizeof(s_aFlexCan_NormalBaudDividerTable) / sizeof(s_aFlexCan_NormalBaudDividerTable[0]); u32Index++) + { + if ((pBaudCfg->eClkSrcHz == s_aFlexCan_NormalBaudDividerTable[u32Index].eClkHz) && (pBaudCfg->eBaudrate == s_aFlexCan_NormalBaudDividerTable[u32Index].eBaudrate)) + { + /* when pCan fd enabled, pCan normal bit set by CBT !!!! */ + pBaudCfg->u32Cbt = FLEXCAN_CBT_EPRESDIV(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Presdiv - 1U) | + FLEXCAN_CBT_ERJW(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Rjw - 1U) | + FLEXCAN_CBT_EPSEG1(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Pseg1 - 1U) | + FLEXCAN_CBT_EPSEG2(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Pseg2 - 1U) | + FLEXCAN_CBT_EPROPSEG(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Propseg - 1U) | + FLEXCAN_CBT_BTF(1U); /* SMP = 1: use 3 bits per CAN sample */ + + u8RetVal = 0U; + break; + } + } + + + if (u8RetVal == 0U) + { + u8RetVal = 1U; + + /* loop for fd data bit rate */ + for (u32Index = 0U; u32Index < sizeof(s_aFlexCan_DataBaudDividerTable) / sizeof(s_aFlexCan_DataBaudDividerTable[0]); u32Index++) + { + if ((pBaudCfg->eClkSrcHz == s_aFlexCan_DataBaudDividerTable[u32Index].eClkHz) && (pBaudCfg->eDataBaud == s_aFlexCan_DataBaudDividerTable[u32Index].eBaudrate)) + { + pBaudCfg->u32FdCtrl = FLEXCAN_FDCTRL_FDRATE(pBaudCfg->bEnBrs) | + /* MBDSR0, pMb 0-31 data length, 8-0,16-1,32-2,64-3 */ + FLEXCAN_FDCTRL_MBDSR0(pBaudCfg->eMbDataWidth == FLEXCAN_DATAWIDTH_8 ? 0U : (pBaudCfg->eMbDataWidth == FLEXCAN_DATAWIDTH_16 ? 1U : + (pBaudCfg->eMbDataWidth == FLEXCAN_DATAWIDTH_32 ? 2U : 3U))) + | FLEXCAN_FDCTRL_TDCOFF(1U); + + + /* when pCan fd enabled, pCan normal bit set by CBT !!!! */ + pBaudCfg->u32FdCbt = FLEXCAN_FDCBT_FPRESDIV(s_aFlexCan_DataBaudDividerTable[u32Index].u32Presdiv - 1U) | + FLEXCAN_FDCBT_FRJW(s_aFlexCan_DataBaudDividerTable[u32Index].u32Rjw - 1U) | + FLEXCAN_FDCBT_FPSEG1(s_aFlexCan_DataBaudDividerTable[u32Index].u32Pseg1 - 1U) | + FLEXCAN_FDCBT_FPSEG2(s_aFlexCan_DataBaudDividerTable[u32Index].u32Pseg2 - 1U) | + FLEXCAN_FDCBT_FPROPSEG(s_aFlexCan_DataBaudDividerTable[u32Index].u32Propseg); + + u8RetVal = 0U; + break; + } + } + } + + + } + } + else + { + u32Mod = (uint32_t)pBaudCfg->eClkSrcHz % (uint32_t)pBaudCfg->eBaudrate; + if (u32Mod != 0U) + { + u8RetVal = 1U; + } + + else + { + u8RetVal = 1U; + /* loop check for normal bit rate */ + for (u32Index = 0U; u32Index < sizeof(s_aFlexCan_NormalBaudDividerTable) / sizeof(s_aFlexCan_NormalBaudDividerTable[0]); u32Index++) + { + if ((pBaudCfg->eClkSrcHz == s_aFlexCan_NormalBaudDividerTable[u32Index].eClkHz) && (pBaudCfg->eBaudrate == s_aFlexCan_NormalBaudDividerTable[u32Index].eBaudrate)) + { + /* when pCan fd enabled, pCan normal bit set by CBT !!!! */ + pBaudCfg->u32Ctrl1 = FLEXCAN_CTRL1_PRESDIV(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Presdiv - 1U) | + FLEXCAN_CTRL1_RJW(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Rjw - 1U) | + FLEXCAN_CTRL1_PSEG1(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Pseg1 - 1U) | + FLEXCAN_CTRL1_PSEG2(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Pseg2 - 1U) | + FLEXCAN_CTRL1_PROPSEG(s_aFlexCan_NormalBaudDividerTable[u32Index].u32Propseg - 1U); + + u8RetVal = 0U; + } + } + + + } + } + + + return u8RetVal; + +} + +/** + * @brief Set Legacy Rx FIFO + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pRxFilterList Filter id list + * @param u32RxFilterCnt Filter id list length + * @return FLEXCAN_ERROR_OK is ok + */ +static FLEXCAN_ErrorType FLEXCAN_LL_SetLegacyFifo(uint8_t u8CanIndex, FLEXCAN_RxMbFilterType *pRxFilterList, uint32_t u32RxFilterCnt) +{ + FLEXCAN_ErrorType tRetVal; + uint32_t u32FilterNum; + uint32_t u32FilterNumLeft; + uint32_t u32Index; + + FLEXCAN_Type *pCan; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + tRetVal = FLEXCAN_LL_CheckFdInstance(u8CanIndex); + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + /* set legacy fifo */ + FLEXCAN_HWA_EnableLegacyFifo(pCan); + + + /* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 */ + /* Format A: RTR IDE | RXIDA (standard =29-19, extended = 29-1) | */ + /* Format B: RTR IDE | RXIDB_0 (standart = 29-19, extended = 29-16) MSB compare | RTR IDE|RXIDB_1 (standart = 13-3, extended = 13-0) MSB compare */ + /* Format C: RXIDC_0 (std/ext = 31-24) MSB compare | RXIDC_1 (std/ext = 23-16) MSB compare | RXIDC_2 (std/ext =15-8) MSB compare | RXIDC_3 (std/ext =7-0) MSB compare */ + + /* set always format A */ + + + u32FilterNum = 0U; + + /* filter start from MB 6 */ + for (u32Index = 0U; u32Index < u32RxFilterCnt; u32Index++) + { + /* extended id */ + if (pRxFilterList[u32Index].eRxFrameType == FLEXCAN_ID_EXT) + { + FLEXCAN_HWA_MbRam(pCan, 4U * 6U + u32FilterNum, (1U << 30) | (pRxFilterList[u32Index].u32RxCanId << 1)); /* id */ + FLEXCAN_HWA_SetIndividualMask(pCan, u32FilterNum, (1U << 30) | pRxFilterList[u32Index].u32RxCanIdMask) ; /* mask */ + } + else /* standard id */ + { + FLEXCAN_HWA_MbRam(pCan, 4U * 6U + u32FilterNum, pRxFilterList[u32Index].u32RxCanId << 19); /* id */ + FLEXCAN_HWA_SetIndividualMask(pCan, u32FilterNum, (1U << 30) | (pRxFilterList[u32Index].u32RxCanIdMask << 19)) ; /* mask */ + } + + u32FilterNum++; + } + + /* filter elements number are multiple of 8 */ + u32FilterNumLeft = 8U - u32RxFilterCnt % 8U; + /* set left same to last filter */ + for (u32Index = 0U; u32Index < u32FilterNumLeft; u32Index++) + { + /* extended id */ + if (pRxFilterList[u32FilterNum - 1U].eRxFrameType == FLEXCAN_ID_EXT) + { + FLEXCAN_HWA_MbRam(pCan, 4U * 6U + u32FilterNum + u32Index, (1U << 30) | (pRxFilterList[u32FilterNum - 1U].u32RxCanId << 1)); /* id */ + FLEXCAN_HWA_SetIndividualMask(pCan, u32FilterNum + u32Index, (1U << 30) | pRxFilterList[u32FilterNum - 1U].u32RxCanIdMask); /* mask */ + } + else /* standard id */ + { + FLEXCAN_HWA_MbRam(pCan, 4U * 6U + u32FilterNum + u32Index, pRxFilterList[u32FilterNum - 1U].u32RxCanId << 19); /* id */ + FLEXCAN_HWA_SetIndividualMask(pCan, u32FilterNum + u32Index, (1U << 30) | (pRxFilterList[u32FilterNum - 1U].u32RxCanIdMask << 19)); /* mask */ + + } + } + + /* set fifo filter, 1 group filter contains 8 filter elements (2MBs) */ + /* left for tx = MaxMb-6 - (RFFN+1)*2 */ + u32FilterNum = u32FilterNum / 8U + (u32FilterNum % 8U > 0U ? 1U : 0U); + FLEXCAN_HWA_SetLegacyFifoFilterNum(pCan, u32FilterNum); + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; +} + +/** + * @brief Set Enhanced Rx FIFO + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pRxFilterList Filter id list + * @param u32RxFilterCnt Filter id list length + * @param u8WaterMark DMA Wartmark + * @return FLEXCAN_ERROR_OK is ok + */ +static FLEXCAN_ErrorType FLEXCAN_LL_SetEnhancedFifo(uint8_t u8CanIndex, FLEXCAN_RxMbFilterType *pRxFilterList, uint32_t u32RxFilterCnt, uint8_t u8WaterMark) +{ + FLEXCAN_ErrorType tRetVal; + uint32_t u32FilterERFCRNum; + uint32_t u32Index; + FLEXCAN_Type *pCan; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + tRetVal = FLEXCAN_LL_CheckFdInstance(u8CanIndex); + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + + uint32_t u32ExtIDFilterNum; + uint32_t u32StdIDFilterNum; + uint32_t u32TempERFCR; + + /* current pCan instance */ + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + /* Configure the filter elements by writing in the ERFFELn registers (ERFFELn registers are implemented in RAM; thus, they must be explicitly initialized prior to any reception). */ + + /* standard id filter */ + /* 31-30 29-28 27 26-16 15-12 11 10-0 */ + /* FSCH=b00 Reserved RTR filter STD ID filter Reserved RTR mask STD ID mask id_filter&id_mask */ + /* FSCH=b01 Reserved RTR filter STD ID filter2 Reserved RTR mask STD ID filter1 id filter1<=id<= id filter2 */ + /* FSCH=b10 Reserved RTR filter2 STD ID filter2 Reserved RTR filter1 STD ID filter1 id filter1= id = id filter2 */ + + /* extended id filter */ + /* 31-30 29 28-0 */ + /* FSCH=00b RTR filter EXT ID filter */ + /* Reserved RTR mask EXT ID mask */ + /* FSCH=01b RTR filter EXT ID filter2 */ + /* Reserved RTR mask EXT ID filter1 */ + /* FSCH=10b RTR filter2 EXT ID filter2 */ + /* Reserved RTR filter1 EXT ID filter1 */ + + u32ExtIDFilterNum = 0U; + u32StdIDFilterNum = 0U; + + /* get extended id count and standard id count */ + for (u32Index = 0U; u32Index < u32RxFilterCnt; u32Index++) + { + if (pRxFilterList[u32Index].eRxFrameType == FLEXCAN_ID_EXT) + { + /* extended id first */ + /* pCan->ERFFEL[u32Index] &= 0xFFFFFFFU; */ + FLEXCAN_HWA_EnhancedFifoFilter(pCan, u32ExtIDFilterNum * 2U, pRxFilterList[u32Index].u32RxCanId); /* id */ + FLEXCAN_HWA_EnhancedFifoFilter(pCan, u32ExtIDFilterNum * 2U + 1U, pRxFilterList[u32Index].u32RxCanIdMask); /* mask */ + + u32ExtIDFilterNum++; + } + } + + for (u32Index = 0U; u32Index < u32RxFilterCnt; u32Index++) + { + /* standard id */ + if (pRxFilterList[u32Index].eRxFrameType == FLEXCAN_ID_STD) + { + FLEXCAN_HWA_EnhancedFifoFilter(pCan, u32ExtIDFilterNum * 2U + u32StdIDFilterNum, (pRxFilterList[u32Index].u32RxCanId << 16) | pRxFilterList[u32Index].u32RxCanIdMask); + u32StdIDFilterNum++; + } + } + + /* standard id number must multiple of 2 */ + tRetVal = (FLEXCAN_ErrorType)(tRetVal | ((u32StdIDFilterNum % 2U == 1U) ? FLEXCAN_ERROR_INVALID_PARAM : FLEXCAN_ERROR_OK)); + + if (tRetVal == FLEXCAN_ERROR_OK) + { + /* total id filter number in ERFCR, two std */ + u32FilterERFCRNum = u32StdIDFilterNum / 2U + u32ExtIDFilterNum - 1U; + + + + /* Write one to ERFSR[ERFCLR] to reset Enhanced Rx FIFO engine */ + FLEXCAN_HWA_ERFSRResetEnhancedFifo(pCan); + /* Clear EFRSR[ERFUFW], EFRSR[ERFOVF], EFRSR[ERFWMI], and EFRSR[ERFDA], if they are set. */ + FLEXCAN_HWA_ERFSRClearEnhancedFifoFlag(pCan, FLEXCAN_ERFSR_ERFUFW_MASK | FLEXCAN_ERFSR_ERFWMI_MASK | FLEXCAN_ERFSR_ERFDA_MASK); + /* Write EFRCR[NFE] to configure the total number of enhanced Rx FIFO filter elements to be used in Enhanced Rx FIFO reception. */ + + + /* set rx fifo filter num */ + u32TempERFCR = ((u32FilterERFCRNum) << FLEXCAN_ERFCR_NFE_SHIFT)&FLEXCAN_ERFCR_NFE_MASK; + + /* Write ERFCR[NEXIF] to configure the number of extended ID and standard ID filter elements to be used in Enhanced Rx FIFO reception (NEXIF �� NFE + 1). */ + /* set rx fifo extended id filter num, <= NFE+1 */ + u32TempERFCR |= (u32ExtIDFilterNum << FLEXCAN_ERFCR_NEXIF_SHIFT)&FLEXCAN_ERFCR_NEXIF_MASK; + + u32TempERFCR |= FLEXCAN_ERFCR_ERFWM(u8WaterMark - 1U); /* receive 1 message will indicate to fifo water mark */ + + u32TempERFCR |= FLEXCAN_ERFCR_DMALW(19U); + + u32TempERFCR |= FLEXCAN_ERFCR_ERFEN_MASK; /* enable enhance fifo dma */ + + FLEXCAN_HWA_SetERFCR(pCan, u32TempERFCR); + + /* set enhanced fifo */ + FLEXCAN_HWA_EnableFDFifo(pCan); + + /* Configure the Enhanced Rx FIFO watermark by writing ERFCR[ERFWM]. */ + + /* If interrupts will be used, set the interrupt enables in the ERIER register */ + + /* If DMA will be used, set MCR[DMA] to enable DMA operation and write ERFCR[DMALW] to configure the number of words to transfer for each Enhanced Rx FIFO data element */ + + } + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; + +} + + + +/** + * @brief Process Tx Iflag and return result + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param u8Handler Transmit Handler + * @return 1 means process successfully and can transmit next time, 0 means no active flag, 0xff means out of range + */ +static uint8_t FLEXCAN_LL_ProcessTx(uint8_t u8CanIndex, uint8_t u8Handler) +{ + uint8_t u8Index; + FLEXCAN_Type *pCan; + FLEXCAN_SettingType *pCurSetting; + uint32_t u32Iflag; + uint32_t u32HandlerMask; + + pCurSetting = &s_aFlexCan_Setting_Table[u8CanIndex]; + +#if FLEXCAN_CHECK_PARAMETERS == STD_ON + if(u8Handler < pCurSetting->u8TxMbCnt1) + { +#endif + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + u32Iflag = FLEXCAN_HWA_GetFlag1(pCan);; + u32HandlerMask = (1U << (pCurSetting->u8TxMbStart1+u8Handler)); + + u32Iflag = u32Iflag & u32HandlerMask; + + if(u32Iflag>0U) + FLEXCAN_HWA_SetFlag1(pCan, u32Iflag); + + u8Index = ((u32Iflag>0U)?1U:0U); +#if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + else + { + u8Index = 0xFFU; + } +#endif + + return u8Index; +} + + +/* ################################################################################## */ +/* ################################ Global Functions ################################ */ + + + +/** + * @brief Initial FLEXCAN variables Memory + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + */ +void FLEXCAN_InitMemory(uint8_t u8CanIndex) +{ + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + FLEXCAN_ErrorType tRetVal; + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + if (tRetVal == FLEXCAN_ERROR_OK) + { + #endif + + s_aFlexCan_Setting_Table[u8CanIndex].bEnableFd = 0U; + s_aFlexCan_Setting_Table[u8CanIndex].bEnableFifo = 0U; + s_aFlexCan_Setting_Table[u8CanIndex].bEnableDMA = 0U; + s_aFlexCan_Setting_Table[u8CanIndex].pRxBuf = NULL; + s_aFlexCan_Setting_Table[u8CanIndex].u8RxMbCnt1 = 0U; + s_aFlexCan_Setting_Table[u8CanIndex].u8RxMbStart1 = 0U; + s_aFlexCan_Setting_Table[u8CanIndex].u8TxMbCnt1 = 0U; + s_aFlexCan_Setting_Table[u8CanIndex].u8TxMbStart1 = 0U; + s_aFlexCan_Setting_Table[u8CanIndex].u8RxFifoCnt = 0U; + s_aFlexCan_Setting_Table[u8CanIndex].eMbDataWidth = FLEXCAN_DATAWIDTH_8; + s_aFlexCan_Setting_Table[u8CanIndex].u8EnhancedFifoDmaWM = 0U; + s_aFlexCan_ErrorNotifyTable[u8CanIndex] = NULL; + s_aFlexCan_TxNotifyTable[u8CanIndex] = NULL; + s_aFlexCan_RxNotifyTable[u8CanIndex] = NULL; + + s_aFlexCan_CanUsed[u8CanIndex] = 0U; + + /* set first state */ + s_aCurrentSequence[u8CanIndex] = FLEXCAN_SEQUENCE_DEINIT; + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + +} + + +/** + * @brief Initial CAN + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pInitCfg clock, baud-rate, canfd, data length and so on. + * @return 0 is ok, others are not ok + */ +FLEXCAN_ErrorType FLEXCAN_Init(uint8_t u8CanIndex, const FLEXCAN_InitType *const pInitCfg) +{ + FLEXCAN_ErrorType tRetVal; + uint32_t u32TempCtrl1; + uint32_t u32TempMcr; + uint8_t u8Result; + FLEXCAN_Type *pCan; + FLEXCAN_BaudCfgType tBaudCfg; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] == FLEXCAN_SEQUENCE_DEINIT)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + + if (pInitCfg == NULL || (pInitCfg->u8EnhancedFifoDmaWM > 12U)) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + else + { + /* DMA only support in Legacy Rx FIFO and Enhance Rx FIFO */ + if (pInitCfg->bEnDma != 0U) + { + if ((pInitCfg->bEnRxFifo == 0U)) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + } + } + + if ((pInitCfg->bEnFd == 0U) && (pInitCfg->bEnBrs == 1U)) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + + if ((pInitCfg->bEnFd == 1U) && (u8CanIndex >= FLEXCAN_FD_INSTANCE_COUNT)) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #endif + /* set not start state */ + s_aCurrentSequence[u8CanIndex] = FLEXCAN_SEQUENCE_NOTSTART; + + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + u8Result = 0U; + tRetVal = FLEXCAN_ERROR_OK; + + FLEXCAN_HWA_SetMcrDisable(pCan, TRUE); + FLEXCAN_HWA_SetCtrl1(pCan, 0U); + FLEXCAN_HWA_SetCtrl1BaudSrc(pCan, pInitCfg->eClkSrcSel); + + FLEXCAN_HWA_SetMcrDisable(pCan, FALSE); + + /* mcr->B.bitMDIS = 0; */ + + FLEXCAN_HWA_SetHaltFreeze(pCan); + + /* wait for bitFRZACK=1 on freeze mode entry/exit */ + if (FLEXCAN_HWA_WaitMcrFreezen(pCan, 10000U) != 0U) + { + tRetVal |= FLEXCAN_ERROR_TIMEOUT; + } + else + { +// FLEXCAN_HWA_SetCtrl2(pCan, +// FLEXCAN_CTRL2_WRMFRZ(1U) | /* initial ram ecc */ +// FLEXCAN_CTRL2_TASD(20U) | +// FLEXCAN_CTRL2_DIRECT_EN(((pInitCfg->eDirect) & FLEXCAN_CTRL2_DIRECT_EN_MASK) ? 1U : 0U) | +// FLEXCAN_CTRL2_DIRECT_TRIG(((pInitCfg->eDirect) & FLEXCAN_CTRL2_DIRECT_TRIG_MASK) ? 1U : 0U) | +// FLEXCAN_CTRL2_ISOCANFDEN(1U)); + FLEXCAN_HWA_SetCtrl2(pCan, + FLEXCAN_CTRL2_WRMFRZ(1U) | /* initial ram ecc */ + FLEXCAN_CTRL2_TASD(20U) | + FLEXCAN_CTRL2_ISOCANFDEN(1U)); + + + + tBaudCfg.bEnFd = pInitCfg->bEnFd; + tBaudCfg.bEnBrs = pInitCfg->bEnBrs; + tBaudCfg.eMbDataWidth = pInitCfg->eMbDataWidth; + + tBaudCfg.eClkSrcHz = pInitCfg->eClkSrcHz; + tBaudCfg.eBaudrate = pInitCfg->eBaudrate; + tBaudCfg.eDataBaud = pInitCfg->eDataBaud; + + + u8Result = FLEXCAN_LL_ProcessBaud(&tBaudCfg); + + + if (u8Result) + { + tRetVal = FLEXCAN_ERROR_INVALID_PARAM; + } + else + { + /* when pCan fd disabled, pCan normal bit set by CTRL1 !!!! */ + u32TempCtrl1 = FLEXCAN_CTRL1_CLKSRC(pInitCfg->eClkSrcSel) | FLEXCAN_CTRL1_LOM(pInitCfg->bListenOnly); + + if (!tBaudCfg.bEnFd) + { + u32TempCtrl1 |= tBaudCfg.u32Ctrl1; /* SMP = 1: use 3 bits per CAN sample */ + } + else + { + FLEXCAN_HWA_SetCBT(pCan, tBaudCfg.u32Cbt); + + FLEXCAN_HWA_SetFDCTRL(pCan, tBaudCfg.u32FdCtrl); + FLEXCAN_HWA_SetFDCBT(pCan, tBaudCfg.u32FdCbt); + } + + + FLEXCAN_HWA_SetCtrl1(pCan, u32TempCtrl1); + + /* initial RAM to avoid ECC error */ + FLEXCAN_LL_EmbededRam_Init(u8CanIndex); + + u32TempMcr = FLEXCAN_MCR_MDIS(0) | /* enable pCan module */ + FLEXCAN_MCR_FRZ(1) | /* not frozen */ + FLEXCAN_MCR_RFEN(((!pInitCfg->bEnFd) && pInitCfg->bEnRxFifo) ? 1U : 0U) | /* Legacy RX FIFO, only when canfd not enable */ + FLEXCAN_MCR_HALT(1) | /* not halt */ + FLEXCAN_MCR_SOFTRST(0) | /* not reset */ + FLEXCAN_MCR_SUPV(1) | /* supervisor mode */ + FLEXCAN_MCR_WRNEN(0) | /* wake up disable */ + FLEXCAN_MCR_SRXDIS(1) | /* self reception disable */ + FLEXCAN_MCR_IRMQ(0) | /* individual Rx masking */ + FLEXCAN_MCR_DMA(pInitCfg->bEnDma) | /* DMA enable */ + FLEXCAN_MCR_PNET_EN(0) | /* Pretended Networking Enable */ + FLEXCAN_MCR_LPRIOEN(0) | /* Local Priority disable */ + FLEXCAN_MCR_AEN(0) | /* abort disable */ + FLEXCAN_MCR_FDEN(pInitCfg->bEnFd) | /* CAN FD enable */ + FLEXCAN_MCR_IDAM(0) | /* ID Acceptance Mode for Rx FIFO, format A */ + FLEXCAN_MCR_MAXMB(0); /* Max number of Message Buffer, num 31 is the 32th MB */ + + FLEXCAN_HWA_SetMCR(pCan, u32TempMcr); /* Negate FlexCAN 1 halt state for 32 MBs */ + + /* store setting value */ + s_aFlexCan_Setting_Table[u8CanIndex].bEnableFd = pInitCfg->bEnFd; + s_aFlexCan_Setting_Table[u8CanIndex].bEnableFifo = pInitCfg->bEnRxFifo; + s_aFlexCan_Setting_Table[u8CanIndex].bEnableDMA = pInitCfg->bEnDma; + s_aFlexCan_Setting_Table[u8CanIndex].eMbDataWidth = pInitCfg->eMbDataWidth; + s_aFlexCan_Setting_Table[u8CanIndex].u8EnhancedFifoDmaWM = pInitCfg->u8EnhancedFifoDmaWM; + } + } + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; + +} + + +/** + * @brief De-initial can instance + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @return 0 is ok, others are not ok + */ +FLEXCAN_ErrorType FLEXCAN_DeInit(uint8_t u8CanIndex) +{ + FLEXCAN_ErrorType tRetVal; + uint32_t u32TempMcr; + FLEXCAN_Type *pCan; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if (tRetVal == FLEXCAN_ERROR_OK) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + FLEXCAN_HWA_SetHaltFreeze(pCan); + + /* wait for bitFRZACK=1 on freeze mode entry/exit */ + if (FLEXCAN_HWA_WaitMcrFreezen(pCan, 10000U) != 0U) + { + tRetVal |= FLEXCAN_ERROR_TIMEOUT; + } + else + { + if(u8CanIndex < FLEXCAN_FD_INSTANCE_COUNT) + { + FLEXCAN_HWA_DisableFDFifo(pCan); + } + + + FLEXCAN_HWA_DisableLegacyFifo(pCan); + + u32TempMcr = FLEXCAN_MCR_MDIS(1) | /* enable pCan module */ + FLEXCAN_MCR_FRZ(0) | /* not frozen */ + FLEXCAN_MCR_RFEN(0U) | /* RX FIFO disable */ + FLEXCAN_MCR_HALT(0) | /* not halt */ + FLEXCAN_MCR_SOFTRST(0) | /* not reset */ + FLEXCAN_MCR_SUPV(1) | /* supervisor mode */ + FLEXCAN_MCR_WRNEN(0) | /* wake up disable */ + FLEXCAN_MCR_SRXDIS(1) | /* self reception disable */ + FLEXCAN_MCR_IRMQ(0) | /* individual Rx masking */ + FLEXCAN_MCR_DMA(0) | /* DMA enable */ + FLEXCAN_MCR_PNET_EN(0) | /* Pretended Networking Enable */ + FLEXCAN_MCR_LPRIOEN(0) | /* Local Priority disable */ + FLEXCAN_MCR_AEN(0) | /* abort disable */ + FLEXCAN_MCR_FDEN(0) | /* CAN FD enable */ + FLEXCAN_MCR_IDAM(0) | /* ID Acceptance Mode for Rx FIFO, format A */ + FLEXCAN_MCR_MAXMB(0); /* Max number of Message Buffer, num 31 is the 32th MB */ + + + FLEXCAN_HWA_SetCtrl1(pCan, 0U); + FLEXCAN_HWA_SetMCR(pCan, u32TempMcr); /* Negate FlexCAN 1 halt state for 32 MBs */ + + /* clear setting value */ + FLEXCAN_InitMemory(u8CanIndex); + } + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; +} + + +/** + * @brief Configure can receive message box and id filter + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pRxMbCfg contains CAN Instance, Rx CAN ID and Mask + * @return 0 is ok + */ +FLEXCAN_ErrorType FLEXCAN_RxFilterConfig(uint8_t u8CanIndex, const FLEXCAN_MBConfigType *const pRxMbCfg) +{ + FLEXCAN_ErrorType tRetVal; + FLEXCAN_Type *pCan; + FLEXCAN_RxMbFilterType *pCurRxCfg; + uint32_t u32Mask; + uint8_t u8Index; + FLEXCAN_SettingType *pCurSetting; + uint8_t bIndividualMask; + uint32_t u32TempAddr; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] == FLEXCAN_SEQUENCE_NOTSTART)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + if (pRxMbCfg == NULL) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + else + { + /* check buffer point if it is null */ + if ((pRxMbCfg->pRxBuf == NULL) || (((pRxMbCfg->u8RxFilterFifoCnt > 0U) && (pRxMbCfg->pRxFilterFifoList == NULL)))) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + } + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + bIndividualMask = 1U; + + /* current pCan instance */ + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + /* current pCan message pMb cnt */ + pCurSetting = &s_aFlexCan_Setting_Table[u8CanIndex]; + + + pCurSetting->pRxBuf = pRxMbCfg->pRxBuf; + + pCurSetting->u8RxMbStart1 = 0U; /* receive message buffer always start from 0 */ + pCurSetting->u8TxMbStart1 = 0U; + pCurSetting->u8RxMbCnt1 = pRxMbCfg->u8RxFilterMBCnt; + pCurSetting->u8TxMbCnt1 = pRxMbCfg->u8TxMsgCnt; + pCurSetting->u8RxFifoCnt = pRxMbCfg->u8RxFilterFifoCnt; + + if (pCurSetting->bEnableFifo) + { + /* only non-fd fifo need rx filter between rx and tx message buffer */ + if (pCurSetting->bEnableFd) + { +#if 0 + /* must multiple of 2 */ + if (pRxMbCfg->u8RxFilterFifoCnt % 2U) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } +#endif + + /* set fifo filter parameter */ + tRetVal = (FLEXCAN_ErrorType)(tRetVal | FLEXCAN_LL_SetEnhancedFifo(u8CanIndex, pRxMbCfg->pRxFilterFifoList, (uint32_t)pRxMbCfg->u8RxFilterFifoCnt, + pCurSetting->u8EnhancedFifoDmaWM)); + } + else + { + /* insert rx filter before tx message buffer, every group filter contains 8 elements(2MBs), at least 2 groups */ + if (pRxMbCfg->u8RxFilterFifoCnt <= 8U) + { + pCurSetting->u8RxMbStart1 = 8U; + } + else + { + pCurSetting->u8RxMbStart1 = (uint8_t)(6U + 2U * (pRxMbCfg->u8RxFilterFifoCnt / 8U + (pRxMbCfg->u8RxFilterFifoCnt % 8U > 0U ? 1U : 0U))); + + } + pCurSetting->u8TxMbStart1 = (uint8_t)(pCurSetting->u8RxMbStart1 + pCurSetting->u8RxMbCnt1); + + + /* set fifo filter parameter */ + tRetVal |= FLEXCAN_LL_SetLegacyFifo(u8CanIndex, pRxMbCfg->pRxFilterFifoList, (uint32_t)pRxMbCfg->u8RxFilterFifoCnt); + } + + + } + else + { + if (pCurSetting->bEnableFd) + { + + /* clear enhanced fifo */ + FLEXCAN_HWA_DisableFDFifo(pCan); + } + else + { + /* clear legacy fifo */ + FLEXCAN_HWA_DisableLegacyFifo(pCan); + } + } + + + /* For normal message buffer. */ + + /* fifo can exist with normal mb */ + /* Receive MB first set */ + + for (u8Index = 0U; u8Index < pCurSetting->u8RxMbCnt1; u8Index++) + { + uint8_t u8MBIndex; + /* ############## current rx pMb #################### */ + u8MBIndex = (uint8_t)(pCurSetting->u8RxMbStart1 + u8Index); + pCurSetting->u8TxMbStart1 ++; + /* current rx filter */ + pCurRxCfg = &(pRxMbCfg->pRxFilterMBList[u8Index]); + /* message buffer 1th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8MBIndex, pCurSetting->eMbDataWidth, 0U); + + FLEXCAN_MB_IDE_SET(u32TempAddr, pCurRxCfg->eRxFrameType); + + /* message buffer 2th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8MBIndex, pCurSetting->eMbDataWidth, 4U); + + /* 1. set filter id */ + if (pCurRxCfg->eRxFrameType == FLEXCAN_ID_STD) + { + FLEXCAN_MB_STDID_SET(u32TempAddr, pCurRxCfg->u32RxCanId); + + u32Mask = pCurRxCfg->u32RxCanIdMask << 18U; /* stardard id left shift 18 bits */ + } + else /* extended id filter */ + { + FLEXCAN_MB_EXTID_SET(u32TempAddr, pCurRxCfg->u32RxCanId); + u32Mask = pCurRxCfg->u32RxCanIdMask; /* stardard id */ + } + + /* message buffer 1th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8MBIndex, pCurSetting->eMbDataWidth, 0U); + /* set code 0x04U to enable rx */ + FLEXCAN_MB_CODE_SET(u32TempAddr, 4U); + + /* 3. set rx filter u32Mask */ + if (bIndividualMask) + { + /* In FRZ mode, init CAN1 16 msg buf filters */ + FLEXCAN_HWA_SetIndividualMask(pCan, (uint32_t)u8MBIndex, u32Mask); + } + else + { + /* global u32Mask */ + /* Global acceptance u32Mask: check all ID bits */ + if (u8MBIndex == 14U) + { + FLEXCAN_HWA_SetRx14Mask(pCan, u32Mask); + } + else if (u8MBIndex == 15U) + { + FLEXCAN_HWA_SetRx15Mask(pCan, u32Mask); + } + else + { + FLEXCAN_HWA_SetGlobalMask(pCan, u32Mask); + } + } + + + } + u8Index = (uint8_t)(pCurSetting->u8TxMbStart1 + pCurSetting->u8TxMbCnt1 - (uint8_t)0x1U); + + /* set max pMb number */ + FLEXCAN_HWA_AttachMCR(pCan, FLEXCAN_MCR_MAXMB(u8Index) /* Maximum pMb index */ + | FLEXCAN_MCR_IRMQ(bIndividualMask)); /* individual Rx masking */ + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; +} + + +/** + * @brief Configure can interrupt + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pIntCfg Contians interrupt enable and call back function points + * @return 0 is ok + */ +FLEXCAN_ErrorType FLEXCAN_SetInterrupt(uint8_t u8CanIndex, const FLEXCAN_InterruptType *const pIntCfg) +{ + FLEXCAN_ErrorType tRetVal; + FLEXCAN_Type *pCan; + uint32_t u32Mask; + uint8_t u8Index; + FLEXCAN_SettingType *pCurSetting; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] == FLEXCAN_SEQUENCE_NOTSTART)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + if (pIntCfg == NULL) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + else + { + /* check buffer point if it is null */ + if (((pIntCfg->bEnRxFifoInterrupt == 1U) && (pIntCfg->pRxFifoNotify == NULL)) + || ((pIntCfg->bEnRxMBInterrupt == 1U) && (pIntCfg->pRxMBNotify == NULL)) + || ((pIntCfg->bEnErrorInterrupt == 1U) && (pIntCfg->pErrorNotify == NULL))) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + } + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + pCurSetting = &s_aFlexCan_Setting_Table[u8CanIndex]; + + if ((pIntCfg->bEnErrorInterrupt) || (pIntCfg->bEnRxFifoInterrupt) || (pIntCfg->bEnRxMBInterrupt)) + { + } + + + if (pIntCfg->bEnErrorInterrupt) + { + FLEXCAN_HWA_AttachCtrl1(pCan, FLEXCAN_CTRL1_ERRMSK(1U) | /* error interrupt u32Mask */ + FLEXCAN_CTRL1_BOFFMSK(1U)); /* busoff interrupt u32Mask */ + + + FLEXCAN_HWA_AttachCtrl2(pCan, FLEXCAN_CTRL2_ERRMSK_FAST(1U) /* fast error */); + + s_aFlexCan_ErrorNotifyTable[u8CanIndex] = pIntCfg->pErrorNotify; + } + + if (pIntCfg->bEnRxFifoInterrupt) + { + /* interrupt for fifo */ + if (pCurSetting->bEnableFifo) + { + /* can fd fifo interrupt */ + if (pCurSetting->bEnableFd) + { + /* enhanced fifo data available interrupt */ + FLEXCAN_HWA_SetERFIERDataInterrupt(pCan); + } + else /* non-fd fifo interrupt */ + { + /* MB 5 at least one message in fifo interrupt */ + FLEXCAN_HWA_SetMaskFifoInterrupt(pCan); + } + s_aFlexCan_RxFifoNotifyTable[u8CanIndex] = pIntCfg->pRxFifoNotify; + } + } + if (pIntCfg->bEnTxMBInterrupt) + { + u32Mask = 0U; + + for (u8Index = 0U; u8Index < pCurSetting->u8TxMbCnt1; u8Index++) + { + u32Mask = (u32Mask << 1U) | (1U << pCurSetting->u8TxMbStart1); + } + + /* MB 31-0 u32Mask */ + FLEXCAN_HWA_AttachMaskMbInterrupt(pCan, u32Mask); + + s_aFlexCan_TxNotifyTable[u8CanIndex] = pIntCfg->pTxMBNotify; + } + + if (pIntCfg->bEnRxMBInterrupt) + { + u32Mask = 0U; + + for (u8Index = 0U; u8Index < pCurSetting->u8RxMbCnt1; u8Index++) + { + u32Mask = (u32Mask << 1U) | (1U << pCurSetting->u8RxMbStart1); + } + + /* MB 31-0 u32Mask */ + FLEXCAN_HWA_AttachMaskMbInterrupt(pCan, u32Mask); + + s_aFlexCan_RxNotifyTable[u8CanIndex] = pIntCfg->pRxMBNotify; + } + s_aFlexCan_Setting_Table[u8CanIndex].bEnableFifoInt = pIntCfg->bEnRxFifoInterrupt; + s_aFlexCan_Setting_Table[u8CanIndex].bEnableTxMBInt = pIntCfg->bEnTxMBInterrupt; + s_aFlexCan_Setting_Table[u8CanIndex].bEnableRxMBInt = pIntCfg->bEnRxMBInterrupt; + s_aFlexCan_Setting_Table[u8CanIndex].bEnableErrInt = pIntCfg->bEnRxMBInterrupt; + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; +} + + +/** + * @brief Start can instance + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @return 0 is ok + */ +FLEXCAN_ErrorType FLEXCAN_Start(uint8_t u8CanIndex) +{ + FLEXCAN_ErrorType tRetVal; + uint32_t u32TempMcr; + FLEXCAN_Type *pCan; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] == FLEXCAN_SEQUENCE_NOTSTART)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + /* set started state */ + s_aCurrentSequence[u8CanIndex] = FLEXCAN_SEQUENCE_STARTED; + + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + u32TempMcr = FLEXCAN_HWA_GetMCR(pCan); + + u32TempMcr &= ~(FLEXCAN_MCR_FRZ(1U) | /* not frozen */ + FLEXCAN_MCR_HALT(1U) /* not halt */ + /*| FLEXCAN_MCR_SUPV(1) user mode */ + ); /* not reset */ + + FLEXCAN_HWA_SetMCR(pCan, u32TempMcr); + + if (FLEXCAN_HWA_WaitMcrExitFreezen(pCan, 10000U) != 0U) + { + tRetVal |= FLEXCAN_ERROR_TIMEOUT; + } + else + { + + if (FLEXCAN_HWA_WaitMcrReady(pCan, 10000U) != 0U) + { + tRetVal |= FLEXCAN_ERROR_TIMEOUT; + } + else + { + + s_aFlexCan_CanUsed[u8CanIndex] = 1U; + } + } + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; +} + + +/** + * @brief Stop can instance + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + */ +FLEXCAN_ErrorType FLEXCAN_Stop(uint8_t u8CanIndex) +{ + FLEXCAN_ErrorType tRetVal; + uint32_t u32TempMcr; + FLEXCAN_Type *pCan; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] >= FLEXCAN_SEQUENCE_DEINIT)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + /* set started state */ + s_aCurrentSequence[u8CanIndex] = FLEXCAN_SEQUENCE_NOTSTART; + + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + u32TempMcr = FLEXCAN_HWA_GetMCR(pCan); + + u32TempMcr |= FLEXCAN_MCR_FRZ(1U) | /* not frozen */ + FLEXCAN_MCR_HALT(1U) /* not halt */ + /*| FLEXCAN_MCR_SUPV(1) user mode */ + ; /* not reset */ + + FLEXCAN_HWA_SetMCR(pCan, u32TempMcr); + + /* must wait */ + if (FLEXCAN_HWA_WaitMcrFreezen(pCan, 10000U) != 0U) + { + tRetVal |= FLEXCAN_ERROR_TIMEOUT; + } + else + { + + /* must wait */ + if (FLEXCAN_HWA_WaitMcrNoReady(pCan, 10000U) != 0U) + { + tRetVal |= FLEXCAN_ERROR_TIMEOUT; + } + else + { + s_aFlexCan_CanUsed[u8CanIndex] = 0U; + } + } + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + + #endif + + return tRetVal; +} + + +/** + * @brief Transmit data, if tx disable, must call FLEXCAN_TransmitProcess after transmiting + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pTxMsg contains CAN instance, CAN ID, CAN FD and CAN data. + * @return 0 is ok + */ +FLEXCAN_ErrorType FLEXCAN_TransmitData(uint8_t u8CanIndex, const FLEXCAN_TxMsgType *const pTxMsg) +{ + FLEXCAN_ErrorType tRetVal; + uint32_t *pSrc; + uint32_t *pDest; + uint32_t u32Index; + FLEXCAN_Type *pCan; + FLEXCAN_SettingType *pCurSetting; + uint8_t u8TxRealMbIndex; + uint32_t u32WordLen; + uint32_t u32TempAddr; + uint32_t u32Code; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] == FLEXCAN_SEQUENCE_STARTED)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + if (pTxMsg == NULL) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + else + { + /* check buffer point if it is null */ + if (&(pTxMsg->aData) == NULL) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + else + { + if (pTxMsg->u32DataLen > (uint32_t)s_aFlexCan_Setting_Table[u8CanIndex].eMbDataWidth) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + } + } + + if ((pTxMsg->bEnFd == 1U) && (u8CanIndex >= FLEXCAN_FD_INSTANCE_COUNT)) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #endif + + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + pCurSetting = &s_aFlexCan_Setting_Table[u8CanIndex]; + if (pTxMsg->u8TxHandler >= pCurSetting->u8TxMbCnt1) + { + tRetVal = FLEXCAN_ERROR_INVALID_PARAM; + } + else + { + u8TxRealMbIndex = (uint8_t)(pTxMsg->u8TxHandler + pCurSetting->u8TxMbStart1); + + /* message buffer 1th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, pCurSetting->eMbDataWidth, 0U); + u32Code = FLEXCAN_MB_CODE_GET(u32TempAddr); + if((0x8 != u32Code) && (0U != u32Code)) + { + tRetVal = FLEXCAN_ERROR_BUSY; + } + else + { + + /* message buffer 1th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, pCurSetting->eMbDataWidth, 0U); + /* clear last value */ + FLEXCAN_REG32_CONTENT(u32TempAddr) = 0U; + + FLEXCAN_MB_EDL_SET(u32TempAddr, pTxMsg->bEnFd); + FLEXCAN_MB_BRS_SET(u32TempAddr, pTxMsg->bEnBrs); + + FLEXCAN_MB_IDE_SET(u32TempAddr, pTxMsg->eFrameType); + + /* SRR */ + FLEXCAN_MB_SRR_SET(u32TempAddr, 0U); + /* DLC */ + u32Index = FLEXCAN_DataLenToDlc(pTxMsg->u32DataLen); + FLEXCAN_MB_DLC_SET(u32TempAddr, u32Index); + + /* message buffer 2th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, pCurSetting->eMbDataWidth, 4U); + /* clear last value */ + FLEXCAN_REG32_CONTENT(u32TempAddr) = 0U; + + /* standard id */ + if (pTxMsg->eFrameType == FLEXCAN_ID_STD) + { + FLEXCAN_MB_STDID_SET(u32TempAddr, pTxMsg->u32CanId); + } + else /* extended id */ + { + FLEXCAN_MB_EXTID_SET(u32TempAddr, pTxMsg->u32CanId); + } + + FLEXCAN_MB_PRIO_SET(u32TempAddr, 0U); + + pSrc = (uint32_t *)(uint32_t)(&(pTxMsg->aData[0])); + /* message buffer 3th word */ + pDest = (uint32_t *)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, pCurSetting->eMbDataWidth, 8U); + + u32WordLen = pTxMsg->u32DataLen / 4U + (pTxMsg->u32DataLen % 4U > 0U ? 1U : 0U); + + /* revert data to little endian */ + for (u32Index = 0U; u32Index < u32WordLen; u32Index++) + { + /* big endian to little endian */ + REV_BYTES_32(pSrc[u32Index], pDest[u32Index]); + } + + + /* message buffer 1th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, pCurSetting->eMbDataWidth, 0U); + + + /* CODE set 0x0C to transmit */ + FLEXCAN_MB_CODE_SET(u32TempAddr, 0x0CU); + + + if (pTxMsg->bWaitTxCompleted) + { + u32TempAddr = 0U; + u32WordLen = FLEXCAN_HWA_GetFlag1NoFifoFlag(pCan, u8TxRealMbIndex); + while ((u32WordLen == 0U) && (u32TempAddr++ < pTxMsg->u16WaitTxTimeout)) + { + u32WordLen = FLEXCAN_HWA_GetFlag1NoFifoFlag(pCan, u8TxRealMbIndex); + } + + if (u32WordLen == 0U) + { + tRetVal = FLEXCAN_ERROR_TIMEOUT; + } + + } + else + { + u32WordLen = FLEXCAN_HWA_GetFlag1NoFifoFlag(pCan, u8TxRealMbIndex); + if (u32WordLen == 0U) + { + tRetVal = FLEXCAN_ERROR_TIMEOUT; + } + } + + } + } + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; +} + + +/** + * @brief Process flag after transmit + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param u8Handler Transmit Handler + * @return 1 means process successfully and can transmit next time, 0 means no active flag, 0xff means out of range + */ +uint8_t FLEXCAN_TransmitProcess(uint8_t u8CanIndex, uint8_t u8TxHandler) +{ + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + FLEXCAN_ErrorType tRetVal; + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + if (tRetVal == FLEXCAN_ERROR_OK) + { + #endif + return FLEXCAN_LL_ProcessTx(u8CanIndex, u8TxHandler); + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + else + { + return 0U; + } + #endif +} + + +/** + * @brief Abort transmit with special transmit handler + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param u8TxHandler Transmit handler + * @return 0 is ok + */ +FLEXCAN_ErrorType FLEXCAN_TransmitAbort(uint8_t u8CanIndex, uint8_t u8TxHandler) +{ + FLEXCAN_ErrorType tRetVal; + FLEXCAN_SettingType *pCurSetting; + FLEXCAN_Type *pCan; + uint8_t u8TxRealMbIndex; + uint32_t u32TempAddr; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] == FLEXCAN_SEQUENCE_STARTED)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + + if (tRetVal == FLEXCAN_ERROR_OK) + { + + #endif + + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + pCurSetting = &s_aFlexCan_Setting_Table[u8CanIndex]; + if (u8TxHandler >= pCurSetting->u8TxMbCnt1) + { + tRetVal = FLEXCAN_ERROR_INVALID_PARAM; + } + + else + { + u8TxRealMbIndex = (uint8_t)(u8TxHandler + pCurSetting->u8TxMbStart1); + /* message buffer 1th word */ + u32TempAddr = (uint32_t)FLEXCAN_MB_WORDN_ADDR(&(pCan->RAM[0U]), u8TxRealMbIndex, pCurSetting->eMbDataWidth, 0U); + + + /* CODE set 0x09 to aborting transmit */ + FLEXCAN_MB_CODE_SET(u32TempAddr, 0x09U); + } + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; +} + + +/** + * @brief Receive data when polling (not used when rx interrupt enabled) + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pRxBufList is FLEXCAN_RxMsgType type point point, and don't need to be initialed + * @return 0 is ok + */ +FLEXCAN_ErrorType FLEXCAN_Receive_Polling(uint8_t u8CanIndex, FLEXCAN_RxMsgListType *const pRxBufList) +{ + FLEXCAN_ErrorType tRetVal; + uint8_t u8RetVal; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] == FLEXCAN_SEQUENCE_STARTED)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + if (pRxBufList == NULL) + { + tRetVal |= FLEXCAN_ERROR_INVALID_PARAM; + } + + + if (tRetVal == FLEXCAN_ERROR_OK) + { + + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + u8RetVal = 0U; + + pRxBufList->u8RxMsgCnt = 0U; + pRxBufList->pRxMsgBuf = s_aFlexCan_Setting_Table[u8CanIndex].pRxBuf; + + + if (s_aFlexCan_CanUsed[u8CanIndex] == 1U) + { + /* receive from fifo or normal */ + if (s_aFlexCan_Setting_Table[u8CanIndex].bEnableFifo) + { + u8RetVal = FLEXCAN_LL_ReceiveFifo(u8CanIndex, s_aFlexCan_Setting_Table[u8CanIndex].bEnableFd, pRxBufList->pRxMsgBuf); + } + else + { + u8RetVal = FLEXCAN_LL_PollingMb(u8CanIndex, pRxBufList->pRxMsgBuf); + } + pRxBufList->u8RxMsgCnt = u8RetVal; + } + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; +} + + + +/** + * @brief Get can error + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pErrorInfo is error information + * @return 0 is no error, others contains error + */ +FLEXCAN_ErrorType FLEXCAN_GetErrorInfo(uint8_t u8CanIndex, FLEXCAN_ErrorInfoType *const pErrorInfo) +{ + FLEXCAN_ErrorType tRetVal; + uint32_t u32ESR1Status, u32ECRStatus; + FLEXCAN_Type *pCan; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] >= FLEXCAN_SEQUENCE_NOTSTART)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + + if (tRetVal == FLEXCAN_ERROR_OK) + { + + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + u32ESR1Status = FLEXCAN_HWA_GetErrorInfo(pCan); + pErrorInfo->u32ErrorValue = u32ESR1Status; + + u32ECRStatus = FLEXCAN_HWA_GetErrorCount(pCan); + pErrorInfo->u32ErrorValue &= FLEXCAN_ESR1_BIT1ERR_FAST_MASK | FLEXCAN_ESR1_BIT0ERR_FAST_MASK | FLEXCAN_ESR1_CRCERR_FAST_MASK | FLEXCAN_ESR1_FRMERR_FAST_MASK | + FLEXCAN_ESR1_STFERR_FAST_MASK | + FLEXCAN_ESR1_ERROVR_MASK | FLEXCAN_ESR1_ERRINT_FAST_MASK | FLEXCAN_ESR1_BOFFDONEINT_MASK | FLEXCAN_ESR1_TWRNINT_MASK | FLEXCAN_ESR1_RWRNINT_MASK | + FLEXCAN_ESR1_BIT1ERR_MASK | FLEXCAN_ESR1_BIT0ERR_MASK | FLEXCAN_ESR1_ACKERR_MASK | FLEXCAN_ESR1_CRCERR_MASK | FLEXCAN_ESR1_FRMERR_MASK | FLEXCAN_ESR1_STFERR_MASK | + FLEXCAN_ESR1_TXWRN_MASK | FLEXCAN_ESR1_RXWRN_MASK | FLEXCAN_ESR1_FLTCONF_MASK | FLEXCAN_ESR1_BOFFINT_MASK | FLEXCAN_ESR1_ERRINT_MASK; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_BIT1ERR_FAST_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BIT1ERR_FAST = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BIT1ERR_FAST = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_BIT0ERR_FAST_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BIT0ERR_FAST = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BIT0ERR_FAST = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_CRCERR_FAST_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_CRCERR_FAST = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_CRCERR_FAST = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_FRMERR_FAST_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_FRMERR_FAST = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_FRMERR_FAST = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_STFERR_FAST_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_STFERR_FAST = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_STFERR_FAST = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_ERROVR_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_ERROVR = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_ERROVR = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_ERRINT_FAST_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_ERRINT_FAST = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_ERRINT_FAST = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_BOFFDONEINT_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BOFFDONEINT = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BOFFDONEINT = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_TWRNINT_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_TWRNINT = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_TWRNINT = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_RWRNINT_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_RWRNINT = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_RWRNINT = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_BIT1ERR_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BIT1ERR = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BIT1ERR = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_BIT0ERR_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BIT0ERR = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BIT0ERR = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_ACKERR_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_ACKERR = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_ACKERR = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_CRCERR_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_CRCERR = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_CRCERR = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_FRMERR_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_FRMERR = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_FRMERR = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_STFERR_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_STFERR = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_STFERR = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_TXWRN_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_TXWRN = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_TXWRN = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_RXWRN_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_RXWRN = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_RXWRN = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_FLTCONF_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_FLTCONF = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_FLTCONF = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_BOFFINT_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BOFFINT = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_BOFFINT = 0U; + + if(pErrorInfo->u32ErrorValue & FLEXCAN_ESR1_ERRINT_MASK) + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_ERRINT = 1U; + else + pErrorInfo->tErrorDetail.u8Error_FLEXCAN_ESR1_ERRINT = 0U; + + pErrorInfo->u32RxErrCnt = (u32ECRStatus & FLEXCAN_ECR_RXERRCNT_MASK) >> FLEXCAN_ECR_RXERRCNT_SHIFT; + pErrorInfo->u32RxErrCnt_Fast = (u32ECRStatus & FLEXCAN_ECR_RXERRCNT_FAST_MASK) >> FLEXCAN_ECR_RXERRCNT_FAST_SHIFT; + pErrorInfo->u32TxErrCnt = (u32ECRStatus & FLEXCAN_ECR_TXERRCNT_MASK) >> FLEXCAN_ECR_TXERRCNT_SHIFT; + pErrorInfo->u32TxErrCnt_Fast = (u32ECRStatus & FLEXCAN_ECR_TXERRCNT_FAST_MASK) >> FLEXCAN_ECR_TXERRCNT_FAST_SHIFT; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + else + { + PROCESS_UNUSED_VAR(u32ESR1Status); + PROCESS_UNUSED_VAR(u32ECRStatus); + } + #endif + + return tRetVal; +} + +/** + * @brief Clear can error + * + * @param u8CanIndex Can Index, must less than FLEXCAN_INSTANCE_COUNT + * @param pErrorInfo is error information + * @return 0 is no error, others contains error + */ +FLEXCAN_ErrorType FLEXCAN_ClrErrorInfo(uint8_t u8CanIndex, const FLEXCAN_ErrorInfoType *const pErrorInfo) +{ + FLEXCAN_ErrorType tRetVal; + FLEXCAN_Type *pCan; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + + if ((tRetVal == FLEXCAN_ERROR_OK) && (s_aCurrentSequence[u8CanIndex] >= FLEXCAN_SEQUENCE_NOTSTART)) + { + tRetVal = FLEXCAN_ERROR_OK; + } + else + { + tRetVal |= FLEXCAN_ERROR_INVALID_SEQUENCE; + } + + + if (tRetVal == FLEXCAN_ERROR_OK) + { + #else + tRetVal = FLEXCAN_ERROR_OK; + #endif + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + FLEXCAN_HWA_ClrErrorInfo(pCan, pErrorInfo->u32ErrorValue); + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif + + return tRetVal; +} + + + + +/** + * @brief Transfer Data length to DLC + * + * @param u32DataLen data length + * @return DLC + */ +uint32_t FLEXCAN_DataLenToDlc(uint32_t u32DataLen) +{ + uint32_t u32Dlc; + + switch (u32DataLen) + { + case 0U: + case 1U: + case 2U: + case 3U: + case 4U: + case 5U: + case 6U: + case 7U: + case 8U: + { + u32Dlc = u32DataLen; + } + break; + case 12U: + { + u32Dlc = 9U; + } + break; + case 16U: + { + u32Dlc = 10U; + } + break; + case 20U: + { + u32Dlc = 11U; + } + break; + case 24U: + { + u32Dlc = 12U; + } + break; + case 32U: + { + u32Dlc = 13U; + } + break; + case 48U: + { + u32Dlc = 14U; + } + break; + case 64U: + { + u32Dlc = 15U; + + } + break; + + default: + u32Dlc = 0U; + break; + } + + return u32Dlc; +} + + +/** + * @brief Transfer DLC to Data length + * + * @param u32Dlc DLC Data Length + * @return + */ +uint32_t FLEXCAN_DlcToDataLen(uint32_t u32Dlc) +{ + uint32_t u32DataLen; + + + switch (u32Dlc) + { + case 0U: + case 1U: + case 2U: + case 3U: + case 4U: + case 5U: + case 6U: + case 7U: + case 8U: + { + u32DataLen = u32Dlc; + } + break; + case 9U: + { + u32DataLen = 12U; + } + break; + case 10U: + { + u32DataLen = 16U; + } + break; + case 11U: + { + u32DataLen = 20U; + } + break; + case 12U: + { + u32DataLen = 24U; + } + break; + case 13U: + { + u32DataLen = 32U; + } + break; + case 14U: + { + u32DataLen = 48U; + } + break; + case 15U: + { + u32DataLen = 64U; + } + break; + + default: + u32DataLen = 0U; + break; + } + + return u32DataLen; +} + + +/* ################################################################################## */ +/* ############################## Interrupt Services ################################ */ + +/** + * @brief Can interrupt process + * + * @param u8CanIndex Can Index, Must less than FLEXCAN_INSTANCE_COUNT + */ +void FLEXCAN_IRQHandler(uint8_t u8CanIndex) +{ + uint8_t u8RecNum, u8Index; + uint32_t u32Flag1, u32ERFSR; + FLEXCAN_Type *pCan; + FLEXCAN_RxMsgType *pRxMsgList; + uint8_t u8FifoInterrupt; + FLEXCAN_ErrorType tRetVal; + + FLEXCAN_ErrorInfoType pErrorInfo; + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + /* check parameter */ + tRetVal = FLEXCAN_LL_CheckInstance(u8CanIndex); + if (tRetVal == FLEXCAN_ERROR_OK) + { + #endif + + pCan = (FLEXCAN_Type *)s_aFlexCan_InstanceTable[u8CanIndex]; + + FLEXCAN_GetErrorInfo(u8CanIndex, &pErrorInfo); + + pRxMsgList = s_aFlexCan_Setting_Table[u8CanIndex].pRxBuf; + + u32Flag1 = FLEXCAN_HWA_GetFlag1(pCan); + + + /* check pCan error */ + if (pErrorInfo.u32ErrorValue != 0U) + { + /* error notification */ + if (s_aFlexCan_ErrorNotifyTable[u8CanIndex] != NULL) + { + /* clear can error */ + s_aFlexCan_ErrorNotifyTable[u8CanIndex](u8CanIndex, &pErrorInfo); + } + } + + tRetVal = FLEXCAN_LL_CheckFdInstance(u8CanIndex); + + if (tRetVal == FLEXCAN_ERROR_OK) + { + u32ERFSR = FLEXCAN_HWA_ERFSRGetEnhancedFifoFlag(pCan, FLEXCAN_ERFSR_ERFDA_SHIFT, FLEXCAN_ERFSR_ERFDA_MASK); + u8FifoInterrupt = ((true == s_aFlexCan_Setting_Table[u8CanIndex].bEnableFd) && (0U != u32ERFSR) && (s_aFlexCan_Setting_Table[u8CanIndex].bEnableFifoInt)); + } + else + { + u8FifoInterrupt = 0U; + } + u8FifoInterrupt = (uint8_t)(u8FifoInterrupt | ((false == s_aFlexCan_Setting_Table[u8CanIndex].bEnableFd) && (u32Flag1 & 0x20U) && + (s_aFlexCan_Setting_Table[u8CanIndex].bEnableFifoInt))); + + /* check pCan receive data from fifo or normal */ + if ((s_aFlexCan_Setting_Table[u8CanIndex].bEnableFifo) && u8FifoInterrupt) + { + u8RecNum = FLEXCAN_LL_ReceiveFifo(u8CanIndex, s_aFlexCan_Setting_Table[u8CanIndex].bEnableFd, pRxMsgList); + /* rx notification */ + if ((u8RecNum > 0U) && (s_aFlexCan_RxFifoNotifyTable[u8CanIndex] != NULL)) + { + for (u8Index = 0U; u8Index < u8RecNum; u8Index++) + { + s_aFlexCan_RxFifoNotifyTable[u8CanIndex](u8CanIndex, &pRxMsgList[u8Index]); + } + } + } + + /* check transmit interrupt */ + if (s_aFlexCan_Setting_Table[u8CanIndex].bEnableTxMBInt) + { + for (u8Index = 0U; u8Index < s_aFlexCan_Setting_Table[u8CanIndex].u8TxMbCnt1; u8Index++) + { + u8RecNum = FLEXCAN_LL_ProcessTx(u8CanIndex,u8Index); + if ((u8RecNum == 1U) && (s_aFlexCan_TxNotifyTable[u8CanIndex] != NULL)) + { + s_aFlexCan_TxNotifyTable[u8CanIndex](u8CanIndex, u8Index); + } + } + } + + /* check receive interrupt */ + if (s_aFlexCan_Setting_Table[u8CanIndex].bEnableRxMBInt) + { + u8RecNum = FLEXCAN_LL_PollingMb(u8CanIndex, pRxMsgList); + if ((u8RecNum > 0U) && (s_aFlexCan_RxNotifyTable[u8CanIndex] != NULL)) + { + for (u8Index = 0U; u8Index < u8RecNum; u8Index++) + { + s_aFlexCan_RxNotifyTable[u8CanIndex](u8CanIndex, &pRxMsgList[u8Index]); + } + } + } + + PROCESS_UNUSED_VAR(pCan); + + #if FLEXCAN_CHECK_PARAMETERS == STD_ON + } + #endif +} + diff --git a/Src/fc7xxx_driver_fmc.c b/Src/fc7xxx_driver_fmc.c new file mode 100644 index 0000000..abb4d1f --- /dev/null +++ b/Src/fc7xxx_driver_fmc.c @@ -0,0 +1,197 @@ +/** + * @file fc7xxx_driver_fmc.c + * @author Flagchip + * @brief FC7xxx Fmc driver source code + * @version 0.1.0 + * @date 2024-1-5 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-1-5 Flagchip120 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_fmc.h" + +/* ################################################################################## */ +/* ####################################### Macro #################################### */ + + +/* ################################################################################## */ +/* ################################ Local Variables ################################# */ +static FMC_Type *const s_apFmcBase[FMC_INSTANCE_COUNT] = FMC_BASE_PTRS; + +/* ################################################################################## */ +/* ########################### Local Prototype Functions ############################ */ + + +/** + * \brief FMC PFlash Driver Function for lock/unlock sector + * + * \param pFMC FMC instance + * \param u32Address sector address + * \param bLock 0U-unlock, 1U-lock + */ +static FMC_Lock_StatusType FMCDRIVER_PFlashLockRegion(const FMC_InstanceType eInstance, uint32_t u32Address, uint8_t bLock); + +/** + * \brief FMC DFlash Driver Function for lock/unlock sector + * + * \param pFMC FMC instance + * \param u32Address sector address + * \param bLock 0U-unlock, 1U-lock + */ +static FMC_Lock_StatusType FMCDRIVER_DFlashLockRegion(const FMC_InstanceType eInstance, uint32_t u32Address, uint8_t bLock); + +/* ################################################################################## */ +/* ########################### Global Prototype Functions ########################### */ + + +/* ################################################################################## */ +/* ################################ Local Functions ################################# */ + +/** + * \brief FMC PFlash Driver Function for lock/unlock sector + * + * \param eInstance FMC instance + * \param u32Address sector address + * \param bLock 0U-unlock, 1U-lock + */ +static FMC_Lock_StatusType FMCDRIVER_PFlashLockRegion(const FMC_InstanceType eInstance, uint32_t u32Address, uint8_t bLock) +{ + FMC_Type *const pFMC = s_apFmcBase[eInstance]; + FMC_Lock_StatusType tRetVal; + uint32_t u32Index; + uint32_t u32Length; + uint32_t u32Temp; + + tRetVal = FMC_LOCK_ERROR_OK; + + /* 1 bank contains more than 256KB, used FB_CPELCK for first and last 256KB used FB_FPELCK */ + if ((u32Address >= PFLASH_ADDR_START) && (u32Address <= (PFLASH_ADDR_START + PFLASH_TOTAL_SIZE))) + { + /* PFLASH bank index */ + u32Index = (u32Address - PFLASH_ADDR_START) / PFLASH_BANK_SIZE; + u32Length = ((u32Address - PFLASH_ADDR_START) % PFLASH_BANK_SIZE) ; + if (u32Length < (PFLASH_BANK_SIZE - FLASH_256KB_SIZE)) /* first 768KB */ + { + u32Temp = ((uint32_t)1UL << ((u32Address - PFLASH_ADDR_START - PFLASH_BANK_SIZE * u32Index) >> 16)); + u32Temp = bLock ? (FMC_HWA_GetFBCPELCKValue(pFMC, u32Index) | u32Temp) : (FMC_HWA_GetFBCPELCKValue(pFMC, u32Index) & ~u32Temp); + FMC_HWA_SetFBCPELCKValue(pFMC, u32Index, u32Temp); + } + else /* last 256KB */ + { + u32Temp = ((u32Address - PFLASH_ADDR_START - PFLASH_BANK_SIZE * u32Index - PFLASH_PHANTOM_OFFSET) >> 13); + u32Temp = ((uint32_t)1UL << u32Temp); + u32Temp = bLock ? (FMC_HWA_GetFBFPELCKValue(pFMC, u32Index) | u32Temp) : (FMC_HWA_GetFBFPELCKValue(pFMC, u32Index) & ~u32Temp); + FMC_HWA_SetFBFPELCKValue(pFMC, u32Index, u32Temp); + } + } + else + { + tRetVal = FMC_LOCK_ERROR_INVALID_ADDR; + } + return tRetVal; +} + + +/** + * \brief FMC DFlash Driver Function for lock/unlock sector + * + * \param eInstance FMC instance + * \param u32Address sector address + * \param bLock 0U-unlock, 1U-lock + */ +static FMC_Lock_StatusType FMCDRIVER_DFlashLockRegion(const FMC_InstanceType eInstance, uint32_t u32Address, uint8_t bLock) +{ + FMC_Type *const pFMC = s_apFmcBase[eInstance]; + FMC_Lock_StatusType tRetVal; + uint32_t u32Index; + uint32_t u32Temp; + tRetVal = FMC_LOCK_ERROR_OK; + + /* 1 bank contains only 128KB, only used FB_FPELCK */ + u32Index = 2U; + if ((u32Address >= DFLASH_ADDR_START) && (u32Address <= DFLASH_ADDR_END)) + { + u32Temp = 1UL << ((u32Address - DFLASH_ADDR_START - DFLASH_BANK0_SIZE * (u32Index - 2U)) >> 13); + u32Temp = bLock ? (FMC_HWA_GetFBFPELCKValue(pFMC, u32Index) | u32Temp) : (FMC_HWA_GetFBFPELCKValue(pFMC, u32Index) & ~u32Temp); + FMC_HWA_SetFBFPELCKValue(pFMC, u32Index, u32Temp); + } + else + { + tRetVal = FMC_LOCK_ERROR_INVALID_ADDR; + } + return tRetVal; +} + + +/* ################################################################################## */ +/* ################################# Global Functions ############################### */ + +/** + * \brief FMC Driver Function for flash lock + * + * \param pFmcParam FMC driver flash lock parameter + * \return ErrorType + */ +FMC_Lock_StatusType FMCDRIVER_FlashLock(FMC_DRIVER_Lock_ParamType *pFmcParam) +{ + uint32_t u32Addr, u32Length, u32LockSize, u32TempAddr; + + FMC_Lock_StatusType tRetVal; + tRetVal = FMC_LOCK_ERROR_OK; + + u32Addr = pFmcParam->u32Address; + u32Length = pFmcParam->u32Length; + u32LockSize = (pFmcParam->bClass == FMC_Page) ? FLASH_PROGRAM_PAGE_SIZE : FLASH_ERASE_SECTOR_SIZE; + + /* Address and length should aligned by page/sector */ + if (pFmcParam->u32Address & (u32LockSize - 1U)) + { + tRetVal = FMC_LOCK_ERROR_INVALID_ADDR; + pFmcParam->u32ErrorAddress = pFmcParam->u32Address; + } + if (pFmcParam->u32Length & (u32LockSize - 1U)) + { + tRetVal = FMC_LOCK_ERROR_INVALID_SIZE; + pFmcParam->u32ErrorAddress = pFmcParam->u32Address; + } + + if (tRetVal == FMC_LOCK_ERROR_OK) + { + for (u32TempAddr = u32Addr; u32TempAddr < u32Addr + u32Length; u32TempAddr += u32LockSize) + { + if (pFmcParam->bFlash == FMC_PFlash) + { + tRetVal = FMCDRIVER_PFlashLockRegion(pFmcParam->bFMC, u32TempAddr, pFmcParam->bLock); + } + else + { + tRetVal = FMCDRIVER_DFlashLockRegion(pFmcParam->bFMC, u32TempAddr, pFmcParam->bLock); + } + } + } + return tRetVal; +} + +/** + * \brief FMC set ota active block + * + * \param eInstance FMC instance + * \param bLock 0U-active block 0, 1U-active block 1 + */ +void FMCDRIVER_SwapBlock(const FMC_InstanceType eInstance, FMC_API_ACTIVE_BLOCK_TYPE bActive) +{ + FMC_Type *const pFMC = s_apFmcBase[eInstance]; + if (0U == FMC_HWA_GetOTACtrlValue(pFMC, 0)) + { + FMC_HWA_SetOTAActive(pFMC, 0, bActive); + FMC_HWA_SetOTAEnable(pFMC, 0); + } +} + diff --git a/Src/fc7xxx_driver_fpu.c b/Src/fc7xxx_driver_fpu.c new file mode 100644 index 0000000..3a76265 --- /dev/null +++ b/Src/fc7xxx_driver_fpu.c @@ -0,0 +1,51 @@ +/** + * @file fc7xxx_driver_fpu.c + * @author Flagchip051 + * @brief FC4xxx FPU driver type definition and API + * @version 0.1.0 + * @date 2024-01-11 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-11 Flagchip054 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_fpu.h" + +/* Note: library user should add interrupt stack support, add compiler support */ +/* + * @details @verbatim +If only want use FPU, +1) configure FCIDE to enable FPU compiler support, "Properties" -> C/C++ Build -> Settings -> Tool Settings -> Target Processor -> Float ABI -> FP instructions(hard) -> FPU Type set to "fpv5-sp-d16" +2) configure FCIDE to enable FPU compiler support, "Properties" -> C/C++ Build -> Settings -> Tool Settings -> GNU Arm Cross C Compiler -> Preprocessor -> Defined symbols(-D) -> Add "__FPU_PRESENT=1" (without ") +3) and call FPU_Enable to enable FPU at the beginning of program. + +If want to use DSP, +1) configure FCIDE to enable FPU compiler support, Properties -> C/C++ Build -> Settings -> Tool Settings -> Target Processor -> Float ABI -> FP instructions(hard) +2) add MACRO "DRIVER_CM7_DSP_ENABLE" in FCIDE Properties -> C/C++ General -> Paths and Symbols -> Symbols -> GNU C and GNU C++ and Assembly +3) add Include Path to project Properties -> C/C++ General -> Paths and Symbols -> Includes -> GNU C and GNU C++ and Assembly: + ../../../../../../Template/Device/CMSIS5_590/DSP/Include + ../../../../../../Template/Device/CMSIS5_590/Core/Include + ../../../../../../Template/Device/CMSIS5_590/DSP/PrivateInclude +4) and call FPU_Enable to enable FPU at the beginning of program. + @endverbatim + */ + +void FPU_Enable(void) +{ + FPU_HWA_Enable(); /* set CP10 and CP11 Full Access */ + __DSB(); + __ISB(); +} + +void FPU_Disable(void) +{ + FPU_HWA_Disable(); /* Access denied. Any attempted access generates a NOCP UsageFault */ +} + diff --git a/Src/fc7xxx_driver_freqm.c b/Src/fc7xxx_driver_freqm.c new file mode 100644 index 0000000..530751a --- /dev/null +++ b/Src/fc7xxx_driver_freqm.c @@ -0,0 +1,186 @@ +/** + * @file fc7xxx_driver_freqm.c + * @author Flagchip + * @brief FC7xxx FREQM driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-14 qxw0100 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_freqm.h" +#include "fc7xxx_driver_pcc.h" +#include "interrupt_manager.h" + +/********* Local variable ************/ +static FREQM_Type * const pFreqmPtrs = FREQM; + +static FREQM_MesCntStartCallBackType s_pMesCntStartCallback = NULL; +static FREQM_MesCntStopCallBackType s_pMesCntStopCallback = NULL; +static FREQM_RefCntStopCallBackType s_pRefCntStopCallback = NULL; +static FREQM_FaultCallBackType s_pFaultCallback = NULL; + + +/********* Global Functions ************/ +/** + * @brief Initialize FREQM configuration + * + * @param pInitStruct the basic configurations of the FREQM + * @return FREQM_StatusType whether the operation is successfully + */ +FREQM_StatusType FREQM_Init(const FREQM_InitType *const pInitStruct) +{ + FREQM_StatusType eRet = FREQM_STATUS_SUCCESS; + if (NULL == pInitStruct) + { + eRet = FREQM_STATUS_PARAM_INVALID; + } + else + { + /* Configure the clock divider value */ + FREQM_HWA_MesClk_PreDiv(pFreqmPtrs,pInitStruct->u8PredivVal); + /* Select the clock source to be measured */ + FREQM_HWA_MesClkSel(pFreqmPtrs,pInitStruct->eClkSel); + /* Set and clear the S/W reset */ + PCC_GenPeripheralReset(PCC_CLK_FREQM); + /* Configure the measure counter targer value */ + FREQM_HWA_SetMesLength(pFreqmPtrs,pInitStruct->u32MesLen); + /* Configure the reference counter target value */ + FREQM_HWA_SetRefTimeout(pFreqmPtrs,pInitStruct->u32RefTo); + } + return eRet; +} + +/** + * @brief De-initialize the FREQM + * + * @param eInstance the selected FREQM + * @return FREQM_StatusType whether the operation is successfully + */ +FREQM_StatusType FREQM_DeInit() +{ + FREQM_StatusType eStatus = FREQM_STATUS_SUCCESS; + /* Set register to reset value */ + FREQM_HWA_MesClk_PreDiv(pFreqmPtrs,0U); + FREQM_HWA_MesClkSel(pFreqmPtrs,(FREQM_MesClkSelType)0); + FREQM_HWA_SetMesLength(pFreqmPtrs,0xFFFFFFFFU); + FREQM_HWA_SetRefTimeout(pFreqmPtrs,0xFFFFFFFFU); + + FREQM_HWA_DisableCntEventInterrupt(pFreqmPtrs); + s_pMesCntStartCallback = NULL; + s_pMesCntStopCallback = NULL; + s_pRefCntStopCallback = NULL; + s_pFaultCallback = NULL; + + return eStatus; +} + +/** + * @brief Clear all FREQM status + * + * @return FREQM_StatusType whether the operation is successfully + */ +FREQM_StatusType FREQM_ClearStatus() +{ + FREQM_StatusType eStatus = FREQM_STATUS_SUCCESS; + uint32_t u32TimeOutVal = 0xffff; + uint32_t u32CntStatus; + + FREQM_HWA_SetRefCnt(pFreqmPtrs,0U); + + do + { + u32CntStatus = FREQM_HWA_GetCntStatus(pFreqmPtrs); + u32TimeOutVal--; + }while(u32CntStatus!=0U); + + if(u32TimeOutVal == 0U) + { + eStatus = FREQM_STATUS_TIMEOUT; + } + return eStatus; +} + +/** + * @brief Start the reference/measure counter + * + */ +void FREQM_StartMeasureCnt() +{ + FREQM_HWA_SetMesCnt(pFreqmPtrs,0U); +} + +/** + * @brief Get saved reference counter value + * + * @return uint32_t saved reference counter value + */ +uint32_t FREQM_GetRefCntSave() +{ + return FREQM_HWA_GetRefCntSave(pFreqmPtrs); +} + +/** + * @brief FREQM initialize interrupt function + * + * @param pIntStruct FREQM interrupt structure + * @return FREQM_StatusType whether the operation is successfully + */ +FREQM_StatusType FREQM_InterruptInit(const FREQM_InterruptType *const pIntrStruct) +{ + FREQM_StatusType eStatus = FREQM_STATUS_SUCCESS; + + FREQM_HWA_EnableCntEventInterrupt(pFreqmPtrs); + /*register callback functions*/ + s_pMesCntStartCallback = pIntrStruct->pMesCntStartCallback; + s_pMesCntStopCallback = pIntrStruct->pMesCntStopCallback; + s_pRefCntStopCallback = pIntrStruct->pRefCntStopCallback; + s_pFaultCallback = pIntrStruct->pFaultCallback; + + return eStatus; +} + +/** + * @brief Interrupt IRQ handle of FREQM + * + */ +void FREQM_IRQHandler(void) +{ + uint32_t u32CntStatus; + bool bIntFlag; + + bIntFlag = FREQM_HWA_GetInterruptFlag(pFreqmPtrs); + if(bIntFlag) + { + FREQM_HWA_ClearInterruptFlag(pFreqmPtrs); + } + + u32CntStatus = FREQM_HWA_GetCntStatus(pFreqmPtrs); + + if(u32CntStatus == FREQM_CNT_STATUS_MES_CNT_START_MASK)//0x4 + { + s_pMesCntStartCallback(); + } + else if(u32CntStatus == (FREQM_CNT_STATUS_MES_CNT_START_MASK|FREQM_CNT_STATUS_MES_CNT_STOP_MASK) )//0x6 + { + + s_pMesCntStopCallback(); + } + else if(u32CntStatus == (FREQM_CNT_STATUS_MES_CNT_START_MASK|FREQM_CNT_STATUS_MES_CNT_STOP_MASK|FREQM_CNT_STATUS_REF_CNT_STOP_MASK) )//0x7 + { + s_pRefCntStopCallback(); + } + else + { + s_pFaultCallback(); + } +} diff --git a/Src/fc7xxx_driver_ftu.c b/Src/fc7xxx_driver_ftu.c new file mode 100644 index 0000000..d48df67 --- /dev/null +++ b/Src/fc7xxx_driver_ftu.c @@ -0,0 +1,1810 @@ +/** + * @file fc7xxx_driver_ftu.c + * @author Flagchip + * @brief FC7xxx FTU driver type definition and API + * @version 0.1.0 + * @date 2022-11-15 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2022-11-15 Flagchip070 N/A First version for FC7300 + ******************************************************************************** */ + +#include "fc7xxx_driver_ftu.h" +#include "fc7xxx_driver_pcc.h" +#include "interrupt_manager.h" +#include "HwA_scm.h" + +/********* Local variable ************/ +static const uint32_t s_aFtuMaxCounter[FTU_INSTANCE_COUNT] = {0xFFFFu, 0xFFFFFFu, 0xFFFFFFu, 0xFFFFu, 0xFFFFu, 0xFFFFu, 0xFFFFu, 0xFFFFu}; +static FTU_Type * const s_pFtuBasePtrs[FTU_INSTANCE_COUNT] = FTU_BASE_PTRS; +static FTU_ClkSrcType s_eFtuClkSrc[FTU_INSTANCE_COUNT] = {FTU_NO_CLK}; + +static FTU_ChannelCallBackType s_pChannelCallback[FTU_INSTANCE_COUNT] = {NULL}; +static FTU_FaultCallBackType s_pFaultCallback[FTU_INSTANCE_COUNT] = {NULL}; +static FTU_InterruptCallBackType s_pOverflowCallback[FTU_INSTANCE_COUNT] = {NULL}; +static FTU_InterruptCallBackType s_pReloadPointCallback[FTU_INSTANCE_COUNT] = {NULL}; + +/***************** Local Prototype Functions *********************/ +static void enable_sync_flag(FTU_Type *pFtu, uint16_t u16SyncFlag); +static void disable_sync_flag(FTU_Type *pFtu, uint16_t u16SyncFlag); +static void disable_reload_points(FTU_Type *pFtu, uint16_t u16ReloadPoints); +static void enable_reload_points(FTU_Type *pFtu, uint16_t u16ReloadPoints); + +/********* Local Functions ************/ +/** + * @brief Configure the input capture edge of the selected FTU channel + * + * @param pFtu the base address of the FTU instance + * @param u8Channel channel index of the FTU instance + * @param eEdge input capture edge + */ +static void set_ftu_input_edge(FTU_Type *pFtu, uint8_t u8Channel, FTU_InputCapturePinModeType eEdge) +{ + if (FTU_INPUT_RISING_EDGE == eEdge) + { + FTU_HWA_ConfigChannelEdgeLevel(pFtu, u8Channel, FTU_CHANNEL_EDGE_RISING); + } + else if (FTU_INPUT_FALLING_EDGE == eEdge) + { + FTU_HWA_ConfigChannelEdgeLevel(pFtu, u8Channel, FTU_CHANNEL_EDGE_FALLING); + } + else if (FTU_INPUT_BOTH_EDGE == eEdge) + { + FTU_HWA_ConfigChannelEdgeLevel(pFtu, u8Channel, FTU_CHANNEL_EDGE_BOTH); + } + else + { + FTU_HWA_ConfigChannelEdgeLevel(pFtu, u8Channel, FTU_CHANNEL_EDGE_NOT_USED); + } +} +/** + * @brief Enable the synchronization of the selected FTU instance + * + * @param pFtu the base address of the FTU instance + * @param u16SyncFlag The synchronization flag + */ +static void enable_sync_flag(FTU_Type *pFtu, uint16_t u16SyncFlag) +{ + uint32_t u32Loop; + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_FTUEN)) + { + FTU_HWA_SetModuleUpdateRegBySync(pFtu); + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_LDOK)) + { + FTU_HWA_SetPwmLoadEnable(pFtu); + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_CNTINC)) + { + FTU_HWA_SetCntinSync(pFtu); + } + for(u32Loop = 0; u32Loop < 4u; u32Loop++) + { + if(0u != (u16SyncFlag & (uint16_t)((uint16_t)FTU_SYNC_FLAG_SYNCEN01 << u32Loop))) + { + FTU_HWA_SetChannelSyncEnable(pFtu, u32Loop); + } + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_PWMSYNC)) + { + FTU_HWA_SetPwmSyncMode(pFtu); + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_REINIT)) + { + FTU_HWA_SetReinitBySync(pFtu); + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_SYNCHOM)) + { + FTU_HWA_EnableOutputMaskBySync(pFtu); + } +} + +/** + * @brief Disable the synchronization of the selected FTU instance + * + * @param pFtu the base address of the FTU instance + * @param u16SyncFlag The synchronization flag + */ +static void disable_sync_flag(FTU_Type *pFtu, uint16_t u16SyncFlag) +{ + uint32_t u32Loop; + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_FTUEN)) + { + FTU_HWA_ClearModuleUpdateRegBySync(pFtu); + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_LDOK)) + { + FTU_HWA_ClearPwmLoadEnable(pFtu); + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_CNTINC)) + { + FTU_HWA_ClearCntinSync(pFtu); + } + for(u32Loop = 0; u32Loop < 4u; u32Loop++) + { + if(0u != (u16SyncFlag & ((uint16_t)FTU_SYNC_FLAG_SYNCEN01 << u32Loop))) + { + FTU_HWA_ClearChannelSyncEnable(pFtu, u32Loop); + } + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_PWMSYNC)) + { + FTU_HWA_ClearPwmSyncMode(pFtu); + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_REINIT)) + { + FTU_HWA_ClearReinitBySync(pFtu); + } + if(0u != (u16SyncFlag & (uint16_t)FTU_SYNC_FLAG_SYNCHOM)) + { + FTU_HWA_DisableOutputMaskBySync(pFtu); + } +} + +/** + * @brief Disable the reload points of the selected FTU instance + * + * @param pFtu the base address of the FTU instance + * @param u16ReloadPoints The reload points flag + */ +static void disable_reload_points(FTU_Type *pFtu, uint16_t u16ReloadPoints) +{ + uint32_t u32Loop; + if(0u != (u16ReloadPoints & (uint16_t)FTU_RELOAD_POINT_CNTMAX)) + { + /* Enables Maximum Loading Point */ + FTU_HWA_DisableMaxLoadPoint(pFtu); + } + if(0u != (u16ReloadPoints & (uint16_t)FTU_RELOAD_POINT_CNTMIN)) + { + /* Disables Minimum Loading Point */ + FTU_HWA_DisableMinLoadPoint(pFtu); + } + for(u32Loop = 0u; u32Loop < FTU_CHANNEL_CONTROLS_COUNT; u32Loop++) + { + if(0u != (u16ReloadPoints & (uint16_t)((uint16_t)FTU_RELOAD_POINT_CHANNEL_0 << u32Loop))) + { + /* Channel match is not included as a reload opportunity */ + FTU_HWA_DisableChannelMatchReload(pFtu, u32Loop); + } + } +} + +/** + * @brief Enable the reload points of the selected FTU instance + * + * @param pFtu the base address of the FTU instance + * @param u16ReloadPoints The reload points flag + */ +static void enable_reload_points(FTU_Type *pFtu, uint16_t u16ReloadPoints) +{ + uint32_t u32Loop; + if(0u != (u16ReloadPoints & (uint32_t)FTU_RELOAD_POINT_CNTMAX)) + { + /* Enables Maximum Loading Point */ + FTU_HWA_EnableMaxLoadPoint(pFtu); + } + if(0u != (u16ReloadPoints & (uint32_t)FTU_RELOAD_POINT_CNTMIN)) + { + /* Enables Minimum Loading Point */ + FTU_HWA_EnableMinLoadPoint(pFtu); + } + for(u32Loop = 0; u32Loop < FTU_CHANNEL_CONTROLS_COUNT; u32Loop++) + { + if(0u != (u16ReloadPoints & ((uint32_t)FTU_RELOAD_POINT_CHANNEL_0 << u32Loop))) + { + /* Channel match is included as a reload opportunity */ + FTU_HWA_EnableChannelMatchReload(pFtu, u32Loop); + } + } +} + +/********* Global Functions ************/ +/** + * @brief Enable the reload points of the selected FTU instance + * + * @param eInstance the selected FTU instance + * @param u16ReloadPoints The reload points flag + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EnableReloadPoints(const FTU_InstanceType eInstance, uint16_t u16ReloadPoints) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + enable_reload_points(s_pFtuBasePtrs[eInstance], u16ReloadPoints); + } + return eStatus; +} + +/** + * @brief Disable the reload points of the selected FTU instance + * + * @param eInstance the selected FTU instance + * @param u16ReloadPoints The reload points flag + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DisableReloadPoints(const FTU_InstanceType eInstance, uint16_t u16ReloadPoints) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + disable_reload_points(s_pFtuBasePtrs[eInstance], u16ReloadPoints); + } + return eStatus; +} + +/** + * @brief enable the synchronization of the selected FTU + * + * @param eInstance the selected FTU instance + * @param u16ReloadPoints The synchronization flag + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EnableSync(const FTU_InstanceType eInstance, uint16_t u16SyncFlag) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + enable_sync_flag(s_pFtuBasePtrs[eInstance], u16SyncFlag); + } + return eStatus; +} + +/** + * @brief disable the synchronization of the selected FTU + * + * @param eInstance the selected FTU instance + * @param u16ReloadPoints The synchronization flag + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DisableSync(const FTU_InstanceType eInstance, uint16_t u16SyncFlag) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + disable_sync_flag(s_pFtuBasePtrs[eInstance], u16SyncFlag); + } + return eStatus; +} + +/** + * @brief Initialize FTU basic configuration + * + * @param eInstance the selected FTU instance + * @param pCommonStruct the basic configurations of the FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_CommonInit(const FTU_InstanceType eInstance, const FTU_CommonType *const pCommonStruct) +{ + FTU_StatusType eRet = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eRet = FTU_STATUS_PARAM_INVALID; + } + else if (pCommonStruct->u32OverflowValue > s_aFtuMaxCounter[(uint32_t)eInstance]) + { + eRet = FTU_STATUS_PARAM_INVALID; + } + else + { + if (true == pCommonStruct->bGtbEnable) + { + FTU_HWA_EnableGlobalTimeBase(s_pFtuBasePtrs[eInstance]); + } + else + { + FTU_HWA_DisableGlobalTimeBase(s_pFtuBasePtrs[eInstance]); + } + FTU_HWA_DisableModuleCpwmMode(s_pFtuBasePtrs[eInstance]); + /* set FTU prescale */ + FTU_HWA_SetModulePrescale(s_pFtuBasePtrs[eInstance], pCommonStruct->ePrescaler); + /* configure fault filter prescaler */ + FTU_HWA_ConfigModuleFilterPrescale(s_pFtuBasePtrs[eInstance], pCommonStruct->eFliterPrescaler); + /*set the compare register as max value*/ + FTU_HWA_SetModuleCompareValue(s_pFtuBasePtrs[eInstance], (uint32_t)pCommonStruct->u32OverflowValue); + /*set initial value as 0*/ + FTU_HWA_SetCounterInitialValue(s_pFtuBasePtrs[eInstance], 0u); + /*set any value to clear the current counter register to initial value*/ + FTU_HWA_ClearModuleCounter(s_pFtuBasePtrs[eInstance], (uint32_t)0x1U); + /* set ftu OUTMASK sync mode, set bit SYNCHOM and OUTMASK register will update when then sync event happened */ + FTU_HWA_EnableOutputMaskBySync(s_pFtuBasePtrs[eInstance]); + /* set ftu debug mode */ + FTU_HWA_ConfigDebugMode(s_pFtuBasePtrs[eInstance], (uint32_t)pCommonStruct->eDbgMode); + /* Disable channel match trigger/interrupt when count-up/down in CPWM/QUAD mode */ + FTU_HWA_ConfigUpDownDisable(s_pFtuBasePtrs[eInstance], pCommonStruct->eUpDownDisable); + /*configure the synchronization*/ + disable_sync_flag(s_pFtuBasePtrs[eInstance], ~pCommonStruct->u16SyncFlag); + enable_sync_flag(s_pFtuBasePtrs[eInstance], pCommonStruct->u16SyncFlag); + + /*configure the reload points*/ + disable_reload_points(s_pFtuBasePtrs[eInstance], ~pCommonStruct->u16ReloadPoints); + enable_reload_points(s_pFtuBasePtrs[eInstance], pCommonStruct->u16ReloadPoints); + + /* configure hardware trigger mode */ + FTU_HWA_ConfigTrigMode(s_pFtuBasePtrs[eInstance], pCommonStruct->eHwTrigMode); + /* configure the frequency of the reload opportunities*/ + FTU_HWA_ConfigFreqOfReloadOp(s_pFtuBasePtrs[eInstance], pCommonStruct->u8ReloadFreq); + + /* select clock source */ + if (FTU_INTERNAL_CLK == pCommonStruct->eClkSrc) + { + s_eFtuClkSrc[eInstance] = FTU_INTERNAL_CLK; + } + else if (FTU_EXTERNAL_CLK0 == pCommonStruct->eClkSrc) + { + s_eFtuClkSrc[eInstance] = FTU_EXTERNAL_CLK0; + FTU_HWA_ConfigExternalClkSrc(s_pFtuBasePtrs[eInstance], FTU_TCLK0_USED); + } + else if (FTU_EXTERNAL_CLK1 == pCommonStruct->eClkSrc) + { + s_eFtuClkSrc[eInstance] = FTU_EXTERNAL_CLK1; + FTU_HWA_ConfigExternalClkSrc(s_pFtuBasePtrs[eInstance], FTU_TCLK1_USED); + } + else if (FTU_EXTERNAL_CLK2 == pCommonStruct->eClkSrc) + { + s_eFtuClkSrc[eInstance] = FTU_EXTERNAL_CLK2; + FTU_HWA_ConfigExternalClkSrc(s_pFtuBasePtrs[eInstance], FTU_TCLK2_USED); + } + else + { + s_eFtuClkSrc[eInstance] = FTU_NO_CLK; + } + } + return eRet; +} + +/** + * @brief De-initialize the FTU instance + * + * @param eInstance the selected FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DeInit(const FTU_InstanceType eInstance) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + s_eFtuClkSrc[eInstance] = FTU_NO_CLK; + s_pChannelCallback[eInstance] = NULL; + s_pFaultCallback[eInstance] = NULL; + s_pOverflowCallback[eInstance] = NULL; + s_pReloadPointCallback[eInstance] = NULL; + + FTU_HWA_ClearModuleRegister(s_pFtuBasePtrs[eInstance]); + } + return eStatus; +} + +/** + * @brief Fills in the FTU configuration structure with the default settings. + * + * @param pCommonStruct Pointer to the user configuration structure + */ +void FTU_GetDefaultInitCfg(FTU_CommonType *pCommonStruct) +{ + DEV_ASSERT(NULL_PTR != pCommonStruct); + pCommonStruct->ePrescaler = FTU_DIV_1; + pCommonStruct->eFliterPrescaler = FTU_FLT_DIV_1; + pCommonStruct->u32OverflowValue = 0xFFFF; + pCommonStruct->eClkSrc = FTU_INTERNAL_CLK; + pCommonStruct->u16ReloadPoints = (uint16_t)FTU_RELOAD_POINT_CNTMAX; + pCommonStruct->u8ReloadFreq = 0; + pCommonStruct->u16SyncFlag = 0; + pCommonStruct->eHwTrigMode = FTU_CLEARS_TRIG_WHEN_DETECTED; + pCommonStruct->eDbgMode = FTU_DBG_COUNTER_WORKS_CHN_WORKS; + pCommonStruct->eUpDownDisable = FTU_DISABLE_TRIG_INTR_NONE; + pCommonStruct->bGtbEnable = false; +} + +/** + * @brief Configure FTU to counter mode + * + * @param eInstance the selected FTU instance + * @param pCounterStruct the configurations of the counter mode + * @return FTU_StatusType whether the operation is successfully + * @note This function will stop timer + */ +FTU_StatusType FTU_CounterModeInit(const FTU_InstanceType eInstance, const FTU_CounterModeType *const pCounterStruct) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else if ( (pCounterStruct->u32CounterValue > s_aFtuMaxCounter[(uint32_t)eInstance]) + || (pCounterStruct->u32InitialValue > s_aFtuMaxCounter[(uint32_t)eInstance])) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* disable ftu timer */ + FTU_HWA_ConfigModuleClkSrc(s_pFtuBasePtrs[eInstance], FTU_MODULE_NO_CLK); + /* set FTU MOD register value */ + FTU_HWA_SetModuleCompareValue(s_pFtuBasePtrs[eInstance], (uint32_t)pCounterStruct->u32CounterValue); + /*set initial value */ + FTU_HWA_SetCounterInitialValue(s_pFtuBasePtrs[eInstance], (uint32_t)pCounterStruct->u32InitialValue); + } + return eStatus; +} + +/** + * @brief Update the duty cycle of the FTU instance + * + * @param eInstance the selected FTU instance + * @param u8Channel the selected FTU channel + * @param u32Duty duty cycle of the PWM mode + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_PwmUpdateDuty(const FTU_InstanceType eInstance, uint8_t u8Channel, uint32_t u32Duty) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + uint8_t u8CpwmFlag; + if (((uint32_t)eInstance >= FTU_INSTANCE_COUNT) || + (u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) || + (u32Duty > s_aFtuMaxCounter[(uint32_t)eInstance])) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* get the cpwm flag*/ + u8CpwmFlag = FTU_HWA_GetModuleCpwmMode(s_pFtuBasePtrs[eInstance]); + if(0u != u8CpwmFlag) + { + /* Duty value div 2 if cpwm mode*/ + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel, (uint32_t)u32Duty >> 1u); + } + else + { + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel, u32Duty); + } + } + return eStatus; +} + +static void set_deadtime(FTU_Type *pFtu, uint8_t u8Channel, uint32_t u32Deadtime, bool bPair) +{ + /* enable channel deadtime, channel 0/1 2/3 4/5 6/7 are combined*/ + FTU_HWA_EnableChannelDeadtime(pFtu, u8Channel); + if(u32Deadtime < 1024u) + { + if(bPair) + { + /* PAIRDEADTIME has a high priority*/ + FTU_HWA_ConfigPairDeadtimePrescaler(pFtu, u8Channel, FTU_DEADTIME_PRESCALER_DIV_1); + FTU_HWA_ConfigPairDeadtimeValue(pFtu, u8Channel, u32Deadtime); + } + else + { + /* DEADTIME shoud recover PAIRDEADTIME*/ + FTU_HWA_ConfigDeadtimePrescaler(pFtu, FTU_DEADTIME_PRESCALER_DIV_1); + FTU_HWA_ConfigDeadtimeValue(pFtu, u32Deadtime); + } + } + else if(u32Deadtime < 4096u) + { + /*deadtime should multiply 2*/ + if(bPair) + { + /* PAIRDEADTIME has a high priority*/ + FTU_HWA_ConfigPairDeadtimePrescaler(pFtu, u8Channel, + FTU_DEADTIME_PRESCALER_DIV_4); + FTU_HWA_ConfigPairDeadtimeValue(pFtu, (uint32_t)u8Channel, u32Deadtime >> 2u); + } + else + { + /* DEADTIME shoud recover PAIRDEADTIME*/ + FTU_HWA_ConfigDeadtimePrescaler(pFtu, FTU_DEADTIME_PRESCALER_DIV_4); + FTU_HWA_ConfigDeadtimeValue(pFtu, u32Deadtime >> 2u); + } + } + else + { + /*deadtime should multiply 4*/ + if(bPair) + { + /* PAIRDEADTIME has a high priority*/ + FTU_HWA_ConfigPairDeadtimePrescaler(pFtu, u8Channel, FTU_DEADTIME_PRESCALER_DIV_16); + FTU_HWA_ConfigPairDeadtimeValue(pFtu, u8Channel, u32Deadtime >> 4u); + } + else + { + /* DEADTIME shoud recover PAIRDEADTIME*/ + FTU_HWA_ConfigDeadtimePrescaler(pFtu, FTU_DEADTIME_PRESCALER_DIV_16); + FTU_HWA_ConfigDeadtimeValue(pFtu, u32Deadtime >> 4u); + } + } +} + +/** + * @brief Configure FTU to PWM mode + * + * @param eInstance the selected FTU instance + * @param pPwmModeStruct the configurations of the PWM mode + * @return FTU_StatusType whether the operation is successfully + * @note This function will stop timer + */ +FTU_StatusType FTU_PwmModeInit(const FTU_InstanceType eInstance, const FTU_PwmModeType *const pPwmModeStruct) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + uint8_t u8Channel; + uint32_t u32Loop; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else if (pPwmModeStruct->u32PwmPeriod > s_aFtuMaxCounter[(uint32_t)eInstance]) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + + for (u32Loop = 0u; u32Loop < pPwmModeStruct->u32ChannelCount; u32Loop++) + { + if (pPwmModeStruct->pPwmChannels[u32Loop].u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + break; + } + + if ( (pPwmModeStruct->pPwmChannels[u32Loop].u32PwmDuty > s_aFtuMaxCounter[(uint32_t)eInstance]) + || (pPwmModeStruct->pPwmChannels[u32Loop].u32PhaseShift > s_aFtuMaxCounter[(uint32_t)eInstance])) + { + eStatus = FTU_STATUS_PARAM_INVALID; + break; + } + + if ( (FTU_CENTER_ALIGNED_PWM == pPwmModeStruct->eAlignedMode) + && (0u < pPwmModeStruct->pPwmChannels[u32Loop].u32PhaseShift)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + break; + } + if ( (true == pPwmModeStruct->pPwmChannels[u32Loop].bLinkMode) + && (0u < pPwmModeStruct->pPwmChannels[u32Loop].u32PhaseShift)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + break; + } + if (( (true == pPwmModeStruct->pPwmChannels[u32Loop].bLinkMode) + || (0u < pPwmModeStruct->pPwmChannels[u32Loop].u32PhaseShift)) + && (pPwmModeStruct->pPwmChannels[u32Loop].u8Channel & 1u)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + break; + } + } + + if (FTU_STATUS_SUCCESS == eStatus) + { + /* disable ftu timer */ + FTU_HWA_ConfigModuleClkSrc(s_pFtuBasePtrs[eInstance], FTU_MODULE_NO_CLK); + if (FTU_EDGE_ALIGNED_PWM == pPwmModeStruct->eAlignedMode) + { + FTU_HWA_DisableModuleCpwmMode(s_pFtuBasePtrs[eInstance]); + FTU_HWA_SetModuleCompareValue(s_pFtuBasePtrs[eInstance], pPwmModeStruct->u32PwmPeriod); + } + else + { + FTU_HWA_EnableModuleCpwmMode(s_pFtuBasePtrs[eInstance]); + FTU_HWA_SetModuleCompareValue(s_pFtuBasePtrs[eInstance], pPwmModeStruct->u32PwmPeriod >> 1u); + } + set_deadtime(s_pFtuBasePtrs[eInstance], 0u, pPwmModeStruct->u32PublicDeadtime, false); + + for (u32Loop = 0u; u32Loop < pPwmModeStruct->u32ChannelCount; u32Loop++) + { + FTU_PwmChannelType *pChannelCfg = &pPwmModeStruct->pPwmChannels[u32Loop]; + u8Channel = pChannelCfg->u8Channel; + if(pChannelCfg->bLinkMode) + { + /* set channel(n+1) complement of channel(n) output */ + FTU_HWA_EnableChannelComplement(s_pFtuBasePtrs[eInstance], u8Channel); + if (!pChannelCfg->bLinkChannelComplement) + { + FTU_HWA_ClearChannelPolarity(s_pFtuBasePtrs[eInstance], (uint8_t)1U << u8Channel); + FTU_HWA_SetChannelPolarity(s_pFtuBasePtrs[eInstance], (uint8_t)1U << (u8Channel + (uint8_t)1U)); + } + else + { + FTU_HWA_ClearChannelPolarity(s_pFtuBasePtrs[eInstance], + (uint8_t)1U << u8Channel| (uint8_t)1U << (u8Channel + 1u)); + } + /*link mode, the u8Channel+1->csc.ELSB bit must be set*/ + FTU_HWA_ConfigChannelPwmLinkMode(s_pFtuBasePtrs[eInstance], u8Channel + (uint8_t)1U); + /* enable u8Channel sync function of the ftu*/ + FTU_HWA_EnableChannelSync(s_pFtuBasePtrs[eInstance], u8Channel); + /* configure pin output as channel mode*/ + FTU_HWA_ConfigTrigOutputMode(s_pFtuBasePtrs[eInstance], u8Channel, FTU_TRIG_OUTPUT_AS_CHANNEL_MODE); + FTU_HWA_ConfigTrigOutputMode(s_pFtuBasePtrs[eInstance], u8Channel + 1u, FTU_TRIG_OUTPUT_AS_CHANNEL_MODE); + /* enable FTU output */ + FTU_HWA_EnableChannelsOutput(s_pFtuBasePtrs[eInstance], (uint8_t)3U << u8Channel); + } + else + { + if (pChannelCfg->u32PhaseShift) + { + FTU_HWA_ClearChannelPolarity(s_pFtuBasePtrs[eInstance], (uint8_t)1U << (u8Channel + 1)); + /* enable u8Channel sync function of the ftu*/ + FTU_HWA_EnableChannelSync(s_pFtuBasePtrs[eInstance], u8Channel); + + /*Enable enhanced phase shift mode*/ + FTU_HWA_EnableChannelPhase(s_pFtuBasePtrs[eInstance], u8Channel); + FTU_HWA_EnableChannelEnhancedPhase(s_pFtuBasePtrs[eInstance], u8Channel); + } + else + { + /* enable u8Channel sync function of the ftu*/ + FTU_HWA_DisableChannelSync(s_pFtuBasePtrs[eInstance], u8Channel); + + /*Enable enhanced phase shift mode*/ + FTU_HWA_DisableChannelPhase(s_pFtuBasePtrs[eInstance], u8Channel); + FTU_HWA_DisableChannelPhase(s_pFtuBasePtrs[eInstance], u8Channel); + } + + /* disable channel(n+1) complement of channel(n) output */ + FTU_HWA_DisableChannelComplement(s_pFtuBasePtrs[eInstance], u8Channel); + FTU_HWA_ClearChannelPolarity(s_pFtuBasePtrs[eInstance], (uint8_t)1U << u8Channel); + /* enable FTU output */ + FTU_HWA_EnableChannelsOutput(s_pFtuBasePtrs[eInstance], (uint8_t)1U << u8Channel); + /* configure pin output as channel mode*/ + FTU_HWA_ConfigTrigOutputMode(s_pFtuBasePtrs[eInstance], u8Channel, FTU_TRIG_OUTPUT_AS_CHANNEL_MODE); + + } + /* set FTU pwm mode */ + if ( (FTU_PWM_HIGH_TRUE_PULSE == pChannelCfg->ePinMode) + && (FTU_EDGE_ALIGNED_PWM == pPwmModeStruct->eAlignedMode)) + { + FTU_HWA_ConfigChannelMode(s_pFtuBasePtrs[eInstance], u8Channel, FTU_CHANNEL_MODE_EDGE_ALIGN_PWM); + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], u8Channel, FTU_CHANNEL_PWM_HIGH_TRUE); + } + else if ( (FTU_PWM_LOW_TRUE_PULSE == pChannelCfg->ePinMode) + && (FTU_EDGE_ALIGNED_PWM == pPwmModeStruct->eAlignedMode)) + { + FTU_HWA_ConfigChannelMode(s_pFtuBasePtrs[eInstance], u8Channel, FTU_CHANNEL_MODE_EDGE_ALIGN_PWM); + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], u8Channel, FTU_CHANNEL_PWM_LOW_TRUE); + } + else if ( (FTU_PWM_HIGH_TRUE_PULSE == pChannelCfg->ePinMode) + && (FTU_CENTER_ALIGNED_PWM == pPwmModeStruct->eAlignedMode)) + { + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], u8Channel, FTU_CHANNEL_PWM_HIGH_TRUE); + } + else if ( (FTU_PWM_LOW_TRUE_PULSE == pChannelCfg->ePinMode) + && (FTU_CENTER_ALIGNED_PWM == pPwmModeStruct->eAlignedMode)) + { + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], u8Channel, FTU_CHANNEL_PWM_LOW_TRUE); + } + + if (pChannelCfg->bDeadtimeEnable) + { + FTU_HWA_EnableChannelDeadtime(s_pFtuBasePtrs[eInstance], u8Channel); + } + else + { + FTU_HWA_DisableChannelDeadtime(s_pFtuBasePtrs[eInstance], u8Channel); + } + + /* set the period time and duty time */ + if(FTU_CENTER_ALIGNED_PWM == pPwmModeStruct->eAlignedMode) + { + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel, pChannelCfg->u32PwmDuty >> 1u); + } + else + { + if (pChannelCfg->u32PhaseShift) + { + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel, pChannelCfg->u32PhaseShift); + if ((pChannelCfg->u32PhaseShift + pChannelCfg->u32PwmDuty) > pPwmModeStruct->u32PwmPeriod) + { + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel + 1, + pChannelCfg->u32PhaseShift + pChannelCfg->u32PwmDuty - pPwmModeStruct->u32PwmPeriod - 1); + } + else + { + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel + 1, + pChannelCfg->u32PhaseShift + pChannelCfg->u32PwmDuty); + } + + } + else + { + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel, pChannelCfg->u32PwmDuty); + } + } + set_deadtime(s_pFtuBasePtrs[eInstance], u8Channel, pChannelCfg->u32ChannelDeadtime, true); + } + } + return eStatus; +} + +/** + * @brief Configure FTU to output compare mode + * + * @param eInstance the selected FTU instance + * @param pOutputModeStruct the configurations of the output compare mode + * @return FTU_StatusType whether the operation is successfully + * @note This function will stop timer + */ +FTU_StatusType FTU_OutputCompareModeInit(const FTU_InstanceType eInstance, + const FTU_OutputCompareModeType *const pOCConfig) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if (((uint32_t)eInstance >= FTU_INSTANCE_COUNT) || (pOCConfig->u8Channel >= FTU_CHANNEL_CONTROLS_COUNT)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else if ( pOCConfig->u32CompareValue > s_aFtuMaxCounter[(uint32_t)eInstance]) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* disable ftu timer */ + FTU_HWA_ConfigModuleClkSrc(s_pFtuBasePtrs[eInstance], FTU_MODULE_NO_CLK); + FTU_HWA_DisableChannelEnhancedPhase(s_pFtuBasePtrs[eInstance], pOCConfig->u8Channel); + FTU_HWA_DisableChannelPhase(s_pFtuBasePtrs[eInstance], pOCConfig->u8Channel); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pOCConfig->u8Channel, + FTU_MEASURE_MODE_OFF); + FTU_HWA_ConfigChannelMode(s_pFtuBasePtrs[eInstance], pOCConfig->u8Channel, FTU_CHANNEL_MODE_OUTPUT_COMPARE); + if (FTU_OUTPUT_TOGGLE_PIN == pOCConfig->eOutputMode) + { + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pOCConfig->u8Channel, FTU_CHANNEL_OC_TOGGLE); + } + else if (FTU_OUTPUT_CLEAR_PIN == pOCConfig->eOutputMode) + { + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pOCConfig->u8Channel, FTU_CHANNEL_OC_CLEAR); + } + else if (FTU_OUTPUT_SET_PIN == pOCConfig->eOutputMode) + { + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pOCConfig->u8Channel, FTU_CHANNEL_OC_SET); + } + /* Disable Up-Down Mode*/ + FTU_HWA_DisableModuleCpwmMode(s_pFtuBasePtrs[eInstance]); + /* enable FTU output */ + FTU_HWA_EnableChannelsOutput(s_pFtuBasePtrs[eInstance], (uint8_t)1U << pOCConfig->u8Channel); + /* configure initial level */ + if (FTU_OUTPUT_CMP_INIT_LOW == pOCConfig->eInitLevel) + { + FTU_HWA_ClearChannelPolarity(s_pFtuBasePtrs[eInstance], (uint8_t)1U << pOCConfig->u8Channel); + } + else + { + FTU_HWA_SetChannelPolarity(s_pFtuBasePtrs[eInstance], (uint8_t)1U << pOCConfig->u8Channel); + } + /* configure pin output as channel mode*/ + FTU_HWA_ConfigTrigOutputMode(s_pFtuBasePtrs[eInstance], pOCConfig->u8Channel, FTU_TRIG_OUTPUT_AS_CHANNEL_MODE); + /* set FTU CV register value*/ + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], pOCConfig->u8Channel, (uint32_t)pOCConfig->u32CompareValue); + + } + return eStatus; +} + +/** + * @brief Enable the output trigger of the selected FTU instance + * + * @param eInstance the selected FTU instance + * @param u32TriggerOutputMask the output trigger mask + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EnableTriggerOutput(const FTU_InstanceType eInstance, uint32_t u32TriggerOutputMask) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* enable the channel match trigger */ + FTU_HWA_EnableChannelTriggerOut(s_pFtuBasePtrs[eInstance], (uint8_t)(u32TriggerOutputMask & (uint32_t)FTU_TRIG_OUTPUT_MASK_ALL_CHANNEL_MATCH)); + if (0u != (u32TriggerOutputMask & (uint32_t)FTU_TRIG_OUTPUT_MASK_RELOAD)) + { + /* enable reload trigger */ + FTU_HWA_EnableReloadTrigger(s_pFtuBasePtrs[eInstance]); + } + } + return eStatus; +} + +/** + * @brief Disable the output trigger of the selected FTU instance + * + * @param eInstance the selected FTU instance + * @param u32TriggerOutputMask the output trigger mask + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DisableTriggerOutput(const FTU_InstanceType eInstance, uint32_t u32TriggerOutputMask) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* disenable the channel match trigger */ + FTU_HWA_DisableChannelTriggerOut(s_pFtuBasePtrs[eInstance], (uint8_t)(u32TriggerOutputMask & (uint32_t)FTU_TRIG_OUTPUT_MASK_ALL_CHANNEL_MATCH)); + if (0u != (u32TriggerOutputMask & (uint32_t)FTU_TRIG_OUTPUT_MASK_RELOAD)) + { + /* disable reload trigger */ + FTU_HWA_DisableReloadTrigger(s_pFtuBasePtrs[eInstance]); + } + } + return eStatus; +} + +/** + * @brief Start the FTU instance + * + * @param eInstance the selected FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_StartTimer(const FTU_InstanceType eInstance) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* set FTU module clock source */ + if (s_eFtuClkSrc[eInstance] == FTU_NO_CLK) + { + eStatus = FTU_STATUS_NO_CLOCK_SOURCE; + } + else if(s_eFtuClkSrc[eInstance] == FTU_INTERNAL_CLK) + { + FTU_HWA_ConfigModuleClkSrc(s_pFtuBasePtrs[eInstance], FTU_MODULE_INTERNAL_CLK); + } + else + { + FTU_HWA_ConfigModuleClkSrc(s_pFtuBasePtrs[eInstance], FTU_MODULE_EXTERNAL_CLK); + } + } + return eStatus; +} + +/** + * @brief Stop the FTU global time base + * + * @param u32InstanceMask The selected FTU, each bit represents an instance + */ +void FTU_StopGlobalTimeBase(uint32_t u32InstanceMask) +{ + uint32_t u32GTB = 0u, u32Loop0; + for (u32Loop0 = 0u; u32Loop0 < FTU_INSTANCE_COUNT; u32Loop0++) + { + uint32_t u32InstanceFlag = 1u << u32Loop0; + if (0u != (u32InstanceMask & u32InstanceFlag)) + { + u32GTB |= u32InstanceFlag; + SCM_HWA_ClearFtuGTBMask((uint8_t)u32Loop0); + } + } + SCM_HWA_ClearFtuGTBSelect(u32GTB); +} + +/** + * @brief Start the FTU global time base + * + * @param u32InstanceMask The selected FTU, each bit represents an instance + * @param u32StartMask Start time, refer to FTU_GlobalTimeBaseStartType + */ +void FTU_StartGlobalTimeBase(uint32_t u32InstanceMask, uint32_t u32StartMask) +{ + uint32_t u32GTB = 0u, u32Loop0, u32Loop1; + for (u32Loop0 = 0u; u32Loop0 < FTU_INSTANCE_COUNT; u32Loop0++) + { + uint32_t u32InstanceFlag = 1u << u32Loop0; + if (0u != (u32InstanceMask & u32InstanceFlag)) + { + if (u32StartMask & FTU_GTB_START_AT_ONCE) + { + u32GTB |= u32InstanceFlag; + } + for (u32Loop1 = 0u; u32Loop1 < TSTMP_MODULATE_COUNT; u32Loop1++) + { + if (u32StartMask & (FTU_GTB_START_AT_TSTMP1_MOD0 << u32Loop1)) + { + SCM_HWA_ConfigFtuGTBMask((uint8_t)u32Loop0, (1u << u32Loop1)); + } + } + } + } + SCM_HWA_SetFtuGTBSelect(u32GTB); +} + +/** + * @brief Stop the FTU instance + * + * @param eInstance the selected FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_StopTimer(const FTU_InstanceType eInstance) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* clear FTU module clock source */ + FTU_HWA_ConfigModuleClkSrc(s_pFtuBasePtrs[eInstance], FTU_MODULE_NO_CLK); + //FTU_HWA_ClearModuleCounter(s_pFtuBasePtrs[eInstance], 0); + } + return eStatus; +} + +/** + * @brief Ftu initialize interrupt function + * + * @param eInstance the selected FTU instance + * @param pIntStruct the configurations of the interrupt + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_InterruptInit(const FTU_InstanceType eInstance, const FTU_InterruptType *const pIntrStruct) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + uint32_t u32Loop; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + for(u32Loop = 0u; u32Loop < FTU_CHANNEL_CONTROLS_COUNT; u32Loop++) + { + if (0u != (pIntrStruct->u32InterruptMask & ((uint32_t)FTU_INTR_MASK_CHANNEL_0 << u32Loop))) + { + /* Enable Channel Interrupt */ + FTU_HWA_EnableChannelInterrupt(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop); + } + else + { + /* Disable Channel Interrupt */ + FTU_HWA_DisableChannelInterrupt(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop); + } + } + + if (0u != (pIntrStruct->u32InterruptMask & (uint32_t)FTU_INTR_MASK_OVERFLOW)) + { + /* Enable Overflow Interrupt */ + FTU_HWA_EnableOverflowInterrupt(s_pFtuBasePtrs[eInstance]); + } + else + { + /* Disable Overflow Interrupt */ + FTU_HWA_DisableOverflowInterrupt(s_pFtuBasePtrs[eInstance]); + } + + if (0u != (pIntrStruct->u32InterruptMask & (uint32_t)FTU_INTR_MASK_FAULT)) + { + /* Enable Fault Interrupt */ + FTU_HWA_EnableModuleFaultInterrupt(s_pFtuBasePtrs[eInstance]); + } + else + { + /* Disable Fault Interrupt */ + FTU_HWA_DisableModuleFaultInterrupt(s_pFtuBasePtrs[eInstance]); + } + + if (0u != (pIntrStruct->u32InterruptMask & (uint32_t)FTU_INTR_MASK_RELOAD_POINT)) + { + /* Enable Reload Point Interrupt */ + FTU_HWA_EnableReloadPointInterrupt(s_pFtuBasePtrs[eInstance]); + } + else + { + /* Disable Reload Point Interrupt */ + FTU_HWA_DisableReloadPointInterrupt(s_pFtuBasePtrs[eInstance]); + } + + /*register callback functions*/ + s_pChannelCallback[eInstance] = pIntrStruct->pChannelCallback; + s_pFaultCallback[eInstance] = pIntrStruct->pFaultCallback; + s_pOverflowCallback[eInstance] = pIntrStruct->pOverflowCallback; + s_pReloadPointCallback[eInstance] = pIntrStruct->pReloadPointCallback; + } + return eStatus; +} + +/** + * @brief initialize fault input of the selected Ftu instance + * + * @param eInstance the selected FTU instance + * @param pFaultInit the fault configurations of the FTU instance + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_FaultInit(const FTU_InstanceType eInstance, const FTU_FaultInitType *const pFaultInit) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + uint32_t u32Loop, u32Temp; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* configure fault mode */ + FTU_HWA_ConfigModuleFaultMode(s_pFtuBasePtrs[eInstance], pFaultInit->eFaultMode); + /* Disable all fault inputs*/ + u32Temp = FTU_HWA_GetFaultEnable(s_pFtuBasePtrs[eInstance]); + FTU_HWA_DisableModuleFault(s_pFtuBasePtrs[eInstance], 0xFu); + /* configure fault filter value */ + FTU_HWA_SetModuleFaultFilterValue(s_pFtuBasePtrs[eInstance], pFaultInit->u8FilterValue); + /* recover fault inputs*/ + FTU_HWA_EnableModuleFault(s_pFtuBasePtrs[eInstance], (uint8_t)u32Temp); + /* enables the fault control in channels */ + for(u32Loop = 0u; u32Loop < FTU_FAULT_COUNT; u32Loop++) + { + if (0u != (pFaultInit->u8FaultChannelEnable & ((uint8_t)FTU_FAULT_FOR_CHANNEL01 << u32Loop))) + { + FTU_HWA_EnableChannelFault(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop << 1u); + } + else + { + FTU_HWA_DisableChannelFault(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop << 1u); + } + } + + /* set fault disable channel output delay value */ + FTU_HWA_SetFaultDelay0(s_pFtuBasePtrs[eInstance], pFaultInit->u8FaultDisableDelay0); + FTU_HWA_SetFaultDelay1(s_pFtuBasePtrs[eInstance], pFaultInit->u8FaultDisableDelay1); + } + return eStatus; +} + +/** + * @brief Select fault disable channel output delay value + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number, range is 0-7. + * @param eSelection Fault disable channel output delay value selection. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_FaultSelectDelayValue(const FTU_InstanceType eInstance, uint8_t u8Channel, FTU_FaultDisableDelayType eDelaySelection) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else if (u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + FTU_HWA_SelectFaultDelay(s_pFtuBasePtrs[eInstance], u8Channel, eDelaySelection); + } + return eStatus; +} + +/** + * @brief Enable a fault input + * + * @param eInstance the selected FTU instance + * @param pFaultCtrl configurations of the fault input + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_FaultEnable(const FTU_InstanceType eInstance, const FTU_FaultControlType *const pFaultCtrl) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + + if (((uint32_t)eInstance >= FTU_INSTANCE_COUNT) || + (pFaultCtrl->u8FaultIndex >= FTU_FAULT_COUNT)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* configure fault input polarity */ + FTU_HWA_ConfigFaultPolarity(s_pFtuBasePtrs[eInstance], pFaultCtrl->u8FaultIndex, (uint8_t)pFaultCtrl->eFaultPol); + if(true == pFaultCtrl->bFaultFilterEnable) + { + FTU_HWA_EnableModuleFaultGlitchFilter(s_pFtuBasePtrs[eInstance], 1u << pFaultCtrl->u8FaultIndex); + } + else + { + FTU_HWA_DisableModuleFaultGlitchFilter(s_pFtuBasePtrs[eInstance], 1u << pFaultCtrl->u8FaultIndex); + } + /* enable fault input */ + FTU_HWA_EnableModuleFault(s_pFtuBasePtrs[eInstance], 1u << pFaultCtrl->u8FaultIndex); + } + return eStatus; +} + +/** + * @brief Disable a fault input + * + * @param eInstance the selected FTU instance + * @param u32FaultIndex index of the fault input + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_FaultDisable(const FTU_InstanceType eInstance, uint32_t u32FaultIndex) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if (((uint32_t)eInstance >= FTU_INSTANCE_COUNT) || + (u32FaultIndex >= FTU_FAULT_COUNT)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + FTU_HWA_DisableModuleFault(s_pFtuBasePtrs[eInstance], 0x1u << u32FaultIndex); + } + return eStatus; +} + +/** + * @brief initialize a input capture channel of the selected Ftu instance + * + * @param eInstance the selected FTU instance + * @param pInputChannel configurations of the input capture channel + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_InputCaptureChannelInit(const FTU_InstanceType eInstance, + const FTU_InputChannelType *const pInputChannel) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + + if (((uint32_t)eInstance >= FTU_INSTANCE_COUNT) || + (pInputChannel->u8Channel >= FTU_CHANNEL_CONTROLS_COUNT)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + FTU_HWA_DisableQuadratureMode(s_pFtuBasePtrs[eInstance]); + FTU_HWA_DisableChannelEnhancedPhase(s_pFtuBasePtrs[eInstance], pInputChannel->u8Channel); + FTU_HWA_DisableChannelPhase(s_pFtuBasePtrs[eInstance], pInputChannel->u8Channel); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pInputChannel->u8Channel, + FTU_MEASURE_MODE_OFF); + FTU_HWA_ConfigChannelMode(s_pFtuBasePtrs[eInstance], pInputChannel->u8Channel, FTU_CHANNEL_MODE_INPUT); + if(pInputChannel->u8Channel < FTU_INPUT_FILTER_COUNT) + { + /* set FTU input capture filter value */ + FTU_HWA_ConfigInputCaptureFilter( + s_pFtuBasePtrs[eInstance], pInputChannel->u8Channel, + pInputChannel->u8FilterValue); + + } + + set_ftu_input_edge(s_pFtuBasePtrs[eInstance], pInputChannel->u8Channel, pInputChannel->eInputMode); + } + return eStatus; +} + +/** + * @brief initialize the quadrature decoder mode + * + * @param eInstance the selected FTU instance + * @param pQuadInit configurations of the quadrature decoder + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_QuadratureModeInit(const FTU_InstanceType eInstance, + const FTU_QuadratureInitType *const pQuadInit) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + + if (((uint32_t)eInstance != FTU_INSTANCE_1) && + ((uint32_t)eInstance != FTU_INSTANCE_2) && + ((uint32_t)eInstance != FTU_INSTANCE_4) && + ((uint32_t)eInstance != FTU_INSTANCE_5)) + { + /* Only FTU1/2/4/5 support quadrature decode*/ + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + /* set quadrature mode */ + FTU_HWA_ConfigQuadratureMode(s_pFtuBasePtrs[eInstance], pQuadInit->eQuadMode); + /* set PHA polarity*/ + if(pQuadInit->bPhaInverted) + { + FTU_HWA_EnablePhaInv(s_pFtuBasePtrs[eInstance]); + } + else + { + FTU_HWA_DisablePhaInv(s_pFtuBasePtrs[eInstance]); + } + /* set PHB polarity*/ + if(pQuadInit->bPhbInverted) + { + FTU_HWA_EnablePhbInv(s_pFtuBasePtrs[eInstance]); + } + else + { + FTU_HWA_DisablePhbInv(s_pFtuBasePtrs[eInstance]); + } + + /* Set counter direction */ + FTU_HWA_ConfigQuadDirection(s_pFtuBasePtrs[eInstance], pQuadInit->eQuadDirection); + /* Set overflow direction */ + FTU_HWA_ConfigTimerOverflowDir(s_pFtuBasePtrs[eInstance], pQuadInit->eOveflowDirection); + /* set top value */ + FTU_HWA_SetModuleCompareValue(s_pFtuBasePtrs[eInstance], pQuadInit->u16TopValue); + /* set bottom value */ + FTU_HWA_SetCounterInitialValue(s_pFtuBasePtrs[eInstance], pQuadInit->u16BottomValue); + + /* Set phase A glitch filter value */ + if (0U != pQuadInit->u8PhaFilterVal) + { + FTU_HWA_ConfigChannelFilterValue(s_pFtuBasePtrs[eInstance], 0, pQuadInit->u8PhaFilterVal); + FTU_HWA_EnablePhaGlitchFilter(s_pFtuBasePtrs[eInstance]); + } + else + { + FTU_HWA_DisablePhaGlitchFilter(s_pFtuBasePtrs[eInstance]); + } + /* Set phase B glitch filter value */ + if (0U != pQuadInit->u8PhbFilterVal) + { + FTU_HWA_ConfigChannelFilterValue(s_pFtuBasePtrs[eInstance], 1, pQuadInit->u8PhbFilterVal); + FTU_HWA_EnablePhbGlitchFilter(s_pFtuBasePtrs[eInstance]); + } + else + { + FTU_HWA_DisablePhbGlitchFilter(s_pFtuBasePtrs[eInstance]); + } + /* enable the quadrature*/ + FTU_HWA_EnableQuadratureMode(s_pFtuBasePtrs[eInstance]); + } + return eStatus; +} +/** + * @brief Enable FTU interrupt + * + * @param eInstance the selected FTU instance + * @param u32InterruptMask interrupt enable mask + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EnableInterrupt(const FTU_InstanceType eInstance, uint32_t u32InterruptMask) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + uint32_t u32Loop; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + for(u32Loop = 0u; u32Loop < FTU_CHANNEL_CONTROLS_COUNT; u32Loop++) + { + if (0u != (u32InterruptMask & ((uint32_t)FTU_INTR_MASK_CHANNEL_0 << u32Loop))) + { + /* Enable Channel Interrupt */ + FTU_HWA_EnableChannelInterrupt(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop); + } + } + + if (0u != (u32InterruptMask & (uint32_t)FTU_INTR_MASK_OVERFLOW)) + { + /* Enable Overflow Interrupt */ + FTU_HWA_EnableOverflowInterrupt(s_pFtuBasePtrs[eInstance]); + } + + if (0u != (u32InterruptMask & (uint32_t)FTU_INTR_MASK_FAULT)) + { + /* Enable Fault Interrupt */ + FTU_HWA_EnableModuleFaultInterrupt(s_pFtuBasePtrs[eInstance]); + } + + if (0u != (u32InterruptMask & (uint32_t)FTU_INTR_MASK_RELOAD_POINT)) + { + /* Enable Reload Point Interrupt */ + FTU_HWA_EnableReloadPointInterrupt(s_pFtuBasePtrs[eInstance]); + } + } + return eStatus; +} + +/** + * @brief Disable FTU interrupt + * + * @param eInstance the selected FTU instance + * @param u32InterruptMask interrupt disable mask + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_DisableInterrupt(const FTU_InstanceType eInstance, uint32_t u32InterruptMask) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + uint32_t u32Loop; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + for(u32Loop = 0; u32Loop < FTU_CHANNEL_CONTROLS_COUNT; u32Loop++) + { + if (0u != (u32InterruptMask & ((uint32_t)FTU_INTR_MASK_CHANNEL_0 << u32Loop))) + { + /* Disable Channel Interrupt */ + FTU_HWA_DisableChannelInterrupt(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop); + } + } + + if (0u != (u32InterruptMask & (uint32_t)FTU_INTR_MASK_OVERFLOW)) + { + /* Disable Overflow Interrupt */ + FTU_HWA_DisableOverflowInterrupt(s_pFtuBasePtrs[eInstance]); + } + + if (0u != (u32InterruptMask & (uint32_t)FTU_INTR_MASK_FAULT)) + { + /* Disable Fault Interrupt */ + FTU_HWA_DisableModuleFaultInterrupt(s_pFtuBasePtrs[eInstance]); + } + + if (0u != (u32InterruptMask & (uint32_t)FTU_INTR_MASK_RELOAD_POINT)) + { + /* Disable Reload Point Interrupt */ + FTU_HWA_DisableReloadPointInterrupt(s_pFtuBasePtrs[eInstance]); + } + } + return eStatus; +} + +/** + * @brief Clear the fault flag of the FTU instance + * + * @param eInstance the selected FTU instance + * @param u32FaultFlag flag to clear + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_ClearFault(const FTU_InstanceType eInstance, uint32_t u32FaultFlag) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + FTU_HWA_ClearModuleFaultFlag(s_pFtuBasePtrs[eInstance], (uint8_t)u32FaultFlag); + } + return eStatus; +} + +/** + * @brief Get the fault flag of the FTU instance + * + * @param eInstance the selected FTU instance + * @return uint32_t the fault flag of the selected Ftu instance + */ +uint32_t FTU_GetFaultFlag(const FTU_InstanceType eInstance) +{ + uint32_t u32FaultFlag = 0; + if ((uint32_t)eInstance < FTU_INSTANCE_COUNT) + { + u32FaultFlag = FTU_HWA_ReadModuleFaultFlag(s_pFtuBasePtrs[eInstance]); + } + return u32FaultFlag; +} + + +/** + * @brief Enable ftu channel DMA + * + * @param eInstance the selected FTU instance + * @param u32DmaMask The dma channel mask. + * @return FTU_StatusType whether the operation is successfully + */ + +FTU_StatusType FTU_EnableChannelDma(const FTU_InstanceType eInstance, uint32_t u32DmaMask) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + uint32_t u32Loop; + if ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + for(u32Loop = 0u; u32Loop < FTU_CHANNEL_CONTROLS_COUNT; u32Loop++) + { + if (0u != (u32DmaMask & ((uint32_t)FTU_INTR_MASK_CHANNEL_0 << u32Loop))) + { + /* Enable Channel Interrupt */ + FTU_HWA_EnableChannelDma(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop); + } + } + + } + return eStatus; +} + +/** + * @brief Initialize a Expect Edge Number Measurement channel + * + * @param eInstance the selected FTU instance + * @param pExpectEdgeNumMeasure measurement configuration. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_ExpectEdgeNumberMeasureChannelInit(const FTU_InstanceType eInstance, FTU_ExpectEdgeNumberMeasureType *pExpectEdgeNumMeasure) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ( ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + || (pExpectEdgeNumMeasure->u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) + || (pExpectEdgeNumMeasure->u8Channel & 1u)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + FTU_HWA_ConfigChannelMode(s_pFtuBasePtrs[eInstance], pExpectEdgeNumMeasure->u8Channel, + FTU_CHANNEL_MODE_INPUT); + set_ftu_input_edge(s_pFtuBasePtrs[eInstance], pExpectEdgeNumMeasure->u8Channel, + pExpectEdgeNumMeasure->eEdgeMode); + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pExpectEdgeNumMeasure->u8Channel + 1u, + FTU_CHANNEL_EDGE_NOT_USED); + FTU_HWA_ConfigEdgeNumber(s_pFtuBasePtrs[eInstance], pExpectEdgeNumMeasure->u8Channel + 1, + pExpectEdgeNumMeasure->u8ExpectEdgeNumber); + if (FTU_MEASURE_CONTINUOUS_MODE == pExpectEdgeNumMeasure->eContinuouslyMode) + { + FTU_HWA_EnableMeasureContinous(s_pFtuBasePtrs[eInstance], pExpectEdgeNumMeasure->u8Channel); + } + else + { + FTU_HWA_DisableMeasureContinous(s_pFtuBasePtrs[eInstance], pExpectEdgeNumMeasure->u8Channel); + } + /* Must put the ICM_MODE setting at the end, otherwise it will not be configured correctly. */ + FTU_HWA_ConfigInputCaptureMeasureMode( s_pFtuBasePtrs[eInstance], pExpectEdgeNumMeasure->u8Channel, + FTU_MEASURE_EXPECT_EDGE_NUMBER); + } + return eStatus; +} + +/** + * @brief Initialize a Edge Number Measurement channel + * + * @param eInstance the selected FTU instance + * @param pEdgeNumMeasure measurement configuration. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_EdgeNumberMeasureChannelInit(const FTU_InstanceType eInstance, FTU_EdgeNumberMeasureType *pEdgeNumMeasure) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ( ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + || (pEdgeNumMeasure->u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) + || (pEdgeNumMeasure->u8Channel & 1u) + || (pEdgeNumMeasure->u32StartWindow >= pEdgeNumMeasure->u32EndWindow) + || (pEdgeNumMeasure->u32StartWindow > s_aFtuMaxCounter[eInstance])) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + FTU_HWA_ConfigChannelMode(s_pFtuBasePtrs[eInstance], pEdgeNumMeasure->u8Channel, + FTU_CHANNEL_MODE_INPUT); + set_ftu_input_edge(s_pFtuBasePtrs[eInstance], pEdgeNumMeasure->u8Channel, pEdgeNumMeasure->eEdgeMode); + + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pEdgeNumMeasure->u8Channel + 1u, + FTU_CHANNEL_EDGE_NOT_USED); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pEdgeNumMeasure->u8Channel, + FTU_MEASURE_ICENM_WIND_WRITE); + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], pEdgeNumMeasure->u8Channel, + pEdgeNumMeasure->u32StartWindow); + FTU_HWA_SetChannelValue(s_pFtuBasePtrs[eInstance], pEdgeNumMeasure->u8Channel + 1u, + pEdgeNumMeasure->u32EndWindow); + FTU_HWA_ConfigInputCaptureMeasureMode( s_pFtuBasePtrs[eInstance], pEdgeNumMeasure->u8Channel, + FTU_MEASURE_EDGE_NUMBER); + if (FTU_MEASURE_CONTINUOUS_MODE == pEdgeNumMeasure->eContinuouslyMode) + { + FTU_HWA_EnableMeasureContinous(s_pFtuBasePtrs[eInstance], pEdgeNumMeasure->u8Channel); + } + else + { + FTU_HWA_DisableMeasureContinous(s_pFtuBasePtrs[eInstance], pEdgeNumMeasure->u8Channel); + } + + } + return eStatus; +} + +/** + * @brief Get the expect edge number result of the channel + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number, range is 0-7. + * @param pResult point to the result buffer. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_GetExpectEdgeNumberResult(const FTU_InstanceType eInstance, uint8_t u8Channel, FTU_ExpectEdgeNumberResultType *pResult) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ( ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + || (u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) + || (u8Channel & 1u)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + pResult->u32FirstEdgeTime = FTU_HWA_GetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel); + pResult->u32LastEdgeTime = FTU_HWA_GetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel + 1); + } + return eStatus; +} + +/** + * @brief Get Edge number counter + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number. + * @return uint8_t Edge number counter + */ +uint8_t FTU_GetEdgeNumberCount(const FTU_InstanceType eInstance, uint8_t u8Channel) +{ + uint8_t u8Count = 0; + if ( ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + || (u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) + || (u8Channel & 1u)) + { + + } + else + { + u8Count = FTU_HWA_GetEdgeNumberCount(s_pFtuBasePtrs[eInstance], u8Channel); + } + return u8Count; +} +/** + * @brief Initialize a signal measure channel + * + * @param eInstance the selected FTU instance + * @param pMeasure measurement configuration. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_SignalMeasureChannelInit(const FTU_InstanceType eInstance, FTU_SignalMeasureType *pMeasure) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ( ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + || (pMeasure->u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) + || (pMeasure->u8Channel & 1u)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_MEASURE_MODE_OFF); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u, FTU_MEASURE_MODE_OFF); + FTU_HWA_DisableChannelEnhancedPhase(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel); + FTU_HWA_DisableChannelPhase(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel); + FTU_HWA_DisableChannelEnhancedPhase(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u); + FTU_HWA_DisableChannelPhase(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u); + FTU_HWA_DisableModuleCpwmMode(s_pFtuBasePtrs[eInstance]); + + FTU_HWA_ConfigChannelMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_CHANNEL_MODE_INPUT); + FTU_HWA_ConfigChannelMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u, FTU_CHANNEL_MODE_INPUT); + if (FTU_SIGNAL_MEASURE_HIGH_TIME == pMeasure->eMeasureMode) + { + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_CHANNEL_EDGE_RISING); + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u, FTU_CHANNEL_EDGE_FALLING); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_MEASURE_MODE_DUTY_CYCLE); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1, FTU_MEASURE_MODE_DUTY_CYCLE); + FTU_HWA_SetChannelPolarity(s_pFtuBasePtrs[eInstance], 1u << pMeasure->u8Channel); + } + else if (FTU_SIGNAL_MEASURE_LOW_TIME == pMeasure->eMeasureMode) + { + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_CHANNEL_EDGE_RISING); + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u, FTU_CHANNEL_EDGE_FALLING); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_MEASURE_MODE_DUTY_CYCLE); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u, FTU_MEASURE_MODE_DUTY_CYCLE); + FTU_HWA_ClearChannelPolarity(s_pFtuBasePtrs[eInstance], 1u << pMeasure->u8Channel); + } + else if (FTU_SIGNAL_MEASURE_PERIOD_RISING_EDGE == pMeasure->eMeasureMode) + { + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_CHANNEL_EDGE_RISING); + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u, FTU_CHANNEL_EDGE_NOT_USED); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_MEASURE_MODE_PERIOD); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u, FTU_MEASURE_MODE_PERIOD); + } + else if (FTU_SIGNAL_MEASURE_PERIOD_FALLING_EDGE == pMeasure->eMeasureMode) + { + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_CHANNEL_EDGE_FALLING); + FTU_HWA_ConfigChannelEdgeLevel(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u, FTU_CHANNEL_EDGE_NOT_USED); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel, FTU_MEASURE_MODE_PERIOD); + FTU_HWA_ConfigInputCaptureMeasureMode(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel + 1u, FTU_MEASURE_MODE_PERIOD); + } + + if (FTU_MEASURE_CONTINUOUS_MODE == pMeasure->eContinuouslyMode) + { + FTU_HWA_EnableMeasureContinous(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel); + } + else + { + FTU_HWA_DisableMeasureContinous(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel); + } + + if (FTU_MEASURE_START_IMMEDIATELY == pMeasure->eStartMode) + { + FTU_HWA_EnableMeasureStartImmd(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel); + } + else + { + FTU_HWA_DisableMeasureStartImmd(s_pFtuBasePtrs[eInstance], pMeasure->u8Channel); + } + } + return eStatus; +} +/** + * @brief Re-start measurement when in single mode + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number, range is 0-7. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_SignalMeasureChannelSingle(const FTU_InstanceType eInstance, uint8_t u8Channel) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ( ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + || (u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) + || (u8Channel & 1u)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + FTU_HWA_SingleMeasurement(s_pFtuBasePtrs[eInstance], u8Channel); + } + return eStatus; +} + +/** + * @brief Get the measurement result of the channel + * + * @param eInstance the selected FTU instance + * @param u8Channel FTU channel number, range is 0-7. + * @param pResult point to the result buffer. + * @return FTU_StatusType whether the operation is successfully + */ +FTU_StatusType FTU_GetSignalMeasureResult(const FTU_InstanceType eInstance, uint8_t u8Channel, FTU_SignalMeasureValueType *pResult) +{ + FTU_StatusType eStatus = FTU_STATUS_SUCCESS; + if ( ((uint32_t)eInstance >= FTU_INSTANCE_COUNT) + || (u8Channel >= FTU_CHANNEL_CONTROLS_COUNT) + || (u8Channel & 1u)) + { + eStatus = FTU_STATUS_PARAM_INVALID; + } + else + { + FTU_MeasurementModeType eMeasureMode = FTU_HWA_GetMeasureMode(s_pFtuBasePtrs[eInstance], u8Channel); + if (FTU_MEASURE_MODE_DUTY_CYCLE == eMeasureMode) + { + if (FTU_HWA_GetChannelPolarity(s_pFtuBasePtrs[eInstance], 1u << u8Channel)) + { + pResult->u32StartTime = FTU_HWA_GetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel); + pResult->u32EndTime = FTU_HWA_GetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel + 1); + } + else + { + pResult->u32StartTime = FTU_HWA_GetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel + 1); + pResult->u32EndTime = FTU_HWA_GetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel); + } + } + else if(FTU_MEASURE_MODE_PERIOD == eMeasureMode) + { + pResult->u32StartTime = FTU_HWA_GetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel + 1); + pResult->u32EndTime = FTU_HWA_GetChannelValue(s_pFtuBasePtrs[eInstance], u8Channel); + } + else + { + pResult->u32StartTime = 0u; + pResult->u32EndTime = 0u; + } + } + return eStatus; +} + + + +/** + * @brief Interrupt IRQ handle of FTU instance + * + * @param eInstance the selected FTU instance + */ +void FTUn_IRQHandler(const FTU_InstanceType eInstance) +{ + uint32_t u32FaultFlag = 0u; + uint8_t u8FaultEnable = FTU_HWA_ReadFaultIntrEnable(s_pFtuBasePtrs[eInstance]); + uint8_t u8OverflowFlag = FTU_HWA_ReadModuleOverflowFlag(s_pFtuBasePtrs[eInstance]); + uint8_t u8ReloadFlag = FTU_HWA_ReadReloadIntrEnable(s_pFtuBasePtrs[eInstance]); + uint32_t u32Loop, u32ChannelIntrFlag = 0; + uint16_t u16TimeStamp; + + u8OverflowFlag = FTU_HWA_ReadModuleOverflowIntrEnable(s_pFtuBasePtrs[eInstance]) & u8OverflowFlag; + u8ReloadFlag = FTU_HWA_ReadModuleReloadFlag(s_pFtuBasePtrs[eInstance]) & u8ReloadFlag; + if(0u != u8FaultEnable) + { + u32FaultFlag = FTU_HWA_ReadModuleFaultFlag(s_pFtuBasePtrs[eInstance]); + } + + /* Clear interrupt flag*/ + if (0u != u8OverflowFlag) + { + FTU_HWA_ClearOverflowFlag(s_pFtuBasePtrs[eInstance]); + } + if (0u != u8ReloadFlag) + { + FTU_HWA_ClearReloadFlag(s_pFtuBasePtrs[eInstance]); + } + + for (u32Loop = 0U; u32Loop < FTU_CHANNEL_CONTROLS_COUNT; u32Loop++) + { + if ((0u != FTU_HWA_ReadChannelInterruptFlag(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop)) && + (0u != FTU_HWA_ReadChannelInterruptEnableFlag(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop))) + { + FTU_HWA_ClearChannelInterruptFlag(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop); + u32ChannelIntrFlag |= (uint8_t)(1u << u32Loop); + } + } + + /* call callback functions*/ + if ((0u != u8OverflowFlag) && (NULL != s_pOverflowCallback[eInstance])) + { + s_pOverflowCallback[eInstance](); + } + + if ((0u != u8ReloadFlag) && (NULL != s_pReloadPointCallback[eInstance])) + { + s_pReloadPointCallback[eInstance](); + } + + if ((0u != u32FaultFlag) && (NULL != s_pFaultCallback[eInstance])) + { + for (u32Loop = 0U; u32Loop < FTU_FAULT_COUNT; u32Loop++) + { + if (0u != (u32FaultFlag & ((uint32_t)1u << u32Loop))) + { + s_pFaultCallback[eInstance](u32Loop); + } + } + } + + if ((0u != u32ChannelIntrFlag) && (NULL != s_pChannelCallback[eInstance])) + { + for (u32Loop = 0U; u32Loop < FTU_CHANNEL_CONTROLS_COUNT; u32Loop++) + { + if (0u != (u32ChannelIntrFlag & ((uint32_t)1u << u32Loop))) + { + u16TimeStamp = (uint16_t)FTU_HWA_GetChannelValue(s_pFtuBasePtrs[eInstance], (uint8_t)u32Loop); + s_pChannelCallback[eInstance](u32Loop, u16TimeStamp); + } + } + } +} diff --git a/Src/fc7xxx_driver_gpio.c b/Src/fc7xxx_driver_gpio.c new file mode 100644 index 0000000..68080a3 --- /dev/null +++ b/Src/fc7xxx_driver_gpio.c @@ -0,0 +1,175 @@ +/** + * @file fc7xxx_driver_gpio.h + * @author Flagchip + * @brief FC7xxx GPIO driver type definition and API + * @version 0.1.0 + * @date 2023-2-14 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 31/12/2022 Flagchip0121 N/A First version for FC7240 +********************************************************************************/ + +#include "fc7xxx_driver_gpio.h" + +/** @brief Gpio instance list */ +static GPIO_Type *s_pGpioInstanceTable[GPIO_INSTANCE_COUNT] = GPIO_BASE_PTRS; + +/** + * @brief Initialize GPIO. + * + * @param eGpio GPIO instance + * @param pInitStruct Initialization structure of GPIO. + */ +GPIO_StatusType GPIO_InitPins(const GPIO_InstanceType eGpio, const GPIO_InitType *const pInitStruct) +{ + GPIO_StatusType eRet = GPIO_STATUS_SUCCESS; + GPIO_Type *pGpio; + uint32_t u32TempPins = 0U; + uint8_t u8PinIndex = 0U; + + if ((uint32_t)eGpio >= GPIO_INSTANCE_COUNT) + { + eRet = GPIO_STATUS_PARAM_INVALID; + } + else + { + pGpio = s_pGpioInstanceTable[(uint32_t)(eGpio)]; + u32TempPins = pInitStruct->u32GpioPins; + while (u32TempPins != 0u) + { + if ((u32TempPins & ((uint32_t)1 << u8PinIndex)) != 0u) + { + if (GPIO_OUT == pInitStruct->ePinDirection) + { + if (GPIO_LOW == pInitStruct->ePinLevel) + { + GPIO_HWA_ClearPinOutput(pGpio, u8PinIndex); + } + else + { + GPIO_HWA_SetPinOutput(pGpio, u8PinIndex); + } + GPIO_HWA_SetPinDirection(pGpio, u8PinIndex); + } + else if (GPIO_IN == pInitStruct->ePinDirection) + { + GPIO_HWA_ClearPinDirection(pGpio, u8PinIndex); + } + else + { + GPIO_HWA_SetPinInputDisable(pGpio, u8PinIndex); /* GPIO_ZERO == pInitStruct->ePinDirection */ + } + } + else + { + + } + u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); + u8PinIndex++; + } + } + return eRet; +} +/** + * @brief De-initialize the GPIO pin + * + * @param eGpio Gpio instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Gpio instance. + * @return GPIO status type. + */ +GPIO_StatusType GPIO_Deinit(const GPIO_InstanceType eGpio, const uint32_t u32Pins) +{ + DEV_ASSERT(eGpio < GPIO_INSTANCE_COUNT); + + GPIO_StatusType eRet = GPIO_STATUS_SUCCESS; + GPIO_Type *pGpio = s_pGpioInstanceTable[(uint32_t)(eGpio)]; + uint8_t u8PinIndex = 0U; + uint32_t u32TempPins = u32Pins; + + while (u32TempPins != 0) + { + if (u32TempPins & ((uint32_t)1 << u8PinIndex)) + { + GPIO_HWA_ClearPinDirection(pGpio, u8PinIndex); + GPIO_HWA_ClearPinDataOutput(pGpio, u8PinIndex); + GPIO_HWA_ClearPinInputDisable(pGpio, u8PinIndex); + } + u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); + u8PinIndex++; + } + return eRet; +} + +/** + * @brief Read level of input port pins. + * + * @param eGpio Port instance for GPIO functionality + * @param u32Pins The bit of u32Pins indicate the pin number of this Port. + * @return Pins level + */ +uint32_t GPIO_ReadPins(const GPIO_InstanceType eGpio, const uint32_t u32Pins) +{ + DEV_ASSERT(eGpio < GPIO_INSTANCE_COUNT); + GPIO_Type *pGpio = s_pGpioInstanceTable[(uint32_t)eGpio]; + return (GPIO_HWA_ReadPortDataInput(pGpio) & u32Pins); +} + +/** + * @brief Write gpio level to u32Pins. + * + * @param eGpio Port instance for GPIO functionality + * @param u32Pins The bit of u32Pins indicate the pin number of this Port. + * @param eOutput Output level enumeration + * @return Port return type. + */ +GPIO_StatusType GPIO_WritePins(const GPIO_InstanceType eGpio, const uint32_t u32Pins, const GPIO_PinLevelType eOutput) +{ + GPIO_StatusType eRet = GPIO_STATUS_SUCCESS; + GPIO_Type *pGpio = s_pGpioInstanceTable[(uint32_t)eGpio]; + if (((uint32_t)eGpio >= GPIO_INSTANCE_COUNT) || (eOutput > GPIO_HIGH)) + { + eRet = GPIO_STATUS_PARAM_INVALID; + } + else + { + if (GPIO_HIGH == eOutput) + { + GPIO_HWA_SetPortOutput(pGpio, u32Pins); + } + else + { + GPIO_HWA_ClearPortOutput(pGpio, u32Pins); + } + } + return eRet; +} + +/** + * @brief Toggle gpio api + * + * @param eGpio eGpio Port instance for GPIO functionality + * @param u32Pins The bit of u32Pins indicate the pin number of this Port. + * @return Port return type. + */ +GPIO_StatusType GPIO_Toggle(const GPIO_InstanceType eGpio, const uint32_t u32Pins) +{ + GPIO_StatusType eRet = GPIO_STATUS_SUCCESS; + GPIO_Type *pGpio = s_pGpioInstanceTable[(uint32_t)eGpio]; + if ((uint32_t)(eGpio >= GPIO_INSTANCE_COUNT)) + { + eRet = GPIO_STATUS_PARAM_INVALID; + } + else + { + GPIO_HWA_TogglePort(pGpio, u32Pins); + } + return eRet; +} diff --git a/Src/fc7xxx_driver_hsm.c b/Src/fc7xxx_driver_hsm.c new file mode 100644 index 0000000..094c12d --- /dev/null +++ b/Src/fc7xxx_driver_hsm.c @@ -0,0 +1,648 @@ +/** + * @file fc7xxx_driver_hsm.c + * @author Flagchip0103 + * @brief FC7xxx HSM driver source file + * @version 0.1.0 + * @date 2023-12-20 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2023-12-20 Flagchip0103 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_hsm.h" + +/* ################################################################################## */ +/* ##################################### Macros ##################################### */ + +typedef enum { + HSM_CMD_ID_TRNG = 0xb55du, + HSM_CMD_ID_SHA = 0xfce2u, + HSM_CMD_ID_ECC_SIGN = 0xde41u, + HSM_CMD_ID_ECC_VERIFY = 0xa522u, + HSM_CMD_ID_SM2_GENKEYPAIR = 0xc9ddu, + HSM_CMD_ID_SM2_ENCRY = 0x30f1u, + HSM_CMD_ID_SM2_DECRY = 0x6351u, + HSM_CMD_ID_SM2_SIGN = 0xe814u, + HSM_CMD_ID_SM2_VERIFY = 0x6e1eu, + HSM_CMD_ID_SM2_GENZA = 0xdbbeu, + HSM_CMD_ID_SM2_GENHASH = 0x5ce5u, + HSM_CMD_ID_SM4_ENCRY = 0xfd5au, + HSM_CMD_ID_SM4_DECRY = 0x4aedu, + HSM_CMD_ID_ECC_ENCRY = 0x4d3fu, + HSM_CMD_ID_ECC_DECRY = 0x97e4u, + HSM_CMD_ID_REQUEST_AUTH = 0x33d9u, + HSM_CMD_ID_LIFECYCLE_CHANGE = 0xbe63u, /* prefa,fa not support in sdk */ + HSM_CMD_ID_DEBUG_AUTH = 0x3928u, // TODO: delete + HSM_CMD_ID_ISP_AUTH = 0xAFBAu, // TODO: delete + HSM_CMD_ID_REVOKE_MRK = 0x19bbu, // TODO: delete + HSM_CMD_ID_REVOKE_UMRK = 0xfdb4u, // TODO: delete + HSM_CMD_ID_USER_KEY_ERASE = 0xac3au, // TODO: delete + HSM_CMD_ID_FLASHTEST_VERIFY = 0xcc29u, // TODO: delete + HSM_CMD_ID_UESR_CODE_VERIFY = 0x72d6u, // TODO: delete + HSM_CMD_ID_CANCEL_JOB = 0x17c3u, + HSM_CMD_ID_SELF_TEST = 0x4e93u, + HSM_CMD_ID_NVR_OTP = 0x2cd8u, + HSM_CMD_ID_LIFECYCLE_CHANGE_TAKE_EFFECT = 0x30fau, + HSM_CMD_ID_USER_KEY_MANAGE = 0xf4cfu, + HSM_CMD_ID_SPACE_MANAGE = 0x4ac0u, + HSM_CMD_ID_AES_ENCRY = 0xa2c6u, + HSM_CMD_ID_AES_DECRY = 0x6576u, + HSM_CMD_ID_CMAC_GEN = 0xf0b9u, + HSM_CMD_ID_XMAC_GEN = 0x32acu, + HSM_CMD_ID_CCM_ENCRY = 0x862fu, + HSM_CMD_ID_CCM_DECRY = 0x79a4u, + HSM_CMD_ID_GCM_ENCRY = 0xd1a6u, + HSM_CMD_ID_GCM_DECRY = 0xc0a3u, + HSM_CMD_ID_MD5 = 0x9371u, + HSM_CMD_ID_SM3 = 0xcfe5u, + HSM_CMD_ID_MONOTONIC_COUNTER = 0xdc97u, + HSM_CMD_ID_RSA = 0x866cu, + HSM_CMD_ID_USRK_GEN = 0xddb7u, // TODO: delete + HSM_CMD_ID_LOAD_FIRMWARE = 0x503du, + HSM_CMD_ID_DH_SM = 0x7F8Au, + HSM_CMD_ID_ECDH = 0x4b06u, + HSM_CMD_ID_DH = 0xb81bu, + HSM_CMD_ID_DH_PBKDF2 = 0xa47du, + HSM_CMD_ID_DH_GMPBKDF = 0xbe1fu, + HSM_CMD_ID_SCATTER_HASH = 0x465du, + HSM_CMD_ID_RAW_AESM = 0x42fdu, + HSM_CMD_ID_SCATTER_MAC = 0xa9e1u, + HSM_CMD_ID_ECC_GENKEYPAIR = 0x16b6u, + HSM_CMD_ID_RSA_SSA_PKCS1V15_SIGN = 0xd047u, + HSM_CMD_ID_RSA_SSA_PSS_SIGN = 0xd873u, + HSM_CMD_ID_RSA_ES_PKCS1V15_ENCRYPT = 0x3090u, + HSM_CMD_ID_RSA_ES_OAEP_ENCRYPT = 0x7F0Bu, + HSM_CMD_ID_RSA_SSA_PKCS1V15_VERIFY = 0x1577u, + HSM_CMD_ID_RSA_SSA_PSS_VERIFY = 0x0076u, + HSM_CMD_ID_RSA_ES_PKCS1V15_DECRYPT = 0x26d5u, + HSM_CMD_ID_RSA_ES_OAEP_DECRYPT = 0xc284u, +} HSM_CmdIdType; + +#define HSMCOM_TRNG_SRC_0 0x40cau +#define HSMCOM_TRNG_SRC_1 0xc51cu +#define HSMCOM_TRNG_SRC_ANY 0x359bu +#define HSMCOM_TRNG_SRC_XOR 0x80a5u +#define HSMCOM_DRNG_SRC 0x648Cu +#define HSMCOM_LIFECYCLE_OEM_DEV 0x4792u +#define HSMCOM_LIFECYCLE_OEM_PDT 0xA4F1u +#define HSMCOM_LIFECYCLE_IN_FIELD 0xaddcu +#define HSMCOM_INCREASE_COUNTER 0xd27fu +#define HSMCOM_READ_COUNTER 0x1875u +#define HSMCOM_SET_COUNTER_VAL 0x439du +#define HSMCOM_INCREASE_COUNTER_WHEN_EQUAL 0x6834u +#define HSMCOM_READ_ALL_FLEX_COUNTERS 0x6a47u +#define HSMCOM_SET_SINGLE_CFG 0x9e4du +#define HSMCOM_GET_SINGLE_CFG 0xaf42u +#define HSMCOM_INCREASE_COUNTER2 0xd280u +#define HSMCOM_READ_COUNTER2 0x1876u +#define HSMCOM_NVR_OTP_READ 0x9C2Fu +#define HSMCOM_NVR_OTP_WRITE 0x358Cu +#define HSMCOM_KEYMANAGER_IMPORT_USER_KEY 0xdcf1u +#define HSMCOM_KEYMANAGER_REVOKE_USER_KEY 0x7278u +#define HSMCOM_KEYMANAGER_EXPORT_USER_KEY 0xd8c9u +#define HSMCOM_KEYMANAGER_GEN_UESR_KEY 0x1853u +#define HSMCOM_KEYMANAGER_ENABLE_KEY_RAM_COPY 0x5ec5u +#define HSMCOM_KEYMANAGER_DISABLE_KEY_RAM_COPY 0x5918u +#define HSMCOM_KEYSPACE_GET_STATUS 0xe39cu +#define HSMCOM_KEYSPACE_NEATEN 0xb12bu +#define HSMCOM_REVOK_UMRK0 0x5edcu +#define HSMCOM_REVOK_UMRK1 0x20d9u +#define HSMCOM_REVOK_UMRK2 0x6ba1u +#define HSMCOM_REVOK_UMRK3 0xac50u + +/* ################################################################################## */ +/* ################################# Local Variables ################################ */ +#define AUTH_CHECK_DATA_BYTE_CNT 32 +static uint32_t s_aHsmDat[8]; +static HSMCom_AuthCheckType s_tHsmDummyCfg = {0, 0, &(s_aHsmDat[0]), &(s_aHsmDat[0]), &(s_aHsmDat[0]), &(s_aHsmDat[0]), &(s_aHsmDat[0]), AUTH_CHECK_DATA_BYTE_CNT}; + +/* ################################################################################## */ +/* ########################### Local Functions Prototype ############################ */ + +/* ################################################################################## */ +/* ################################# Local Functions ############################### */ +static HSM_StatusType hsm_assign_val(HSM_CmdType *pCmd, uint32_t u32Cmd, uint32_t u32Address) +{ + HSM_StatusType eRet = HSM_STATUS_SUCCESS; + + if (NULL != pCmd) + { + pCmd->u32Cmd = u32Cmd; + pCmd->u32Addr = u32Address; + } + else + { + eRet = HSM_STATUS_PARAM_ERR; + } + + return eRet; +} + +/* ################################################################################## */ +/* ################################# Global Functions ############################### */ +HSM_StatusType HSM_TrueRandGetSrc0(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_TRNG << 16u) | HSMCOM_TRNG_SRC_0, (uint32_t)pCfg); +} + +HSM_StatusType HSM_TrueRandGetSrc1(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_TRNG << 16u) | HSMCOM_TRNG_SRC_1, (uint32_t)pCfg); +} + +HSM_StatusType HSM_TrueRandGetSrcXor(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_TRNG << 16) | HSMCOM_TRNG_SRC_XOR, (uint32_t)pCfg); +} + +HSM_StatusType HSM_TrueRandGet(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_TRNG << 16) | HSMCOM_TRNG_SRC_ANY, (uint32_t)pCfg); +} + +HSM_StatusType HSM_PseudoRandGet(HSM_CmdType *pCmd, const HSMCom_TrueRandType*pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_TRNG << 16) | HSMCOM_DRNG_SRC, (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sha(HSM_CmdType *pCmd, const HSMCom_ShaType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SHA << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_ShaEx(HSM_CmdType *pCmd, const HSMCom_Sha2Type *pCfg) +{ + uint32_t u32CtrBits = (pCfg->tCfg.eInputFmt & 0x1) | ((pCfg->tCfg.eOutputFmt & 0x1) << 1); + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SHA << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_HashInitEx(HSM_CmdType *pCmd, const HSMCom_ShaType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SCATTER_HASH << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_HashUpdateEx(HSM_CmdType *pCmd, const HSMCom_ShaType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SCATTER_HASH << 16) | 5u, (uint32_t)pCfg); +} + +HSM_StatusType HSM_HashFinallyEx(HSM_CmdType *pCmd, const HSMCom_ShaType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SCATTER_HASH << 16) | 6u, (uint32_t)pCfg); +} + +HSM_StatusType HSM_CmacAesm(HSM_CmdType *pCmd, const HSMCom_AesmRawApiType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RAW_AESM << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_CmacScatter(HSM_CmdType *pCmd, const HSMCom_ScatterMacType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SCATTER_MAC << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_EccSign(HSM_CmdType *pCmd, const HSMCom_EccSignType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_ECC_SIGN << 16 | 1u), (uint32_t)pCfg); +} + +HSM_StatusType HSM_EccVerify(HSM_CmdType *pCmd, const HSMCom_EccVerifyType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_ECC_VERIFY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_EccGenKeyPair(HSM_CmdType *pCmd, const HSMCom_EccKeyPairGenType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_ECC_GENKEYPAIR << 16 | 1u), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm2GenKeyPair(HSM_CmdType *pCmd, const HSMCom_Sm2GenKeyPairType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM2_GENKEYPAIR << 16 | 1u), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm2Encry(HSM_CmdType *pCmd, const HSMCom_Sm2EncryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM2_ENCRY << 16 | 1u), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm2Decry(HSM_CmdType *pCmd, const HSMCom_Sm2DecryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM2_DECRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm2Sign(HSM_CmdType *pCmd, const HSMCom_Sm2SignType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM2_SIGN << 16 | 1u), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm2Verify(HSM_CmdType *pCmd, const HSMCom_Sm2VerifyType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM2_VERIFY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm2GenZa(HSM_CmdType *pCmd, const HSMCom_Sm2GenZaType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM2_GENZA << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm2GenHash(HSM_CmdType *pCmd, const HSMCom_Sm2GenHashType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM2_GENHASH << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm4Encrypt(HSM_CmdType *pCmd, const HSMCom_Sm4EncryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM4_ENCRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm4Decrypt(HSM_CmdType *pCmd, const HSMCom_Sm4DecryptType *pCfg) +{ + return hsm_assign_val(pCmd, (HSM_CMD_ID_SM4_DECRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_EccEasyEncry(HSM_CmdType *pCmd, const HSMCom_EccEasyEncryType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_ECC_ENCRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_EccEasyDecry(HSM_CmdType *pCmd, const HSMCom_EccEasyDecryType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_ECC_DECRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_EccPointCalc(HSM_CmdType *pCmd, const HSMCom_EccCalcType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_ECC_DECRY << 16) | 1u, (uint32_t)pCfg); +} + +HSM_StatusType HSM_ScatterHashInit(HSM_CmdType *pCmd, const HSMCom_ScatterHashType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SCATTER_HASH << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_ScatterHashUpdate(HSM_CmdType *pCmd, const HSMCom_ScatterHashType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SCATTER_HASH << 16) | 5u, (uint32_t)pCfg); +} + +HSM_StatusType HSM_ScatterHashFinally(HSM_CmdType *pCmd, const HSMCom_ScatterHashType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SCATTER_HASH << 16) | 6u, (uint32_t)pCfg); +} + +HSM_StatusType HSM_RequestAuthorization(HSM_CmdType *pCmd, const HSMCom_RequestAuthType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_REQUEST_AUTH << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_OemDevEnter(HSM_CmdType *pCmd) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_LIFECYCLE_CHANGE << 16) | HSMCOM_LIFECYCLE_OEM_DEV, (uint32_t)(&s_tHsmDummyCfg)); +} + +HSM_StatusType HSM_OemPdtEnter(HSM_CmdType *pCmd) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_LIFECYCLE_CHANGE << 16) | HSMCOM_LIFECYCLE_OEM_PDT, (uint32_t)(&s_tHsmDummyCfg)); +} + +HSM_StatusType HSM_InFieldEnter(HSM_CmdType *pCmd) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_LIFECYCLE_CHANGE << 16) | HSMCOM_LIFECYCLE_IN_FIELD, (uint32_t)(&s_tHsmDummyCfg)); +} + +HSM_StatusType HSM_CancelJob(HSM_CmdType *pCmd, const HSMCom_CancelJobType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_CANCEL_JOB << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_SelfTest(HSM_CmdType *pCmd, const HSMCom_SelfTestType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SELF_TEST << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_NvrOtpProgram(HSM_CmdType *pCmd, const HSMCom_NvrOtpType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_NVR_OTP << 16) | HSMCOM_NVR_OTP_WRITE, (uint32_t)pCfg); +} + +HSM_StatusType HSM_NvrOtpRead(HSM_CmdType *pCmd, const HSMCom_NvrOtpType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_NVR_OTP << 16) | HSMCOM_NVR_OTP_READ, (uint32_t)pCfg); +} + +HSM_StatusType HSM_TakeEffect(HSM_CmdType *pCmd) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_LIFECYCLE_CHANGE_TAKE_EFFECT << 16), (uint32_t)0); +} + +HSM_StatusType HSM_UserKeyRevoke(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_USER_KEY_MANAGE << 16) | HSMCOM_KEYMANAGER_REVOKE_USER_KEY, (uint32_t)pCfg); +} + +HSM_StatusType HSM_UserKeyImport(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_USER_KEY_MANAGE << 16) | HSMCOM_KEYMANAGER_IMPORT_USER_KEY, (uint32_t)pCfg); +} + +HSM_StatusType HSM_UserKeyExport(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_USER_KEY_MANAGE << 16) | HSMCOM_KEYMANAGER_EXPORT_USER_KEY, (uint32_t)pCfg); +} + +HSM_StatusType HSM_EraseKeyFlash(HSM_CmdType *pCmd, HSMCom_BasicType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_USER_KEY_ERASE << 16) | 0xa80f, (uint32_t)pCfg); +} + +HSM_StatusType HSM_UserKeyGen(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_USER_KEY_MANAGE << 16) | HSMCOM_KEYMANAGER_GEN_UESR_KEY, (uint32_t)pCfg); +} + +HSM_StatusType HSM_EnableKeyRamCopy(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_USER_KEY_MANAGE << 16) | HSMCOM_KEYMANAGER_ENABLE_KEY_RAM_COPY, (uint32_t)pCfg); +} + +HSM_StatusType HSM_DisableKeyRamCopy(HSM_CmdType *pCmd, const HSMCom_UserKeyManageType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_USER_KEY_MANAGE << 16) | HSMCOM_KEYMANAGER_DISABLE_KEY_RAM_COPY, (uint32_t)pCfg); +} + +HSM_StatusType HSM_GetKeySpaceStatus(HSM_CmdType *pCmd, const HSMCom_KeySpaceStatusType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SPACE_MANAGE << 16) | HSMCOM_KEYSPACE_GET_STATUS, (uint32_t)pCfg); +} + +HSM_StatusType HSM_TidyUpKeySpace(HSM_CmdType *pCmd, const HSMCom_KeySpaceStatusType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SPACE_MANAGE << 16) | HSMCOM_KEYSPACE_NEATEN, (uint32_t)pCfg); +} + +HSM_StatusType HSM_AesEncrypt(HSM_CmdType *pCmd, const HSMCom_AesEncryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_AES_ENCRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Aes_FlexEncrypt(HSM_CmdType *pCmd, const HSMCom_FlexAesEncryptType *pCfg) +{ + uint32_t u32CtrBits =0x1 | + ((pCfg->tCfg.epad & 0x1) << 1) | ((pCfg->tCfg.eInputFmt & 0x1) << 2) | + ((pCfg->tCfg.eOutputFmt & 0x1) << 3) | ((pCfg->tCfg.eBackend & 0x1) << 4) ; + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_AES_ENCRY << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_AesDecrypt(HSM_CmdType *pCmd, const HSMCom_AesDecryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_AES_DECRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Aes_FlexDecrypt(HSM_CmdType *pCmd, const HSMCom_FlexAesDecryptType *pCfg) +{ + uint32_t u32CtrBits = 0x1 | + ((pCfg->tCfg.epad & 0x1) << 1) | ((pCfg->tCfg.eInputFmt & 0x1) << 2) | + ((pCfg->tCfg.eOutputFmt & 0x1) << 3) | ((pCfg->tCfg.eBackend & 0x1) << 4) ; + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_AES_DECRY << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_CMac(HSM_CmdType *pCmd, const HSMCom_CMacType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_CMAC_GEN << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_CmacEx(HSM_CmdType *pCmd, const HSMCom_CMacExType *pCfg) +{ + uint32_t u32CtrBits = (pCfg->tCfg.eBackend & 0x1) | ((pCfg->tCfg.eInputFmt & 0x1) << 1) | ((pCfg->tCfg.eOutputFmt & 0x1) << 2); + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_CMAC_GEN << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_XMac(HSM_CmdType *pCmd, const HSMCom_XMacType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_XMAC_GEN << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_XMacEx(HSM_CmdType *pCmd, const HSMCom_XMacExType *pCfg) +{ + uint32_t u32CtrBits = (pCfg->tCfg.eBackend & 0x1) | ((pCfg->tCfg.eInputFmt & 0x1) << 1) | ((pCfg->tCfg.eOutputFmt & 0x1) << 2); + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_XMAC_GEN << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_CcmEncry(HSM_CmdType *pCmd, const HSMCom_CcmEncryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_CCM_ENCRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_CcmEncryEx(HSM_CmdType *pCmd, const HSMCom_CcmEncryptExType *pCfg) +{ + uint32_t u32CtrBits = (pCfg->tCfg.eBackend & 0x1); + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_CCM_ENCRY << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_CcmDecry(HSM_CmdType *pCmd, const HSMCom_CcmDecryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_CCM_DECRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_CcmDecryEx(HSM_CmdType *pCmd, const HSMCom_CcmDecryptExType *pCfg) +{ + uint32_t u32CtrBits = (pCfg->tCfg.eBackend & 0x1); + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_CCM_DECRY << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_GcmEncry(HSM_CmdType *pCmd, const HSMCom_GcmEncryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_GCM_ENCRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_GcmEncryEx(HSM_CmdType *pCmd, const HSMCom_GcmEncryptExType *pCfg) +{ + uint32_t u32CtrBits = (pCfg->tCfg.eBackend & 0x1); + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_GCM_ENCRY << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_GcmDecry(HSM_CmdType *pCmd, const HSMCom_GcmDecryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_GCM_DECRY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_GcmDecryEx(HSM_CmdType *pCmd, const HSMCom_GcmDecryptExType *pCfg) +{ + uint32_t u32CtrBits = (pCfg->tCfg.eBackend & 0x1); + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_GCM_DECRY << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_Md5(HSM_CmdType *pCmd, const HSMCom_Md5Type *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MD5 << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Md5Ex(HSM_CmdType *pCmd, const HSMCom_Md5Type *pCfg) +{ + uint32_t u32CtrBits = (pCfg->tCfg.eIntputFmt & 0x1) | ((pCfg->tCfg.eOutputFmt & 0x1) << 1); + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MD5 << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm3(HSM_CmdType *pCmd, const HSMCom_Sm3Type *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM3 << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_Sm3Ex(HSM_CmdType *pCmd, const HSMCom_Sm3Type *pCfg) +{ + uint32_t u32CtrBits = (pCfg->tCfg.eIntputFmt & 0x1) | ((pCfg->tCfg.eOutputFmt & 0x1) << 1); + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_SM3 << 16) | u32CtrBits, (uint32_t)pCfg); +} + +HSM_StatusType HSM_MonotonicCounterIncrease(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MONOTONIC_COUNTER << 16) | HSMCOM_INCREASE_COUNTER, (uint32_t)pCfg); +} + +HSM_StatusType HSM_MonotonicCounterRead(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MONOTONIC_COUNTER << 16) | HSMCOM_READ_COUNTER, (uint32_t)pCfg); +} + +HSM_StatusType HSM_MonotonicCounterSetValue(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MONOTONIC_COUNTER << 16) | HSMCOM_SET_COUNTER_VAL, (uint32_t)pCfg); +} + +HSM_StatusType HSM_MonotonicIncCountWhenEqu(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MONOTONIC_COUNTER << 16) | HSMCOM_INCREASE_COUNTER_WHEN_EQUAL, (uint32_t)pCfg); +} + +HSM_StatusType HSM_MonotonicReadAllFlexCounters(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MONOTONIC_COUNTER << 16) | HSMCOM_READ_ALL_FLEX_COUNTERS, (uint32_t)pCfg); +} + +HSM_StatusType HSM_MonotonicCounterSetSingleCfg(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MONOTONIC_COUNTER << 16) | HSMCOM_SET_SINGLE_CFG, (uint32_t)pCfg); +} + +HSM_StatusType HSM_MonotonicCounterGetSingleCfg(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MONOTONIC_COUNTER << 16) | HSMCOM_GET_SINGLE_CFG, (uint32_t)pCfg); +} + +HSM_StatusType HSM_MonotonicIncreaseCounter2(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MONOTONIC_COUNTER << 16) | HSMCOM_INCREASE_COUNTER2, (uint32_t)pCfg); +} + +HSM_StatusType HSM_MonotonicReadCounter2(HSM_CmdType *pCmd, const HSMCom_MonCountType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_MONOTONIC_COUNTER << 16) | HSMCOM_READ_COUNTER2, (uint32_t)pCfg); +} + +HSM_StatusType HSM_Rsa(HSM_CmdType *pCmd, const HSMCom_RsaType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_RSA_SSA_PSS_Sign(HSM_CmdType *pCmd, const HSMCom_RsaSsaPssSignType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA_SSA_PSS_SIGN << 16), (uint32_t)pCfg); +} +HSM_StatusType HSM_RSA_SSA_PSS_Verify(HSM_CmdType *pCmd, const HSMCom_RsaSsaPssVerifyType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA_SSA_PSS_VERIFY << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_RSA_SSA_ES_PKCS1V15_Encrypt(HSM_CmdType *pCmd, const HSMCom_RsaEsPkcs1V15EncryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA_ES_PKCS1V15_ENCRYPT << 16), (uint32_t)pCfg); +} +HSM_StatusType HSM_RSA_SSA_ES_PKCS1V15_Decrypt(HSM_CmdType *pCmd, const HSMCom_RsaEsPkcs1V15DecryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA_ES_PKCS1V15_DECRYPT << 16), (uint32_t)pCfg); +} +HSM_StatusType HSM_RSA_SSA_ES_PKCS1V15_Verify(HSM_CmdType *pCmd, const HSMCom_RsaSsaPkcs1V15VerifyType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA_SSA_PKCS1V15_VERIFY << 16), (uint32_t)pCfg); +} +HSM_StatusType HSM_RSA_SSA_ES_PKCS1V15_Sign(HSM_CmdType *pCmd, const HSMCom_RsaSsaPkcs1V15SignType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA_SSA_PKCS1V15_SIGN << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_RSA_SSA_ES_OAEP_Encrypt(HSM_CmdType *pCmd, const HSMCom_RsaEsOaepEncryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA_ES_OAEP_ENCRYPT << 16), (uint32_t)pCfg); +} +HSM_StatusType HSM_RSA_SSA_ES_OAEP_Decrypt(HSM_CmdType *pCmd, const HSMCom_RsaEsOaepDecryptType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA_ES_OAEP_DECRYPT << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_BigNumberCalc(HSM_CmdType *pCmd, const HSMCom_BigNumberCalcType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_RSA << 16) | 1u, (uint32_t)pCfg); +} + +HSM_StatusType HSM_LoadFirmware(HSM_CmdType *pCmd) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_LOAD_FIRMWARE << 16), (uint32_t)0); +} + +HSM_StatusType HSM_SMDH(HSM_CmdType *pCmd, HSMCom_SmDHType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_DH_SM << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_ECDH(HSM_CmdType *pCmd, HSMCom_ECDHType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_ECDH << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_DH(HSM_CmdType *pCmd, HSMCom_RsaDHType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_DH << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_PBKDF2(HSM_CmdType *pCmd, HSMCom_Pbkdf2Type *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_DH_PBKDF2 << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_GMPBKDF(HSM_CmdType *pCmd, HSMCom_GMpbkdfType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_DH_GMPBKDF << 16), (uint32_t)pCfg); +} + +HSM_StatusType HSM_RevokeUmrk0(HSM_CmdType *pCmd) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_REVOKE_UMRK << 16)|HSMCOM_REVOK_UMRK0, (uint32_t)0); +} + +HSM_StatusType HSM_RevokeUmrk1(HSM_CmdType *pCmd) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_REVOKE_UMRK << 16)|HSMCOM_REVOK_UMRK1, (uint32_t)0); +} + +HSM_StatusType HSM_RevokeUmrk2(HSM_CmdType *pCmd) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_REVOKE_UMRK << 16)|HSMCOM_REVOK_UMRK2, (uint32_t)0); +} + +HSM_StatusType HSM_RevokeUmrk3(HSM_CmdType *pCmd) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_REVOKE_UMRK << 16)|HSMCOM_REVOK_UMRK3, (uint32_t)0); +} + +HSM_StatusType HSM_GenUsrk(HSM_CmdType *pCmd,const HSMCom_RsaType *pCfg) +{ + return hsm_assign_val(pCmd,(uint32_t)(HSM_CMD_ID_USRK_GEN << 16), (uint32_t)pCfg); +} diff --git a/Src/fc7xxx_driver_intm.c b/Src/fc7xxx_driver_intm.c new file mode 100644 index 0000000..5e12985 --- /dev/null +++ b/Src/fc7xxx_driver_intm.c @@ -0,0 +1,190 @@ +/** + * @file fc7xxx_driver_intm.c + * @author Flagchip + * @brief FC7240 INTM driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-10 Flagchip084 N/A FC7240 release version + ******************************************************************************** */ + +#include "fc7xxx_driver_intm.h" +#include "interrupt_manager.h" + +/* ################################################################################## */ +/* ##################################### Macros ##################################### */ + +/* ################################################################################## */ +/* ################################# Local Variables ################################ */ + +static INTM_Type *const s_aIntm_Base[INTM_INSTANCE_MAX] = INTM_BASE_PTRS; +static INTM_ISRCallbackType s_aIntmISRCallback[INTM_INSTANCE_MAX][INTM_IRQ_MONITOR_MAX] = {NULL}; +/* ################################################################################## */ +/* ########################### Local Functions Prototype ############################ */ +void INTM0_IRQHandler(void); +void INTMn_IRQHandler(INTM_InstanceType eInstance); + +/* ################################################################################## */ +/* ################################# Local Functions ############################### */ + +/* ################################################################################## */ +/* ################################# Global Functions ############################### */ + +INTM_ReturnType INTM_Init(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex, INTM_InitType *pInitCfg) +{ + INTM_MonitorType *pMonitor; + + if ((NULL == pInitCfg) || (eInstance >= INTM_INSTANCE_MAX) || (eIrqMonitorIndex >= INTM_IRQ_MONITOR_MAX)) + { + return INTM_RETURN_E_PARAM; + } + + if (pInitCfg->u32SrcDelayCnt >= 0xFFFFFFU) + { + return INTM_RETURN_E_PARAM; + } + + if (pInitCfg->u16IrqNumber >= IRQn_MAX) + { + return INTM_RETURN_E_PARAM; + } + + pMonitor = INTM_HWA_GetIrqMonitor(s_aIntm_Base[eInstance], (uint8_t)eIrqMonitorIndex); + INTM_HWA_SetIRQReqNum(pMonitor, pInitCfg->u16IrqNumber); + INTM_HWA_EnableReset(pMonitor, pInitCfg->bEnReset); + INTM_HWA_EnableInterrupt(pMonitor, pInitCfg->bEnInterrupt); + INTM_HWA_SetLatency(pMonitor, pInitCfg->u32SrcDelayCnt); + if (pInitCfg->eMode == INTM_INTERRUPT_MODE_INACTIVE) + { + INTM_HWA_EnableInactiveMode(pMonitor, true); + } + else + { + INTM_HWA_EnableInactiveMode(pMonitor, false); + } + s_aIntmISRCallback[eInstance][eIrqMonitorIndex] = pInitCfg->pIntmIsrCallback; + return INTM_RETURN_OK; +} + +INTM_ReturnType INTM_enable(INTM_InstanceType eInstance, bool bEnable) +{ + if (eInstance >= INTM_INSTANCE_MAX) + { + return INTM_RETURN_E_PARAM; + } + + INTM_HWA_Enable(s_aIntm_Base[eInstance], bEnable); + + return INTM_RETURN_OK; +} + +INTM_ReturnType INTM_StartInactiveMode(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex) +{ + INTM_MonitorType *pMonitor; + + if ((eInstance >= INTM_INSTANCE_MAX) || (eIrqMonitorIndex >= INTM_IRQ_MONITOR_MAX)) + { + return INTM_RETURN_E_PARAM; + } + + pMonitor = INTM_HWA_GetIrqMonitor(s_aIntm_Base[eInstance], (uint8_t)eIrqMonitorIndex); + INTM_HWA_StartInactiveMode(pMonitor); + return INTM_RETURN_OK; +} + +INTM_ReturnType INTM_StopInactiveMode(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex) +{ + INTM_MonitorType *pMonitor; + + if ((eInstance >= INTM_INSTANCE_MAX) || (eIrqMonitorIndex >= INTM_IRQ_MONITOR_MAX)) + { + return INTM_RETURN_E_PARAM; + } + + pMonitor = INTM_HWA_GetIrqMonitor(s_aIntm_Base[eInstance], (uint8_t)eIrqMonitorIndex); + INTM_HWA_StopInactiveMode(pMonitor); + return INTM_RETURN_OK; +} + +INTM_ReturnType INTM_SetAcknowledge(INTM_InstanceType eInstance, uint16_t u16IrqNumber) +{ + if (eInstance >= INTM_INSTANCE_MAX) + { + return INTM_RETURN_E_PARAM; + } + + INTM_HWA_SetIACKR(s_aIntm_Base[eInstance], u16IrqNumber); + + return INTM_RETURN_OK; +} + +uint32_t INTM_GetCounterValue(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex) +{ + INTM_MonitorType *pMonitor; + + if ((eInstance >= INTM_INSTANCE_MAX) || (eIrqMonitorIndex >= INTM_IRQ_MONITOR_MAX)) + { + return 0; + } + + pMonitor = INTM_HWA_GetIrqMonitor(s_aIntm_Base[eInstance], (uint8_t)eIrqMonitorIndex); + return INTM_HWA_GetTimerCounter(pMonitor); +} + +INTM_ReturnType INTM_ClearIntFlag(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex) +{ + INTM_MonitorType *pMonitor; + + if ((eInstance >= INTM_INSTANCE_MAX) || (eIrqMonitorIndex >= INTM_IRQ_MONITOR_MAX)) + { + return INTM_RETURN_E_PARAM; + } + + pMonitor = INTM_HWA_GetIrqMonitor(s_aIntm_Base[eInstance], (uint8_t)eIrqMonitorIndex); + INTM_HWA_SetTimerCounter(pMonitor, 0U); + return INTM_RETURN_OK; +} + +bool INTM_GetTimeoutStatus(INTM_InstanceType eInstance, INTM_IrqMonitorType eIrqMonitorIndex) +{ + INTM_MonitorType *pMonitor; + + if ((eInstance >= INTM_INSTANCE_MAX) || (eIrqMonitorIndex >= INTM_IRQ_MONITOR_MAX)) + { + return false; + } + + pMonitor = INTM_HWA_GetIrqMonitor(s_aIntm_Base[eInstance], (uint8_t)eIrqMonitorIndex); + return INTM_HWA_ReadStatus(pMonitor); +} + +void INTMn_IRQHandler(INTM_InstanceType eInstance) +{ + uint8_t u8i; + INTM_MonitorType *pMonitor; + + for (u8i = 0; u8i < (uint8_t)INTM_IRQ_MONITOR_MAX; u8i++) + { + pMonitor = INTM_HWA_GetIrqMonitor(s_aIntm_Base[eInstance], u8i); + if (INTM_HWA_ReadStatus(pMonitor)) + { + if (s_aIntmISRCallback[eInstance][u8i] != NULL) + { + s_aIntmISRCallback[eInstance][u8i](); + } + } + } +} + +void INTM0_IRQHandler(void) +{ + INTMn_IRQHandler(INTM_INSTANCE_0); +} diff --git a/Src/fc7xxx_driver_ism.c b/Src/fc7xxx_driver_ism.c new file mode 100644 index 0000000..08df27d --- /dev/null +++ b/Src/fc7xxx_driver_ism.c @@ -0,0 +1,347 @@ +/** + * @file fc7xxx_driver_ism.c + * @author Flagchip + * @brief FC7xxx ISM driver type definition and API + * @version 0.1.0 + * @date 2023-02-13 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-1-10 Flagchip095 N/A First version for FC7240 + ******************************************************************************** */ +#include "fc7xxx_driver_ism.h" + +/* ################################################################################## */ +/* ####################################### Macro #################################### */ +#define FPC_INSTANCE_COUNT (16U) +#define LAM_INSTANCE_COUNT (16U) +#define ECM_INSTANCE_COUNT (4U) +/* ################################################################################## */ +/* ################################### Type define ################################## */ + +/* ################################################################################## */ +/* ################################ Local Variables ################################# */ +static ISM_Type *const s_apIsmBase[ISM_INSTANCE_COUNT] = ISM_BASE_PTRS; +static ISM_EventISRCallbackType s_apEventISRCallback = NULL; +static FPC_ISRCallbackType s_apFpcISRCallback[FPC_INSTANCE_COUNT] = {NULL}; +static LAM_ISRCallbackType s_apLamOverFlowIsrCallback[LAM_INSTANCE_COUNT] = {NULL}; +/* ################################################################################## */ +/* ########################### Local Prototype Functions ############################ */ + +/* ################################################################################## */ +/* ######################### Global prototype Functions ############################ */ +void ISM0_IRQHandler(void); +/* ################################################################################## */ +/* ################################ Local Functions ################################ */ + +/* ################################################################################## */ +/* ################################ Global Functions ################################ */ + +void ISM_Init(const ISM_InitCfgType *pInitConfig) +{ + ISM_Type *pIsm = ISM; + + DEV_ASSERT(ISM_HWA_PARAM_ECMC(pIsm) == ECM_INSTANCE_COUNT); + DEV_ASSERT(ISM_HWA_PARAM_FPC(pIsm) == FPC_INSTANCE_COUNT); + DEV_ASSERT(ISM_HWA_PARAM_LAM(pIsm) == LAM_INSTANCE_COUNT); + DEV_ASSERT(pInitConfig != NULL); + + s_apEventISRCallback = pInitConfig->pEventIsrCallback; + ISM_HWA_InterruptEnable(pIsm, pInitConfig->bIntEnable); +} + +uint8_t ISM_GetEcmEventHappenedChannels(void) +{ + ISM_Type *pIsm = ISM; + + return (uint8_t)ISM_HWA_GetEcs(pIsm); +} + +uint16_t ISM_GetLamEventHappenedChannels(void) +{ + ISM_Type *pIsm = ISM; + + return ISM_HWA_GetEs(pIsm); +} + +void ISM_ClearEcmEventHappenedChannels(uint8_t u8Channels) +{ + ISM_Type *pIsm = ISM; + + ISM_HWA_ClearEcs(pIsm, (uint32_t)u8Channels); +} + +void ISM_ClearLamEventHappenedChannels(uint16_t u16Channels) +{ + ISM_Type *pIsm = ISM; + + ISM_HWA_ClearEs(pIsm, (uint32_t)u16Channels); +} + +void ISM_EnableEcmSystemEvent(uint32_t u32Channels, bool bEnable) +{ + ISM_Type *pIsm = ISM; + + ISM_HWA_EnableEcmSystemEvent(pIsm, u32Channels, bEnable); +} + +void ISM_EnableLamSystemEvent(uint32_t u32Channels, bool bEnable) +{ + ISM_Type *pIsm = ISM; + + ISM_HWA_EnableLamSystemEvent(pIsm, u32Channels, bEnable); +} + +void ISM_EcmEventConfig(uint8_t u8LamIndex, uint8_t u8EcmIndex, uint8_t u8EventCount) +{ + ISM_Type *pIsm = ISM; + + DEV_ASSERT(u8LamIndex < LAM_INSTANCE_COUNT); + DEV_ASSERT(u8EcmIndex < ECM_INSTANCE_COUNT); + if (u8EcmIndex == 0U) + { + ISM_HWA_SetEcm0EcCtrl(pIsm, u8EventCount, u8LamIndex); + } + else if (u8EcmIndex == 1U) + { + ISM_HWA_SetEcm1EcCtrl(pIsm, u8EventCount, u8LamIndex); + } + else if (u8EcmIndex == 2U) + { + ISM_HWA_SetEcm2EcCtrl(pIsm, u8EventCount, u8LamIndex); + } + else if (u8EcmIndex == 3U) + { + ISM_HWA_SetEcm3EcCtrl(pIsm, u8EventCount, u8LamIndex); + } + else + { + + } +} + +void ISM_ClearLamStatusCounter(uint8_t u8LamIndex) +{ + LAM_Type *pLam; + + DEV_ASSERT(u8LamIndex < LAM_INSTANCE_COUNT); + + pLam = ISM_HWA_GetLam(ISM, u8LamIndex); + + ISM_HWA_ClearLamStatusCounter(pLam); +} + +uint32_t ISM_GetLamStatusCounter(uint8_t u8LamIndex) +{ + LAM_Type *pLam; + + DEV_ASSERT(u8LamIndex < LAM_INSTANCE_COUNT); + + pLam = ISM_HWA_GetLam(ISM, u8LamIndex); + + return ISM_HWA_GetLamStatusCounter(pLam); +} + +void ISM_ClearLamStatusOvfl(uint8_t u8LamIndex) +{ + LAM_Type *pLam; + + DEV_ASSERT(u8LamIndex < LAM_INSTANCE_COUNT); + + pLam = ISM_HWA_GetLam(ISM, u8LamIndex); + + ISM_HWA_ClearLamStatusOvfl(pLam); +} + +bool ISM_GetLamStatusOvfl(uint8_t u8LamIndex) +{ + LAM_Type *pLam; + + DEV_ASSERT(u8LamIndex < LAM_INSTANCE_COUNT); + + pLam = ISM_HWA_GetLam(ISM, u8LamIndex); + + return ISM_HWA_GetLamStatusOvfl(pLam); +} + +void ISM_Enable(bool bEnable) +{ + ISM_Type *pIsm = ISM; + + ISM_HWA_Enable(pIsm, bEnable); +} + +void ISM_InterruptEnable(bool bEnable) +{ + ISM_Type *pIsm = ISM; + + ISM_HWA_InterruptEnable(pIsm, bEnable); +} + +void ISM_LamOverflowInterruptEnable(uint8_t u8LamIndex, bool bEnable) +{ + LAM_Type *pLam; + + DEV_ASSERT(u8LamIndex < LAM_INSTANCE_COUNT); + + pLam = ISM_HWA_GetLam(ISM, u8LamIndex); + + ISM_HWA_SetLamCtrIen(pLam, bEnable); +} + +void ISM_LamEnable(uint8_t u8LamIndex, bool bEnable) +{ + LAM_Type *pLam; + + DEV_ASSERT(u8LamIndex < LAM_INSTANCE_COUNT); + + pLam = ISM_HWA_GetLam(ISM, u8LamIndex); + + ISM_HWA_SetLamCtrEn(pLam, bEnable); +} + +void ISM_LamConfig(uint8_t u8LamIndex, const ISM_LamCfgType *pConfig) +{ + uint32_t u32TempValue = 0; + LAM_Type *pLam; + + DEV_ASSERT(u8LamIndex < LAM_INSTANCE_COUNT); + DEV_ASSERT(pConfig != NULL); + + pLam = ISM_HWA_GetLam(ISM, u8LamIndex); + + ISM_HWA_SetLamCtrIen(pLam, pConfig->bOvflIntEnable); + ISM_HWA_SetLamCounter(pLam, pConfig->u32EvtCntThreshold); + + u32TempValue |= ISM_LAM_CONFIG_RCS(pConfig->u8SrcSel); + u32TempValue |= ISM_LAM_CONFIG_MCS(pConfig->u8MonSel); + u32TempValue |= ISM_LAM_CONFIG_IVW(pConfig->eInvWin); + u32TempValue |= ISM_LAM_CONFIG_EDS(pConfig->eWinEdgSel); + u32TempValue |= ISM_LAM_CONFIG_EWS(pConfig->eEvtWinSel); + u32TempValue |= ISM_LAM_CONFIG_RMS(pConfig->eRunMode); + u32TempValue |= ISM_LAM_CONFIG_MOS(pConfig->eMonSrcSel); + u32TempValue |= ISM_LAM_CONFIG_IVM(pConfig->eInvMon); + u32TempValue |= ISM_LAM_CONFIG_IVR(pConfig->eInvRef); + + s_apLamOverFlowIsrCallback[u8LamIndex] = pConfig->pLamOverFlowIsrCallback; + + ISM_HWA_SetLamConfig(pLam, u32TempValue); +} + +void ISM_FpcGlitchInterruptEnable(uint8_t u8FpcIndex, bool bEnable) +{ + FPC_Type *pFpc; + + DEV_ASSERT(u8FpcIndex < FPC_INSTANCE_COUNT); + + pFpc = ISM_HWA_GetFpc(ISM, u8FpcIndex); + + ISM_HWA_SetFpcCtrlIen(pFpc, bEnable); +} + +void ISM_FpcEnable(uint8_t u8FpcIndex, bool bEnable) +{ + FPC_Type *pFpc; + + DEV_ASSERT(u8FpcIndex < FPC_INSTANCE_COUNT); + + pFpc = ISM_HWA_GetFpc(ISM, u8FpcIndex); + + ISM_HWA_SetFpcCtrlEn(pFpc, bEnable); +} + +void ISM_FpcConfig(uint8_t u8FpcIndex, const ISM_FpcCfgType *pConfig) +{ + uint32_t u32TempValue = 0; + FPC_Type *pFpc; + + DEV_ASSERT(u8FpcIndex < FPC_INSTANCE_COUNT); + DEV_ASSERT(pConfig != NULL); + + pFpc = ISM_HWA_GetFpc(ISM, u8FpcIndex); + + ISM_HWA_SetFpcCtrlIen(pFpc, pConfig->bGlitchIntEnable); + + u32TempValue |= ISM_FPC_CONFIG_FED(pConfig->eFallingDelayNode); + u32TempValue |= ISM_FPC_CONFIG_FEG(pConfig->eFallingDetectMode); + u32TempValue |= ISM_FPC_CONFIG_RED(pConfig->eRisingDelayNode); + u32TempValue |= ISM_FPC_CONFIG_REG(pConfig->eRisingDetectMode); + u32TempValue |= ISM_FPC_CONFIG_CMP(pConfig->u32ThresholdValue); + + s_apFpcISRCallback[u8FpcIndex] = pConfig->pFpcIsrCallback; + + ISM_HWA_SetFpcConfig(pFpc, u32TempValue); +} + +void ISM0_IRQHandler(void) +{ + uint8_t u8i; + FPC_Type *pFpc; + LAM_Type *pLam; + uint8_t u8EcmFlags; + uint16_t u16LamFlags; + ISM_Type *pIsm = s_apIsmBase[ISM_INSTANCE_0]; + + u8EcmFlags = ISM_HWA_GetEcs(pIsm)&ISM_HWA_GetEnabledEcmSystemEvent(pIsm); + u16LamFlags = ISM_HWA_GetEs(pIsm)&ISM_HWA_GetEnabledLamSystemEvent(pIsm); + + if (s_apEventISRCallback != NULL) + { + s_apEventISRCallback(u16LamFlags, u8EcmFlags); + } + + ISM_HWA_ClearEcs(pIsm, u8EcmFlags); + ISM_HWA_ClearEs(pIsm, u16LamFlags); + + for (u8i = 0; u8i < FPC_INSTANCE_COUNT; u8i++) + { + pFpc = ISM_HWA_GetFpc(s_apIsmBase[ISM_INSTANCE_0], u8i); + if (ISM_HWA_GetFpcCtrlIen(pFpc)) + { + uint32_t u32Status = 0U; + if (ISM_HWA_GetFpcRgd(pFpc)) + { + u32Status |= (uint32_t)FPC_RISING_GLITCH_DETECTED; + } + if (ISM_HWA_GetFpcFgd(pFpc)) + { + u32Status |= (uint32_t)FPC_FALLING_GLITCH_DETECTED; + } + if (s_apFpcISRCallback[u8i] != NULL) + { + s_apFpcISRCallback[u8i](u32Status); + } + if ((u32Status & (uint32_t)FPC_RISING_GLITCH_DETECTED) == (uint32_t)FPC_RISING_GLITCH_DETECTED) + { + ISM_HWA_ClearFpcRgd(pFpc); + } + if ((u32Status & (uint32_t)FPC_FALLING_GLITCH_DETECTED) == (uint32_t)FPC_FALLING_GLITCH_DETECTED) + { + ISM_HWA_ClearFpcFgd(pFpc); + } + } + } + + for (u8i = 0; u8i < LAM_INSTANCE_COUNT; u8i++) + { + pLam = ISM_HWA_GetLam(s_apIsmBase[ISM_INSTANCE_0], u8i); + if (ISM_HWA_GetLamCtrIen(pLam)) + { + if (ISM_HWA_GetLamStatusOvfl(pLam)) + { + if (s_apLamOverFlowIsrCallback[u8i] != NULL) + { + s_apLamOverFlowIsrCallback[u8i](); + } + } + ISM_HWA_ClearLamStatusOvfl(pLam); + } + } + +} diff --git a/Src/fc7xxx_driver_lin.c b/Src/fc7xxx_driver_lin.c new file mode 100644 index 0000000..7880537 --- /dev/null +++ b/Src/fc7xxx_driver_lin.c @@ -0,0 +1,1502 @@ +/** + * @file fc7xxx_driver_lin.c + * @author Flagchip + * @brief FC7xxx LIN driver type definition and API + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-14 Flagchip0122 N/A FC7xxx internal release version + ******************************************************************************** */ + +#include "fc7xxx_driver_lin.h" +#include "device_header.h" +#include "fc7xxx_driver_fcuart.h" + +/* ################################################################################## */ +/* ####################################### Macro #################################### */ + +/** UART Instance Number */ +#define LIN_INSTANCE_NUM FCUART_INSTANCE_COUNT + +/* ################################################################################## */ +/* ################################### type define ################################## */ + +/* ################################################################################## */ +/* ################################ Local Variables ################################# */ + +static uint8_t s_aInstanceUsed[LIN_INSTANCE_NUM] = {0}; +static lin_config_t *s_aLinConfig[LIN_INSTANCE_NUM] = {0}; +static lin_xfer_state_t *s_aLinXfer[LIN_INSTANCE_NUM] = {0}; + +/* UART instance array */ +static FCUART_Type *const s_aFCUART_InstanceTable[FCUART_INSTANCE_COUNT] = FCUART_BASE_PTRS; + +/* ################################################################################## */ +/* ########################### Local Prototype Functions ############################ */ +static LIN_StatusType LIN_DrvCalBaudrate(uint8_t u8LinIndex, uint32_t *u32OverSamp, + uint32_t *u32Sbr); +static LIN_NodeType LIN_DrvCheckMode(uint8_t u8LinIndex); +LOCAL_INLINE uint8_t BIT(uint8_t A, uint8_t B); +static uint8_t LIN_DrvParityMake(uint8_t PID); +static uint8_t LIN_DrvParityCheck(uint8_t PID); +static void LIN_DrvHeaderHandle(uint8_t u8LinIndex, uint8_t u8ReceiveByte); +static uint8_t LIN_DrvMakeCheckSum(uint8_t u8LinIndex, uint8_t *pBuf, uint8_t u8Size, + uint8_t u8Pid); +static void LIN_DrvReceiveFrameData(uint8_t u8LinIndex, uint8_t u8ReceiveByte); +static void LIN_DrvSendFrameData(uint8_t u8LinIndex, uint8_t u8ReceiveByte); +static void LIN_DrvFrameHandle(uint8_t u8LinIndex); +static void LIN_DrvWakeupHandle(uint8_t u8LinIndex); + +/* ################################################################################## */ +/* ########################### Global Prototype Functions ########################### */ + +/* ################################################################################## */ +/* ################################ Local Functions ################################# */ + +/** + * @brief LIN instance generate baudrate value, include oversample value and sbr value. + */ +static LIN_StatusType LIN_DrvCalBaudrate(uint8_t u8LinIndex, uint32_t *u32OverSamp, + uint32_t *u32Sbr) +{ + LIN_StatusType tRetVal = LIN_STATUS_ERROR; + uint32_t u32SbrTemp; + uint32_t u32OverSampTemp; + uint32_t u32TempSmbDiff; + uint32_t u32SmbDiff; + uint32_t u32CalcSmb; + uint32_t u32OverSamp1; + uint32_t u32Sbr1; + uint32_t u32Smb; + + u32OverSamp1 = 4U; /* 4..32 */ + u32Smb = s_aLinConfig[u8LinIndex]->clockSrcFreq / s_aLinConfig[u8LinIndex]->baudRate; + + /* sbr = srcFreq/baudrate/oversamp */ + u32Sbr1 = (uint16_t)(u32Smb / (u32OverSamp1)); + u32CalcSmb = (u32OverSamp1) * (u32Sbr1); + + if (u32CalcSmb > u32Smb) + { + u32SmbDiff = u32CalcSmb - u32Smb; + } + else + { + u32SmbDiff = u32Smb - u32CalcSmb; + } + + if (u32SmbDiff != 0U) + { + + /* loop to find the best u32OverSamp1 value possible, one that generates minimum u32SmbDiff + * iterate through the rest of the supported values of u32OverSamp */ + for (u32OverSampTemp = 5U; u32OverSampTemp <= 32U; u32OverSampTemp++) + { + /* calculate the temporary u32Sbr value */ + u32SbrTemp = (uint32_t)(u32Smb / u32OverSampTemp); + /* calculate the baud rate based on the temporary u32OverSamp and u32Sbr values */ + u32CalcSmb = (uint32_t)(u32OverSampTemp * u32SbrTemp); + + if (u32CalcSmb > u32Smb) + { + u32TempSmbDiff = u32CalcSmb - u32Smb; + } + else + { + u32TempSmbDiff = u32Smb - u32CalcSmb; + } + + if (u32TempSmbDiff < u32SmbDiff) + { + u32SmbDiff = u32TempSmbDiff; + u32OverSamp1 = u32OverSampTemp; /* update and store the best u32OverSamp value calculated */ + u32Sbr1 = u32SbrTemp; /* update store the best u32Sbr value calculated */ + } + + /* when differ is 0U, break */ + if (u32SmbDiff == 0U) + { + break; + } + } + } + + /* check differ */ + if (u32SmbDiff == 0U) + { + tRetVal = LIN_STATUS_SUCCESS; + + /* out the calculated value */ + *u32Sbr = u32Sbr1; + *u32OverSamp = u32OverSamp1; + } + else + { + tRetVal = LIN_STATUS_ERROR; + } + + return tRetVal; +} + +/** + * @brief Check the node mode, slave or master. + */ +static LIN_NodeType LIN_DrvCheckMode(uint8_t u8LinIndex) { return s_aLinConfig[u8LinIndex]->nodeMode; } + +/** + * @brief Bit function. + */ +LOCAL_INLINE uint8_t BIT(uint8_t A, uint8_t B) { return (uint8_t)((A >> B) & 0x01U); } + +/** + * @brief Make parity value. + */ +static uint8_t LIN_DrvParityMake(uint8_t PID) +{ + uint8_t parity; + uint8_t retVal; + + parity = (uint8_t)((((0xFFU & BIT(PID, 0U)) ^ (0xFFU & BIT(PID, 1U)) ^ (0xFFU & BIT(PID, 2U)) ^ (0xFFU & BIT(PID, 4U))) << 6U) | + ((0xFFU ^ (BIT(PID, 1U)) ^ (0xFFU & BIT(PID, 3U)) ^ (0xFFU & BIT(PID, 4U)) ^ (0xFFU & BIT(PID, 5U))) << 7U)); + + /* Making parity bits */ + retVal = (uint8_t)(PID | parity); + + return retVal; +} + +/** + * @brief Check parity value. + */ +static uint8_t LIN_DrvParityCheck(uint8_t PID) +{ + uint8_t parity; + uint8_t retVal; + + parity = (uint8_t)((((0xFFU & BIT(PID, 0U)) ^ (0xFFU & BIT(PID, 1U)) ^ (0xFFU & BIT(PID, 2U)) ^ (0xFFU & BIT(PID, 4U))) << 6U) | + ((0xFFU ^ (BIT(PID, 1U)) ^ (0xFFU & BIT(PID, 3U)) ^ (0xFFU & BIT(PID, 4U)) ^ (0xFFU & BIT(PID, 5U))) << 7U)); + + /* If parity bits are incorrect */ + if ((PID & 0xC0U) != parity) + { + retVal = 0xFFU; + } + else + { + retVal = (uint8_t)(PID & 0x3FU); + } + + return retVal; +} + +/** + * @brief Handle the frame header step by step, break field, sync field and PID field. + */ +static void LIN_DrvHeaderHandle(uint8_t u8LinIndex, uint8_t u8ReceiveByte) +{ + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + /* Step 1: Handle the break field state. */ + if (FCUART_HWA_GetStatus(base, FCUART_STAT_LBKDIF)) + { + FCUART_HWA_ClearStatus(base, (uint32_t)FCUART_STAT_LBKDIF); + /* Disable the lin break detect interrupt and clean the status flag. */ + FCUART_HWA_SetLinBreakDetectInterrupt(base, false); + /* Disable lin detect feature, so the data can be stored to RX FIFO. */ + FCUART_HWA_SetLinBreakDetectEnable(base, false); + + /* In this state, maste need send sync field character 0x55U, slave need call callback fucntion.*/ + if (LIN_NODE_MASTER == LIN_DrvCheckMode(u8LinIndex)) + { + if (xferState->currentNodeState == LIN_NODE_STATE_SEND_BREAK_FIELD) + { + xferState->currentNodeState = LIN_NODE_STATE_SEND_PID; + xferState->isBusBusy = true; + + FCUART_HWA_SetData(base, 0x55U); + xferState->currentNodeState = LIN_NODE_STATE_RECV_SYNC; + } + } + else + { + xferState->isBusBusy = true; + xferState->currentEventId = LIN_RECV_BREAK_FIELD_OK; + /* call user's application. */ + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + /* Enter next state. */ + xferState->currentNodeState = LIN_NODE_STATE_RECV_SYNC; + } + } + /* Step 2: receive sync filed 0x55U. */ + else if (xferState->currentNodeState == LIN_NODE_STATE_RECV_SYNC) + { + /* If sync byte is 0x55U,transfer success, other failed, maybe baudrate error or protocol error. */ + if (0x55U == u8ReceiveByte) + { + xferState->currentEventId = LIN_SYNC_OK; + xferState->currentNodeState = LIN_NODE_STATE_RECV_PID; + + if (LIN_NODE_MASTER == LIN_DrvCheckMode(u8LinIndex)) + { + FCUART_HWA_SetData(base, (uint32_t)xferState->currentPid); + } + } + else + { + xferState->isBusBusy = false; + xferState->currentEventId = LIN_SYNC_ERROR; + + /* Inform user the transfer status. */ + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + + /* Go to IDLE state, start a new transfer. */ + LIN_DrvGoToIdleMode(u8LinIndex); + } + } + /* Step 3: receive and Check PID. */ + else if (xferState->currentNodeState == LIN_NODE_STATE_RECV_PID) + { + /* master node only check if the receive data is match current pid, then enter next state. */ + if (LIN_NODE_MASTER == LIN_DrvCheckMode(u8LinIndex)) + { + /* Update the xfer state */ + if (u8ReceiveByte == xferState->currentPid) + { + xferState->currentNodeState = LIN_NODE_STATE_RECV_DATA; + xferState->isBusBusy = false; + xferState->currentEventId = LIN_PID_OK; + } + else + { + xferState->currentNodeState = LIN_NODE_STATE_IDLE; + xferState->isBusBusy = false; + xferState->currentEventId = LIN_PID_ERROR; + } + + /* Inform user the transfer status. */ + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + } + else + { + xferState->currentId = LIN_DrvParityCheck(u8ReceiveByte); + xferState->currentPid = u8ReceiveByte; + + /* Update xfer state. */ + if (0xFFU == xferState->currentId) + { + xferState->currentNodeState = LIN_NODE_STATE_IDLE; + xferState->isBusBusy = false; + xferState->currentEventId = LIN_PID_ERROR; + } + else + { + xferState->currentNodeState = LIN_NODE_STATE_RECV_DATA; + xferState->isBusBusy = false; + xferState->currentEventId = LIN_PID_OK; + } + + /* Inform user the transfer status. */ + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + } + } + else + { + /* Misra check */ + } +} + + +/** + * @brief Make checksum byte + */ +static uint8_t LIN_DrvMakeCheckSum(uint8_t u8LinIndex, uint8_t *pBuf, uint8_t u8Size, uint8_t u8Pid) +{ + lin_config_t *pConfig = s_aLinConfig[u8LinIndex]; + uint16_t u16Checksum = 0U; + uint8_t u8Length = 0U; + + if ((pConfig->numOfClassicPID == 0U) || (pConfig->numOfClassicPID == 255U)) + { + if (pConfig->classicPID != NULL) + { + for (uint8_t i = 0U; i < pConfig->numOfClassicPID; i++) + { + if (u8Pid == pConfig->classicPID[i]) + { + u8Pid = 0U; + break; + } + } + } + } + + /* For PID is 0x3C (ID 0x3C) or 0x7D (ID 0x3D) or 0xFE (ID 0x3E) or 0xBF (ID 0x3F)*/ + if ((0x3CU == u8Pid) || (0x7DU == u8Pid) || (0xFEU == u8Pid) || (0xBFU == u8Pid)) + { + u8Pid = 0U; + } + + u16Checksum += u8Pid; + + for (u8Length = 0U; u8Length < u8Size; u8Length++) + { + u16Checksum += *pBuf; + pBuf++; + if (u16Checksum > 0xFFU) + { + u16Checksum -= 0xFFU; + } + } + + return ~(uint8_t)(u16Checksum); +} + +/** + * @brief receive frame data in IRQ handler. + */ +static void LIN_DrvReceiveFrameData(uint8_t u8LinIndex, uint8_t u8ReceiveByte) +{ + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + xferState->cntByte++; + + if (xferState->cntByte < xferState->rxSize) + { + *(xferState->rxBuff) = u8ReceiveByte; + xferState->rxBuff++; + } + /* Checksum data. */ + else if (xferState->cntByte == xferState->rxSize) + { + xferState->checkSum = u8ReceiveByte; + xferState->rxBuff -= (xferState->rxSize - 1U); + + /* Checksun compared. */ + if (xferState->checkSum == LIN_DrvMakeCheckSum(u8LinIndex, xferState->rxBuff, + xferState->rxSize - 1U, xferState->currentPid)) + { + xferState->currentNodeState = LIN_NODE_STATE_RECV_DATA_COMPLETED; + xferState->currentEventId = LIN_RX_COMPLETED; + } + else + { + xferState->currentEventId = LIN_CHECKSUM_ERROR; + } + + /* call user's application. */ + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + + /* Go to IDLE state, start a new transfer. */ + LIN_DrvGoToIdleMode(u8LinIndex); + } + /* Maybe error occurred. */ + else + { + /* MISRA-2012 check. */ + } +} + +/** + * @brief This API will send frame data, due to the LIN node will receive the byte sent by itself, + * we will also check the receive data while sending bytes. + */ +static void LIN_DrvSendFrameData(uint8_t u8LinIndex, uint8_t u8ReceiveByte) +{ + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + + if (xferState->cntByte < xferState->txSize) + { + /* The received byte should be the byte just send. */ + if (u8ReceiveByte != *(xferState->txBuff - 1)) + { + xferState->currentEventId = LIN_READBACK_ERROR; + + /* call user's application. */ + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + } + else + { + if (xferState->cntByte == (xferState->txSize - 1U)) + { + FCUART_HWA_SetData(base, (uint32_t)xferState->checkSum); + } + else + { + FCUART_HWA_SetData(base, (uint32_t) * (xferState->txBuff)); + } + + xferState->txBuff++; + xferState->cntByte++; + } + } + /* Last byte received, no need to send anything. */ + else if (xferState->cntByte == xferState->txSize) + { + if (u8ReceiveByte != xferState->checkSum) + { + xferState->currentEventId = LIN_READBACK_ERROR; + } + else + { + xferState->currentEventId = LIN_TX_COMPLETED; + } + + /* call user's application. */ + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + + /* Go to IDLE state, start a new transfer. */ + LIN_DrvGoToIdleMode(u8LinIndex); + } + else + { + /* MISRA Check. */ + } +} + +/** + * @brief Handle the frame data, sending or receiving frame data. + */ +static void LIN_DrvFrameHandle(uint8_t u8LinIndex) +{ + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + uint8_t u8ReceiveByte = 0U; + + if (FCUART_HWA_GetStatus(base, FCUART_STAT_RDRFF)) + { + u8ReceiveByte = FCUART_HWA_GetData(base); + } + + /* Handle node to recive frame data. */ + if (LIN_NODE_STATE_RECV_DATA == xferState->currentNodeState) + { + LIN_DrvReceiveFrameData(u8LinIndex, u8ReceiveByte); + } + /* Handle node to send frame data. */ + else if (LIN_NODE_STATE_SEND_DATA == xferState->currentNodeState) + { + LIN_DrvSendFrameData(u8LinIndex, u8ReceiveByte); + } + /* Handle header. */ + else + { + LIN_DrvHeaderHandle(u8LinIndex, u8ReceiveByte); + } +} + +/** + * @brief This API will handle wakeup signal, and calculate the value wakeup signal send. + * Actually, step 1, FCUART will wait a low level in RX pin, and than inverse the RX data + * while the rise edge is coming, another interrupt will be triggered, the time between this + * two interrupt is the wakeup time value. + */ +static void LIN_DrvWakeupHandle(uint8_t u8LinIndex) +{ + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + uint32_t s_wakeupTime = 0U; + + /* Clear status.*/ + FCUART_HWA_ClearStatus(base, FCUART_STAT_RPAEIF); + + /* Step 1, record the first receive active time. */ + if (false == FCUART_HWA_GetReceiveDataInverse(base)) + { + /* Call the uer time value call function. */ + if (NULL != s_aLinConfig[u8LinIndex]->getIntervalTimeValueCallback) + { + s_aLinConfig[u8LinIndex]->getIntervalTimeValueCallback(&s_wakeupTime); + } + + /* Chang the receive data inverse, and receive the next interrupt. */ + FCUART_HWA_SetReceiveDataInverse(base, true); + } + /* Step 2. calculate the wakeup time. */ + else + { + FCUART_HWA_SetReceiveDataInverse(base, false); + + /* Call the uer time value call function. */ + if (NULL != s_aLinConfig[u8LinIndex]->getIntervalTimeValueCallback) + { + s_aLinConfig[u8LinIndex]->getIntervalTimeValueCallback(&s_wakeupTime); + } + + if (150U < s_wakeupTime) + { + xferState->currentEventId = LIN_WAKEUP_SIGNAL; + + /* call user's application. */ + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + + /* Enter IDLE state to prepare next transfer. */ + LIN_DrvGoToIdleMode(u8LinIndex); + } + } +} + +/* ################################################################################## */ +/* ################################ Global Functions ################################ */ + +/** + * @brief Init the LIN instance for LIN network. This API will help initialize the FCUART to expect state, + * but will nots start the TX&RX function, if users want to start the LIN protocol transfer, please + * call the function LIN_DrvStart() after this API is called. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pConfig Configuration for LIN hardware, must not be null. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_USEED : The instance has been used, user should use another instance or de-initialize this instance + * firstly. + * - LIN_STATUS_ERROR : the baudrate has not been set successfully. + */ +LIN_StatusType LIN_DrvInit(uint8_t u8LinIndex, lin_config_t *pConfig) +{ + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + uint32_t u32BaudRegValue = 0U; + uint32_t u32CtrlRegValue = 0U; + uint32_t u32StatRegValue = 0U; + uint32_t u32Sbr = 0U; + uint32_t u32OverSamp = 0U; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + DEV_ASSERT(pConfig != NULL); + + /* Check the LIN instance used or not. */ + if (s_aInstanceUsed[u8LinIndex] == 1U) + { + tRetVal = LIN_STATUS_USEED; + } + else + { + s_aLinConfig[u8LinIndex] = pConfig; + + /* Reset the hardware LIN instance to expect state. */ + FCUART_HWA_SoftwareReset(base); + + /* Set BAUD register configuration: + * - calculate the baudrate generated value. + * - LIN break detect interrupt enable; + * - RX pin active edge disabled, for checking the wakeup signal; + * - Stop bit set to 1; + */ + tRetVal = LIN_DrvCalBaudrate(u8LinIndex, &u32OverSamp, &u32Sbr); + u32BaudRegValue |= FCUART_BAUD_OVR_SAMP(u32OverSamp - 1U) | FCUART_BAUD_BEDGE_SAMP( + 1U) | FCUART_BAUD_SBR(u32Sbr); + FCUART_HWA_SetBaud(base, u32BaudRegValue); + FCUART_HWA_SetLinBreakDetectInterrupt(base, true); + + /* Set LIN break send and detect to 13 bits minimum. If in slave node, only enable detect feature. */ + u32StatRegValue |= FCUART_STAT_BCGL(1U) | FCUART_STAT_LBKDE(0U); + FCUART_HWA_WriteClearSTAT(base, u32StatRegValue); + + /* Set CTRL register configuration: + * - Enable frame error interrupt; + * - Enable receive interrupt; + * - 8 bits transfer mode enabled; + * - Parity check mode disable; + */ + u32CtrlRegValue |= FCUART_CTRL_FEIE(1U) | FCUART_CTRL_RIE(1U) | FCUART_CTRL_BMSEL(0U) | FCUART_CTRL_PE(0U); + FCUART_HWA_SetCtrl(base, u32CtrlRegValue); + + /* Do not use the FIFO feature. the baudrate of LIN protocol is not too high, so do not use fifo feature. */ + FCUART_HWA_SetFifo(base, 0U); + + /* FIFO watermark set to 0. */ + FCUART_HWA_SetWaterMark(base, 0U); + + /* Update the instance used state. */ + s_aInstanceUsed[u8LinIndex] = 1U; + } + + return tRetVal; +} + +/** + * @brief De-Init the LIN instance used by LIN network. + * This API will help disable the fcuart interrupts and stop the TX/RX transfer. + * + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : The instance has not been initialized. + */ +LIN_StatusType LIN_DrvDeInit(uint8_t u8LinIndex) +{ + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + + /* Instance has not been initialized, no need to do anything */ + if (s_aInstanceUsed[u8LinIndex] == 0U) + { + tRetVal = LIN_STATUS_NOT_INIT; + } + else + { + /* Check if still bytes need to be send or receive. wait the protocol is not busy. */ + while (xferState->isBusBusy) + { + } + + /* Update LIN instance to initialize state. */ + s_aLinConfig[u8LinIndex] = NULL; + s_aLinXfer[u8LinIndex] = NULL; + s_aInstanceUsed[u8LinIndex] = 0U; + + /* Stop TX/TX function and FCUART instance. */ + FCUART_HWA_SetTxTransfer(base, false); + FCUART_HWA_SetRxTransfer(base, false); + + /* Reset the FCUART instance. */ + FCUART_HWA_SoftwareReset(base); + } + + return tRetVal; +} + +/** + * @brief Help users get the default configuration of LIN node. users should provide the configuration structure + * in app code, and transfer the ptr address to driver code. uses can also set this parameters in the application code + * as designed. + * + * @param u8NodeMode LIN node mode select, 0 for slave mode and 1 for master mode. + * @param pConfig default configuration for LIN node, must not be null. + */ +void LIN_DrvGetDefaultConfig(LIN_NodeType eNodeMode, lin_config_t *pConfig) +{ + /* Check NUll ptr for bus error. */ + DEV_ASSERT(pConfig != NULL); + + pConfig->nodeMode = eNodeMode; /*!< Node mode as Master node or Slave node. 0: slave 1: master */ + pConfig->baudRate = 19200U; /*!< baudrate configurations for LIN protocol. */ + pConfig->getIntervalTimeValueCallback = NULL; /*!< Callback function to get time interval in nanoseconds */ + pConfig->classicPID = NULL; /*!< List of PIDs use classic checksum */ + pConfig->numOfClassicPID = 0U; /*!< Number of PIDs use classic checksum */ +} + +/** + * @brief Start LIN node transfer, this API should be called after LIN hardware has been initialized, and must + * be called before starting a LIN node transfer. Users should provide a tansfer structure for storing the + * transfer state, ant LIN node state changed will be stored to this xfer state. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pXferState Transfer state structure which will help store the trasnfer state. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_PARAM_ERROR: the parameter setting maybe not correct, maybe instance has bot been initialized. + */ +LIN_StatusType LIN_DrvStart(uint8_t u8LinIndex, lin_xfer_state_t *pXferState) +{ + LIN_StatusType tRetVal = LIN_STATUS_ERROR; + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + + DEV_ASSERT(pXferState != NULL); + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + + /* If instance has not been intialized, inform users with the error state. */ + if (0U == s_aInstanceUsed[u8LinIndex]) + { + tRetVal = LIN_STATUS_PARAM_ERROR; + } + else + { + /* Register transfer ptr. */ + s_aLinXfer[u8LinIndex] = pXferState; + + /* Initialize the xfer state of LIN transfer. */ + pXferState->isTxBusy = false; + pXferState->isRxBusy = false; + pXferState->isBusBusy = false; + pXferState->isRxBlocking = false; + pXferState->isTxBlocking = false; + pXferState->timeoutCounterFlag = false; + pXferState->timeoutCounter = 0U; + pXferState->currentNodeState = LIN_NODE_STATE_IDLE; + pXferState->currentEventId = LIN_NO_EVENT; + + FCUART_HWA_SetTxTransfer(base, true); + FCUART_HWA_SetRxTransfer(base, true); + { + /*TOBE CHECKED*/ + uint32_t u32Temp; + u32Temp = FCUART_HWA_GetSTAT(base); + u32Temp |= FCUART_STAT_M1F | FCUART_STAT_M0F | FCUART_STAT_FEF; + FCUART_HWA_ClearStatus(base, u32Temp); + FCUART_HWA_GetData(base); + } + + /* Slave will enter the IDEL state, and listening the protocol all time, waiting for a break files. */ + if (LIN_NODE_SLAVE == s_aLinConfig[u8LinIndex]->nodeMode) + { + /* Start hardware. */ + FCUART_HWA_SetLinBreakDetectEnable(base, true); + FCUART_HWA_SetLinBreakDetectInterrupt(base, true); + } + + tRetVal = LIN_STATUS_SUCCESS; + } + + return tRetVal; +} + +/** + * @brief This function will help install callback function that used by application code. + * users can handle some needed operations in driver code or get some important states. + * or uses can also setting this in transfer state structure. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param callback user's callbak function that need be called in driver code. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : The instance required has bot been initialized. + */ +LIN_StatusType LIN_DrvInstallUserCallback(uint8_t u8LinIndex, lin_callback_t callback) +{ + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + LIN_StatusType tRetVal = LIN_STATUS_ERROR; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + if (NULL == xferState) + { + tRetVal = LIN_STATUS_NOT_INIT; + } + else + { + xferState->Callback = callback; + tRetVal = LIN_STATUS_SUCCESS; + } + + return tRetVal; +} + +/** + * @brief This function will help users send a header in master node which will help start a new + * frame transfer. please do not used this API will LIN instance is configured as slave node. + * This API will make a parity ID, and only send a break field to the protocol, all the other + * filed like sync filed and pid byte will be handled in FCUART IRQHandler. more details can + * refer to IRQ routine. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param u8Id The ID data that useds need to send in header. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required has not been intialized. + * - LIN_STATUS_UNSUPPORTED : Current node is slave not, could not send header to protocol. + * - LIN_STATUS_BUSY : Bus busy which means node is sending or receiving another frame. + */ +LIN_StatusType LIN_DrvSendHeader(uint8_t u8LinIndex, uint8_t u8Id) +{ + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + DEV_ASSERT(xferState != NULL); + + /* Check node state. */ + if (xferState->currentNodeState == LIN_NODE_STATE_UNINIT) + { + tRetVal = LIN_STATUS_NOT_INIT; + } + /* Slave node can not send header. */ + else if (s_aLinConfig[u8LinIndex]->nodeMode == LIN_NODE_SLAVE) + { + tRetVal = LIN_STATUS_UNSUPPORTED; + } + else + { + if (xferState->isBusBusy == true) + { + tRetVal = LIN_STATUS_BUSY; + } + else + { + /* Update node state. */ + xferState->currentId = u8Id; + xferState->currentPid = LIN_DrvParityMake(u8Id); + xferState->currentEventId = LIN_NO_EVENT; + xferState->currentNodeState = LIN_NODE_STATE_SEND_BREAK_FIELD; + xferState->isBusBusy = false; + + /* Start hardware. */ + FCUART_HWA_SetLinBreakDetectEnable(base, true); + FCUART_HWA_SetLinBreakDetectInterrupt(base, true); + + /* Send a break filed to protocol. */ + FCUART_HWA_SendBreakField(base); + } + } + + return tRetVal; +} + +/** + * @brief This API will help users send a frame data through LIN protocol, and will return only when + * all frame data has been sent to the protocol, or while timeout occurred, so please configure + * the u32TimeOut parameter as needed. And currentlyt this API has not implement the OS feature, + * so do not call this API in interrupt routine, otherwise, routine maybe halted by this API. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pTxBuf TX buffer whihc will be sent to protocol, MUST NOT BE NULL. + * @param u8Length bytes lengths in TX buffer. + * @param u32TimeOut Timeout value, 0 indicates timeout feature is not used, in unit of millieconds. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required has not been initialized. + * - LIN_STATUS_BUSY : Bus busy, node is transfer state. + */ +LIN_StatusType LIN_DrvSendFrameBlocking(uint8_t u8LinIndex, uint8_t *pTxBuf, uint8_t u8Length, + uint32_t u32TimeOut) +{ + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + DEV_ASSERT((NULL != pTxBuf) && (0U != u8Length)); + DEV_ASSERT(xferState != NULL); + + /* Check node state. */ + if (xferState->currentNodeState == LIN_NODE_STATE_UNINIT) + { + tRetVal = LIN_STATUS_NOT_INIT; + } + else + { + if (xferState->isBusBusy) + { + tRetVal = LIN_STATUS_BUSY; + } + else + { + xferState->currentNodeState = LIN_NODE_STATE_SEND_DATA; + xferState->currentEventId = LIN_NO_EVENT; + + xferState->txBuff = pTxBuf; + xferState->txSize = u8Length + 1U; + xferState->cntByte = 0U; + xferState->checkSum = LIN_DrvMakeCheckSum(u8LinIndex, pTxBuf, u8Length, + xferState->currentPid); + xferState->isTxBusy = true; + xferState->isBusBusy = true; + xferState->isTxBlocking = true; + xferState->timeoutCounter = u32TimeOut; + xferState->timeoutCounterFlag = false; + + FCUART_HWA_SetLinBreakDetectEnable(base, false); + FCUART_HWA_SetData(base, (uint32_t) * (xferState->txBuff)); + + xferState->txBuff++; + xferState->cntByte++; + + /* Waiting for teansfer complete. */ + while (xferState->isTxBusy == true) + { + if (xferState->timeoutCounterFlag == true) + { + tRetVal = LIN_STATUS_TIMEOUT; + break; + } + } + + LIN_DrvGoToIdleMode(u8LinIndex); + } + } + + return tRetVal; +} + +/** + * @brief This API will help users send a frame data through LIN protocol, this API will return immediately. + * data will be stored in txbuffer, users can check the transmit status while data is sending. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pTxBuf TX buffer whihc will be sent to protocol, MUST NOT BE NULL. + * @param u8Length bytes lengths in TX buffer. + * @param u32TimeOut Timeout value, 0 indicates timeout feature is not used, in unit of millieconds. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required has not been initialized. + * - LIN_STATUS_BUSY : Bus busy, node is transfer state. + */ +LIN_StatusType LIN_DrvSendFrameNonBlocking(uint8_t u8LinIndex, uint8_t *pTxBuf, uint8_t u8Length) +{ + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + DEV_ASSERT((NULL != pTxBuf) && (0U != u8Length)); + DEV_ASSERT(xferState != NULL); + + /* Check node state. */ + if (xferState->currentNodeState == LIN_NODE_STATE_UNINIT) + { + tRetVal = LIN_STATUS_NOT_INIT; + } + else + { + if (xferState->isBusBusy) + { + tRetVal = LIN_STATUS_BUSY; + } + else + { + xferState->currentNodeState = LIN_NODE_STATE_SEND_DATA; + xferState->currentEventId = LIN_NO_EVENT; + + xferState->txBuff = pTxBuf; + xferState->txSize = u8Length + 1U; + xferState->cntByte = 0U; + xferState->checkSum = LIN_DrvMakeCheckSum(u8LinIndex, pTxBuf, u8Length, xferState->currentPid); + xferState->isTxBusy = true; + xferState->isBusBusy = true; + + FCUART_HWA_SetLinBreakDetectEnable(base, false); + FCUART_HWA_SetData(base, (uint32_t) * (xferState->txBuff)); + + xferState->txBuff++; + xferState->cntByte++; + } + } + + return tRetVal; +} + +/** + * @brief This API will help users get the LIN transfer status while data is sending. and will also + * help user get remainning byte in transfer still need sending in buffer. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pRemainBytes Address to be stored the remain byte value, should not be NULL. + * @return operation status: + * - LIN_STATUS_TIMEOUT : node transfer timeout occurred. + * - LIN_STATUS_SUCCESS : transfer complete. + * - LIN_STATUS_BUSY : transfer is going + */ +LIN_StatusType LIN_DrvGetTransmitStatus(uint8_t u8LinIndex, uint8_t *pRemainBytes) +{ + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + /* Return the remaining byte inlcude checksun byte. */ + *pRemainBytes = xferState->txSize - xferState->cntByte; + + /* Check LIN node status. */ + if (xferState->timeoutCounterFlag == true) + { + tRetVal = LIN_STATUS_TIMEOUT; + } + else if (xferState->isTxBusy == true) + { + tRetVal = LIN_STATUS_BUSY; + } + else + { + } + + return tRetVal; +} + +/** + * @brief This API will help users receive frame data through LIN protocol, this API will return only when + * all frame data has been received from the protocol, or while timeout occurred, so please configure + * the u32TimeOut parameter as needed. And currently, this API has not implement the OS feature, + * so do not call this API in interrupt routine, otherwise, routine maybe halted by this API. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pRxBuf RX buffer which will be received from protocol, MUST not be NULL. + * @param u8Length bytes lengths should be received. + * @param u32TimeOut Timeout value, 0 indicates timeout feature is not used, in millieconds. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance has not been initialized + * - LIN_STATUS_BUSY : Bus in busy state, need wait bus idle. + * - LIN_STATUS_TIMEOUT : Timeout occurred, data received may not successful. + */ +LIN_StatusType LIN_DrvReceiveFrameBlocking(uint8_t u8LinIndex, uint8_t *pRxBuf, uint8_t u8Length, + uint32_t u32TimeOut) +{ + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + DEV_ASSERT((NULL != pRxBuf) && (0U != u8Length)); + DEV_ASSERT(xferState != NULL); + + /* Check node state. */ + if (xferState->currentNodeState == LIN_NODE_STATE_UNINIT) + { + tRetVal = LIN_STATUS_NOT_INIT; + } + else + { + if (xferState->isBusBusy) + { + tRetVal = LIN_STATUS_BUSY; + } + else + { + xferState->currentNodeState = LIN_NODE_STATE_RECV_DATA; + xferState->currentEventId = LIN_NO_EVENT; + + xferState->rxBuff = pRxBuf; + xferState->rxSize = u8Length + 1U; + xferState->cntByte = 0U; + xferState->isRxBusy = true; + xferState->isBusBusy = true; + xferState->isRxBlocking = true; + xferState->timeoutCounter = u32TimeOut; + xferState->timeoutCounterFlag = false; + + /* Waiting for complete. */ + while (xferState->isRxBusy == true) + { + if (true == xferState->timeoutCounterFlag) + { + tRetVal = LIN_STATUS_TIMEOUT; + break; + } + } + + FCUART_HWA_SetLinBreakDetectEnable(base, false); + } + } + + return tRetVal; +} + +/** + * @brief This API will help users receive frame data through LIN protocol, this API will return immediately. + * data will be stored in rxbuffer, users can check the receive status while using this API. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pRxBuf RX buffer which will be received from protocol, MUST not be NULL. + * @param u8Length bytes lengths should be received. + * @param u32TimeOut Timeout value, 0 indicates timeout feature is not used, in millieconds. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance has not been initialized + * - LIN_STATUS_BUSY : Bus in busy state, need wait bus idle. + * - LIN_STATUS_TIMEOUT : Timeout occurred, data received may not successful. + */ +LIN_StatusType LIN_DrvReceiveFrameNonBlocking(uint8_t u8LinIndex, uint8_t *pRxBuf, uint8_t u8Length) +{ + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + DEV_ASSERT((NULL != pRxBuf) && (0U != u8Length)); + DEV_ASSERT(xferState != NULL); + + /* Check node state. */ + if (xferState->currentNodeState == LIN_NODE_STATE_UNINIT) + { + tRetVal = LIN_STATUS_NOT_INIT; + } + else + { + if (xferState->isBusBusy) + { + tRetVal = LIN_STATUS_BUSY; + } + else + { + xferState->currentNodeState = LIN_NODE_STATE_RECV_DATA; + xferState->currentEventId = LIN_NO_EVENT; + + xferState->rxBuff = pRxBuf; + xferState->rxSize = u8Length + 1U; + xferState->cntByte = 0U; + xferState->isRxBusy = true; + xferState->isBusBusy = true; + + FCUART_HWA_SetLinBreakDetectEnable(base, false); + } + } + + return tRetVal; +} + +/** + * @brief This API will help users get the LIN transfer status while data is receiving. and will also + * help user get remainning byte in transfer still need receiving in buffer. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param pRemainBytes Address to be stored the remain byte value, should not be NULL. + * @return operation status: + * - LIN_STATUS_TIMEOUT : node transfer timeout occurred. + * - LIN_STATUS_SUCCESS : transfer complete. + * - LIN_STATUS_BUSY : transfer is going, could read the remain byte in pRemainBytes. + */ +LIN_StatusType LIN_DrvGetReceiveStatus(uint8_t u8LinIndex, uint8_t *pRemainBytes) +{ + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + + /* Return the remaining byte inlcude checksun byte. */ + *pRemainBytes = xferState->rxSize - xferState->cntByte; + + if (xferState->timeoutCounterFlag == true) + { + tRetVal = LIN_STATUS_TIMEOUT; + } + else if (xferState->isRxBusy == true) + { + tRetVal = LIN_STATUS_BUSY; + } + else + { + } + return tRetVal; +} + +/** + * @brief Abort transfer both sending or receiving data, actually, call this APU will enter IDLE state. + * will stop end and receive even data transfer is on going. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + */ +LIN_StatusType LIN_DrvAbortTransfer(uint8_t u8LinIndex) +{ + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + + /* Update the LIN state to IDLE state directly. */ + tRetVal = LIN_DrvGoToIdleMode(u8LinIndex); + + return tRetVal; +} + +/** + * @brief This API should be called while no data is transferring, once this API is called, node will + * enter sleep mode, TX/RX and interrupts will also be disabled, and node will wait a wakeup signal + * on the protocol. This API will enable receive active interrupt, once a wakeup signal triggered, + * routine will entern uart IRQHandler to handle this case, and then wakeup the LIN node. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + */ +LIN_StatusType LIN_DrvGoToSleepMode(uint8_t u8LinIndex) +{ + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + + /* Update software status. */ + xferState->currentEventId = LIN_NO_EVENT; + xferState->currentNodeState = LIN_NODE_STATE_SLEEP_MODE; + xferState->isBusBusy = false; + xferState->isRxBusy = false; + xferState->isTxBusy = false; + + /* Disable all enabled interrupt except receive active interrupt. */ + FCUART_HWA_SetLinBreakDetectEnable(base, true); + FCUART_HWA_SetLinBreakDetectInterrupt(base, false); + FCUART_HWA_DisableErrorInterrupt(base); + FCUART_HWA_DisableReceiveInterrupt(base); + FCUART_HWA_SetReceiveActiveInterrupt(base, true); + + return LIN_STATUS_SUCCESS; +} + +/** + * @brief THis API will help confgure the mode into IDLE state. In IDLE state, node will enable receive interrupt and break + * field detect interrupt, slave node will wait the break field from master node, master node will prepare to send a + * new break filed to start a new frame. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + */ +LIN_StatusType LIN_DrvGoToIdleMode(uint8_t u8LinIndex) +{ + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + + /* Update software status. */ + xferState->cntByte = 0U; + xferState->txSize = 0U; + xferState->rxSize = 0U; + xferState->isBusBusy = false; + xferState->isRxBusy = false; + xferState->isTxBusy = false; + xferState->isTxBlocking = false; + xferState->isRxBlocking = false; + xferState->currentId = 0U; + xferState->currentPid = 0U; + xferState->currentEventId = LIN_NO_EVENT; + xferState->currentNodeState = LIN_NODE_STATE_IDLE; + xferState->timeoutCounter = 0U; + xferState->timeoutCounterFlag = false; + + /* Update hardware configration. + * 1. Enable LIN break detect interrupr; + * 2. Enable frame error interrupt. + * 3. Enable receive interrupt; + */ + FCUART_HWA_WriteClearSTAT(base, FCUART_STAT_LBKDIF | FCUART_STAT_RPAEIF | FCUART_STAT_RORF_MASK | FCUART_STAT_NF_MASK | FCUART_STAT_FEF_MASK | FCUART_STAT_PEF_MASK); + FCUART_HWA_SetLinBreakDetectEnable(base, true); + FCUART_HWA_SetLinBreakDetectInterrupt(base, true); + FCUART_HWA_EnableErrorInterrupt(base); + FCUART_HWA_EnableReceiveInterrupt(base); + FCUART_HWA_SetReceiveActiveInterrupt(base, false); + FCUART_HWA_SetReceiveDataInverse(base, false); + + return LIN_STATUS_SUCCESS; +} + +/** + * @brief Sending a wakeup signal to the protocol, all LIN network nodes receive this signal will + * wakeup from sleep mode. Actually, the master will send a character which will cause a 150us + * larger active level to the protocol. while receiving this signal, LIN node will wake up + * from sleep mode. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required is not initialized. + * - LIN_STATUS_BUSY :LIN node state is not correct, need update state firstly. + */ +LIN_StatusType LIN_DrvSendWakeupSignal(uint8_t u8LinIndex) +{ + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + DEV_ASSERT(xferState != NULL); + + /* Check node state. */ + if (xferState->currentNodeState == LIN_NODE_STATE_UNINIT) + { + tRetVal = LIN_STATUS_NOT_INIT; + } + else + { + if (xferState->isBusBusy == true) + { + tRetVal = LIN_STATUS_BUSY; + } + else + { + if (s_aLinConfig[u8LinIndex]->baudRate > 10000U) + { + /* Wakeup signal will be range from 400us to 800us depend on baudrate, 0x80U */ + FCUART_HWA_SetData(base, 0x00U); + } + else + { + /* Wakeup signal will be range from 400us to 4ms depend on baudrate, 0xF8U */ + FCUART_HWA_SetData(base, 0xF8U); + } + + tRetVal = LIN_STATUS_SUCCESS; + } + } + + return tRetVal; +} + +/** + * @brief Get the LIN node state. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return the node current state, refer to @lin_node_state_t + */ +lin_node_state_t LIN_DrvGetNodeState(uint8_t u8LinIndex) +{ + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + DEV_ASSERT(s_aLinXfer[u8LinIndex] != NULL); + + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + return xferState->currentNodeState; +} + +/** + * @brief This API should be called by user's application code, and the timeout periods should be 1ms once. + * Better to provide a timer IRQhandler to call this APIs 1ms onces. internal timeout feature will + * use this API t o handle the time counter. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + */ +LIN_StatusType LIN_DrvTimeOutService(uint8_t u8LinIndex) +{ + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + + if ((LIN_NODE_STATE_SEND_DATA == (xferState->currentNodeState)) || (LIN_NODE_STATE_RECV_DATA == (xferState->currentNodeState))) + { + /* time counter down to 0, timeout occurred. */ + if (0U == xferState->timeoutCounter) + { + xferState->timeoutCounterFlag = true; + + /* If send data blocking feature is enabled. anc callback is not NULL. */ + xferState->currentEventId = LIN_TIMEOUT; + + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + + tRetVal = LIN_DrvGoToIdleMode(u8LinIndex); + } + else + { + xferState->timeoutCounter--; + } + } + + return tRetVal; +} + +/** + * @brief This API will help users set the timeout counter with one API, users should use this feature with + * LIN_DrvTimeOutService() called every fixed time. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @param u32TimeOutValue Timeout value. + * @return operation status: + * - LIN_STATUS_SUCCESS : operation is successfully. + * - LIN_STATUS_NOT_INIT : Instance required is not initialized. + */ +LIN_StatusType LIN_DrvSetTimeOutCounter(uint8_t u8LinIndex, uint32_t u32TimeOutValue) +{ + LIN_StatusType tRetVal = LIN_STATUS_SUCCESS; + + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + if (NULL == xferState) + { + tRetVal = LIN_STATUS_NOT_INIT; + } + else + { + xferState->timeoutCounterFlag = false; + xferState->timeoutCounter = u32TimeOutValue; + } + + return tRetVal; +} + +/** + * @brief This API will help users get the Node timeout flag status. + * + * @param u8LinIndex LIN hardware instance, 0U... + * @return true for timeout occurred, false indicate no timeout. + */ +bool LIN_DrvGetTimeOutFlag(uint8_t u8LinIndex) +{ + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + DEV_ASSERT(NULL != s_aLinXfer[u8LinIndex]); + + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + return xferState->timeoutCounterFlag; +} + +/** + * @brief This is LIN IRQ routine code, uses should call this in the FCUART IRQhandler code. please must implement + * the feature in application code. + * + * @param u8LinIndex LIN hardware instance, 0U... + */ +void LIN_DrvIRQHandler(uint8_t u8LinIndex) +{ + DEV_ASSERT(u8LinIndex < LIN_INSTANCE_NUM); + + FCUART_Type *base = s_aFCUART_InstanceTable[u8LinIndex]; + lin_xfer_state_t *xferState = s_aLinXfer[u8LinIndex]; + + /* Handle the wakeup feature by protocol. */ + if (true == FCUART_HWA_GetReceiveActiveInterrupt(base)) + { + if (FCUART_HWA_GetStatus(base, FCUART_STAT_RPAEIF)) + { + LIN_DrvWakeupHandle(u8LinIndex); + } + } + /* Data or lin break detect has been received from protocol. */ + else if (FCUART_HWA_GetStatus(base, (FCUART_StatType)(FCUART_STAT_LBKDIF | FCUART_STAT_RDRFF))) + { + LIN_DrvFrameHandle(u8LinIndex); + } + /* Handle error status. */ + else + { + if (FCUART_HWA_GetStatus(base, FCUART_STAT_RORF)) + { + xferState->currentEventId = LIN_RX_OVERRUN; + } + else + { + xferState->currentEventId = LIN_FRAME_ERROR; + } + + FCUART_HWA_WriteClearSTAT(base, FCUART_STAT_RORF_MASK | FCUART_STAT_NF_MASK | FCUART_STAT_FEF_MASK | FCUART_STAT_PEF_MASK); + + if (NULL != xferState->Callback) + { + xferState->Callback(u8LinIndex, xferState); + } + + /* Error occurred, enater IDLE state. */ + LIN_DrvGoToIdleMode(u8LinIndex); + } +} diff --git a/Src/fc7xxx_driver_lu.c b/Src/fc7xxx_driver_lu.c new file mode 100644 index 0000000..616ec93 --- /dev/null +++ b/Src/fc7xxx_driver_lu.c @@ -0,0 +1,184 @@ +/** + * @file fc7xxx_driver_lu.c + * @author Flagchip0103 + * @brief FC7xxx LU driver type definition and API + * @version 0.1.0 + * @date 2023-12-19 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2023-12-19 Flagchip0103 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_lu.h" + +/** + * @brief Initialize Lu instance + * + * @param pInitStruct Lu initialization structure + * @return LU return type + */ +LU_StatusType LU_Init(const LU_InitType *const pInitStruct) +{ + uint32_t u32TempReg, u32TempCfg; + LU_StatusType eRet = LU_STATUS_SUCCESS; + LU_Type* pLu = LU; + + DEV_ASSERT(NULL_PTR != pInitStruct); + + /* set AOI0 value */ + LU_HWA_ConfigAOI0(pLu, pInitStruct->eLgNum, 0U); + /* set AOI1 value */ + LU_HWA_ConfigAOI1(pLu, pInitStruct->eLgNum, 0U); + /* set CTRL value */ + LU_HWA_ConfigCtrl(pLu, pInitStruct->eLgNum, 0U); + /* set FILT value */ + LU_HWA_ConfigFilter(pLu, pInitStruct->eLgNum, 0U); + + u32TempCfg = (uint32_t)0U | + LU_AOI_IN_CFG(LU_AOI_IN_N_A, pInitStruct->tAoi0Config.tIn0Config.eInNACfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_B, pInitStruct->tAoi0Config.tIn0Config.eInNBCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_C, pInitStruct->tAoi0Config.tIn0Config.eInNCCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_D, pInitStruct->tAoi0Config.tIn0Config.eInNDCfg); + u32TempReg = (uint32_t)0U | LU_AOI_IN_N_CFG(LU_AOI_IN_0, u32TempCfg); + + u32TempCfg = (uint32_t)0U | + LU_AOI_IN_CFG(LU_AOI_IN_N_A, pInitStruct->tAoi0Config.tIn1Config.eInNACfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_B, pInitStruct->tAoi0Config.tIn1Config.eInNBCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_C, pInitStruct->tAoi0Config.tIn1Config.eInNCCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_D, pInitStruct->tAoi0Config.tIn1Config.eInNDCfg); + u32TempReg |= LU_AOI_IN_N_CFG(LU_AOI_IN_1, u32TempCfg); + + u32TempCfg = (uint32_t)0U | + LU_AOI_IN_CFG(LU_AOI_IN_N_A, pInitStruct->tAoi0Config.tIn2Config.eInNACfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_B, pInitStruct->tAoi0Config.tIn2Config.eInNBCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_C, pInitStruct->tAoi0Config.tIn2Config.eInNCCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_D, pInitStruct->tAoi0Config.tIn2Config.eInNDCfg); + u32TempReg |= LU_AOI_IN_N_CFG(LU_AOI_IN_2, u32TempCfg); + + u32TempCfg = (uint32_t)0U | + LU_AOI_IN_CFG(LU_AOI_IN_N_A, pInitStruct->tAoi0Config.tIn3Config.eInNACfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_B, pInitStruct->tAoi0Config.tIn3Config.eInNBCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_C, pInitStruct->tAoi0Config.tIn3Config.eInNCCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_D, pInitStruct->tAoi0Config.tIn3Config.eInNDCfg); + u32TempReg |= LU_AOI_IN_N_CFG(LU_AOI_IN_3, u32TempCfg); + /* set AOI0 value */ + LU_HWA_ConfigAOI0(pLu, pInitStruct->eLgNum, u32TempReg); + + u32TempCfg = (uint32_t)0U | + LU_AOI_IN_CFG(LU_AOI_IN_N_A, pInitStruct->tAoi1Config.tIn0Config.eInNACfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_B, pInitStruct->tAoi1Config.tIn0Config.eInNBCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_C, pInitStruct->tAoi1Config.tIn0Config.eInNCCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_D, pInitStruct->tAoi1Config.tIn0Config.eInNDCfg); + u32TempReg = (uint32_t)0U | LU_AOI_IN_N_CFG(LU_AOI_IN_0, u32TempCfg); + + u32TempCfg = (uint32_t)0U | + LU_AOI_IN_CFG(LU_AOI_IN_N_A, pInitStruct->tAoi1Config.tIn1Config.eInNACfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_B, pInitStruct->tAoi1Config.tIn1Config.eInNBCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_C, pInitStruct->tAoi1Config.tIn1Config.eInNCCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_D, pInitStruct->tAoi1Config.tIn1Config.eInNDCfg); + u32TempReg |= LU_AOI_IN_N_CFG(LU_AOI_IN_1, u32TempCfg); + + u32TempCfg = (uint32_t)0U | + LU_AOI_IN_CFG(LU_AOI_IN_N_A, pInitStruct->tAoi1Config.tIn2Config.eInNACfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_B, pInitStruct->tAoi1Config.tIn2Config.eInNBCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_C, pInitStruct->tAoi1Config.tIn2Config.eInNCCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_D, pInitStruct->tAoi1Config.tIn2Config.eInNDCfg); + u32TempReg |= LU_AOI_IN_N_CFG(LU_AOI_IN_2, u32TempCfg); + + u32TempCfg = (uint32_t)0U | + LU_AOI_IN_CFG(LU_AOI_IN_N_A, pInitStruct->tAoi1Config.tIn3Config.eInNACfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_B, pInitStruct->tAoi1Config.tIn3Config.eInNBCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_C, pInitStruct->tAoi1Config.tIn3Config.eInNCCfg) | + LU_AOI_IN_CFG(LU_AOI_IN_N_D, pInitStruct->tAoi1Config.tIn3Config.eInNDCfg); + u32TempReg |= LU_AOI_IN_N_CFG(LU_AOI_IN_3, u32TempCfg); + /* set AOI1 value */ + LU_HWA_ConfigAOI1(pLu, pInitStruct->eLgNum, u32TempReg); + + /* force bypass mode */ + LU_HWA_SetLgBypassControl(pLu, pInitStruct->eLgNum, pInitStruct->eAoiMode); + /* set Flip-Flop mode configure */ + LU_HWA_SetLgFlipFlopMode(pLu, pInitStruct->eLgNum, pInitStruct->eFFMode); + u32TempCfg = 0U; + if (pInitStruct->tSyncCtrl.bInputNA) + { + u32TempCfg |= LU_SYNC_CONTROL_INPUT_N(1U, LU_INPUT_N_A); + } + if (pInitStruct->tSyncCtrl.bInputNB) + { + u32TempCfg |= LU_SYNC_CONTROL_INPUT_N(1U, LU_INPUT_N_B); + } + if (pInitStruct->tSyncCtrl.bInputNC) + { + u32TempCfg |= LU_SYNC_CONTROL_INPUT_N(1U, LU_INPUT_N_C); + } + if (pInitStruct->tSyncCtrl.bInputND) + { + u32TempCfg |= LU_SYNC_CONTROL_INPUT_N(1U, LU_INPUT_N_D); + } + /* set LG inputs synchronous control */ + LU_HWA_SetLgInputsSyncCtrl(pLu, pInitStruct->eLgNum, u32TempCfg); + + if (LU_JKFF_MODE == pInitStruct->eFFMode) + { + /* set LG output feedback override control */ + LU_HWA_SetLgFeedbackOverrideCtrl(pLu, pInitStruct->eLgNum, pInitStruct->eFbMode); + } + + if (LU_OUTPUT_INIT_DISABLE > pInitStruct->eFFInitValue) + { + if (LU_OUTPUT_INIT_ONE == pInitStruct->eFFInitValue) + { + /* Configure the output of flip-flop as "1" */ + LU_HWA_ConfigFlipFlopTo1(pLu, pInitStruct->eLgNum); + } + else + { + /* Configure the output of flip-flop as "0" */ + LU_HWA_ConfigFlipFlopTo0(pLu, pInitStruct->eLgNum); + } + /* Flip-Flop initial output enable control */ + LU_HWA_EnableControlFlipFlopInitOutput(pLu, pInitStruct->eLgNum); + } + + /* set input filter sample count for AOI0 */ + LU_HWA_SetAOI0InputFilterSampleCount(pLu, pInitStruct->eLgNum, (uint32_t)pInitStruct->u8Aoi0FiltCnt); + /* set input filter sample period for AOI0 */ + LU_HWA_SetAOI0InputFilterSamplePeriod(pLu, pInitStruct->eLgNum, (uint32_t)pInitStruct->u8Aoi0Period); + /* set input filter sample count for AOI1 */ + LU_HWA_SetAOI1InputFilterSampleCount(pLu, pInitStruct->eLgNum, (uint32_t)pInitStruct->u8Aoi1FiltCnt); + /* set input filter sample period for AOI0 */ + LU_HWA_SetAOI1InputFilterSamplePeriod(pLu, pInitStruct->eLgNum, (uint32_t)pInitStruct->u8Aoi1Period); + + return eRet; +} + +/** + * @brief De-initialize Lu instance + * @param eLu LU instance + */ +void LU_Deinit() +{ + uint8_t u8Index; + LU_Type* pLu = NULL_PTR; + + for (u8Index = 0U; u8Index < (uint8_t)LG_CNT; u8Index++) + { + /* set AOI0 value */ + LU_HWA_ConfigAOI0(pLu, (LU_LgType)u8Index, 0U); + /* set AOI1 value */ + LU_HWA_ConfigAOI1(pLu, (LU_LgType)u8Index, 0U); + /* set CTRL value */ + LU_HWA_ConfigCtrl(pLu, (LU_LgType)u8Index, 0U); + /* set FILT value */ + LU_HWA_ConfigFilter(pLu, (LU_LgType)u8Index, 0U); + } +} + + diff --git a/Src/fc7xxx_driver_mam.c b/Src/fc7xxx_driver_mam.c new file mode 100644 index 0000000..3ed3e5d --- /dev/null +++ b/Src/fc7xxx_driver_mam.c @@ -0,0 +1,259 @@ +/** + * @file fc7xxx_driver_mam.c + * @author Flagchip + * @brief FC7xxx MAM driver source code + * @version 0.1.0 + * @date 2023-02-08 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-10 Flagchip095 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_mam.h" +#include "interrupt_manager.h" + + +#define MAM0_MIN_ADDR 0x01000000U +#define MAM0_MAX_ADDR 0x4049FFFFU + +#define ROM_START_ADDR 0x04800000U +#define ROM_END_ADDR 0x0481FFFFU +#define ROM_BLOCK_SIZE 0x20000U + +#define FLASH0_START_ADDR 0x01000000U +#define FLASH0_END_ADDR 0x011FFFFFU +#define FLASH0_BLOCK_SIZE 0x20000U + +#define NVR_START_ADDR 0x04400000U +#define NVR_END_ADDR 0x04411FFFU +#define NVR_BLOCK_SIZE 0x20000U + +#define NVR_CFG_START_ADDR 0x04420000U +#define NVR_CFG_END_ADDR 0x04431FFFU +#define NVR_CFG_BLOCK_SIZE 0x20000U + +#define FLASH1_START_ADDR 0x04000000U +#define FLASH1_END_ADDR 0x0401FFFFU +#define FLASH1_BLOCK_SIZE 0x2000U + +#define SRAM_START_ADDR 0x21000000U +#define SRAM_END_ADDR 0x21017FFFU +#define SRAM_BLOCK_SIZE 0x4000U + +#define CPU0_DTCM_START_ADDR 0x20000000U +#define CPU0_DTCM_END_ADDR 0x2001FFFFU +#define CPU0_DTCM_BLOCK_SIZE 0x4000U + +#define CPU0_ITCM_START_ADDR 0x00000000U +#define CPU0_ITCM_END_ADDR 0x00007FFFU +#define CPU0_ITCM_BLOCK_SIZE 0x4000U + +#define AFCB0_START_ADDR 0x40000000U +#define AFCB0_END_ADDR 0x4009FFFFU +#define AFCB0_BLOCK_SIZE 0x1000U + +#define AFCB1_START_ADDR 0x40400000U +#define AFCB1_END_ADDR 0x4049FFFFU +#define AFCB1_BLOCK_SIZE 0x1000U + +/** + * @brief Get mam information according to the address + * + * @param u32Addr Input address + */ +static MAM_Inf_Type MAM_Get_MAM_Inf(uint32_t u32Addr); + + +/*************** Local Functions ***************/ +static MAM_Inf_Type MAM_Get_MAM_Inf(uint32_t u32Addr) +{ + MAM_Inf_Type inf = {.error = 0}; + if(MAM0_MIN_ADDR <= u32Addr && u32Addr < MAM0_MAX_ADDR) + { + if(ROM_START_ADDR == u32Addr) + { + inf.block_num = 0; + } + else if(FLASH0_START_ADDR <= u32Addr && u32Addr < FLASH0_END_ADDR) + { + if((u32Addr - FLASH0_START_ADDR)%FLASH0_BLOCK_SIZE == 0U) + { + inf.block_num = (u32Addr - FLASH0_START_ADDR) / FLASH0_BLOCK_SIZE + 1U; + } + else + { + inf.error = 1; + } + } + else if(NVR_START_ADDR <= u32Addr && u32Addr < NVR_END_ADDR) + { + if((u32Addr - NVR_START_ADDR)%NVR_BLOCK_SIZE == 0U) + { + inf.block_num = (u32Addr - NVR_START_ADDR) / NVR_BLOCK_SIZE + 17U; + } + else + { + inf.error = 1; + } + } + else if(NVR_CFG_START_ADDR <= u32Addr && u32Addr < NVR_CFG_END_ADDR) + { + if((u32Addr - NVR_CFG_START_ADDR)%NVR_CFG_BLOCK_SIZE == 0U) + { + inf.block_num = (u32Addr - NVR_CFG_START_ADDR) / NVR_CFG_BLOCK_SIZE + 18U; + } + else + { + inf.error = 1; + } + } + else if(FLASH1_START_ADDR <= u32Addr && u32Addr < FLASH1_END_ADDR) + { + if((u32Addr - FLASH1_START_ADDR)%FLASH1_BLOCK_SIZE == 0U) + { + inf.block_num = (u32Addr - FLASH1_START_ADDR) / FLASH1_BLOCK_SIZE + 19U; + } + else + { + inf.error = 1; + } + } + else if(SRAM_START_ADDR <= u32Addr && u32Addr < SRAM_END_ADDR) + { + if((u32Addr - SRAM_START_ADDR)%SRAM_BLOCK_SIZE == 0U) + { + inf.block_num = (u32Addr - SRAM_START_ADDR) / SRAM_BLOCK_SIZE + 35U; + } + else + { + inf.error = 1; + } + } + else if(CPU0_DTCM_START_ADDR <= u32Addr && u32Addr < CPU0_DTCM_END_ADDR) + { + if((u32Addr - CPU0_DTCM_START_ADDR)%SRAM_BLOCK_SIZE == 0U) + { + inf.block_num = (u32Addr - CPU0_DTCM_START_ADDR) / CPU0_DTCM_BLOCK_SIZE + 43U; + } + else + { + inf.error = 1; + } + } + else if(u32Addr < CPU0_ITCM_END_ADDR) + { + if((u32Addr - CPU0_ITCM_START_ADDR)%CPU0_ITCM_BLOCK_SIZE == 0U) + { + inf.block_num = (u32Addr - CPU0_ITCM_START_ADDR) / CPU0_ITCM_BLOCK_SIZE + 41U; + } + else + { + inf.error = 1; + } + } + else if(AFCB0_START_ADDR <= u32Addr && u32Addr < AFCB0_END_ADDR) + { + if((u32Addr - AFCB0_START_ADDR)%AFCB0_BLOCK_SIZE == 0U) + { + inf.block_num = (u32Addr - AFCB0_START_ADDR) / AFCB0_BLOCK_SIZE + 51U; + } + else + { + inf.error = 1; + } + } + else if(AFCB1_START_ADDR <= u32Addr && u32Addr < AFCB1_END_ADDR) + { + if((u32Addr - AFCB1_START_ADDR)%AFCB1_BLOCK_SIZE == 0U) + { + inf.block_num = (u32Addr - AFCB1_START_ADDR) / AFCB1_BLOCK_SIZE + 211U; + } + else + { + inf.error = 1; + } + } + else + { + inf.error = 1; + } + } + else + { + inf.error = 1; + } + return inf; +} + + +/***************** Global Functions *******************/ +uint8_t MAM_Config(MAM_Master_Type Master, uint32_t u32Addr, uint32_t u32Val) +{ + MAM_Inf_Type inf = MAM_Get_MAM_Inf(u32Addr); + uint32_t reg_idx = 0U; + uint32_t bit_idx = 0U; + uint8_t status = 0U; + if(inf.error == 1U) + { + status = 1; + } + else + { + reg_idx = inf.block_num / 8U + 47U*(uint32_t)Master; /* 371 block , 371/8 + 1*/ + bit_idx = inf.block_num % 8U; + Mam_HWA_Set_ACR(MAM, reg_idx, u32Val << (bit_idx * 4U)); + reg_idx = inf.block_num / 32U + 12U*(uint32_t)Master; /* 371 block , 371/32 + 1*/ + bit_idx = inf.block_num % 32U; + Mam_HWA_Set_ACLR(MAM, reg_idx, 1UL << bit_idx); + } + return status; +} + +uint8_t MAM_Enable_Wdg(MAM_Master_Type Master,uint32_t u32Addr) +{ + uint8_t status = 0U; + uint32_t bit_idx = 0U; + uint32_t regval = 0U; + MAM_Inf_Type inf = MAM_Get_MAM_Inf(u32Addr); + + if(Master >= MAM_MASTER_NUM || inf.error == 1U) + { + status = 1; + } + else + { + bit_idx = (uint32_t)Master; + regval = Mam_HWA_Get_Wdgctr(MAM); + regval |= 1UL << bit_idx; + Mam_HWA_Set_Wdgctr(MAM, regval); + } + return status; +} + +uint8_t MAM_Disable_Wdg(MAM_Master_Type Master,uint32_t u32Addr) +{ + uint8_t status = 0U; + uint32_t regval = 0U; + uint32_t bit_idx = 0U; + MAM_Inf_Type inf = MAM_Get_MAM_Inf(u32Addr); + + if(Master >= MAM_MASTER_NUM || inf.error == 1U) + { + status = 1; + } + else + { + bit_idx = (uint32_t)Master; + regval = Mam_HWA_Get_Wdgctr(MAM); + regval &= ~(1U << bit_idx); + Mam_HWA_Set_Wdgctr(MAM, regval); + } + return status; +} diff --git a/Src/fc7xxx_driver_mb.c b/Src/fc7xxx_driver_mb.c new file mode 100644 index 0000000..d93fce1 --- /dev/null +++ b/Src/fc7xxx_driver_mb.c @@ -0,0 +1,456 @@ +/** + * @file fc7xxx_driver_mb.c + * @author Flagchip070 + * @brief FC7xxx Mailbox driver type definition and API + * @version 0.1.0 + * @date 2022-11-15 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2022-11-15 Flagchip070 N/A First version for FC7300 + ******************************************************************************** */ + +#include "fc7xxx_driver_mb.h" + + +/********* Local variable ************/ +static uint32_t s_u32CoreIndex = MB_NOT_INIT; +static const uint8_t s_aMasterIdTab[MB_INT_CONFIG_COUNT] = { + 0u, 8u +}; + +static void (*s_pRequestCallback)(MB_ReceiveType *pReceive) = NULL; +static void (*s_pDoneCallback)(uint32_t u32ChannelMask) = NULL; + +/******* Local Function Prototype *********/ +static uint32_t core_id_2_index(uint32_t u32MasterId); +static uint8_t get_channel_status(uint32_t u32Channel); + +/** + * @brief Convert core master id to index + * + * @param u32MasterId Core master ID + * + */ +static uint32_t core_id_2_index(uint32_t u32MasterId) +{ + uint32_t u32Index = 0; + uint32_t u32Loop; + for(u32Loop = 0; u32Loop < MB_INT_CONFIG_COUNT; u32Loop++) + { + if(s_aMasterIdTab[u32Loop] == u32MasterId) + { + u32Index = u32Loop; + break; + } + } + return u32Index; +} + +/** + * @brief Get the master security information and processing mode of the channel + * + * @param u32Channel the selected MB channel + * + */ +static uint8_t get_channel_status(uint32_t u32Channel) +{ + uint8_t u8Status = 0; + if(0u == MB_HWA_GetSecure(u32Channel)) + { + u8Status |= MB_CHANNEL_STATUS_SECURE; + } + if(0u != MB_HWA_GetSupervisor(u32Channel)) + { + u8Status |= MB_CHANNEL_STATUS_PRIVILEGED; + } + return u8Status; +} + +/********* Global Functions ************/ + +/** + * @brief Get the index of the core + * + * @return uint32_t index of the core + */ +uint32_t MB_GetCoreIndex(void) +{ + return s_u32CoreIndex; +} + +/** + * @brief Initialize the Mailbox + * + * @param pInitConfig the configurations of the Mailbox + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_Init(const MB_InitType *pInitConfig) +{ + MB_StatusType eStatus = MB_STATUS_SUCCESS; + if(MB_NOT_INIT != s_u32CoreIndex) + { + eStatus = MB_STATUS_ALREADY_INITED; + } + else + { + /* Get Core Index */ +#if defined(DEVICE_TYPE) && (DEVICE_TYPE == FC7XXXHSM) + s_u32CoreIndex = HSM_MAILBOX_CORE_INDEX; +#else + uint32_t u32CoreId; + uint32_t u32Index; + u32CoreId = (MCM->MICR & MCM_MICR_COREID_Msk) >> MCM_MICR_COREID_Pos; + for(u32Index = 0; u32Index < MB_INT_CONFIG_COUNT; u32Index++) + { + if(u32CoreId == s_aMasterIdTab[u32Index]) + { + s_u32CoreIndex = u32Index; + break; + } + } +#endif + if(MB_NOT_INIT != s_u32CoreIndex) + { + /*Registering callback functions*/ + s_pRequestCallback = pInitConfig->pRequestCallback; + s_pDoneCallback = pInitConfig->pDoneCallback; + /*Configure the event mask*/ + MB_HWA_ConfigFlagMask(s_u32CoreIndex, pInitConfig->u32EventMask); + /*Enable event interrupts */ + MB_HWA_ConfigIntrEnable(s_u32CoreIndex, pInitConfig->u32IntrMask); + } + else + { + eStatus = MB_STATUS_FAILED; + } + } + + return eStatus; +} + +/** + * @brief De-initialize the Mailbox + * + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_DeInit(void) +{ + MB_StatusType eStatus = MB_STATUS_UNINIT; + if(MB_NOT_INIT != s_u32CoreIndex) + { + /*Disable all event interrupts and flag*/ + MB_HWA_ConfigFlagMask(s_u32CoreIndex, 0); + MB_HWA_ConfigIntrEnable(s_u32CoreIndex, 0); + s_u32CoreIndex = MB_NOT_INIT; + } + return eStatus; +} + +/** + * @brief Attempt to acquire a Mailbox channel + * + * @param u32Channel the selected Mailbox channel + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_LockChannel(uint32_t u32Channel) +{ + MB_StatusType eStatus = MB_STATUS_SUCCESS; + uint32_t u32Lock; + + if(MB_NOT_INIT == s_u32CoreIndex) + { + eStatus = MB_STATUS_UNINIT; + } + else + { + if(u32Channel < MB_CHANNEL_CONFIG_COUNT) + { + /*Read SEMA to lock the selected channel*/ + u32Lock = MB_HWA_LockChannel(u32Channel); + if(0u == u32Lock) + { + eStatus = MB_STATUS_LOCKED; + } + } + else + { + eStatus = MB_STATUS_PARAM_ERROR; + } + } + return eStatus; +} + +/** + * @brief Release a Mailbox channel + * + * @param u32Channel the selected Mailbox channel + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_ReleaseChannel(uint32_t u32Channel) +{ + MB_StatusType eStatus = MB_STATUS_SUCCESS; + uint32_t u32MasterId; + if(MB_NOT_INIT == s_u32CoreIndex) + { + eStatus = MB_STATUS_UNINIT; + } + else + { + if(u32Channel < MB_CHANNEL_CONFIG_COUNT) + { + /*Check the master core of the channel*/ + u32MasterId = MB_HWA_GetMasterID(u32Channel); + if(u32MasterId == s_aMasterIdTab[s_u32CoreIndex]) + { + /*Release the selected channel*/ + MB_HWA_ReleaseChannel(u32Channel); + } + else + { + eStatus = MB_STATUS_FAILED; + } + } + else + { + eStatus = MB_STATUS_PARAM_ERROR; + } + } + return eStatus; +} + +/** + * @brief Software clears channel lock + * + * @param u32Channel the selected Mailbox channel + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_UnlockChannel(uint32_t u32Channel) +{ + MB_StatusType eStatus = MB_STATUS_SUCCESS; + if(MB_NOT_INIT == s_u32CoreIndex) + { + eStatus = MB_STATUS_UNINIT; + } + else + { + if(u32Channel < MB_CHANNEL_CONFIG_COUNT) + { + MB_HWA_UnlockChanne(u32Channel); + } + else + { + eStatus = MB_STATUS_PARAM_ERROR; + } + } + return eStatus; +} + +/** + * @brief Launching a Mailbox request + * + * @param pRequest Configuration of the request + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_SendRequest(MB_RequestType *pRequest) +{ + MB_StatusType eStatus = MB_LockChannel(pRequest->u8Channel); + if(MB_STATUS_SUCCESS == eStatus) + { + if(pRequest->u8DoneMasterIndex < MB_INT_CONFIG_COUNT) + { + MB_HWA_ConfigDoneMasterId(pRequest->u8Channel, s_aMasterIdTab[pRequest->u8DoneMasterIndex]); + MB_HWA_ConfigDoneMask(pRequest->u8Channel, pRequest->u8DoneMask); + MB_HWA_ConfigAutoUnlock(pRequest->u8Channel, pRequest->u8AutoReleaseFlag); + MB_HWA_WriteData(pRequest->u8Channel, pRequest->aData); + MB_HWA_ConfigRequest(pRequest->u8Channel, pRequest->u8RequestMask); + } + else + { + eStatus = MB_STATUS_PARAM_ERROR; + } + } + return eStatus; +} + +/** + * @brief Attempt to receive a request from the selected channel + * + * @param pReceive Configuration of the receiving request + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_ReceiveChannel(MB_ReceiveType *pReceive) +{ + MB_StatusType eStatus = MB_STATUS_SUCCESS; + uint32_t u32Flag; + if(MB_NOT_INIT == s_u32CoreIndex) + { + eStatus = MB_STATUS_UNINIT; + } + else if(pReceive->u8Channel < MB_CHANNEL_CONFIG_COUNT) + { + u32Flag = MB_HWA_GetFlag(s_u32CoreIndex, MB_EVENT_REQ(pReceive->u8Channel)); + if(0u != u32Flag) + { + /* Clear events flag */ + MB_HWA_ClearFlag(s_u32CoreIndex, u32Flag); + /* receiving data */ + MB_HWA_GetData(pReceive->u8Channel, pReceive->aData); + /* get the security information and processing mode */ + pReceive->u8ChannelStatus = get_channel_status(pReceive->u8Channel); + /*get the master core index of the request*/ + pReceive->u8MasterCoreIndex = (uint8_t)MB_HWA_GetMasterID(pReceive->u8Channel); + pReceive->u8MasterCoreIndex = (uint8_t)core_id_2_index((uint32_t)pReceive->u8MasterCoreIndex); + } + else + { + eStatus = MB_STATUS_NO_REQUEST; + } + } + else + { + eStatus = MB_STATUS_PARAM_ERROR; + } + return eStatus; +} + +/** + * @brief Issue a done event to the selected channel + * + * @param u32Channel the selected Mailbox channel + * @param u32DoneMask The mask for issuing done + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_DoneChannel(uint32_t u32Channel, uint32_t u32DoneMask) +{ + MB_StatusType eStatus = MB_STATUS_SUCCESS; + uint32_t u32DoneMasterId, u32DoneMaskAllow; + if(MB_NOT_INIT == s_u32CoreIndex) + { + eStatus = MB_STATUS_UNINIT; + } + else if(u32Channel < MB_CHANNEL_CONFIG_COUNT) + { + /* Check the done master of the channel*/ + u32DoneMasterId = MB_HWA_GetDoneMasterId(u32Channel); + if(u32DoneMasterId == s_aMasterIdTab[s_u32CoreIndex]) + { + /* Check if the done mask is allowed */ + u32DoneMaskAllow = MB_HWA_GetDoneMask(u32Channel); + if((u32DoneMaskAllow & u32DoneMask) == u32DoneMask) + { + /* issue a done event */ + MB_HWA_SetDone(u32Channel, u32DoneMask); + } + else + { + eStatus = MB_STATUS_FAILED; + } + } + else + { + eStatus = MB_STATUS_FAILED; + } + } + else + { + eStatus = MB_STATUS_PARAM_ERROR; + } + return eStatus; +} + +/** + * @brief Polling the done event of all channels + * + * @param u32PollMask mask of the done event + * @param pDoneMask buffer to store the done events + * @return MB_StatusType whether the operation is successfully + */ +MB_StatusType MB_PollDone(uint32_t u32PollMask, uint32_t *pDoneMask) +{ + MB_StatusType eStatus = MB_STATUS_SUCCESS; + uint32_t u32Flag, u32Index; + *pDoneMask = 0; + + if(MB_NOT_INIT == s_u32CoreIndex) + { + eStatus = MB_STATUS_UNINIT; + } + else if(0u != u32PollMask) + { + for(u32Index = 0; u32Index < MB_CHANNEL_CONFIG_COUNT; u32Index++) + { + if(0u != (u32PollMask & ((uint32_t)1u << u32Index))) + { + u32Flag = MB_HWA_GetFlag(s_u32CoreIndex, MB_EVENT_DONE(u32Index)); + if(0u != u32Flag) + { + /* Clear done flag */ + MB_HWA_ClearFlag(s_u32CoreIndex, u32Flag); + /* store the done event */ + *pDoneMask |= (uint32_t)1u << u32Index; + } + } + } + } + else + { + eStatus = MB_STATUS_PARAM_ERROR; + } + return eStatus; +} + +/** + * @brief Interrupt IRQ handle of Mailbox + * + */ +void MB_IRQProcess(void) +{ + uint32_t u32FlagStat = MB_HWA_GetFlagStat(s_u32CoreIndex, MB_INTn_FLG_STAT_MASK); + uint32_t u32Index, u32MasterCore, u32ChannelMask = 0; + MB_ReceiveType tReceive; + + MB_HWA_ClearFlag(s_u32CoreIndex, u32FlagStat); + for(u32Index = 0; u32Index < MB_CHANNEL_CONFIG_COUNT; u32Index++) + { + /* get the master core index of the channel*/ + u32MasterCore = MB_HWA_GetMasterID(u32Index); + u32MasterCore = core_id_2_index(u32MasterCore); + if(0u != (u32FlagStat & ((uint32_t)1u << u32Index))) + { + /* request event */ + if(NULL != s_pRequestCallback) + { + tReceive.u8Channel = (uint8_t)u32Index; + tReceive.u8ChannelStatus = get_channel_status(u32Index); + tReceive.u8MasterCoreIndex = (uint8_t)u32MasterCore; + MB_HWA_GetData(u32Index, tReceive.aData); + /* call the request callback*/ + s_pRequestCallback(&tReceive); + } + } + if(0u != (u32FlagStat & ((uint32_t)1u << (u32Index + MB_INTn_FLG_STAT_FLG_DONE_INT_STAT_SHIFT)))) + { + u32ChannelMask |= (uint32_t)1u << u32Index; + /*done event*/ + if((0u == MB_HWA_GetAutoClear(u32Index, s_u32CoreIndex)) && (u32MasterCore == s_u32CoreIndex)) + { + /* if channel is not automatically clear, + * and master core is self, release the channel */ + MB_HWA_ReleaseChannel(u32Index); + } + } + } + + if((NULL != s_pDoneCallback) && (0u != u32ChannelMask)) + { + s_pDoneCallback(u32ChannelMask); + } +} diff --git a/Src/fc7xxx_driver_mpu.c b/Src/fc7xxx_driver_mpu.c new file mode 100644 index 0000000..a5e0cca --- /dev/null +++ b/Src/fc7xxx_driver_mpu.c @@ -0,0 +1,128 @@ +/** + * @file fc7xxx_driver_mpu.c + * @author Flagchip085 + * @brief FC7xxx MPU driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details The MPU only checks the CPU master access to CTCM and DTCM memory. When access denied, it will cause MemManage Interrupt. + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_mpu.h" + +void MPU_Disable(void) +{ + __DMB(); /* make sure outstanding transfers are done */ + MPU_HWA_Fault_Disable(); + MPU_HWA_Set_CR(0U); /* disable mpu and clear its control register*/ +} + +void MPU_Enable(MPU_EnableOptionType eOption) +{ + uint32_t u32Option; + + switch (eOption) + { + case MPU_EN_HARDFAULT_NMI: + u32Option = CORTEX_MPU_CTRL_HFNMIENA_MASK; + break; + + case MPU_EN_PRIVILEGED_DEFAULT: + u32Option = CORTEX_MPU_CTRL_RPRIVDEFENA_MASK; + break; + + case MPU_EN_HFNMI_PRIVDEF: + u32Option = (CORTEX_MPU_CTRL_HFNMIENA_MASK | CORTEX_MPU_CTRL_RPRIVDEFENA_MASK); + break; + + case MPU_EN_HFNMI_PRIVDEF_NONE: + u32Option = 0U; + break; + + default: + u32Option = 0U; + break; + } + MPU_HWA_Set_CR(CORTEX_MPU_CTRL_ENABLE_MASK | (((uint32_t)u32Option) & MPU_EN_MASK_U32)); + MPU_HWA_Fault_Enable(); /* mpu fault MemManage INT enable */ + __DSB(); + __ISB(); +} + +MPU_StatusType MPU_RegionDisable(MPU_RegionNumberType eRegion) +{ + MPU_HWA_Set_NR((uint8_t)eRegion); + MPU_HWA_Set_BAR(0x00U); + MPU_HWA_Set_ASR(0x00U); + + return MPU_STATUS_SUCCESS; +} + +MPU_StatusType MPU_RegionEnable(MPU_RegionNumberType eRegion, const MPU_RegionConfigurationType *pConfig) +{ + MPU_StatusType eRet = MPU_STATUS_SUCCESS; + uint32_t u32Srd; + uint32_t u32Asr; + + if ((NULL == pConfig) || + ((uint32_t)eRegion > (uint32_t)MPU_REGION_NUMBER_15) || + (0U != (pConfig->u32BaseAddr & MPU_RBAR_VALID_REGION_MASK_U32)) || + ((uint32_t)pConfig->eRegionSize < (uint32_t)MPU_REGION_SIZE_32B) || + ((uint32_t)pConfig->eRegionSize > (uint32_t)MPU_REGION_SIZE_4GB)) + { + eRet = MPU_STATUS_ERROR; + } + else + { + /* use bit shift is surely safe */ + u32Srd = (((((uint32_t)pConfig->eSubRegionDis_0) << 0) | + (((uint32_t)pConfig->eSubRegionDis_1) << 1) | + (((uint32_t)pConfig->eSubRegionDis_2) << 2) | + (((uint32_t)pConfig->eSubRegionDis_3) << 3) | + (((uint32_t)pConfig->eSubRegionDis_4) << 4) | + (((uint32_t)pConfig->eSubRegionDis_5) << 5) | + (((uint32_t)pConfig->eSubRegionDis_6) << 6) | + (((uint32_t)pConfig->eSubRegionDis_7) << 7)) & 0xFFU); + + u32Asr = CORTEX_MPU_RASR_XN(pConfig->eExecuteNever) | + CORTEX_MPU_RASR_AP(pConfig->eAccessPermission) | + CORTEX_MPU_RASR_TEX(pConfig->eTypeExtLevel) | + CORTEX_MPU_RASR_S(pConfig->eShareable) | + CORTEX_MPU_RASR_C(pConfig->eCacheable) | + CORTEX_MPU_RASR_B(pConfig->eBufferable) | + CORTEX_MPU_RASR_SRD(u32Srd) | + CORTEX_MPU_RASR_SIZE(pConfig->eRegionSize) | + CORTEX_MPU_RASR_ENABLE_MASK; + + MPU_HWA_Set_NR((uint8_t)eRegion); + MPU_HWA_Set_BAR(pConfig->u32BaseAddr & MPU_RBAR_BASEADDR_MASK_U32); /* ignore VALID and REGION bits */ + MPU_HWA_Set_ASR(u32Asr); + } + + return eRet; +} + + + + +MPU_StatusType MPU_CheckExist(void) +{ + uint32_t u32RegVal = MPU_HWA_Get_Type(); + MPU_StatusType eRet = MPU_STATUS_SUCCESS; + + if (0U == u32RegVal) + { + eRet = MPU_STATUS_ERROR; + } + + return eRet; +} diff --git a/Src/fc7xxx_driver_msc.c b/Src/fc7xxx_driver_msc.c new file mode 100644 index 0000000..51d411d --- /dev/null +++ b/Src/fc7xxx_driver_msc.c @@ -0,0 +1,569 @@ +/** + * @file fc7xxx_driver_msc.c + * @author Flagchip + * @brief FC7240 MSC driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-10 Flagchip084 N/A FC7240 release version + ******************************************************************************** */ + +#include "fc7xxx_driver_msc.h" + +/* ################################################################################## */ +/* ####################################### Macro #################################### */ + +/* ################################################################################## */ +/* ################################### Type define ################################## */ + +/* ################################################################################## */ +/* ################################ Local Variables ################################# */ +static MSC_Type *const s_apMscBase[MSC_INSTANCE_COUNT] = MSC_BASE_PTRS; +static MSC_ISRCallbackType s_apMscRFISRCallback[MSC_INSTANCE_COUNT] = {NULL}; +static MSC_ISRCallbackType s_apMscTFISRCallback[MSC_INSTANCE_COUNT] = {NULL}; +static MSC_ISRCallbackType s_apMscCFISRCallback[MSC_INSTANCE_COUNT] = {NULL}; +static MSC_ISRCallbackType s_apMscDFISRCallback[MSC_INSTANCE_COUNT] = {NULL}; +static MSC_ISRCallbackType s_apMscTOISRCallback[MSC_INSTANCE_COUNT] = {NULL}; + +/* ################################################################################## */ +/* ########################### Local Prototype Functions ############################ */ +static void MSCn_IRQHandler(const MSC_InstanceType eInstance); +static void MSC_ClearReceiveInterruptFlag(const MSC_InstanceType eInstance); +static void MSC_ClearTimeFrameInterruptFlag(const MSC_InstanceType eInstance); +static void MSC_ClearCommandFrameInterruptFlag(const MSC_InstanceType eInstance); +static void MSC_ClearDataFrameInterruptFlag(const MSC_InstanceType eInstance); +/* ################################################################################## */ +/* ######################### Global prototype Functions ############################ */ +void MSC0_IRQHandler(void); +/* ################################################################################## */ +/* ################################ Local Functions ################################ */ +static void MSCn_IRQHandler(const MSC_InstanceType eInstance) +{ + uint32_t u32IntFlag = MSC_GetInterruptStatus(eInstance); + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + if (u32IntFlag & MSC_INSR_RFI_MASK) + { + MSC_ClearReceiveInterruptFlag(eInstance); + if (MSC_HWA_GetRfieEnable(pMsc) && s_apMscRFISRCallback[eInstance] != NULL) + { + s_apMscRFISRCallback[eInstance](eInstance); + } + } + if (u32IntFlag & MSC_INSR_TFI_MASK) + { + MSC_ClearTimeFrameInterruptFlag(eInstance); + if (MSC_HWA_GetTfieEnable(pMsc) && s_apMscTFISRCallback[eInstance] != NULL) + { + s_apMscTFISRCallback[eInstance](eInstance); + } + } + if (u32IntFlag & MSC_INSR_CFI_MASK) + { + MSC_ClearCommandFrameInterruptFlag(eInstance); + if (MSC_HWA_GetCfieEnable(pMsc) && s_apMscCFISRCallback[eInstance] != NULL) + { + s_apMscCFISRCallback[eInstance](eInstance); + } + } + if (u32IntFlag & MSC_INSR_DFI_MASK) + { + MSC_ClearDataFrameInterruptFlag(eInstance); + if (MSC_HWA_GetDfieEnable(pMsc) && s_apMscDFISRCallback[eInstance] != NULL) + { + s_apMscDFISRCallback[eInstance](eInstance); + } + } + if (MSC_HWA_GetTofEnable(pMsc)) + { + MSC_HWA_ClearTofEnable(pMsc); + if (MSC_HWA_GetToieEnable(pMsc) && s_apMscTOISRCallback[eInstance] != NULL) + { + s_apMscTOISRCallback[eInstance](eInstance); + } + } +} +/* ################################################################################## */ +/* ################################ Global Functions ################################ */ + +void MSC0_IRQHandler(void) +{ + MSCn_IRQHandler(MSC_INSTANCE_0); +} + +MSC_ReturnType MSC_init(const MSC_InstanceType eInstance, const MSC_InitCfgType *pInitConfig) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + DEV_ASSERT(pInitConfig != NULL); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + uint32_t u32TempValue; + uint32_t u32TimeoutCount = 0xFFFFFFU; + + if (pInitConfig->u8CommandBitLength > 32U || pInitConfig->u8SRLDataBitLength > 16U || pInitConfig->u8SRHDataBitLength > 16U) + { + return MSC_RETURN_E_PARAM; + } + + MSC_HWA_SetMsrRst(pMsc); + + while (MSC_HWA_GetMsrRdone(pMsc) == false) + { + u32TimeoutCount--; + if (u32TimeoutCount == 0U) + { + break; + } + } + + if (u32TimeoutCount == 0U) + { + return MSC_RETURN_E_NOT_OK; + } + + MSC_HWA_ClearMsrDone(pMsc); + + u32TempValue = MSC_TCCTR_PL(pInitConfig->u8PassiveLength) | MSC_TCCTR_WM(pInitConfig->eWorkMode) | MSC_TCCTR_SELH(pInitConfig->bSelSRH) | MSC_TCCTR_SELL(pInitConfig->bSelSRL) | + MSC_TCCTR_NBS(pInitConfig->u8CommandBitLength) | MSC_TCCTR_NHBS(pInitConfig->u8SRHDataBitLength) | MSC_TCCTR_NLBS(pInitConfig->u8SRLDataBitLength); + MSC_HWA_SetTcctr(pMsc, u32TempValue); + + MSC_HWA_SetNp(pMsc, pInitConfig->u8PTFNumber); + + u32TempValue = + MSC_RCCSR_RFT(pInitConfig->eRsvFrameType) | MSC_RCCSR_RBR(pInitConfig->eBaudRate) | MSC_RCCSR_PCTL(pInitConfig->eParity) | MSC_RCCSR_HIDC(pInitConfig->bDelayControl); + MSC_HWA_SetRccsr(pMsc, u32TempValue); + + return MSC_RETURN_OK; +} + +void MSC_initInterrupt(const MSC_InstanceType eInstance, const MSC_InterruptCfgType *pInteruptConfig) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + DEV_ASSERT(pInteruptConfig != NULL); + uint32_t u32TempValue; + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + u32TempValue = MSC_INCR_RFIE(pInteruptConfig->eRFIEMode) | MSC_INCR_TFIE(pInteruptConfig->bTFIntEnable) | MSC_INCR_CFIE(pInteruptConfig->bCFIntEnable) | + MSC_INCR_DFIE(pInteruptConfig->eDFIEMode); + MSC_HWA_SetIncr(pMsc, u32TempValue); + + u32TempValue = MSC_RTOR_TOIE(pInteruptConfig->bTOIntEnable) | MSC_RTOR_TOV(pInteruptConfig->u16TimeoutValue); + MSC_HWA_SetRtor(pMsc, u32TempValue); + + s_apMscRFISRCallback[eInstance] = pInteruptConfig->pReceiveFrameISRCallback; + s_apMscTFISRCallback[eInstance] = pInteruptConfig->pTimeFrameISRCallback; + s_apMscCFISRCallback[eInstance] = pInteruptConfig->pCommandFrameISRCallback; + s_apMscDFISRCallback[eInstance] = pInteruptConfig->pDataFrameISRCallback; + s_apMscTOISRCallback[eInstance] = pInteruptConfig->pReceiveTimeOutISRCallback; +} + +void MSC_SelTranmittingSource(const MSC_InstanceType eInstance, uint32_t u32SourceMask, MSC_TransSourceType eSourceType) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + uint32_t u32TempValue1 = 0; + uint16_t u32TempValue2; + uint8_t u8i; + + u32TempValue2 = (uint16_t)(u32SourceMask & 0xFFFFU); + + for (u8i = 0U; u8i < 16U; u8i++) + { + if ((u32TempValue2 & 0x01U) != 0U) + { + u32TempValue1 |= (uint32_t)eSourceType << (u8i << 1U); + } + u32TempValue2 = u32TempValue2 >> 1; + } + MSC_HWA_SetTcslr(pMsc, u32TempValue1); + + u32TempValue2 = (uint16_t)((u32SourceMask >> 16) & 0xFFFFU); + for (u8i = 0U; u8i < 16U; u8i++) + { + if ((u32TempValue2 & 0x01U) != 0U) + { + u32TempValue1 |= (uint32_t)eSourceType << (u8i << 1U); + } + u32TempValue2 = u32TempValue2 >> 1; + } + MSC_HWA_SetTcshr(pMsc, u32TempValue1); +} + +void MSC_SetEmergencyLoad(const MSC_InstanceType eInstance, uint32_t u32Value) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetTcelr(pMsc, u32Value); +} + +void MSC_SetIOControl(const MSC_InstanceType eInstance, const MSC_IOControlInitType *pIOConfig) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + uint32_t u32TempValue = 0; + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + u32TempValue |= MSC_IOCR_IDS(pIOConfig->eSDIsel); + u32TempValue |= MSC_IOCR_ESC(pIOConfig->eENCSel); + u32TempValue |= MSC_IOCR_ESH(pIOConfig->eENHSel); + u32TempValue |= MSC_IOCR_ESL(pIOConfig->eENLSel); + u32TempValue |= MSC_IOCR_FCLCTRL(pIOConfig->eFclCtrl); + u32TempValue |= MSC_IOCR_IPS(pIOConfig->eSDIPol); + u32TempValue |= MSC_IOCR_ENP(pIOConfig->eENXPol); + u32TempValue |= MSC_IOCR_SOP(pIOConfig->eSOPPol); + u32TempValue |= MSC_IOCR_FCLP(pIOConfig->eFCLPPol); + + MSC_HWA_SetIocr(pMsc, u32TempValue); +} + +void MSC_Enable(const MSC_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetMscEnable(pMsc, true); +} + +void MSC_Disable(const MSC_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetMscEnable(pMsc, false); +} + +void MSC_SetDataFrame(const MSC_InstanceType eInstance, uint32_t u32Data) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetTcdar(pMsc, u32Data); +} + +void MSC_SendDataFrame(const MSC_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + MSC_Type *const pMsc = s_apMscBase[eInstance]; + MSC_HWA_SetDataNeedSend(pMsc); +} + +void MSC_SendCommandFrame(const MSC_InstanceType eInstance, uint32_t u32Command) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetTccor(pMsc, u32Command); +} + +uint8_t MSC_GetReceivedFrameAddr(const MSC_InstanceType eInstance, MSC_RDRxIndexType eIndex) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + DEV_ASSERT(eIndex < MSC_RDRx_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + uint8_t u8Addr = 0U; + + if (eIndex == MSC_RDR0) + { + u8Addr = MSC_HWA_GetRdr0Addr(pMsc); + } + else if (eIndex == MSC_RDR1) + { + u8Addr = MSC_HWA_GetRdr1Addr(pMsc); + } + else if (eIndex == MSC_RDR2) + { + u8Addr = MSC_HWA_GetRdr2Addr(pMsc); + } + else if (eIndex == MSC_RDR3) + { + u8Addr = MSC_HWA_GetRdr3Addr(pMsc); + } + else {} + + return u8Addr; +} + +MSC_ReceiveStatusType MSC_GetReceivedFrame(const MSC_InstanceType eInstance, MSC_RDRxIndexType eIndex, uint8_t *pData) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + DEV_ASSERT(eIndex < MSC_RDRx_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + MSC_ReceiveStatusType eRsvStatus = MSC_RSV_SUCCESS; + + if (eIndex == MSC_RDR0) + { + eRsvStatus = MSC_HWA_GetRdr0Rerr(pMsc); + if (MSC_RSV_SUCCESS == eRsvStatus) + { + *pData = MSC_HWA_GetRdr0Data(pMsc); + } + } + else if (eIndex == MSC_RDR1) + { + eRsvStatus = MSC_HWA_GetRdr1Rerr(pMsc); + if (MSC_RSV_SUCCESS == eRsvStatus) + { + *pData = MSC_HWA_GetRdr1Data(pMsc); + } + } + else if (eIndex == MSC_RDR2) + { + eRsvStatus = MSC_HWA_GetRdr2Rerr(pMsc); + if (MSC_RSV_SUCCESS == eRsvStatus) + { + *pData = MSC_HWA_GetRdr2Data(pMsc); + } + } + else if (eIndex == MSC_RDR3) + { + eRsvStatus = MSC_HWA_GetRdr3Rerr(pMsc); + if (MSC_RSV_SUCCESS == eRsvStatus) + { + *pData = MSC_HWA_GetRdr3Data(pMsc); + } + } + else {} + + return eRsvStatus; +} + +uint32_t MSC_GetInterruptStatus(const MSC_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + return MSC_HWA_GetInsr(pMsc); +} + +void MSC_EnableTrasmit(const MSC_InstanceType eInstance, bool bEnable) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + if (bEnable) + { + MSC_HWA_ClearTcdis(pMsc); + } + else + { + MSC_HWA_SetTcdis(pMsc); + } +} + +void MSC_ClearReceiveInterruptFlag(const MSC_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_ClearCrfi(pMsc); +} + +void MSC_ClearTimeFrameInterruptFlag(const MSC_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_ClearCtfi(pMsc); +} + +void MSC_ClearCommandFrameInterruptFlag(const MSC_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_ClearCcfi(pMsc); +} + +void MSC_ClearDataFrameInterruptFlag(const MSC_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_ClearCdfi(pMsc); +} + +void MSC_EnableDataFrameInterrupt(const MSC_InstanceType eInstance, bool bEnable) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetDfieEnable(pMsc, bEnable); +} + +void MSC_EnableCommandFrameInterrupt(const MSC_InstanceType eInstance, bool bEnable) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetCfieEnable(pMsc, bEnable); +} + +void MSC_EnableTimeFrameInterrupt(const MSC_InstanceType eInstance, bool bEnable) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetTfieEnable(pMsc, bEnable); +} + +void MSC_EnableReceiveInterrupt(const MSC_InstanceType eInstance, bool bEnable) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetRfieEnable(pMsc, bEnable); +} + +void MSC_EnableTimeoutInterrupt(const MSC_InstanceType eInstance, bool bEnable) +{ + DEV_ASSERT((uint8_t)eInstance < MSC_INSTANCE_COUNT); + + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + MSC_HWA_SetToieEnable(pMsc, bEnable); +} + +MSC_ReturnType Msc_SwitchENXChannel(const MSC_InstanceType eInstance, Msc_ENxType eEnx, Msc_ENxActiveType eENn, uint32_t u32TimeoutLoops) +{ + MSC_ReturnType eTempReturn = MSC_RETURN_E_NOT_OK; + uint32 u32TempValue; + uint32 u32TempTryCount = 0u; + uint8 u8CmdNeedSend; + uint8 u8CmdFrameBusy; + uint8 u8DataNeedSend; + uint8 u8DataFrameBusy; + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + if (eEnx == MSC_ENC) + { + do + { + u8CmdFrameBusy = MSC_HWA_GetCfb(pMsc); + u8CmdNeedSend = MSC_HWA_GetCmdNeedSend(pMsc); + + if ((u8CmdNeedSend == TRUE) || (u8CmdFrameBusy == TRUE)) + { + u32TempValue = TRUE; + } + else + { + u32TempValue = FALSE; + } + + /* check receive rc flag */ + if (u32TempValue == FALSE) + { + break; + } + else + { + u32TempTryCount++; + } + } while (u32TempTryCount < u32TimeoutLoops); + + if (u32TempTryCount != u32TimeoutLoops) + { + u32TempValue = (MSC_HWA_GetIocr(pMsc) & ~MSC_IOCR_ESC_MASK) | MSC_IOCR_ESC(eENn); + MSC_HWA_SetIocr(pMsc, u32TempValue); + eTempReturn = MSC_RETURN_OK; + } + } + else + { + do + { + u8DataFrameBusy = MSC_HWA_GetDfb(pMsc); + u8DataNeedSend = MSC_HWA_GetDataNeedSend(pMsc); + + if ((u8DataFrameBusy == TRUE) || (u8DataNeedSend == TRUE)) + { + u32TempValue = TRUE; + } + else + { + u32TempValue = FALSE; + } + + /* check receive rc flag */ + if (u32TempValue == FALSE) + { + break; + } + else + { + u32TempTryCount++; + } + } while (u32TempTryCount < u32TimeoutLoops); + + if (u32TempTryCount != u32TimeoutLoops) + { + if (eEnx == MSC_ENH) + { + u32TempValue = (MSC_HWA_GetIocr(pMsc) & ~MSC_IOCR_ESH_MASK) | MSC_IOCR_ESH(eENn); + MSC_HWA_SetIocr(pMsc, u32TempValue); + } + else + { + u32TempValue = (MSC_HWA_GetIocr(pMsc) & ~MSC_IOCR_ESL_MASK) | MSC_IOCR_ESL(eENn); + MSC_HWA_SetIocr(pMsc, u32TempValue); + } + eTempReturn = MSC_RETURN_OK; + } + } + + return eTempReturn; +} + +MSC_ReturnType Msc_SwitchSDIChannel(const MSC_InstanceType eInstance, MSC_SDISelectionType eSDIChannel, uint32_t u32TimeoutLoops) +{ + MSC_ReturnType eTempReturn = MSC_RETURN_E_NOT_OK; + uint32_t u32TempValue; + uint32_t u32TempTryCount = 0u; + MSC_Type *const pMsc = s_apMscBase[eInstance]; + + do + { + u32TempValue = MSC_HWA_GetRxBusy(pMsc); + + /* check receive rc flag */ + if (u32TempValue == 0U) + { + break; + } + else + { + u32TempTryCount++; + } + } while (u32TempTryCount < u32TimeoutLoops); + + if (u32TempTryCount != u32TimeoutLoops) + { + u32TempValue = (MSC_HWA_GetIocr(pMsc) & ~MSC_IOCR_IDS_MASK) | MSC_IOCR_IDS(eSDIChannel); + MSC_HWA_SetIocr(pMsc, u32TempValue); + + eTempReturn = MSC_RETURN_OK; + } + return eTempReturn; +} diff --git a/Src/fc7xxx_driver_overlay.c b/Src/fc7xxx_driver_overlay.c new file mode 100644 index 0000000..744dfbb --- /dev/null +++ b/Src/fc7xxx_driver_overlay.c @@ -0,0 +1,498 @@ +/** + * @file fc7xxx_driver_overlay.c + * @author Flagchip + * @brief FC7xxx overlay driver type definition and API + * @version 0.1.0 + * @date 2023-12-25 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + */ + +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2023-12-25 Flagchip0038 N/A First version for FC7240 +********************************************************************************/ + +#include "fc7xxx_driver_overlay.h" + +typedef void (*Void_Type)(void); +typedef void (*U32_Type)(uint32_t u32Data); +typedef void (*SizeEnum_Type)(OVERLAY_OverlaySizeType eSize); + +static Void_Type const s_aRegionEnDisable[OVERLYA_REGION_CNT] = +{ + OVERLAY_HWA_OverlayRegion0Disable, + OVERLAY_HWA_OverlayRegion1Disable, + OVERLAY_HWA_OverlayRegion2Disable +}; + + +static Void_Type const s_aRegionEnEnable[OVERLYA_REGION_CNT] = +{ + OVERLAY_HWA_OverlayRegion0Enable, + OVERLAY_HWA_OverlayRegion1Enable, + OVERLAY_HWA_OverlayRegion2Enable +}; + +static U32_Type const s_aRegionSrc[OVERLYA_REGION_CNT] = +{ + OVERLAY_HWA_SetOverlayRegion0Src, + OVERLAY_HWA_SetOverlayRegion1Src, + OVERLAY_HWA_SetOverlayRegion2Src +}; + +static U32_Type const s_aRegionDst[OVERLYA_REGION_CNT] = +{ + OVERLAY_HWA_SetOverlayRegion0Dst, + OVERLAY_HWA_SetOverlayRegion1Dst, + OVERLAY_HWA_SetOverlayRegion2Dst +}; + +static SizeEnum_Type const s_aRegionSize[OVERLYA_REGION_CNT] = +{ + OVERLAY_HWA_SetOverlayRegion0Size, + OVERLAY_HWA_SetOverlayRegion1Size, + OVERLAY_HWA_SetOverlayRegion2Size +}; + +static OVERLAY_ErrorCallback_Type s_tErrorCallbackFunc; + +/** + * @brief Overlay region initial function + * + * @param pOverlayInitCfg initial parameters + * @return ERROR_OK is ok, others are not ok + */ +OVERLAY_ErrorType OVERLAY_RegionInit(OVERLAY_OverlayRegionInitType *pOverlayInitCfg) +{ + OVERLAY_ErrorType eRetval; + uint32_t u32Index; + uint32_t u32ErrorInfo; + + eRetval = OVERLAY_ERROR_OK; + + /* global overlay Disable */ + OVERLAY_HWA_OverlayDisable(); + + /* loop all region */ + for (u32Index = 0U; (u32Index < OVERLYA_REGION_CNT) && (eRetval == OVERLAY_ERROR_OK); u32Index++) + { + /* check overlay region enable */ + if (pOverlayInitCfg->aOverlayRegionEn[u32Index]) + { + if ((pOverlayInitCfg->aOverlayRegionSrc[u32Index] >= PFLASH_START) && + (pOverlayInitCfg->aOverlayRegionSrc[u32Index] <= PFLASH_END) && + (pOverlayInitCfg->aOverlayRegionDst[u32Index] >= SRAM_START) && + (pOverlayInitCfg->aOverlayRegionDst[u32Index] <= SRAM_END) + ) + { + + /* disable region n */ + s_aRegionEnDisable[u32Index](); + + /* source */ + s_aRegionSrc[u32Index](pOverlayInitCfg->aOverlayRegionSrc[u32Index]); + + /* dest */ + s_aRegionDst[u32Index](pOverlayInitCfg->aOverlayRegionDst[u32Index]); + + /* size */ + s_aRegionSize[u32Index](pOverlayInitCfg->aOverlayRegionSize[u32Index]); + + /* enable region n */ + s_aRegionEnEnable[u32Index](); + } + else + { + eRetval = OVERLAY_ERROR_ADDR; + } + } + else + { + /* disable region n */ + s_aRegionEnDisable[u32Index](); + } + + } + + if (eRetval == OVERLAY_ERROR_OK) + { + /* global overlay enable */ + OVERLAY_HWA_OverlayEnable(); + } + + /* check error flag */ + u32ErrorInfo = OVERLAY_HWA_GetErrorFlag(); + if (u32ErrorInfo) + { + eRetval = OVERLAY_ERROR_FLAG; + } + + return eRetval; +} + +/** + * @brief De-Init Overlay Region + * + * @return ERROR_OK is ok, others are not ok + */ +OVERLAY_ErrorType OVERLAY_RegionDeInit(void) +{ + OVERLAY_ErrorType eRetval; + uint32_t u32Index; + + eRetval = OVERLAY_ERROR_OK; + + /* disable global overlay */ + OVERLAY_HWA_OverlayDisable(); + + for (u32Index = 0U; u32Index < OVERLYA_REGION_CNT; u32Index++) + { + /* disable region n */ + s_aRegionEnDisable[u32Index](); + + /* source */ + s_aRegionSrc[u32Index](0U); + + /* dest */ + s_aRegionDst[u32Index](0U); + + /* size */ + s_aRegionSize[u32Index](OVERLAY_OVERLAYSIZE_1KB); + } + + return eRetval; +} + + +/** + * @brief Far initial function + * + * @param pFarInitCfg initial parameters + * @return ERROR_OK is ok, others are not ok + */ +OVERLAY_ErrorType OVERLAY_FARInit(OVERLAY_FARInitType *pFarInitCfg) +{ + OVERLAY_ErrorType eRetval; + uint32_t u32ErrorInfo; + + eRetval = OVERLAY_ERROR_OK; + + if (pFarInitCfg->u32FAREn == 0U) + { + + /* disable far */ + OVERLAY_HWA_FARDisable(); + } + else + { + /* must align to 64KB, */ + if ((pFarInitCfg->u32FARSize <= OVERLAY_FAR_SIZE_MAX) && + ((pFarInitCfg->u32FARSize & OVERLAY_FAR_SIZE_MASK) == 0U) + ) + { + if ((pFarInitCfg->u32FARDst >= PFLASH_START) && + (pFarInitCfg->u32FARDst <= PFLASH_END) + ) + { + /* disable far */ + OVERLAY_HWA_FARDisable(); + + /* set far dest */ + OVERLAY_HWA_SetFarDst(pFarInitCfg->u32FARDst); + /* set far size */ + OVERLAY_HWA_SetFarSize(pFarInitCfg->u32FARSize / OVERLAY_FAR_SIZE_ALIGN - 1); + /* disable enable */ + OVERLAY_HWA_FAREnable(); + } + else + { + eRetval = OVERLAY_ERROR_ADDR; + } + } + else + { + eRetval = OVERLAY_ERROR_SIZE; + } + } + + if (eRetval == OVERLAY_ERROR_OK) + { + /* enable far */ + OVERLAY_HWA_FAREnable(); + } + + + /* check error flag */ + u32ErrorInfo = OVERLAY_HWA_GetErrorFlag(); + if (u32ErrorInfo) + { + eRetval = OVERLAY_ERROR_FLAG; + } + + + return eRetval; +} + +/** + * @brief De-Init FAR Region + * + * @return ERROR_OK is ok, others are not ok + */ +OVERLAY_ErrorType OVERLAY_FARDeInit(void) +{ + OVERLAY_ErrorType eRetval; + + eRetval = OVERLAY_ERROR_OK; + + /* disable global far */ + OVERLAY_HWA_FARDisable(); + + /* set far dest */ + OVERLAY_HWA_SetFarDst(0x01000000U); + /* set far size */ + OVERLAY_HWA_SetFarSize(0U); + + return eRetval; +} + +/** + * @brief Enable or Disable Interrupt + * + * @param pInterruptCfg interrupt config parameter + */ +void OVERLAY_SetInterrupt(OVERLAY_InterruptType *pInterruptCfg) +{ + if (pInterruptCfg->bEnableInterrupt) + { + OVERLAY_HWA_ErrorInterruptEnable(); + s_tErrorCallbackFunc = pInterruptCfg->pCallBack; + } + else + { + OVERLAY_HWA_ErrorInterruptDisable(); + s_tErrorCallbackFunc = NULL; + } + +} + +/** + * @brief Get Error Info + * + * @param pErrorInfo error info point + */ +void OVERLAY_GetErrorInfo(OVERLAY_ErrorInfoType *pErrorInfo) +{ + uint32_t u32ErrorInfo; + u32ErrorInfo = OVERLAY_HWA_GetErrorFlag(); + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_FAR_SIZE_INTR_MASK) + { + pErrorInfo->bError_FAR_SIZE_INTR = 1U; + } + else + { + pErrorInfo->bError_FAR_SIZE_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_FAR_DST_OVERFLOW_INTR_MASK) + { + pErrorInfo->bError_FAR_DST_OVERFLOW_INTR = 1U; + } + else + { + pErrorInfo->bError_FAR_DST_OVERFLOW_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_FAR_DST_NO_FLASH_INTR_MASK) + { + pErrorInfo->bError_FAR_DST_NO_FLASH_INTR = 1U; + } + else + { + pErrorInfo->bError_FAR_DST_NO_FLASH_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION2_D_CROS_INTR_MASK) + { + pErrorInfo->bError_REGION2_D_CROS_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION2_D_CROS_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION2_S_CROS_INTR_MASK) + { + pErrorInfo->bError_REGION2_S_CROS_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION2_S_CROS_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION2_SIZE_INTR_MASK) + { + pErrorInfo->bError_REGION2_SIZE_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION2_SIZE_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION2_DST_INTR_MASK) + { + pErrorInfo->bError_REGION2_DST_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION2_DST_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION2_SRC_INTR_MASK) + { + pErrorInfo->bError_REGION2_SRC_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION2_SRC_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION1_D_CROS_INTR_MASK) + { + pErrorInfo->bError_REGION1_D_CROS_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION1_D_CROS_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION1_S_CROS_INTR_MASK) + { + pErrorInfo->bError_REGION1_S_CROS_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION1_S_CROS_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION1_SIZE_INTR_MASK) + { + pErrorInfo->bError_REGION1_SIZE_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION1_SIZE_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION1_DST_INTR_MASK) + { + pErrorInfo->bError_REGION1_DST_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION1_DST_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION1_SRC_INTR_MASK) + { + pErrorInfo->bError_REGION1_SRC_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION1_SRC_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION0_D_CROS_INTR_MASK) + { + pErrorInfo->bError_REGION0_D_CROS_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION0_D_CROS_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION0_S_CROS_INTR_MASK) + { + pErrorInfo->bError_REGION0_S_CROS_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION0_S_CROS_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION0_SIZE_INTR_MASK) + { + pErrorInfo->bError_REGION0_SIZE_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION0_SIZE_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION0_DST_INTR_MASK) + { + pErrorInfo->bError_REGION0_DST_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION0_DST_INTR = 0U; + } + + if (u32ErrorInfo & AHB_OVERLAY_INTR_FLAG_REGION0_SRC_INTR_MASK) + { + pErrorInfo->bError_REGION0_SRC_INTR = 1U; + } + else + { + pErrorInfo->bError_REGION0_SRC_INTR = 0U; + } +} + +/** + * @brief Clear Error Info + * + * @param pErrorInfo error info point + */ +void OVERLAY_ClrErrorInfo(OVERLAY_ErrorInfoType *pErrorInfo) +{ + uint32_t u32ErrorInfo; + + u32ErrorInfo = AHB_OVERLAY_INTR_FLAG_FAR_SIZE_INTR(pErrorInfo->bError_FAR_SIZE_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_FAR_DST_OVERFLOW_INTR(pErrorInfo->bError_FAR_DST_OVERFLOW_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_FAR_DST_NO_FLASH_INTR(pErrorInfo->bError_FAR_DST_NO_FLASH_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION2_D_CROS_INTR(pErrorInfo->bError_REGION2_D_CROS_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION2_S_CROS_INTR(pErrorInfo->bError_REGION2_S_CROS_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION2_SIZE_INTR(pErrorInfo->bError_REGION2_SIZE_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION2_DST_INTR(pErrorInfo->bError_REGION2_DST_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION2_SRC_INTR(pErrorInfo->bError_REGION2_SRC_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION1_D_CROS_INTR(pErrorInfo->bError_REGION1_D_CROS_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION1_S_CROS_INTR(pErrorInfo->bError_REGION1_S_CROS_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION1_SIZE_INTR(pErrorInfo->bError_REGION1_SIZE_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION1_DST_INTR(pErrorInfo->bError_REGION1_DST_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION1_SRC_INTR(pErrorInfo->bError_REGION1_SRC_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION0_D_CROS_INTR(pErrorInfo->bError_REGION0_D_CROS_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION0_S_CROS_INTR(pErrorInfo->bError_REGION0_S_CROS_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION0_SIZE_INTR(pErrorInfo->bError_REGION0_SIZE_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION0_DST_INTR(pErrorInfo->bError_REGION0_DST_INTR); + u32ErrorInfo |= AHB_OVERLAY_INTR_FLAG_REGION0_SRC_INTR(pErrorInfo->bError_REGION0_SRC_INTR); + + OVERLAY_HWA_ClrErrorFlag(u32ErrorInfo); +} +/** + * @brief Call Me in Overlay Error interrupt handler + * + */ +void OVERLAY_ErrorInterruptRoutine(void) +{ + OVERLAY_ErrorInfoType tErrorInfo; + if (s_tErrorCallbackFunc != NULL) + { + OVERLAY_GetErrorInfo(&tErrorInfo); + s_tErrorCallbackFunc(tErrorInfo); + } +} diff --git a/Src/fc7xxx_driver_pcc.c b/Src/fc7xxx_driver_pcc.c new file mode 100644 index 0000000..61c9638 --- /dev/null +++ b/Src/fc7xxx_driver_pcc.c @@ -0,0 +1,421 @@ +/** + * @file fc7xxx_driver_pcc.c + * @author Flagchip + * @brief FC7xxx PCC driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ + +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 +********************************************************************************/ + +#include "fc7xxx_driver_pcc.h" +#include "fc7xxx_driver_scg.h" +#include "fc7xxx_board_conf.h" + +/***************** mcaro *********************/ +/* PCC property MACRO, defines every peripheral clock system architecture */ +#define PCC_CLK_NOT_APPLY (0U) +#define PCC_CGC_AVAILABLE (1U << 0U) +#define PCC_FUNCCLK_MUXDIVH_USED (1U << 1U) +#define PCC_FUNCCLK_MUXDIVM_USED (1U << 2U) +#define PCC_FUNCCLK_MUXDIVL_USED (1U << 3U) +#define PCC_FUNCCLK_MUXDIVHPIN_USED (1U << 4U) +#define PCC_MOUDULE_DIV_USED (1U << 5U) +#define PCC_CLK_DOMAIN_CORE (1U << 6U) +#define PCC_CLK_DOMAIN_BUS (1U << 7U) +#define PCC_CLK_DOMAIN_SLOW (1U << 8U) +#define PCC_DWP_SWR_AVAILABLE (0U << 9U) + +#define PCC_PROPERTY_MUXDIV_MASK (PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVM_USED | PCC_FUNCCLK_MUXDIVL_USED) +#define PCC_PROPERTY_MUXDIV_ALL_MASK (PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVM_USED | PCC_FUNCCLK_MUXDIVL_USED | PCC_FUNCCLK_MUXDIVHPIN_USED) + +/***************** Type define *********************/ +/** + * @brief PCC clock attribution. + * @param u32RegOffset: the register offset base on PCC module base address 0x4002_4000h + * @param u8ClockProperty include clock domain and clock MUX information by bit filed setting. + */ +typedef struct +{ + uint32_t u32RegOffset; + uint32_t u32ClockProperty; +} PCC_ClockMapType; + +/** + * @brief PCC peripheral clock index map to SCG clock source + * @param ePccClkIndex: PCC peripheral clock index + * @param eScgClkIndex SCG clock source + */ +typedef struct +{ + PCC_ClkGateSrcType ePccClkIndex; + SCG_ClkSrcType eScgClkIndex; +} PCC_ClockIndexMap; + +/***************** Local Variables *********************/ +/** + * @brief PCC clock index to SCG clock source map. +*/ +static const PCC_ClockIndexMap s_tPccClocIndexkMap[PCC_MUX_MAX_NUMBER] = { + {PCC_CLKGATE_SRC_OFF_OR_TCLK, SCG_END_OF_CLOCKS}, + {PCC_CLKGATE_SRC_FOSCDIV, SCG_FOSCDIVH_CLK}, + {PCC_CLKGATE_SRC_SIRCDIV, SCG_SIRCDIVH_CLK}, + {PCC_CLKGATE_SRC_FIRCDIV, SCG_FIRCDIVH_CLK}, + {PCC_CLKGATE_SRC_RESERVE0, SCG_END_OF_CLOCKS}, + {PCC_CLKGATE_SRC_PLL1DIV, SCG_PLL1DIVH_CLK}, + {PCC_CLKGATE_SRC_PLL0DIV, SCG_PLL0DIVH_CLK}, + {PCC_CLKGATE_SRC_RESERVE1, SCG_END_OF_CLOCKS} +}; + +/** + * @brief clock attribution map. + */ +static const PCC_ClockMapType s_tPccClockMap[PCC_END_OF_CLOCKS] = +{ + {0x20, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* DMA0 */ + {0x28, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* DMAMUX0 */ + {0x4C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* ROMC */ + {0x60, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* ERM0 */ + {0x64, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* EIM0 */ + {0x68, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* INTM0 */ + {0x6C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* ISM0 */ + {0x88, PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* WDOG0 */ + {0x98, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL0 */ + {0x9C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL1 */ + {0xA0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL2 */ + {0xA4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL3 */ + {0xA8, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* CRC0 */ + {0xAC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* CORDIC */ + {0xB0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* TSTMP0 */ + {0xB4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* TSTMP1 */ + {0xB8, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_DWP_SWR_AVAILABLE}, /* FCPIT0 */ + {0xBC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_FUNCCLK_MUXDIVL_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* AONTIMER0 */ + {0xC0, PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* RTC */ + {0xC4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU0 */ + {0xC8, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU1 */ + {0xCC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU2 */ + {0xD0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU3 */ + {0xD4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU4 */ + {0xDC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* PTIMER0 */ + {0xE0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* PTIMER1 */ + {0xEC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* ADC0 */ + {0xF0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* ADC1 */ + {0xFC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* WKU0 */ + {0x100, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMP0 */ + {0x104, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMP1 */ + {0x10C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_FUNCCLK_MUXDIVL_USED | PCC_DWP_SWR_AVAILABLE}, /* TMU0 */ + {0x150, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVL_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* SENT0 */ + {0x160, PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* MB0 */ + {0x170, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU0 */ + {0x174, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU1 */ + {0x178, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU2 */ + {0x17C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU3 */ + {0x188, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI0 */ + {0x18C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI1 */ + {0x190, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI2 */ + {0x198, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCIIC0 */ + {0x1A0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART0 */ + {0x1A4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART1 */ + {0x1A8, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART2 */ + {0x1AC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART3 */ + {0x1C0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* LU0 */ + {0x1E0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* FREQM */ + {0x1FC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* STCU */ + {0x200, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* FLEXCAN0 */ + {0x210, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* FLEXCAN1 */ + {0x34C, PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* WDOG1 */ + {0x36C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL4 */ + {0x370, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL5 */ + {0x37C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI3 */ + {0x380, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI4 */ + {0x384, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI5 */ + {0x3FC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU4 */ + {0x400, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU5 */ + {0x404, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU6 */ + {0x408, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU7 */ + {0x41C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCIIC1 */ + {0x420, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART4 */ + {0x424, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART5 */ + {0x428, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART6 */ + {0x42C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART7 */ + {0x450, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* MSC0 */ + {0x480, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* FLEXCAN2 */ + {0x490, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* FLEXCAN3 */ +}; + +/***************** Local Prototype Functions *********************/ + +/***************** Local Functions *********************/ + +/***************** Global Functions *********************/ + +/** + * @brief get PCC function clock status and value. + * + * @param pcc_ClkSrcType eClockName: used for choose PCC clock source to query. + */ +uint32_t PCC_GetPccFunctionClock(const PCC_ClkSrcType eClockName) +{ + uint32_t u32DivVal; + PCC_ClkGateSrcType eSelVal; + uint32_t u32ScgClkIndex = 0U; + uint32_t u32FunctionFreqVal = 0U; + uint32_t u32RegVal, u32ScgClkDivIndex; + const PCC_ClockMapType *pAttributeVal; + + DEV_ASSERT((uint32_t)eClockName < (uint32_t)PCC_END_OF_CLOCKS); + + /* Get peripheral PCC register value */ + u32RegVal = PCC_HWA_GetRegister(s_tPccClockMap[(uint32_t)eClockName].u32RegOffset); + pAttributeVal = &s_tPccClockMap[(uint32_t)eClockName]; + + /* Check peripheral PCC is valid or not and peripheral have function clock or not */ + if ((PCC_CGC_MASK == (u32RegVal & PCC_CGC_MASK)) && (0U != (pAttributeVal->u32ClockProperty & PCC_PROPERTY_MUXDIV_ALL_MASK))) + { + eSelVal = (PCC_ClkGateSrcType)((uint8_t)PCC_GetSEL(u32RegVal)); + /* Get PCC divide value */ + if (PCC_MOUDULE_DIV_USED == (pAttributeVal->u32ClockProperty & PCC_MOUDULE_DIV_USED)) + { + u32DivVal = PCC_GetDIV(u32RegVal) + (uint32_t)1U; + } + else + { + u32DivVal = 1U; + } + + /* Get peripheral function clock source which is from SCG or TCLK */ + if (PCC_CLKGATE_SRC_OFF_OR_TCLK == eSelVal) + { + if (PCC_FUNCCLK_MUXDIVHPIN_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVHPIN_USED)) + { + u32FunctionFreqVal = PCC_FTU_TCLK_FREQ; + } + else + { + u32FunctionFreqVal = 0U; + } + } + else + { + if (PCC_FUNCCLK_MUXDIVH_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVH_USED)) + { + u32ScgClkDivIndex = 0U; + } + else if (PCC_FUNCCLK_MUXDIVM_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVM_USED)) + { + u32ScgClkDivIndex = 1U; + } + else if (PCC_FUNCCLK_MUXDIVL_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVL_USED)) + { + u32ScgClkDivIndex = 2U; + } + else + { + u32ScgClkDivIndex = 0U; + } + u32ScgClkIndex = (uint32_t)s_tPccClocIndexkMap[eSelVal].eScgClkIndex + u32ScgClkDivIndex; + } + + /* If clock source is valid, calculate peripheral function clock */ + if (u32ScgClkIndex < (uint32_t)SCG_END_OF_CLOCKS) + { + u32FunctionFreqVal = SCG_GetScgClockFreq((SCG_ClkSrcType)u32ScgClkIndex) / u32DivVal; + } + } + + return u32FunctionFreqVal; +} + +/** + * @brief get PCC interface clock status and value. + * + * @param pcc_ClkSrcType eClockName: used for choose PCC clock source to query. + */ +uint32_t PCC_GetPccInterfaceClock(const PCC_ClkSrcType eClockName) +{ + uint32_t u32InterfaceFreqVal, u32AttributeVal; + + DEV_ASSERT((uint32_t)eClockName < (uint32_t)PCC_END_OF_CLOCKS); + + u32AttributeVal = s_tPccClockMap[(uint32_t)eClockName].u32ClockProperty; + if (PCC_CLK_DOMAIN_BUS == (u32AttributeVal & PCC_CLK_DOMAIN_BUS)) + { + u32InterfaceFreqVal = SCG_GetScgClockFreq(SCG_BUS_CLK); + } + else if (PCC_CLK_DOMAIN_SLOW == (u32AttributeVal & PCC_CLK_DOMAIN_SLOW)) + { + u32InterfaceFreqVal = SCG_GetScgClockFreq(SCG_SLOW_CLK); + } + else + { + u32InterfaceFreqVal = 0U; + } + + return u32InterfaceFreqVal; +} + + +/** + * @brief set PCC one peripheral clock configuration. + * + * @param PCC_CtrlType* pConfig: the PCC initialize value point set by user. + * @return PCC_StatusType pcc function status + */ +PCC_StatusType PCC_SetPcc(const PCC_CtrlType *const pConfig) +{ + PCC_StatusType eStatus = PCC_STATUS_SUCCESS; + uint32_t u32DivVal; + uint32_t u32ScgClkIndex = 0U, u32ScgClkDivIndex; + uint32_t u32FreqVal = 0U; + uint32_t u32FunctionFreqVal = 0U; + uint32_t u32RegVal = 0U; + uint32_t u32ExpectedRegVal; + const PCC_ClockMapType *pAttributeVal; + + DEV_ASSERT(NULL_PTR != pConfig); + DEV_ASSERT((uint32_t)pConfig->eClockName < (uint32_t)PCC_END_OF_CLOCKS); + + pAttributeVal = &s_tPccClockMap[(uint32_t)pConfig->eClockName]; + /* check peripheral clock domain to calculate module clock */ + if (PCC_CLK_DOMAIN_BUS == (pAttributeVal->u32ClockProperty & PCC_CLK_DOMAIN_BUS)) + { + u32FreqVal = SCG_GetScgClockFreq(SCG_BUS_CLK); + } + else if (PCC_CLK_DOMAIN_SLOW == (pAttributeVal->u32ClockProperty & PCC_CLK_DOMAIN_SLOW)) + { + u32FreqVal = SCG_GetScgClockFreq(SCG_SLOW_CLK); + } + else + { + /* Do nothing */ + } + + if (0U == u32FreqVal) + { + /* Please call SCG function first */ + eStatus = PCC_STATUS_CLOCK_INVALID; + } + + if (PCC_STATUS_SUCCESS == eStatus) + { + /* Disable PCC gate */ + PCC_HWA_SetClockGateControl(pAttributeVal->u32RegOffset,false); + if (pConfig->bEn) + { + if (PCC_MOUDULE_DIV_USED == (pAttributeVal->u32ClockProperty & PCC_MOUDULE_DIV_USED)) + { + u32DivVal = (uint32_t)pConfig->eDivider + (uint32_t)1U; + u32RegVal |= PCC_DIV(pConfig->eDivider); + } + else + { + u32DivVal = 1U; + } + + if (0U != (pAttributeVal->u32ClockProperty & PCC_PROPERTY_MUXDIV_ALL_MASK)) + { + u32RegVal |= PCC_SEL(pConfig->eClkSrc); + } + + if (PCC_CGC_AVAILABLE == (pAttributeVal->u32ClockProperty & PCC_CGC_AVAILABLE)) + { + /* Enable peripheral clock */ + u32RegVal |= PCC_CGC_MASK; + } + + /* Configure PCC register */ + PCC_HWA_SetRegister(pAttributeVal->u32RegOffset,u32RegVal); + + /* Get peripheral function clock source which is from SCG or TCLK */ + if (PCC_CLKGATE_SRC_OFF_OR_TCLK == pConfig->eClkSrc) + { + if (PCC_FUNCCLK_MUXDIVHPIN_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVHPIN_USED)) + { + u32FunctionFreqVal = PCC_FTU_TCLK_FREQ; + } + else + { + u32FunctionFreqVal = 0U; + } + } + else if (PCC_CLKGATE_UNINVOLVED == pConfig->eClkSrc) + { + /* do nothing */ + } + else + { + if (PCC_FUNCCLK_MUXDIVH_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVH_USED)) + { + u32ScgClkDivIndex = 0U; + } + else if (PCC_FUNCCLK_MUXDIVM_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVM_USED)) + { + u32ScgClkDivIndex = 1U; + } + else if (PCC_FUNCCLK_MUXDIVL_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVL_USED)) + { + u32ScgClkDivIndex = 2U; + } + else + { + u32ScgClkDivIndex = 0U; + } + u32ScgClkIndex = (uint32_t)s_tPccClocIndexkMap[(uint32_t)pConfig->eClkSrc].eScgClkIndex + u32ScgClkDivIndex; + } + + /* Calculate peripheral function clock */ + if (u32ScgClkIndex < (uint32_t)SCG_END_OF_CLOCKS) + { + u32FunctionFreqVal = SCG_GetScgClockFreq((SCG_ClkSrcType)u32ScgClkIndex) / u32DivVal; + } + u32ExpectedRegVal = u32RegVal; + } + else + { + /* Clear PCC register */ + PCC_HWA_SetRegister(pAttributeVal->u32RegOffset,0U); + u32ExpectedRegVal = 0U; + u32FunctionFreqVal = 0U; + } + + /* Check PCC register has been configured, If current CPU do not have permission to configure the PCC register, the except value + * will not match the actual value */ + if (u32ExpectedRegVal != PCC_HWA_GetRegister(pAttributeVal->u32RegOffset)) + { + /* In this case, current core does not have permission to control the register */ + eStatus = PCC_STATUS_CONFIGURED_NOT_SUPPORT; + } + else if (u32FunctionFreqVal > 160000000U) + { + /* In this case, current function clock too high, must configured below 150M */ + eStatus = PCC_STATUS_CONFIGURED_NOT_SUPPORT; + } + else + { + /* do nothing */ + } + } + + return eStatus; +} + +/** + * @brief Generate peripheral reset + * + */ +void PCC_GenPeripheralReset(const PCC_ClkSrcType eClockName) +{ + DEV_ASSERT((uint32_t)eClockName < (uint32_t)PCC_END_OF_CLOCKS); + PCC_HWA_SoftwareReset(s_tPccClockMap[(uint32_t)eClockName].u32RegOffset); +} + + diff --git a/Src/fc7xxx_driver_pmc.c b/Src/fc7xxx_driver_pmc.c new file mode 100644 index 0000000..1d8a4cd --- /dev/null +++ b/Src/fc7xxx_driver_pmc.c @@ -0,0 +1,175 @@ +/* @file fc7xxx_driver_pmc.c +* @author Flagchip032 +* @brief FC7xxx PMC driver type definition and API +* @version 0.1.0 +* @date 2022-11-21 +* +* @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. +* +*/ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials Descriptions + * --------- ---------- ------------ --------------- + * 0.1.0 2022-11-21 Flagchip032 First version for FC7xxx + ******************************************************************************** */ +#include "fc7xxx_driver_pmc.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/***************** Local variable *********************/ +static PMC_VolIntCallbackType pIsrNotify = NULL_PTR; + + +/***************** prototype *********************/ +/** + * @brief PMC interrupt function entry + * + */ +void PMC_IRQHandler(void); + +/***************** Global Functions *********************/ +/** + * @brief Get LVCSRRegister Value + * + * @return uint32_t LVCSRRegister Value + */ +uint32_t PMC_GetLVCSRRegister(void) +{ + return PMC_HWA_GetLVCSRRegister(); +} + +/** + * @brief Get All voltage flag + * + * @return uint32_t All voltage flag + */ +uint32_t PMC_GetAllVolFlag(void) +{ + uint32_t u32AllVolFlag = 0U; + u32AllVolFlag = (PMC_HWA_GetLVCSRRegister() & PMC_LVCSR_ALLFLAG_MASK); + return u32AllVolFlag; +} + +/** + * @brief Get specific voltage flag + * + * @param eFlag Voltage flag + * @return boolean If return true, the specific voltage flag is 0, otherwise, the flag is 1. + */ +boolean PMC_GetSpecificVolFlag(const PMC_FlagType eFlag) +{ + return ((PMC_HWA_GetLVCSRRegister() & eFlag) != 0U) ? true : false; +} + +/** + * @brief Clear all voltage flag + * + */ +void PMC_ClearAllVolFlag(void) +{ + PMC_HWA_SetLVCSRRegister(PMC_LVCSR_ALLFLAG_MASK); +} + +/** + * @brief Clear specific voltage flag + * + * @param eFlag Voltage flag + */ +void PMC_ClearSpecificVolFlag(const PMC_FlagType eFlag) +{ + PMC_HWA_SetLVCSRRegister(eFlag); +} + +/** + * @brief Get All voltage status + * + * @return uint32_t All voltage status + */ +uint32_t PMC_GetAllVolStatus(void) +{ + uint32_t u32AllVolStatus = 0U; + u32AllVolStatus = (PMC_HWA_GetLVCSRRegister() & PMC_LVCSR_ALLSTATUS_MASK); + return u32AllVolStatus; +} + +/** + * @brief Get specific voltage status + * + * @param eStatus Specific voltage status + * @return boolean If return true, the specific voltage status is 0, otherwise, the status is 1. + */ +boolean PMC_GetSpecificVolStatus(const PMC_StatusType eStatus) +{ + return ((PMC_HWA_GetLVCSRRegister() & eStatus) != 0U) ? true : false; +} + +/** + * @brief Configure Voltage + * + * @param pCtrl Configuration of voltage + */ +void PMC_ConfigVoltage(const PMC_CtrlType *const pCtrl) +{ + uint32_t u32ConfigVal = 0U; + PMC_HWA_UnlockConfigRegister(); + + if ((pCtrl->bLvdIntEn) || (pCtrl->bHvdIntEn) || (pCtrl->b5VBMonEn) \ + || (pCtrl->bRpmV25En) || (pCtrl->bV15AutoswEn) || (pCtrl->bV15CtrlEn)) + { + pIsrNotify = pCtrl->pIsrNotify; + } + + u32ConfigVal = PMC_CONFIG_LVD_IE(pCtrl->bLvdIntEn) | PMC_CONFIG_HVD_IE(pCtrl->bHvdIntEn) | PMC_CONFIG_V15_CTRL_EN(pCtrl->bV15CtrlEn) | PMC_CONFIG_V15_AUTOSW( + pCtrl->bV15AutoswEn) | PMC_CONFIG_RPM_VDD2P5_EN(pCtrl->bRpmV25En); + PMC_HWA_SetConfigRegister(u32ConfigVal); +} + +/** + * @brief Clear all PMC register + * + */ +void PMC_Deinit(void) +{ + PMC_HWA_SetLVCSRRegister(0x93ff0030U); + PMC_HWA_SetConfigRegister(0x8000U); +} + +/** + * @brief PMC interrupt function entry + * + */ +void PMC_IRQHandler(void) +{ + if (NULL_PTR != pIsrNotify) + { + pIsrNotify(); + } + if(PMC_GetSpecificVolFlag(PMC_HVD5V_FLAG)) + { + PMC_ClearSpecificVolFlag(PMC_HVD5V_FLAG); + } + if (PMC_GetSpecificVolFlag(PMC_HVD2P5V_FLAG)) + { + PMC_ClearSpecificVolFlag(PMC_HVD2P5V_FLAG); + } + if (PMC_GetSpecificVolFlag(PMC_HVD1P1V_FLAG)) + { + PMC_ClearSpecificVolFlag(PMC_HVD1P1V_FLAG); + } + if (PMC_GetSpecificVolFlag(PMC_LVD5V_FLAG)) + { + PMC_ClearSpecificVolFlag(PMC_LVD5V_FLAG); + } + if (PMC_GetSpecificVolFlag(PMC_LVD1P5V_FLAG)) + { + PMC_ClearSpecificVolFlag(PMC_LVD1P5V_FLAG); + } + if (PMC_GetSpecificVolFlag(PMC_HVD1P5V_FLAG)) + { + PMC_ClearSpecificVolFlag(PMC_HVD1P5V_FLAG); + } +} diff --git a/Src/fc7xxx_driver_port.c b/Src/fc7xxx_driver_port.c new file mode 100644 index 0000000..d83178d --- /dev/null +++ b/Src/fc7xxx_driver_port.c @@ -0,0 +1,486 @@ +/** + * @file fc7xxx_driver_port.c + * @author Flagchip + * @brief FC7xxx PORT driver type definition and API + * @version 0.1.0 + * @date 2023-2-4 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 31/12/2022 Flagchip0121 N/A First version for FC7240 +********************************************************************************/ +#include "fc7xxx_driver_port.h" +#include "interrupt_manager.h" + +/** @brief PORTA interrupt entry */ +void PORTA_IRQHandler(void); +/** @brief PORTB interrupt entry */ +void PORTB_IRQHandler(void); +/** @brief PORTC interrupt entry */ +void PORTC_IRQHandler(void); +/** @brief PORTD interrupt entry */ +void PORTD_IRQHandler(void); +/** @brief PORTE interrupt entry */ +void PORTE_IRQHandler(void); + + + +/********* Local Variables ************/ +/** @brief PORT instance list */ +static PORT_Type *const s_pPortInstanceTable[PORT_INSTANCE_COUNT] = PORT_BASE_PTRS; +/** @brief PORT user defined interrupt function */ +static PORT_PinInterruptCallBackType s_pPortPinNotifyTable[PORT_PIN_NUM_MAX] = {NULL}; +/** @brief PORT interrupt mode table */ +static PORT_IntConfigType s_aPortPinIrqTable[PORT_PIN_NUM_MAX] = {PORT_IRQ_DISABLE}; +/** @brief port common interrupt handle function */ +static void Port_CommonProcessInterrupt(const PORT_InstanceType ePort, const uint8_t u8Pin); + + +/***************PORT Global Functions*****************/ +/** + * @brief Initialize port + * + * @param ePort Port instance + * @param pInitStruct Initialization structure of port + * @return Port return type. + */ +PORT_StatusType PORT_InitPins(const PORT_InstanceType ePort, const PORT_InitType *const pInitStruct) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + PORT_Type *pPort; + uint32_t u32PcrRegValue = 0U; + uint32_t u32LowPcrRegValue = 0U; + uint32_t u32HighPcrRegValue = 0U; + + if (((uint32_t)ePort >= PORT_INSTANCE_COUNT) || (NULL == pInitStruct)) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + pPort = s_pPortInstanceTable[(uint32_t)ePort]; + + u32PcrRegValue |= PORT_PCR_MUX(pInitStruct->uPortPinMux.u32PortPinMode); + + u32PcrRegValue |= PORT_PCR_IRQC(pInitStruct->eTriggrtMode); + + u32PcrRegValue |= PORT_PCR_PE(pInitStruct->bPullEn); + u32PcrRegValue |= PORT_PCR_PS(pInitStruct->ePullSel); + + u32PcrRegValue |= PORT_PCR_DSE0(pInitStruct->bDrvStrength0En); + u32PcrRegValue |= PORT_PCR_DSE1(pInitStruct->bDrvStrength1En); + + u32PcrRegValue |= PORT_PCR_PFE(pInitStruct->u8PassiveFilterEn); + + u32PcrRegValue |= PORT_PCR_ISF_MASK; + + u32LowPcrRegValue = u32PcrRegValue & PORT_PCR_LOW_16BITS_MASK; + u32HighPcrRegValue = u32PcrRegValue & PORT_PCR_HIGH_16BITS_MASK; + + PORT_HWA_WriteGPCLR(pPort,pInitStruct->u32PortPins,u32LowPcrRegValue); + PORT_HWA_WriteGPCHR(pPort,pInitStruct->u32PortPins,u32LowPcrRegValue); + PORT_HWA_WriteGICLR(pPort,pInitStruct->u32PortPins,u32HighPcrRegValue); + PORT_HWA_WriteGICHR(pPort,pInitStruct->u32PortPins,u32HighPcrRegValue); + } + return eRet; +} + +/** + * @brief De-initialize the Port instance + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + * @return Port return type. + */ +PORT_StatusType PORT_Deinit(const PORT_InstanceType ePort, const uint32_t u32Pins) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + PORT_Type *pPort = s_pPortInstanceTable[ePort]; + uint8_t u8PinIndex = 0U; + uint32_t u32TempPins = u32Pins; + if ((uint32_t)ePort >= PORT_INSTANCE_COUNT) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + while (u32TempPins != 0u) + { + if ((u32TempPins & ((uint32_t)1 << u8PinIndex)) != 0u) + { + PORT_HWA_ConfigPin(pPort, u8PinIndex, (uint32_t)0U); + s_aPortPinIrqTable[PORT_PIN_NUM(ePort, u8PinIndex)] = PORT_IRQ_DISABLE; + s_pPortPinNotifyTable[PORT_PIN_NUM(ePort, u8PinIndex)] = NULL; + } + u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); + u8PinIndex++; + } + } + return eRet; +} + +/** + * @brief Enable interrupt function of port + * + * @param ePort Port instance enumeration + * @param pIntStruct Interrupt structure of port. + * @return Port return type. + */ +PORT_StatusType PORT_InitInterrupt(const PORT_InstanceType ePort, const PORT_InterruptType *const pIntStruct) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + uint8_t u8PinIndex = 0U; + uint32_t u32TempPins = 0U; + PORT_Type *pPort = s_pPortInstanceTable[ePort]; + if (((uint32_t)ePort >= PORT_INSTANCE_COUNT) || (NULL == pIntStruct)) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + u32TempPins = pIntStruct->u32PortPins; + while (u32TempPins != 0u) + { + if ((u32TempPins & ((uint32_t)1 << u8PinIndex)) != 0u) + { + PORT_HWA_ClearPinInterruptFlag(pPort, u8PinIndex); + PORT_HWA_SetPinInterruptMode(pPort, u8PinIndex, (PORT_IntConfigType)pIntStruct->ePortIsrMode); + + s_aPortPinIrqTable[PORT_PIN_NUM(ePort, u8PinIndex)] = pIntStruct->ePortIsrMode; + if (NULL != pIntStruct->pIsrNotify) + { + s_pPortPinNotifyTable[PORT_PIN_NUM(ePort, u8PinIndex)] = pIntStruct->pIsrNotify; + } + } + + u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); + u8PinIndex++; + } + /* IntMgr_EnableInterrupt((IRQn_Type)((uint32_t)PORTA_IRQn + (uint32_t)ePort)); */ + } + return eRet; +} + +/** + * @brief Enable interrupt function of port + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + * @return Port return type. + */ +PORT_StatusType PORT_EnableInterrupt(const PORT_InstanceType ePort, const uint32_t u32Pins) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + uint8_t u8PinIndex = 0U; + uint32_t u32TempPins = u32Pins; + PORT_Type *pPort = s_pPortInstanceTable[ePort]; + if ((uint32_t)ePort >= PORT_INSTANCE_COUNT) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + while (u32TempPins != 0u) + { + if ((u32TempPins & ((uint32_t)1 << u8PinIndex)) != 0u) + { + PORT_HWA_ClearPinInterruptFlag(pPort, u8PinIndex); + PORT_HWA_SetPinInterruptMode(pPort, u8PinIndex, (PORT_IntConfigType)s_aPortPinIrqTable[PORT_PIN_NUM(ePort, + u8PinIndex)]); + } + u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); + u8PinIndex++; + } + } + return eRet; +} + +/** + * @brief Disable interrupt function of port + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + * @return Port return type. + */ +PORT_StatusType PORT_DisableInterrupt(const PORT_InstanceType ePort, const uint32_t u32Pins) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + uint8_t u8PinIndex = 0U; + uint32_t u32TempPins = u32Pins; + PORT_Type *pPort = s_pPortInstanceTable[ePort]; + if ((uint32_t)ePort >= PORT_INSTANCE_COUNT) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + while (u32TempPins != 0u) + { + if ((u32TempPins & ((uint32_t)1 << u8PinIndex)) != 0u) + { + PORT_HWA_ClearPinInterruptFlag(pPort, u8PinIndex); + PORT_HWA_ClearPinInterruptMode(pPort, u8PinIndex); + } + u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); + u8PinIndex++; + } + } + return eRet; +} + +PORT_StatusType PORT_SetPinsDmaReqMode(const PORT_InstanceType ePort, const uint32_t u32Pins, const PORT_DMAReqType eDMAReqMode) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + uint8_t u8PinIndex = 0U; + uint32_t u32TempPins = u32Pins; + PORT_Type *pPort = s_pPortInstanceTable[ePort]; + if ((uint32_t)ePort >= PORT_INSTANCE_COUNT) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + while (u32TempPins != 0u) + { + if ((u32TempPins & ((uint32_t)1 << u8PinIndex)) != 0u) + { + PORT_HWA_SetPinDMAReqMode(pPort, u8PinIndex, eDMAReqMode); + } + u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); + u8PinIndex++; + } + } + return eRet; +} + +/** + * @brief Initialize digital filter for Port instance + * + * @param ePort Port instance enumeration + * @param pDFStruct Digital filter initialization structure of port + * @return Port return type. + */ +PORT_StatusType PORT_InitDigitalFilterPort(const PORT_InstanceType ePort, const PORT_DigitalFilterType *pDFStruct) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + PORT_Type *pPort = s_pPortInstanceTable[ePort]; + if ((NULL == pDFStruct) || ((uint32_t)ePort >= PORT_INSTANCE_COUNT)) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + if (pDFStruct->u32PortPinsEn != 0u) + { + if (PORT_FILTER_AON32K_CLK == pDFStruct->eClkSrc) + { + PORT_HWA_SetDigitalFilterClkSrc(pPort, pDFStruct->eClkSrc); + } + else + { + PORT_HWA_ClearDigitalFilterClkSrc(pPort); + } + PORT_HWA_ConfigDigitalFilterWidth(pPort, (uint32_t)pDFStruct->u8FilterLength); + PORT_HWA_ConfigDigitalFilter(pPort, pDFStruct->u32PortPinsEn); + } + } + return eRet; +} + +/** + * @brief De-initialize digital filter for Port instance + * + * @param ePort Port instance enumeration + * @return Port return type. + */ +PORT_StatusType PORT_DeinitDigitalFilterPort(const PORT_InstanceType ePort) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + PORT_Type *pPort = s_pPortInstanceTable[ePort]; + if ((uint32_t)ePort >= PORT_INSTANCE_COUNT) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + PORT_HWA_ClearDigitalFilterClkSrc(pPort); + PORT_HWA_ClearDigitalFilterWidth(pPort); + PORT_HWA_ClearDigitalFilterEnable(pPort); + } + return eRet; +} + +/** + * @brief Enable the digital filter function for the specific pin. + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + * @return Port return type. + */ +PORT_StatusType PORT_EnableDigitalFilterPin(const PORT_InstanceType ePort, const uint32_t u32Pins) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + uint8_t u8PinIndex = 0U; + uint32_t u32TempPins = u32Pins; + PORT_Type *pPort; + if ((uint32_t)ePort >= PORT_INSTANCE_COUNT) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + pPort = s_pPortInstanceTable[ePort]; + while (u32TempPins != 0u) + { + if ((u32TempPins & ((uint32_t)1 << u8PinIndex)) != 0u) + { + PORT_HWA_SetDigitalFilterEnable(pPort, u8PinIndex); + } + u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); + u8PinIndex++; + } + } + return eRet; +} + +/** + * @brief Disable the digital filter function for the specific pin. + * + * @param ePort Port instance enumeration + * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. + */ +PORT_StatusType PORT_DisableDigitalFilterPin(const PORT_InstanceType ePort, const uint32_t u32Pins) +{ + PORT_StatusType eRet = PORT_STATUS_SUCCESS; + uint8_t u8PinIndex = 0U; + uint32_t u32TempPins = u32Pins; + PORT_Type *pPort; + if ((uint32_t)ePort >= PORT_INSTANCE_COUNT) + { + eRet = PORT_STATUS_PARAM_INVALID; + } + else + { + pPort = s_pPortInstanceTable[ePort]; + while (u32TempPins != 0u) + { + if ((u32TempPins & ((uint32_t)1 << u8PinIndex)) != 0u) + { + PORT_HWA_ClearDigitalFilterPin(pPort, u8PinIndex); + } + u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); + u8PinIndex++; + } + } + return eRet; +} + + +/** + * \brief port common interrupt handle function + * + * \param ePort port instance + * \param u8Pin bit of u8Pin indicate pin number + */ +static void Port_CommonProcessInterrupt(const PORT_InstanceType ePort, const uint8_t u8Pin) +{ + if (NULL != s_pPortPinNotifyTable[PORT_PIN_NUM(ePort, u8Pin)]) + { + s_pPortPinNotifyTable[PORT_PIN_NUM(ePort, u8Pin)](); + } +} + + +/***************PORT IRQ Functions*****************/ +/** + * \brief PORTA interrupt entry + * + */ +void PORTA_IRQHandler(void) +{ + uint8_t u8PinIndex; + for (u8PinIndex = 0U; u8PinIndex < (uint32_t)32; u8PinIndex++) + { + if (PORT_HWA_ReadPinInterruptFlag(PORTA, u8PinIndex)) + { + PORT_HWA_ClearPinInterruptFlag(PORTA, u8PinIndex); + Port_CommonProcessInterrupt(PORT_A, u8PinIndex); + } + } +} + +/** + * \brief PORTB interrupt entry + * + */ +void PORTB_IRQHandler(void) +{ + uint8_t u8PinIndex; + for (u8PinIndex = 0U; u8PinIndex < (uint8_t)32; u8PinIndex++) + { + if (PORT_HWA_ReadPinInterruptFlag(PORTB, u8PinIndex)) + { + PORT_HWA_ClearPinInterruptFlag(PORTB, u8PinIndex); + Port_CommonProcessInterrupt(PORT_B, u8PinIndex); + } + } +} + +/** + * \brief PORTC interrupt entry + * + */ +void PORTC_IRQHandler(void) +{ + uint8_t u8PinIndex; + for (u8PinIndex = 0U; u8PinIndex < (uint8_t)32; u8PinIndex++) + { + if (PORT_HWA_ReadPinInterruptFlag(PORTC, u8PinIndex)) + { + PORT_HWA_ClearPinInterruptFlag(PORTC, u8PinIndex); + Port_CommonProcessInterrupt(PORT_C, u8PinIndex); + } + } +} + +/** + * \brief PORTD interrupt entry + * + */ +void PORTD_IRQHandler(void) +{ + uint8_t u8PinIndex; + for (u8PinIndex = 0U; u8PinIndex < (uint8_t)32; u8PinIndex++) + { + if (PORT_HWA_ReadPinInterruptFlag(PORTD, u8PinIndex)) + { + PORT_HWA_ClearPinInterruptFlag(PORTD, u8PinIndex); + Port_CommonProcessInterrupt(PORT_D, u8PinIndex); + } + } +} + +/** + * \brief PORTE interrupt entry + * + */ +void PORTE_IRQHandler(void) +{ + uint8_t u8PinIndex; + for (u8PinIndex = 0U; u8PinIndex < (uint8_t)32; u8PinIndex++) + { + if (PORT_HWA_ReadPinInterruptFlag(PORTE, u8PinIndex)) + { + PORT_HWA_ClearPinInterruptFlag(PORTE, u8PinIndex); + Port_CommonProcessInterrupt(PORT_E, u8PinIndex); + } + } +} + diff --git a/Src/fc7xxx_driver_ptimer.c b/Src/fc7xxx_driver_ptimer.c new file mode 100644 index 0000000..cc5d945 --- /dev/null +++ b/Src/fc7xxx_driver_ptimer.c @@ -0,0 +1,326 @@ +/** + * @file fc7xxx_driver_ptimer.c + * @author Flagchip0126 + * @brief FC7xxx PTIMER driver source code + * @version 0.1.0 + * @date 2024-01-15 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Author CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-15 Flagchip0126 N/A First version for FC7240 + ******************************************************************************** */ + +#include + +#include "fc7xxx_driver_ptimer.h" +#include "fc7xxx_driver_scg.h" +#include "HwA_scm.h" + +static PTIMER_Type *const s_apPtimerBase[PTIMER_INSTANCE_COUNT] = PTIMER_BASE_PTRS; + +static uint8_t s_u8ChnNum[PTIMER_INSTANCE_COUNT] = {0U}; + +static PTIMER_InterruptCallbackType s_apPtimerIntNotify[PTIMER_INSTANCE_COUNT] = {NULL}; +static PTIMER_SeqErrorCallbackType s_apPtimerSeqErrorNotify[ADC_INSTANCE_COUNT] = {NULL}; + +/** + * @brief Calculate the delay value base on the delay micro seconds + * + * @param eInstance the Ptimer instance to use + * @param u32DelayUs the delay time in micro seconds + * @return uint16_t the delay time in ptimer clock count + */ +static uint16_t PTIMER_CalcDelayValue(const PTIMER_InstanceType eInstance, const uint32_t u32DelayUs); + +/** + * @brief the internal Ptimer interrupt handler + * + * @param eInstance the Ptimer instance to use + */ +static void PTIMERn_IRQHandler(const PTIMER_InstanceType eInstance); + +void PTIMER0_IRQHandler(void); + +void PTIMER1_IRQHandler(void); + +static uint16_t PTIMER_CalcDelayValue(const PTIMER_InstanceType eInstance, const uint32_t u32DelayUs) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + const PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + + uint32_t u32DelayVal; + uint32_t u32SysFreq; + uint32_t u32PtimerFreqUs = 0U; + PTIMER_ClockPreDividerType ePreDivider = PTIMER_HWA_GetDivPrescaler(pPtimer); + PTIMER_ClockPreDivMultiplyFactorType ePreDivMultFactor = PTIMER_HWA_GetDivMultiply(pPtimer); + uint8_t u8Prescaler = (1U << ePreDivider); + uint8_t u8PrescalerMult = 1U; + + switch (ePreDivMultFactor) + { + case PTIMER_PRE_DIVIDER_MULTIPLY_BY_1: + u8PrescalerMult = 1U; + break; + + case PTIMER_PRE_DIVIDER_MULTIPLY_BY_10: + u8PrescalerMult = 10U; + break; + + case PTIMER_PRE_DIVIDER_MULTIPLY_BY_20: + u8PrescalerMult = 20U; + break; + + case PTIMER_PRE_DIVIDER_MULTIPLY_BY_40: + u8PrescalerMult = 40U; + break; + + default: + u8PrescalerMult = 1U; + break; + } + + u32SysFreq = SCG_GetScgClockFreq(SCG_CORE_CLK); + u32PtimerFreqUs = u32SysFreq / 1000000U; + + u32DelayVal = (u32DelayUs * u32PtimerFreqUs) / ((uint32_t)u8Prescaler * u8PrescalerMult); + DEV_ASSERT(u32DelayVal < (1U << 16U)); + + return (uint16_t)u32DelayVal; +} + +void PTIMER0_IRQHandler(void) +{ + PTIMERn_IRQHandler(PTIMER_INSTANCE_0); +} + +void PTIMER1_IRQHandler(void) +{ + PTIMERn_IRQHandler(PTIMER_INSTANCE_1); +} + +static void PTIMERn_IRQHandler(const PTIMER_InstanceType eInstance) +{ + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + uint8_t u8Channel; + if (PTIMER_HWA_GetInterruptFlag(pPtimer) == true) + { + PTIMER_HWA_ClearInterruptFlag(pPtimer); + if (s_apPtimerIntNotify[eInstance] != NULL) + { + s_apPtimerIntNotify[eInstance](); + } + } + + for (u8Channel = 0U; u8Channel < s_u8ChnNum[eInstance]; u8Channel++) + { + if (PTIMER_HWA_GetChannelSequenceErrorFlag(pPtimer, u8Channel) == true) + { + PTIMER_HWA_ClearChannelSequenceErrorFlag(pPtimer, u8Channel); + if (s_apPtimerSeqErrorNotify[eInstance] != NULL) + { + s_apPtimerSeqErrorNotify[eInstance](u8Channel); + } + } + } +} + +void PTIMER_DeInit(const PTIMER_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + uint8_t u8Chn; + + /* Reset PTIMER Status Ctrl Register */ + PTIMER_HWA_SetStatusCtrl(pPtimer, 0U); + /* Enable PTIMER */ + PTIMER_HWA_Enable(pPtimer); + /* Reset PTIMER Max Cnt Register */ + PTIMER_HWA_SetMaxCount(pPtimer, 0xFFFFU); + /* Reset PTIMER Int Dly Register */ + PTIMER_HWA_SetInterruptDelay(pPtimer, 0xFFFFU); + + for (u8Chn = 0U; u8Chn < PTIMER_DLY_CNT; u8Chn++) + { + PTIMER_HWA_SetChannelControl(pPtimer, u8Chn, false, false, false); + PTIMER_HWA_ClearChannelCounterFlag(pPtimer, u8Chn); + PTIMER_HWA_ClearChannelSequenceErrorFlag(pPtimer, u8Chn); + PTIMER_HWA_SetChannelDelay(pPtimer, u8Chn, 0U); + } + + /* For Pulse out trigger. */ + PTIMER_HWA_DisablePulseOut(pPtimer); + PTIMER_HWA_SetPulseOutDelay(pPtimer, 0U, 0U); + + PTIMER_HWA_LoadValue(pPtimer); + PTIMER_HWA_Disable(pPtimer); +} + +void PTIMER_Init(const PTIMER_InstanceType eInstance, const PTIMER_InitType *const pInitCfg) +{ + DEV_ASSERT(pInitCfg != NULL_PTR); + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[(uint8_t)eInstance]; + + PTIMER_DeInit(eInstance); + + PTIMER_HWA_SetLoadMode(pPtimer, pInitCfg->eLoadValueMode); + PTIMER_HWA_SetDivPrescaler(pPtimer, pInitCfg->eClkPreDiv); + PTIMER_HWA_SetTriggerSource(pPtimer, pInitCfg->eTriggerInput); + PTIMER_HWA_SetDivMultiply(pPtimer, pInitCfg->eClkPreMultFactor); + PTIMER_HWA_SetContinuoiusModeFlag(pPtimer, pInitCfg->bContinuousModeEnable); + PTIMER_HWA_SetDMAEnableFlag(pPtimer, pInitCfg->bDmaEnable); +} + +void PTIMER_InitChannel(const PTIMER_InstanceType eInstance, + const PTIMER_ChannelCfgType aChannelCfg[], const uint8_t u8ChnNum) +{ + DEV_ASSERT(aChannelCfg != NULL_PTR); + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + DEV_ASSERT(u8ChnNum <= PTIMER_DLY_CNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + + uint8_t u8ChnIdx; + uint16_t u16PtimerChannelDelay ; + + for (u8ChnIdx = 0U; u8ChnIdx < u8ChnNum; u8ChnIdx++) + { + PTIMER_HWA_SetChannelControl(pPtimer, u8ChnIdx, aChannelCfg[u8ChnIdx].bPreTriggerEnable, + aChannelCfg[u8ChnIdx].bPreTriggerOutputEnable, aChannelCfg[u8ChnIdx].bPreTriggerBackToBackEnable); + u16PtimerChannelDelay = PTIMER_CalcDelayValue(eInstance, aChannelCfg[u8ChnIdx].u32DelayUs); + PTIMER_HWA_SetChannelDelay(pPtimer, u8ChnIdx, u16PtimerChannelDelay); + } + s_u8ChnNum[eInstance] = u8ChnNum; +} + +void PTIMER_InitInterrupt(const PTIMER_InstanceType eInstance, + const PTIMER_InterruptType *const pInterruptCfg) +{ + DEV_ASSERT(pInterruptCfg != NULL_PTR); + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + + PTIMER_HWA_SetSeqErrIntEnableFlag(pPtimer, pInterruptCfg->bSeqErrIntEnable); + uint16_t u16IntDelay = PTIMER_CalcDelayValue(eInstance, pInterruptCfg->u32IntDelayPeriodUs); + PTIMER_HWA_SetInterruptDelay(pPtimer, u16IntDelay); + PTIMER_HWA_SetInterruptEnableFlag(pPtimer, pInterruptCfg->bDelayIntEnable); + + if (pInterruptCfg->bDelayIntEnable) + { + s_apPtimerIntNotify[eInstance] = pInterruptCfg->pIntNotify; + } + else + { + s_apPtimerIntNotify[eInstance] = NULL; + } + + if (pInterruptCfg->bSeqErrIntEnable) + { + s_apPtimerSeqErrorNotify[eInstance] = pInterruptCfg->pSeqErrorNotify; + } + else + { + s_apPtimerSeqErrorNotify[eInstance] = NULL; + } + + if ((pInterruptCfg->bSeqErrIntEnable == true) || (pInterruptCfg->bDelayIntEnable == true)) + { + switch ((uint8_t)eInstance) + { + case (uint8_t)PTIMER_INSTANCE_0: + IntMgr_EnableInterrupt(PTIMER0_IRQn); + break; + + case (uint8_t)PTIMER_INSTANCE_1: + IntMgr_EnableInterrupt(PTIMER1_IRQn); + break; + + default: + break; + } + } +} + +void PTIMER_SetPeriod(const PTIMER_InstanceType eInstance, uint32_t u32PeriodUs) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + + uint16_t u16MaxCnt = PTIMER_CalcDelayValue(eInstance, u32PeriodUs); + PTIMER_HWA_SetMaxCount(pPtimer, u16MaxCnt); +} + +void PTIMER_SetPulseOut(const PTIMER_InstanceType eInstance, const PTIMER_PulseOutType *pPulseOutCfg) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + DEV_ASSERT(pPulseOutCfg != NULL_PTR); + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + + uint16_t u16PulseOutCfgDlyHigh = PTIMER_CalcDelayValue(eInstance, pPulseOutCfg->u32PulseOutDlyHighUs); + uint16_t u16PulseOutCfgDlyLow = PTIMER_CalcDelayValue(eInstance, pPulseOutCfg->u32PulseOutDlyLowUs); + + PTIMER_HWA_SetPulseOutDelay(pPtimer, u16PulseOutCfgDlyHigh, u16PulseOutCfgDlyLow); +} + +void PTIMER_LoadValue(const PTIMER_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + PTIMER_HWA_LoadValue(pPtimer); +} + +void PTIMER_Enable(const PTIMER_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + PTIMER_HWA_Enable(pPtimer); +} + +void PTIMER_Disable(const PTIMER_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + PTIMER_HWA_Disable(pPtimer); +} + +void PTIMER_EnablePulseOut(const PTIMER_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + PTIMER_HWA_EnablePulseOut(pPtimer); +} + +void PTIMER_DisablePulseOut(const PTIMER_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + PTIMER_HWA_DisablePulseOut(pPtimer); +} + +void PTIMER_SelectInstance01BackToBackMode(SCM_PTimerLMSelType ePTimerLoopMode) +{ + SCM_HWA_PTimerLoopModeSel(ePTimerLoopMode); +} + +void PTIMER_GenerateSWTrigger(const PTIMER_InstanceType eInstance) +{ + DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT); + + PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance]; + PTIMER_HWA_GenerateSwTrigger(pPtimer); +} diff --git a/Src/fc7xxx_driver_rgm.c b/Src/fc7xxx_driver_rgm.c new file mode 100644 index 0000000..7a5b4ae --- /dev/null +++ b/Src/fc7xxx_driver_rgm.c @@ -0,0 +1,312 @@ +/** + * @file fc7xxx_driver_rgm.c + * @author Flagchip + * @brief FC7xxx RGM driver source code + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-12 Flagchip119 N/A First version for FC7240 +********************************************************************************/ +#include "fc7xxx_driver_rgm.h" +#include "interrupt_manager.h" + +/** @brief Rgm user defined CPU0 core related system interrupt function */ +static RGM_InterruptCallBackType s_pRgmCPU0PreIntPtr = NULL; + +/** @brief Rgm pre-reset interrupt entry */ +void RGM_Pre_IRQHandler(void); + +/** + * @brief This api can get RGM_SRS register that indicate the source of the most recent reset. + * + * @return RGM->RGM_SRS register, bit 0-15,29-31 corresponding to RGM_ResetEventType, refer to reference manual for details. + * @note Multiple flags can be set if multiple reset events occur at the same time + */ +uint32_t RGM_GetLastResetFLag(void) +{ + return RGM_HWA_ReadLastResetFlag(); +} + +/** + * @brief This api can get RGM_SSRS register that indicate all reset sources since the last POR or LVD that have not been cleared by software. + * + * @return RGM->RGM_SSRS register, bit 0-15,29-31 corresponding to RGM_ResetEventType, refer to reference manual for details. + */ +uint32_t RGM_GetAllResetFlag(void) +{ + return RGM_HWA_ReadAllResetFlagBeforePOR(); +} + +/** + * @brief This api can clear reset flag of RGM_SSRS register which indicate all reset sources since the last POR or LVD that have not been cleared by software. + * + * @param eReset Enumeration of reset event flag + */ +void RGM_ClearResetFlagAfterPOR(const RGM_ResetEventType eReset) +{ + RGM_HWA_ClearResetFlagAfterPOR(eReset); +} + +/** + * @brief This api can clear all reset flag of RGM_SSRS register which indicate all reset sources since the last POR or LVD that have not been cleared by software. + * + */ +void RGM_ClearAllResetFlagAfterPOR(void) +{ + RGM_HWA_ClearAllResetFlagAfterPOR(); +} + +/** + * @brief Enable reset pin filter + * + * @param eClk Reset pin filter clock source + * @param u8BusClockFilterWidth Bus clock filter width + * @param bLpClkEn select whether enable reset pin filter using AON32clock in low power mode + * @return RGM return type + * @note If use AON32K clock, A reset signal whose length is less than 2 AON32K clock periods will be filtered + */ +RGM_StatusType RGM_EnableResetFilter(RGM_FilterClkSrc eClk, uint8_t u8BusClockFilterWidth, bool bLpClkEn) +{ + RGM_StatusType eRet = RGM_STATUS_SUCCESS; + if(eClk > RGM_RESET_FILTER_AON32K_CLOCK) + { + eRet = RGM_STATUS_PARAM_INVALID; + } + if (RGM_STATUS_SUCCESS == eRet) + { + if (RGM_RESET_FILTER_AON32K_CLOCK == eClk) + { + if ((RGM_HWA_ReadResetPinFilterEnable() & RGM_RSTFLT_RSTFLT_BUS_MASK) >> RGM_RSTFLT_RSTFLT_BUS_SHIFT == 1U) + { + RGM_HWA_DisableBusClockFilter(); + } + RGM_HWA_EnableAon32kClockFilter(); + } + if (RGM_RESET_FILTER_BUS_CLOCK == eClk) + { + if ((RGM_HWA_ReadResetPinFilterEnable() & RGM_RSTFLT_RSTFLT_AON_MASK) >> RGM_RSTFLT_RSTFLT_AON_SHIFT == 1U) + { + RGM_HWA_DisableAon32kClockFilter(); + } + RGM_HWA_SetBusClockFilterWidth(u8BusClockFilterWidth); + RGM_HWA_EnableBusClockFilter(); + } + if (bLpClkEn) + { + RGM_HWA_EnableAon32kLPClockFilter(); + } + } + return eRet; +} + +/** + * @brief Disable reset pin filter + * + * @param eClk Reset pin filter clock source + * @param bLpClkEn select whether disable reset pin filter using AON32clock in low power mode + * @return RGM return type + */ +RGM_StatusType RGM_DisableResetFilter(RGM_FilterClkSrc eClk, bool bLpClkEn) +{ + RGM_StatusType eRet = RGM_STATUS_SUCCESS; + if (eClk > RGM_RESET_FILTER_AON32K_CLOCK) + { + eRet = RGM_STATUS_PARAM_INVALID; + } + if (RGM_STATUS_SUCCESS == eRet) + { + if (RGM_RESET_FILTER_AON32K_CLOCK == eClk) + { + RGM_HWA_DisableAon32kClockFilter(); + } + if (bLpClkEn) + { + RGM_HWA_DisableAon32kLPClockFilter(); + } + if (RGM_RESET_FILTER_BUS_CLOCK == eClk) + { + RGM_HWA_ClearBusClockFilterWidth(); + RGM_HWA_DisableBusClockFilter(); + } + } + return eRet; +} + +/** + * @brief This api can enable interrupt before an system reset appear. + * + * @param eDelay Enumeration of delay cycles + * @param eResetInterrupt Reset event flag, like: RGM_INT_CLKERR0 | RGM_INT_FCSMU + * @return RGM return type + * + * @note Here is the interrupted master switch control + */ +RGM_StatusType RGM_EnableSystemResetInt(RGM_ResetDelayType eDelay, RGM_ResetIntMangerType eResetInterrupt) +{ + RGM_StatusType eRet = RGM_STATUS_SUCCESS; + if (eDelay > RGM_512_CLOCK_CYCLES) + { + eRet = RGM_STATUS_PARAM_INVALID; + } + if (RGM_STATUS_SUCCESS == eRet) + { + RGM_HWA_EnableGlobalResetInterrupt(); + RGM_HWA_SetResetDelay(eDelay); + RGM_HWA_EnableResetInterrupt(eResetInterrupt); + } + return eRet; +} + +/** + * @brief This api can disable interrupt before an system reset appear. + * + * @param eResetInterrupt Reset event flag, like: RGM_INT_CLKERR0 | RGM_INT_FCSMU + * @param bClearDelay Whether to clear delay configuration + * @return RGM return type + */ +RGM_StatusType RGM_DisableSystemResetInt(RGM_ResetIntMangerType eResetInterrupt, bool bClearDelay) +{ + RGM_StatusType eRet = RGM_STATUS_SUCCESS; + if (bClearDelay) + { + RGM_HWA_ClearResetDelay(); + } + RGM_HWA_DisableResetInterrupt(eResetInterrupt); + return eRet; +} + +/** + * @brief Generate software reset through cotex-m register + * + */ +void RGM_GenerateSwReset(void) +{ + CM7_HWA_SystemReset(); +} + +/** + * @brief This api can enable interrupt before an CPU0 core related reset appear. + * + * @param eCPU0Interrupt Reset event flag, like: RGM_CPU_INT_SWRST | RGM_CPU_INT_SYSRST + * @param pIsrNotify Interrupt function + * @return RGM return type + */ +RGM_StatusType RGM_EnableCPU0CoreResetInt(RGM_CPUIntMangerType eCPU0Interrupt,RGM_InterruptCallBackType pIsrNotify) +{ + RGM_StatusType eRet = RGM_STATUS_SUCCESS; + if((uint8_t)eCPU0Interrupt > 0x1FU) + { + eRet = RGM_STATUS_PARAM_INVALID; + } + if (RGM_STATUS_SUCCESS == eRet) + { + RGM_HWA_EnableCPU0InterruptFlag(eCPU0Interrupt); + s_pRgmCPU0PreIntPtr = pIsrNotify; + } + return eRet; +} + +/** + * @brief This api can disable interrupt before an CPU0 core related reset appear. + * + * @param eCPU0Interrupt Reset event flag, like: RGM_CPU_INT_SWRST | RGM_CPU_INT_SYSRST + * @return RGM return type + */ +RGM_StatusType RGM_DisableCPU0CoreResetInt(RGM_CPUIntMangerType eCPU0Interrupt) +{ + RGM_StatusType eRet = RGM_STATUS_SUCCESS; + if((uint8_t)eCPU0Interrupt > 0x1FU) + { + eRet = RGM_STATUS_PARAM_INVALID; + } + if (RGM_STATUS_SUCCESS == eRet) + { + RGM_HWA_DisableCPU0InterruptFlag(eCPU0Interrupt); + } + return eRet; +} + +/** + * @brief Get the CPU0 exit reset flag + * + * @return RGM_CPU_OUT_RST_UNDER CPU0 is under reset + * @return RGM_CPU_OUT_RST_OUT CPU0 is out of reset + */ +RGM_CPUOutResetType RGM_GetCPU0OutResetFlag(void) +{ + return RGM_HWA_GetCPU0OutResetFlag(); +} + +/** + * @brief Generate a CPU0 software reset. + * + */ +void RGM_GenerateCPU0SwReset(void) +{ + RGM_HWA_CPU0SWReset(); +} + +/** + * @brief This api can get RGM_C0_SRS register that indicate the source of the most recent CPU0 reset. + * + * @return RGM->RGM_C0_SRS register, bit 0-20 corresponding to RGM_ResetEventType, refer to reference manual for details. + * @note Multiple flags can be set if multiple reset events occur at the same time + */ +uint32_t RGM_GetCPU0LastResetFLag(void) +{ + return RGM_HWA_ReadCPU0LastResetFlag(); +} + +/** + * @brief This api can get RGM_C0_SSRS register that indicate all CPU0 reset sources since the last POR or LVD that have not been cleared by software. + * + * @returnRGM->RGM_C0_SSRS register, bit 0-20,29-31 corresponding to RGM_CPUResetEventType, refer to reference manual for details. + */ +uint32_t RGM_GetCPU0AllResetFlag(void) +{ + return RGM_HWA_ReadCPU0AllResetFlagBeforePOR(); +} + +/** + * @brief This api can clear reset flag of RGM_C0_SSRS register which indicate CPU0 all reset sources since the last POR or LVD that have not been cleared by software. + * + * @param eReset Enumeration of reset event flag + */ +void RGM_ClearCPU0ResetFlagAfterPOR(const RGM_CPUResetEventType eReset) +{ + RGM_HWA_ClearC0ResetFlagAfterPOR(eReset); +} + +/** + * @brief This api can clear all reset flag of RGM_C0_SSRS register which indicate CPU0 all reset sources since the last POR or LVD that have not been cleared by software. + * + */ +void RGM_ClearCPU0AllResetFlagAfterPOR(void) +{ + RGM_HWA_ClearC0AllResetFlagAfterPOR(); +} + +/** + * @brief RGM Pre-interrupt entry + * + */ +void RGM_Pre_IRQHandler(void) +{ + IntMgr_DisableGlobalInterrupt(); + + if (NULL != s_pRgmCPU0PreIntPtr) + { + s_pRgmCPU0PreIntPtr(RGM_GetCPU0LastResetFLag()); + } + IntMgr_EnableGlobalInterrupt(); +} + diff --git a/Src/fc7xxx_driver_rtc.c b/Src/fc7xxx_driver_rtc.c new file mode 100644 index 0000000..bcc371f --- /dev/null +++ b/Src/fc7xxx_driver_rtc.c @@ -0,0 +1,365 @@ +/** + * @file fc7xxx_driver_rtc.c + * @author Flagchip + * @brief FC7xxx rtc driver type definition and API + * @version 0.1.0 + * @date 2024-01-10 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-10 Flagchip0076 N/A First version for FC7240 +********************************************************************************/ +#include "fc7xxx_driver_rtc.h" + +#include "fc7xxx_driver_csc.h" + + + +/** + * @brief Rtc user defined alarm interrupt function + * */ +static RTC_InterruptCallBackType s_pRTCAlarmNotifyPtr = NULL; + +/** + * @brief Rtc user defined seconds interrupt function + * */ +static RTC_InterruptCallBackType s_pRTCSecondNotifyPtr = NULL; + +/** + * @brief Rtc user defined overflow interrupt function + * */ +static RTC_InterruptCallBackType s_pRTCOverFlowNotifyPtr = NULL; + +/** + * @brief RTC common interrupt function + * */ +static void Rtc_CommonProcessInterrupt(const RTC_IntEventType eIntEvent); + +/** + * @brief RTC interrupt entry + * */ +void RTC_IRQHandler(void); + + +/** + * @brief Initialize Rtc instance + * + * @param pInitStruct Rtc initialization structure + * @return Rtc return type + * @note This function could only write once after POR. + */ +void RTC_Init(const RTC_InitType *const pInitStruct) +{ + DEV_ASSERT(pInitStruct != NULL); + /* Disable interrupt */ + RTC_HWA_DisableOverflowInterrupt(); + /*Disable Second interrupt*/ + RTC_HWA_DisableSecondInterrupt(); + /*Disable Alarm interrupt*/ + RTC_HWA_DisableAlarmInterrupt(); + /* disable the rtc clock*/ + RTC_HWA_DisableRtcCounter(); + /* clear PR register */ + RTC_HWA_SetPrescalerCounterValue(0U); + /* clear SR register */ + RTC_HWA_SetSecondCounterValue(0U); + /* clear CR register */ + RTC_HWA_ConfigControl(0U); + if (pInitStruct->bStableClkoutFreq) + { + RTC_HWA_SetClkoutFreqStable(); + } + else + { + RTC_HWA_SetClkoutFromSelectFreq(); + } + /* TSIC should only be altered when TSIE is clear */ + RTC_HWA_SetSecondAndClkoutFreq(pInitStruct->eSecIntAndClkoutFreq); + /* Set alarm value */ + RTC_HWA_SetAlarmCounterValue(pInitStruct->u32AlarmValue); +} + +/** + * @brief Rtc set interrupt + * + * @param pIntStruct interrupt structure pointer + * @return Rtc return type + * @note this function will stop Rtc timer + */ +RTC_StatusType RTC_InitInterrupt(const RTC_InterruptType *const pIntStruct) +{ + RTC_StatusType eRet = RTC_STATUS_SUCCESS; + if (NULL == pIntStruct) + { + eRet = RTC_STATUS_PARAM_INVALID; + } + else + { + /* disable the rtc timer */ + RTC_HWA_DisableRtcCounter(); + if (pIntStruct->bAlarmIntEn) + { + /* enable alarm interrupt */ + RTC_HWA_EnableAlarmInterrupt(); + s_pRTCAlarmNotifyPtr = pIntStruct->pIsrAlarmNotify; + } + else + { + /* disable alarm interrupt */ + RTC_HWA_DisableAlarmInterrupt(); + s_pRTCAlarmNotifyPtr = NULL; + } + + if (pIntStruct->bOverflowIntEn) + { + /* enable overflow interrupt */ + RTC_HWA_EnableOverflowInterrupt(); + s_pRTCOverFlowNotifyPtr = pIntStruct->pIsrOverflowNotify; + } + else + { + /* disable overflow interrupt */ + RTC_HWA_DisableOverflowInterrupt(); + s_pRTCOverFlowNotifyPtr = NULL; + } + + if (pIntStruct->bSecondIntEn) + { + /* enable second interrupt */ + RTC_HWA_EnableSecondInterrupt(); + s_pRTCSecondNotifyPtr = pIntStruct->pIsrSecondNotify; + } + else + { + /* disable second interrupt */ + RTC_HWA_DisableSecondInterrupt(); + s_pRTCSecondNotifyPtr = NULL; + } + } + return eRet; +} + +/** + * @brief De-initialize Rtc instance + * + */ +void RTC_Deinit(void) +{ + /* disable the rtc timer */ + RTC_HWA_DisableRtcCounter(); + /* clear PR register */ + RTC_HWA_SetPrescalerCounterValue(0U); + /* clear SR register */ + RTC_HWA_SetSecondCounterValue(0U); + /* clear TAR register */ + RTC_HWA_SetAlarmCounterValue(0U); + /* clear IER register */ + RTC_HWA_SetInterruptValue(0U); + /* clear CR register */ + RTC_HWA_ConfigControl(0U); + s_pRTCAlarmNotifyPtr = NULL; + s_pRTCSecondNotifyPtr = NULL; + s_pRTCOverFlowNotifyPtr = NULL; +} + +/** + * @brief Rtc enable interrupt + * + * @param bAlarmIntEn whether enable alarm interrupt + * @param bSecondIntEn whether enable second interrupt + * @param bOverflowIntEn whether enable overflow interrupt + */ +void RTC_EnableInterrupt(const bool bAlarmIntEn, const bool bSecondIntEn, const bool bOverflowIntEn) +{ + /* disable the rtc timer */ + RTC_HWA_DisableRtcCounter(); + if (bAlarmIntEn) + { + /* enable alarm interrupt */ + RTC_HWA_EnableAlarmInterrupt(); + } + if (bSecondIntEn) + { + /* enable second interrupt */ + RTC_HWA_EnableSecondInterrupt(); + } + if (bOverflowIntEn) + { + /* enable overflow interrupt */ + RTC_HWA_EnableOverflowInterrupt(); + } + /*enable the rtc clock*/ + RTC_HWA_EnableRtcCounter(); +} + +/** + * @brief Rtc disable interrupt + * + * @param bAlarmIntEn whether disable alarm interrupt + * @param bSecondIntEn whether disable second interrupt + * @param boverflowIntEn whether disable overflow interrupt + */ +void RTC_DisableInterrupt(const bool bAlarmIntEn, const bool bSecondIntEn, const bool boverflowIntEn) +{ + /* disable the rtc timer */ + RTC_HWA_DisableRtcCounter(); + if (bAlarmIntEn) + { + /* disable alarm interrupt */ + RTC_HWA_DisableAlarmInterrupt(); + } + if (bSecondIntEn) + { + /* disable second interrupt */ + RTC_HWA_DisableSecondInterrupt(); + } + if (boverflowIntEn) + { + /* disable overflow interrupt */ + RTC_HWA_DisableOverflowInterrupt(); + } + /*enable the rtc clock*/ + RTC_HWA_EnableRtcCounter(); +} + +/** + * @brief rtc start + * + */ +void RTC_Start(void) +{ + /*enable the rtc clock*/ + RTC_HWA_EnableRtcCounter(); +} + +/** + * @brief Rtc stop + * + */ +void RTC_Stop(void) +{ + /*disable the rtc clock*/ + RTC_HWA_DisableRtcCounter(); +} + +/** + * @brief Rtc alarm value + * + * @param u32AlarmValue Input value + */ +void RTC_UpdateAlarmValue(const uint32_t u32AlarmValue) +{ + /*disable the rtc clock*/ + RTC_HWA_DisableRtcCounter(); + /* clear PR register */ + RTC_HWA_SetPrescalerCounterValue(0U); + /* Set alarm value */ + RTC_HWA_SetAlarmCounterValue(RTC_HWA_ReadSecondValue() + u32AlarmValue - (uint32_t)1U); + /*enable the rtc clock*/ + RTC_HWA_EnableRtcCounter(); +} + +/** + * @brief Get Rtc counter value + * + * @return Rtc counter value + */ +uint32_t RTC_GetTime(void) +{ + return RTC_HWA_ReadSecondValue(); +} + +/** + * @brief Check RTC overflow flag + * + * @return Overflow flag + */ +bool RTC_CheckOverflowFlag(void) +{ + return RTC_HWA_GetOverflowFlag(); +} + +/** + * @brief Set second counter value + * @param u32Value the second value. + * */ +void RTC_SetSecondCounterValue(uint32_t u32Value) +{ + RTC_HWA_DisableRtcCounter(); + RTC_HWA_SetSecondCounterValue(u32Value); + RTC_HWA_EnableRtcCounter(); +} + +/** + * @brief RTC common interrupt function + * + * @param eIntEvent RTC interrupt event + */ +static void Rtc_CommonProcessInterrupt(const RTC_IntEventType eIntEvent) +{ + switch (eIntEvent) + { + case RTC_ALARM_INT: + if (NULL != s_pRTCAlarmNotifyPtr) + { + s_pRTCAlarmNotifyPtr(); + } + break; + case RTC_SECOND_INT: + if (NULL != s_pRTCSecondNotifyPtr) + { + s_pRTCSecondNotifyPtr(); + } + break; + case RTC_OVERFLOW_INT: + if (NULL != s_pRTCOverFlowNotifyPtr) + { + s_pRTCOverFlowNotifyPtr(); + } + break; + default: + /* do nothing*/ + break; + } +} + +/** + * @brief RTC alarm interrupt handler entry + * + */ +void RTC_IRQHandler(void) +{ + bool overflow_flag = RTC_HWA_GetOverflowFlag(); + bool overflow_enablebit = RTC_HWA_GetOverflowEnable(); + bool alarm_flag = RTC_HWA_GetAlarmFlag(); + bool alarm_enablebit = RTC_HWA_GetAlarmEnable(); + if ((overflow_flag) && (overflow_enablebit)) + { + /*oveflow Int*/ + /*disable the rtc clock*/ + RTC_HWA_DisableRtcCounter(); + RTC_HWA_SetSecondCounterValue(0u); + Rtc_CommonProcessInterrupt(RTC_OVERFLOW_INT); + + + } + else if ((alarm_flag) && (alarm_enablebit)) + { + /*alarm Int*/ + RTC_HWA_SetAlarmCounterValue(0u); + Rtc_CommonProcessInterrupt(RTC_ALARM_INT); + + } + else + { + /*second Int*/ + Rtc_CommonProcessInterrupt(RTC_SECOND_INT); + } +} diff --git a/Src/fc7xxx_driver_scg.c b/Src/fc7xxx_driver_scg.c new file mode 100644 index 0000000..ef8545e --- /dev/null +++ b/Src/fc7xxx_driver_scg.c @@ -0,0 +1,1941 @@ +/** + * @file fc7xxx_driver_scg.c + * @author Flagchip + * @brief FC7xxx SCG driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ + +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 +********************************************************************************/ +#include "fc7xxx_driver_scg.h" +#include "fc7xxx_board_conf.h" + +#if ((FOSC_FREQUENCY < 16000000U) || (FOSC_FREQUENCY > 48000000U)) +#error "FOSC is not in range 16M ~ 48 M" +#endif + +/***************** Macros *********************/ +#define SIRC_CLOCK 12000000U +#define SIRC32K_CLOCK 32000U +#define FIRC_CLOCK 96000000U +#define NVM_CLOCK 12000000U +#define FOSC_STABILIZATION_TIMEOUT 96000U +#define FIRC_STABILIZATION_TIMEOUT 20U +#define SIRC_STABILIZATION_TIMEOUT 100U +#define SOSC_STABILIZATION_TIMEOUT 320500U +#define PLL_STABILIZATION_TIMEOUT 320500U +#define SCG_CLKSRC_STABILIZATION_TIMEOUT 1000U +#define CLOCK_OFF_STABILIZATION_TIMEOUT 1000U /* clock out time is about 1us */ +#define CLOCK_DIV_STABILIZATION_TIMEOUT 1000U + +#define PLL0_CLK_MAX 240000000U +#define PLL1_CLK_MAX 320000000U +#define PLL_VCO_CLK_MAX 800000000U +#define PLL_VCO_CLK_MIN 300000000U +#define PLL_FEEDBACK_CLK_MAX 4000000U +#define PLL_FEEDBACK_CLK_MIN 2000000U +#define SYS_CORE_CLK_MAX 240000000U +#define SYS_BUS_CLK_MAX 120000000U +#define SYS_SLOW_CLK_MAX 60000000U + +#define FOSC_DIVH_MAX_CLOCK 48000000U +#define FOSC_DIVM_MAX_CLOCK 48000000U +#define FOSC_DIVL_MAX_CLOCK 48000000U +#define FIRC_DIVH_MAX_CLOCK 96000000U +#define FIRC_DIVM_MAX_CLOCK 96000000U +#define FIRC_DIVL_MAX_CLOCK 48000000U +#define PLL0_DIVH_MAX_CLOCK 240000000U +#define PLL0_DIVM_MAX_CLOCK 120000000U +#define PLL0_DIVL_MAX_CLOCK 60000000U +#define PLL1_DIVH_MAX_CLOCK 320000000U +#define PLL1_DIVM_MAX_CLOCK 160000000U +#define PLL1_DIVL_MAX_CLOCK 80000000U + +/***************** mcaro function *********************/ +#define SCG_CheckClockAckStatus(x, timeout, returnVal) \ + while ((x) && (timeout > 0U)) \ + { \ + timeout--; \ + } \ + if (timeout != 0U) \ + { \ + returnVal = SCG_STATUS_SUCCESS; \ + } \ + else \ + { \ + returnVal = SCG_STATUS_TIMEOUT; \ + } + + +#define SCG_GetDivHClock(_clock_, input_freq, ouput_freq) \ + { \ + uint32_t u32DivRegVal; \ + \ + u32DivRegVal = SCG_HWA_GetClockDiv(_clock_); \ + ouput_freq = SCG_CALCULATE_DIVH_FREQ(input_freq, u32DivRegVal); \ + } + +#define SCG_GetDivMClock(_clock_, input_freq, ouput_freq) \ + { \ + uint32_t u32DivRegVal; \ + u32DivRegVal = SCG_HWA_GetClockDiv(_clock_); \ + ouput_freq = SCG_CALCULATE_DIVM_FREQ(input_freq, u32DivRegVal); \ + } + +#define SCG_GetDivLClock(_clock_, input_freq, ouput_freq) \ + { \ + uint32_t u32DivRegVal; \ + u32DivRegVal = SCG_HWA_GetClockDiv(_clock_); \ + ouput_freq = SCG_CALCULATE_DIVL_FREQ(input_freq, u32DivRegVal); \ + } + +/***************** Local Functions *********************/ + +static uint32_t SCG_CalculateSircFreq(const SCG_ClkSrcType eScgClockName) +{ + uint32_t u32Freq; + + if (SCG_SIRC_CLK == eScgClockName) + { + u32Freq = SIRC_CLOCK; + } + else if (SCG_SIRCDIVH_CLK == eScgClockName) + { + SCG_GetDivHClock(SCG_SIRC_CLOCK_SYMBOL, SIRC_CLOCK, u32Freq); + } + else if (SCG_SIRCDIVM_CLK == eScgClockName) + { + SCG_GetDivMClock(SCG_SIRC_CLOCK_SYMBOL, SIRC_CLOCK, u32Freq); + } + else if (SCG_SIRCDIVL_CLK == eScgClockName) + { + SCG_GetDivLClock(SCG_SIRC_CLOCK_SYMBOL, SIRC_CLOCK, u32Freq); + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + + return u32Freq; +} + +static uint32_t SCG_CalculateFircFreq(const SCG_ClkSrcType eScgClockName) +{ + uint32_t u32Freq; + + if (true == SCG_HWA_GetClockVliad(SCG_FIRC_CLOCK_SYMBOL)) + { + if (SCG_FIRC_CLK == eScgClockName) + { + u32Freq = FIRC_CLOCK; + } + else if (SCG_FIRCDIVH_CLK == eScgClockName) + { + SCG_GetDivHClock(SCG_FIRC_CLOCK_SYMBOL, FIRC_CLOCK, u32Freq); + } + else if (SCG_FIRCDIVM_CLK == eScgClockName) + { + SCG_GetDivMClock(SCG_FIRC_CLOCK_SYMBOL, FIRC_CLOCK, u32Freq); + } + else if (SCG_FIRCDIVL_CLK == eScgClockName) + { + SCG_GetDivLClock(SCG_FIRC_CLOCK_SYMBOL, FIRC_CLOCK, u32Freq); + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + + return u32Freq; +} + +static uint32_t SCG_CalculateFoscFreq(const SCG_ClkSrcType eScgClockName) +{ + uint32_t u32Freq; + + if (true == SCG_HWA_GetClockVliad(SCG_FOSC_CLOCK_SYMBOL)) + { + if (SCG_FOSC_CLK == eScgClockName) + { + u32Freq = FOSC_FREQUENCY; + } + else if (SCG_FOSCDIVH_CLK == eScgClockName) + { + SCG_GetDivHClock(SCG_FOSC_CLOCK_SYMBOL, FOSC_FREQUENCY, u32Freq); + } + else if (SCG_FOSCDIVM_CLK == eScgClockName) + { + SCG_GetDivMClock(SCG_FOSC_CLOCK_SYMBOL, FOSC_FREQUENCY, u32Freq); + } + else if (SCG_FOSCDIVL_CLK == eScgClockName) + { + SCG_GetDivLClock(SCG_FOSC_CLOCK_SYMBOL, FOSC_FREQUENCY, u32Freq); + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + + return u32Freq; +} + +static uint32_t SCG_CalculatePll0Freq(const SCG_ClkSrcType eScgClockName) +{ + uint32_t u32Freq, u32ClkFreq; + uint32_t u32Temp, u32PreDiv, u32PstDiv; + uint32_t u32Mult; + + if (true == SCG_HWA_GetClockVliad(SCG_PLL0_CLOCK_SYMBOL)) + { + u32Temp = SCG_HWA_GetPllSrc(SCG_PLL0_CLOCK_SYMBOL); + if (u32Temp == (uint32_t)SCG_PLLSOURCE_FIRC) + { + + u32ClkFreq = FIRC_CLOCK / 2U; + } + else + { + /* (u32Temp == (uint32_t)SCG_PLLSOURCE_FOSC) */ + u32ClkFreq = FOSC_FREQUENCY; + } + u32PreDiv = SCG_HWA_GetPllPrediv(SCG_PLL0_CLOCK_SYMBOL) + 1U; + u32Mult = SCG_HWA_GetPllMult(SCG_PLL0_CLOCK_SYMBOL) + 1U; + u32PstDiv = SCG_HWA_GetPllPstdiv(SCG_PLL0_CLOCK_SYMBOL); + if(u32PstDiv == 0U) + { + u32PstDiv = 1U; + } + u32ClkFreq = (u32ClkFreq / (u32PreDiv) * (u32Mult)) >> (u32PstDiv); + + if (SCG_PLL0_CLK == eScgClockName) + { + u32Freq = u32ClkFreq; + } + else if (SCG_PLL0DIVH_CLK == eScgClockName) + { + SCG_GetDivHClock(SCG_PLL0_CLOCK_SYMBOL, u32ClkFreq, u32Freq); + } + else if (SCG_PLL0DIVM_CLK == eScgClockName) + { + SCG_GetDivMClock(SCG_PLL0_CLOCK_SYMBOL, u32ClkFreq, u32Freq); + } + else if (SCG_PLL0DIVL_CLK == eScgClockName) + { + SCG_GetDivLClock(SCG_PLL0_CLOCK_SYMBOL, u32ClkFreq, u32Freq); + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + + return u32Freq; +} + +static uint32_t SCG_CalculatePll1Freq(const SCG_ClkSrcType eScgClockName) +{ + uint32_t u32Freq, u32ClkFreq; + uint32_t u32Temp, u32PreDiv, u32PstDiv; + uint32_t u32Mult; + + if (true == SCG_HWA_GetClockVliad(SCG_PLL1_CLOCK_SYMBOL)) + { + u32Temp = SCG_HWA_GetPllSrc(SCG_PLL1_CLOCK_SYMBOL); + if (u32Temp == (uint32_t)SCG_PLLSOURCE_FIRC) + { + u32ClkFreq = FIRC_CLOCK / 2U; + } + else + { + /* (u32Temp == (uint32_t)SCG_PLLSOURCE_FOSC) */ + u32ClkFreq = FOSC_FREQUENCY; + } + u32PreDiv = SCG_HWA_GetPllPrediv(SCG_PLL1_CLOCK_SYMBOL) + 1U; + u32Mult = SCG_HWA_GetPllMult(SCG_PLL1_CLOCK_SYMBOL) + 1U; + u32PstDiv = SCG_HWA_GetPllPstdiv(SCG_PLL1_CLOCK_SYMBOL); + if(u32PstDiv == 0U) + { + u32PstDiv = 1U; + } + u32ClkFreq = (u32ClkFreq / (u32PreDiv) * (u32Mult)) >> (u32PstDiv); + + if (SCG_PLL1_CLK == eScgClockName) + { + u32Freq = u32ClkFreq; + } + else if (SCG_PLL1DIVH_CLK == eScgClockName) + { + SCG_GetDivHClock(SCG_PLL1_CLOCK_SYMBOL, u32ClkFreq, u32Freq); + } + else if (SCG_PLL1DIVM_CLK == eScgClockName) + { + SCG_GetDivMClock(SCG_PLL1_CLOCK_SYMBOL, u32ClkFreq, u32Freq); + } + else if (SCG_PLL1DIVL_CLK == eScgClockName) + { + SCG_GetDivLClock(SCG_PLL1_CLOCK_SYMBOL, u32ClkFreq, u32Freq); + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + + return u32Freq; +} + +static uint32_t SCG_CalculateSystemFreq(const SCG_ClkSrcType eScgClockName) +{ + uint32_t u32Freq, u32ClkFreq; + uint32_t u32Temp, u32DivCore, u32DivBus, u32DivSlow; + + u32Temp = (uint32_t)SCG_HWA_GetSysClkSrc(); + + if ((uint32_t)SCG_CLOCK_SRC_FOSC == u32Temp) + { + u32ClkFreq = FOSC_FREQUENCY; + } + else if ((uint32_t)SCG_CLOCK_SRC_FIRC == u32Temp) + { + u32ClkFreq = FIRC_CLOCK; + } + else if ((uint32_t)SCG_CLOCK_SRC_PLL0 == u32Temp) + { + u32ClkFreq = SCG_CalculatePll0Freq(SCG_PLL0_CLK); + } + else if ((uint32_t)SCG_CLOCK_SRC_SIRC == u32Temp) + { + u32ClkFreq = SCG_CalculateSircFreq(SCG_SIRC_CLK); + } + else + { + u32ClkFreq = UNKNOWN_CLOCK; + } + + u32DivCore = (uint32_t)(SCG_HWA_GetSysClkDivCore() + 1U); + u32DivBus = (uint32_t)(SCG_HWA_GetSysClkDivBus() + 1U); + u32DivSlow = (uint32_t)(SCG_HWA_GetSysClkDivSlow() + 1U); + + u32ClkFreq = (uint32_t)(u32ClkFreq / u32DivCore); + + if (SCG_CORE_CLK == eScgClockName) + { + u32Freq = u32ClkFreq; + } + else if (SCG_BUS_CLK == eScgClockName) + { + u32Freq = (uint32_t)(u32ClkFreq / u32DivBus); + } + else + { + /* (SCG_SLOW_CLK == eScgClockName) */ + u32Freq = (uint32_t)((u32ClkFreq / u32DivBus) / u32DivSlow); + } + + return u32Freq; +} + +static uint32_t SCG_CalculateClkOutFreq(void) +{ + uint8_t u8ClockoutSrc; + uint32_t u32Freq; + /* check clock out configuration */ + u8ClockoutSrc = SCG_HWA_GetClkOutSel(); + + if ((uint8_t)SCG_CLOCKOUT_SRC_OFF == u8ClockoutSrc) + { + u32Freq = 0U; + } + else if ((uint8_t)SCG_CLOCKOUT_SRC_FOSC == u8ClockoutSrc) + { + u32Freq = FOSC_FREQUENCY; + } + else if ((uint8_t)SCG_CLOCKOUT_SRC_SIRC == u8ClockoutSrc) + { + u32Freq = SCG_CalculateSircFreq(SCG_SIRC_CLK); + } + else if ((uint8_t)SCG_CLOCKOUT_SRC_FIRC == u8ClockoutSrc) + { + u32Freq = SCG_CalculateFircFreq(SCG_FIRC_CLK); + } + else if ((uint8_t)SCG_CLOCKOUT_SRC_SOSC == u8ClockoutSrc) + { + u32Freq = SOSC_FREQUENCY; + } + else if ((uint8_t)SCG_CLOCKOUT_SRC_PLL1 == u8ClockoutSrc) + { + u32Freq = SCG_CalculatePll1Freq(SCG_PLL1_CLK); + } + else if ((uint8_t)SCG_CLOCKOUT_SRC_PLL0 == u8ClockoutSrc) + { + u32Freq = SCG_CalculatePll0Freq(SCG_PLL0_CLK); + } + else if ((uint8_t)SCG_CLOCKOUT_SRC_SIRC32K == u8ClockoutSrc) + { + u32Freq = SIRC32K_CLOCK; + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + + return u32Freq; +} + +static uint32_t SCG_CalculateCMU4RefFreq(void) +{ + uint32_t u32Freq,u32Temp; + + u32Temp = SCG_HWA_GetClkOutCfg(); + + if((u32Temp & SCG_CLKOUTCFG_CMU4CLK_FOSC_MASK) != 0U) + { + u32Freq = FOSC_FREQUENCY; + } + else if((u32Temp & SCG_CLKOUTCFG_CMU4CLK_SIRC_MASK) != 0U) + { + u32Freq = SIRC_CLOCK; + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + + return u32Freq; +} + +static SCG_StatusType SCG_EnablePLL0(const SCG_PllType *const pPllConfig) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal; + uint32_t u32Freq; + uint32_t u32FeedBackFreq,u32VcoFreq; + uint32_t u32DivHClockFreq = 0u; + uint32_t u32DivMClockFreq = 0u; + uint32_t u32DivLClockFreq = 0u; + uint32_t u32Pll0DivEn = 0u; + + /* check pll is valid, if valid, do not configure PLL */ + if (true == SCG_HWA_GetClockVliad(SCG_PLL0_CLOCK_SYMBOL)) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else + { + /* PLL input is FOSC or FIRC clock/2 */ + u32Freq = (SCG_PLLSOURCE_FOSC == pPllConfig->eSrc) ? (FOSC_FREQUENCY) : (FIRC_CLOCK / 2U); + + /* Check the PLL feedback clock range */ + u32FeedBackFreq = u32Freq / (pPllConfig->u8Prediv + 1U); + if(u32FeedBackFreq < PLL_FEEDBACK_CLK_MIN || u32FeedBackFreq > PLL_FEEDBACK_CLK_MAX) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + else + { + /* Check the PLL VCO clock range */ + u32VcoFreq = u32FeedBackFreq * (pPllConfig->u16Mult + 1U); + if((u32VcoFreq < PLL_VCO_CLK_MIN) || (u32VcoFreq > PLL_VCO_CLK_MAX)) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + else + { + /* Check the PLL out clock range */ + u32Freq = u32VcoFreq >> (uint32_t)pPllConfig->ePstDiv; + if (u32Freq > PLL0_CLK_MAX) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + } + } + + /* Check DIV clock frequency is valid or not */ + if (eStatusVal == SCG_STATUS_SUCCESS) + { + if(pPllConfig->eDivH != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivHClockFreq = (uint32_t)(u32Freq >> ((uint32_t)pPllConfig->eDivH - 1u)); + u32Pll0DivEn |= (uint32_t)SCG_CLOCK_DIV_H; + } + if(pPllConfig->eDivM != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivMClockFreq = (uint32_t)(u32Freq >> ((uint32_t)pPllConfig->eDivM - 1u)); + u32Pll0DivEn |= (uint32_t)SCG_CLOCK_DIV_M; + } + if(pPllConfig->eDivL != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivLClockFreq = (uint32_t)(u32Freq >> ((uint32_t)pPllConfig->eDivL - 1u)); + u32Pll0DivEn |= (uint32_t)SCG_CLOCK_DIV_L; + } + if ((u32DivHClockFreq > PLL0_DIVH_MAX_CLOCK) || (u32DivMClockFreq > PLL0_DIVM_MAX_CLOCK) || (u32DivLClockFreq > PLL0_DIVL_MAX_CLOCK)) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + } + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* unlock PLL CSR register */ + SCG_HWA_UnlockPllCsr(SCG_PLL0_CLOCK_SYMBOL); + + /* Configure PLLCFG register */ + u32TempVal = SCG_PLLCFG_PREDIV(pPllConfig->u8Prediv) | SCG_PLLCFG_MULT(pPllConfig->u16Mult) | SCG_PLLCFG_PSTDIV( + pPllConfig->ePstDiv) | SCG_PLLCFG_SOURCE(pPllConfig->eSrc) ; + SCG_HWA_SetPllCfg(SCG_PLL0_CLOCK_SYMBOL, u32TempVal); + + /* Configure PLLCSR register */ + u32TempVal = SCG_PLLCSR_STEN(pPllConfig->bSten); + SCG_HWA_SetPllCsr(SCG_PLL0_CLOCK_SYMBOL, u32TempVal); + + /* Configure PLLDIV */ + SCG_HWA_DiablePll0Div(SCG_CLOCK_DIV_ALL); + u32TempVal = SCG_HWA_GetClockDiv(SCG_PLL0_CLOCK_SYMBOL); + u32TempVal &= ~(uint32_t)(SCG_PLLDIV_DIVL_MASK | SCG_PLLDIV_DIVM_MASK | SCG_PLLDIV_DIVH_MASK); + u32TempVal |= (SCG_PLLDIV_DIVH(pPllConfig->eDivH) | SCG_PLLDIV_DIVM(pPllConfig->eDivM) | SCG_PLLDIV_DIVL( + pPllConfig->eDivL)); + SCG_HWA_SetPllDiv(SCG_PLL0_CLOCK_SYMBOL, u32TempVal) ; + + /* Set CSR[EN] bit to 1 */ + SCG_HWA_EnablePll(SCG_PLL0_CLOCK_SYMBOL); + + /* Wait PLL valid */ + u32TempVal = PLL_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((false == SCG_HWA_GetClockVliad(SCG_PLL0_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Enable PLLDIV */ + SCG_HWA_EnablePll0Div((SCG_DivEnableType)u32Pll0DivEn); + + if (pPllConfig->bCm) + { + SCG_HWA_EnablePllClockMonitor(SCG_PLL0_CLOCK_SYMBOL); + } + + if (pPllConfig->bCmre) + { + SCG_HWA_EnablePllClockMonitorReset(SCG_PLL0_CLOCK_SYMBOL); + } + + if (pPllConfig->bLock) + { + /* lock CSR register */ + SCG_HWA_LockPllCsr(SCG_PLL0_CLOCK_SYMBOL); + } + + /* Wait DIV[ACK] change to 1 */ + u32TempVal = CLOCK_DIV_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((SCG_HWA_GetPll0DivAck((SCG_DivEnableType)u32Pll0DivEn) != true), u32TempVal, eStatusVal) + } + else + { + /* Clear CFG configuration */ + SCG_HWA_SetPllCfg(SCG_PLL0_CLOCK_SYMBOL, 0U); + + /* Clear CSR configuration */ + SCG_HWA_SetPllCsr(SCG_PLL0_CLOCK_SYMBOL, 0U); + + /* Clear DIV configuration*/ + SCG_HWA_SetPllDiv(SCG_PLL0_CLOCK_SYMBOL, 0U); + } + + } + + return eStatusVal; +} + +static SCG_StatusType SCG_EnablePLL1(const SCG_PllType *const pPllConfig) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal; + uint32_t u32Freq; + uint32_t u32FeedBackFreq,u32VcoFreq; + uint32_t u32DivHClockFreq = 0u; + uint32_t u32DivMClockFreq = 0u; + uint32_t u32DivLClockFreq = 0u; + uint32_t u32Pll1DivEn = 0u; + + /* check pll is valid, if valid, do not configure PLL */ + if (true == SCG_HWA_GetClockVliad(SCG_PLL1_CLOCK_SYMBOL)) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else + { + /* PLL input is FOSC or FIRC clock/2 */ + u32Freq = (SCG_PLLSOURCE_FOSC == pPllConfig->eSrc) ? (FOSC_FREQUENCY) : (FIRC_CLOCK / 2U); + + /* Check the PLL feedback clock range */ + u32FeedBackFreq = u32Freq / (pPllConfig->u8Prediv + 1U); + if(u32FeedBackFreq < PLL_FEEDBACK_CLK_MIN || u32FeedBackFreq > PLL_FEEDBACK_CLK_MAX) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + else + { + /* Check the PLL VCO clock range */ + u32VcoFreq = u32FeedBackFreq * (pPllConfig->u16Mult + 1U); + if((u32VcoFreq < PLL_VCO_CLK_MIN) || (u32VcoFreq > PLL_VCO_CLK_MAX)) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + else + { + /* Check the PLL out clock range */ + u32Freq = u32VcoFreq >> (uint32_t)pPllConfig->ePstDiv; + if (u32Freq > PLL1_CLK_MAX) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + } + } + + /* Check DIV clock frequency is valid or not */ + if (eStatusVal == SCG_STATUS_SUCCESS) + { + if(pPllConfig->eDivH != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivHClockFreq = (uint32_t)(u32Freq >> ((uint32_t)pPllConfig->eDivH - 1u)); + u32Pll1DivEn |= (uint32_t)SCG_CLOCK_DIV_H; + } + if(pPllConfig->eDivM != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivMClockFreq = (uint32_t)(u32Freq >> ((uint32_t)pPllConfig->eDivM - 1u)); + u32Pll1DivEn |= (uint32_t)SCG_CLOCK_DIV_M; + } + if(pPllConfig->eDivL != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivLClockFreq = (uint32_t)(u32Freq >> ((uint32_t)pPllConfig->eDivL - 1u)); + u32Pll1DivEn |= (uint32_t)SCG_CLOCK_DIV_L; + } + if ((u32DivHClockFreq > PLL1_DIVH_MAX_CLOCK) || (u32DivMClockFreq > PLL1_DIVM_MAX_CLOCK) || (u32DivLClockFreq > PLL1_DIVL_MAX_CLOCK)) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + } + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* unlock PLL CSR register */ + SCG_HWA_UnlockPllCsr(SCG_PLL1_CLOCK_SYMBOL); + + /* Configure PLLCFG register */ + u32TempVal = SCG_PLLCFG_PREDIV(pPllConfig->u8Prediv) | SCG_PLLCFG_MULT(pPllConfig->u16Mult) | SCG_PLLCFG_PSTDIV( + pPllConfig->ePstDiv) | SCG_PLLCFG_SOURCE(pPllConfig->eSrc) ; + SCG_HWA_SetPllCfg(SCG_PLL1_CLOCK_SYMBOL, u32TempVal); + + /* Configure PLLCSR register */ + u32TempVal = SCG_PLLCSR_STEN(pPllConfig->bSten); + SCG_HWA_SetPllCsr(SCG_PLL1_CLOCK_SYMBOL, u32TempVal); + + /* Configure PLLDIV */ + SCG_HWA_DiablePll1Div(SCG_CLOCK_DIV_ALL); + u32TempVal = SCG_HWA_GetClockDiv(SCG_PLL1_CLOCK_SYMBOL); + u32TempVal &= ~(uint32_t)(SCG_PLLDIV_DIVL_MASK | SCG_PLLDIV_DIVM_MASK | SCG_PLLDIV_DIVH_MASK); + u32TempVal |= (SCG_PLLDIV_DIVH(pPllConfig->eDivH) | SCG_PLLDIV_DIVM(pPllConfig->eDivM) | SCG_PLLDIV_DIVL( + pPllConfig->eDivL)); + SCG_HWA_SetPllDiv(SCG_PLL1_CLOCK_SYMBOL, u32TempVal) ; + + /* Set CSR[EN] bit to 1 */ + SCG_HWA_EnablePll(SCG_PLL1_CLOCK_SYMBOL); + + /* Wait PLL valid */ + u32TempVal = PLL_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((false == SCG_HWA_GetClockVliad(SCG_PLL1_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Enable PLLDIV */ + SCG_HWA_EnablePll1Div((SCG_DivEnableType)u32Pll1DivEn); + + if (pPllConfig->bCm) + { + SCG_HWA_EnablePllClockMonitor(SCG_PLL1_CLOCK_SYMBOL); + } + + if (pPllConfig->bCmre) + { + SCG_HWA_EnablePllClockMonitorReset(SCG_PLL1_CLOCK_SYMBOL); + } + + if (pPllConfig->bLock) + { + /* lock CSR register */ + SCG_HWA_LockPllCsr(SCG_PLL1_CLOCK_SYMBOL); + } + + /* Wait DIV[ACK] change to 1 */ + u32TempVal = CLOCK_DIV_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((SCG_HWA_GetPll1DivAck((SCG_DivEnableType)u32Pll1DivEn) != true), u32TempVal, eStatusVal) + } + else + { + /* Clear CFG configuration */ + SCG_HWA_SetPllCfg(SCG_PLL1_CLOCK_SYMBOL, 0U); + + /* Clear CSR configuration */ + SCG_HWA_SetPllCsr(SCG_PLL1_CLOCK_SYMBOL, 0U); + + /* Clear DIV configuration*/ + SCG_HWA_SetPllDiv(SCG_PLL1_CLOCK_SYMBOL, 0U); + } + + } + + return eStatusVal; +} + +static SCG_StatusType SCG_DisablePLL0(void) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal; + + /* unlock PLL CSR register */ + SCG_HWA_UnlockPllCsr(SCG_PLL0_CLOCK_SYMBOL); + + /* Clear CFG configuration */ + SCG_HWA_SetPllCfg(SCG_PLL0_CLOCK_SYMBOL, 0U); + + /* Clear CSR configuration */ + SCG_HWA_SetPllCsr(SCG_PLL0_CLOCK_SYMBOL, 0U); + + u32TempVal = CLOCK_OFF_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((true == SCG_HWA_GetClockVliad(SCG_PLL0_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Clear CSR register */ + SCG_HWA_SetPllCsr(SCG_PLL0_CLOCK_SYMBOL, 0U); + + /* In order to avoid the DIV register value not cleared, Clear PLL DIV register twice */ + SCG_HWA_SetPllDiv(SCG_PLL0_CLOCK_SYMBOL, 0U); + SCG_HWA_SetPllDiv(SCG_PLL0_CLOCK_SYMBOL, 0U); + } + + + return eStatusVal; +} + +static SCG_StatusType SCG_DisablePLL1(void) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal; + + /* unlock PLL CSR register */ + SCG_HWA_UnlockPllCsr(SCG_PLL1_CLOCK_SYMBOL); + + /* Clear CFG configuration */ + SCG_HWA_SetPllCfg(SCG_PLL1_CLOCK_SYMBOL, 0U); + + /* Clear CSR configuration */ + SCG_HWA_SetPllCsr(SCG_PLL1_CLOCK_SYMBOL, 0U); + + u32TempVal = CLOCK_OFF_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((true == SCG_HWA_GetClockVliad(SCG_PLL1_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Clear CSR register */ + SCG_HWA_SetPllCsr(SCG_PLL1_CLOCK_SYMBOL, 0U); + + /* In order to avoid the DIV register value not cleared, Clear PLL DIV register twice */ + SCG_HWA_SetPllDiv(SCG_PLL1_CLOCK_SYMBOL, 0U); + SCG_HWA_SetPllDiv(SCG_PLL1_CLOCK_SYMBOL, 0U); + } + + return eStatusVal; +} + +/** + * @brief Check the system clock frequency + * @details This function check the system clock source valid and the system clock dividers valid, and get the frequency of eClock + * + * @param eClock selected clock source + * @param pSysClkConfig system clock configuration + * @param pClockFreq pointer to the memory to save clock source frequency + * @return SCG_StatusType function status + * + */ +static SCG_StatusType SCG_CheckSystemClockSourceFreq(const SCG_ClockSrcType eClock,const SCG_ClockCtrlType *const pSysClkConfig,uint32_t *pClockFreq) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32Freq; + uint32_t u32FreqCore, u32FreqBus, u32FreqSlow; + bool eClockValid; + + if (SCG_CLOCK_SRC_FOSC == eClock) + { + eClockValid = SCG_HWA_GetClockVliad(SCG_FOSC_CLOCK_SYMBOL); + u32Freq = FOSC_FREQUENCY; + } + else if (SCG_CLOCK_SRC_FIRC == eClock) + { + eClockValid = SCG_HWA_GetClockVliad(SCG_FIRC_CLOCK_SYMBOL); + u32Freq = FIRC_CLOCK; + } + else if (SCG_CLOCK_SRC_PLL0 == eClock) + { + eClockValid = SCG_HWA_GetClockVliad(SCG_PLL0_CLOCK_SYMBOL); + u32Freq = SCG_CalculatePll0Freq(SCG_PLL0_CLK); + + } + else if (SCG_CLOCK_SRC_SIRC == eClock) + { + eClockValid = SCG_HWA_GetClockVliad(SCG_SIRC_CLOCK_SYMBOL); + u32Freq = SIRC_CLOCK; + } + else + { + eClockValid = false; + } + + if(eClockValid == false) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else + { + *pClockFreq = u32Freq; + + if(pSysClkConfig != NULL_PTR) + { + u32FreqCore = u32Freq / ((uint8_t)pSysClkConfig->eDivCore + 1U); + u32FreqBus = u32FreqCore / ((uint8_t)pSysClkConfig->eDivBus + 1U); + u32FreqSlow = u32FreqBus / ((uint8_t)pSysClkConfig->eDivSlow + 1U); + if ((u32FreqCore > SYS_CORE_CLK_MAX) || (u32FreqBus > SYS_BUS_CLK_MAX) || (u32FreqSlow > SYS_SLOW_CLK_MAX)) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + } + } + return eStatusVal; +} + +/** + * @brief Switch system clock source , and configure system clock divider if pSysClkConfig is not null. + * @details If pSysClkConfig is null , and clock switch form slow to fast(eg. FIRC to PLL0), + * the bus and slow clock may exceed the max value. So the new divider must be configured + * if the system clock is switched to a faster source. + * + * @param eClock selected clock source + * @return SCG_StatusType function status + * SCG_STATUS_SUCCESS : clock source and dividers are valid,and switch system clock successfully + * SCG_STATUS_SEQUENCE_ERROR: new clock source is not enabled + * SCG_STATUS_PARAM_ERROR: the core bus slow divider are invalid + * SCG_STATUS_TIMEOUT: switch system clock procedure time out + */ +static SCG_StatusType SCG_SwitchSystemClockWithConfig(const SCG_ClockSrcType eClock,const SCG_ClockCtrlType *const pSysClkConfig) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32Timeout; + uint32_t u32CurClkFreq = 0U,u32NewClkFreq; + uint32_t u32RegValue; + uint8_t u8CurClkSrc,u8ClkSrc; + + u8CurClkSrc = SCG_HWA_GetSysClkSrc(); + if(u8CurClkSrc != eClock) + { + eStatusVal = SCG_CheckSystemClockSourceFreq(eClock,pSysClkConfig,&u32NewClkFreq); + + if(eStatusVal == SCG_STATUS_SUCCESS) + { + /* Get current system clock source frequency */ + if (SCG_CLOCK_SRC_FOSC == u8CurClkSrc) + { + u32CurClkFreq = FOSC_FREQUENCY; + } + else if (SCG_CLOCK_SRC_FIRC == u8CurClkSrc) + { + u32CurClkFreq = FIRC_CLOCK; + } + else if (SCG_CLOCK_SRC_PLL0 == u8CurClkSrc) + { + u32CurClkFreq = SCG_CalculatePll0Freq(SCG_PLL0_CLK); + } + else if (SCG_CLOCK_SRC_SIRC == u8CurClkSrc) + { + u32CurClkFreq = SIRC_CLOCK; + } + else + { + /* Never come here */ + } + + /* To switch the system clock source from slow to fast, configure the divider first to ensure that + the core bus slow clocks do not exceed the max value */ + if((pSysClkConfig != NULL_PTR) && (u32NewClkFreq > u32CurClkFreq)) + { + u32RegValue = SCG_HWA_GetCCR(); + u32RegValue &= ~(SCG_CCR_SYSCLK_CME_MASK | SCG_CCR_DIVCORE_MASK | SCG_CCR_DIVBUS_MASK | SCG_CCR_DIVSLOW_MASK); + u32RegValue |= (uint32_t)((uint32_t)SCG_CCR_SYSCLK_CME(pSysClkConfig->bSysClkMonitor) | + (uint32_t)SCG_CCR_DIVCORE(pSysClkConfig->eDivCore) | + (uint32_t)SCG_CCR_DIVBUS(pSysClkConfig->eDivBus) | + (uint32_t)SCG_CCR_DIVSLOW(pSysClkConfig->eDivSlow)); + SCG_HWA_SetCCR(u32RegValue); + } + + SCG_HWA_SetSystemClock((uint8_t)eClock); + + u32Timeout = SCG_CLKSRC_STABILIZATION_TIMEOUT; + do { + u8ClkSrc = SCG_HWA_GetSysClkSrc(); + --u32Timeout; + if(u32Timeout == 0U) + { + eStatusVal = SCG_STATUS_TIMEOUT; + break; + } + } while((SCG_HWA_GetSysClkUPRD() == false) && (u8ClkSrc != (uint8_t)eClock)); + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* To change the system clock source from fast to slow, configure the divider after selecting the clock source, + because it is safe to divide the slow frequency with the old divider */ + if((pSysClkConfig != NULL_PTR) && (u32NewClkFreq <= u32CurClkFreq)) + { + u32RegValue = SCG_HWA_GetCCR(); + u32RegValue &= ~(SCG_CCR_SYSCLK_CME_MASK | SCG_CCR_DIVCORE_MASK | SCG_CCR_DIVBUS_MASK | SCG_CCR_DIVSLOW_MASK); + u32RegValue |= (uint32_t)((uint32_t)SCG_CCR_SYSCLK_CME(pSysClkConfig->bSysClkMonitor) | + (uint32_t)SCG_CCR_DIVCORE(pSysClkConfig->eDivCore) | + (uint32_t)SCG_CCR_DIVBUS(pSysClkConfig->eDivBus) | + (uint32_t)SCG_CCR_DIVSLOW(pSysClkConfig->eDivSlow)); + SCG_HWA_SetCCR(u32RegValue); + + u32Timeout = SCG_CLKSRC_STABILIZATION_TIMEOUT; + while(SCG_HWA_GetSysClkUPRD() == false) + { + --u32Timeout; + if(u32Timeout == 0U) + { + eStatusVal = SCG_STATUS_TIMEOUT; + break; + } + } + } + } + + } + + } + return eStatusVal; +} + +/***************** Global Functions *********************/ +/** + * @brief Enable SOSC + * + * @param pSoscConfig SOSC configuration + * @return SCG_StatusType Function status + */ +SCG_StatusType SCG_EnableSOSC(const SCG_SoscType *const pSoscConfig) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal; + + DEV_ASSERT(NULL_PTR != pSoscConfig); + DEV_ASSERT(32768U == SOSC_FREQUENCY); + + /* Configure SOSC */ + SCG_HWA_SetSoscRecommendCfg(); + + /* Unlock CSR register first */ + SCG_HWA_UnlockSoscCsrReg(); + + /* Configure SOSC CSR register */ + u32TempVal = SCG_HWA_GetSoscCsr(); + u32TempVal &= ~(uint32_t)(SCG_SOSCCSR_BYPASS_MASK | SCG_SOSCCSR_CM_MASK | SCG_SOSCCSR_CMRE_MASK); + u32TempVal |= SCG_SOSCCSR_BYPASS(pSoscConfig->bBypass); + SCG_HWA_SetSoscCsr(u32TempVal); + + /* Enable SOSC*/ + SCG_HWA_EnableSosc(); + + /* Wait SOSC valid */ + u32TempVal = SOSC_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((false == SCG_HWA_GetClockVliad(SCG_SOSC_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + if (pSoscConfig->bCm) + { + SCG_HWA_EnableSoscClockMonitor(); + } + + if (pSoscConfig->bCmre) + { + SCG_HWA_EnableSoscClockMonitorReset(); + } + + if (pSoscConfig->bLock) + { + /* Lock CSR */ + SCG_HWA_LockSoscCsrReg(); + } + } + else + { + SCG_HWA_SetSoscCsr(0U); + } + + return eStatusVal; +} + +/** + * @brief Disable SOSC + * + * @return SCG_StatusType Function status + */ +SCG_StatusType SCG_DisableSOSC(void) +{ + SCG_StatusType eStatusVal; + uint32_t u32TempVal; + + /* Unlock CSR register first */ + SCG_HWA_UnlockSoscCsrReg(); + + /* Disable SOSC */ + SCG_HWA_DisableSosc(); + + /* Wait SOSC valid */ + u32TempVal = SOSC_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((true == SCG_HWA_GetClockVliad(SCG_SOSC_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Clear CSR register */ + SCG_HWA_SetSoscCsr(0U); + } + + return eStatusVal; +} + +/** + * @brief Enable FOSC clock with input configuration + * + * @param pFoscConfig FOSC configuration + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_EnableFOSC(const SCG_FoscType *const pFoscConfig) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal,u32FoscFreq; + uint8_t u8MSBVal; + uint32_t u32DivHClockFreq = 0U; + uint32_t u32DivMClockFreq = 0U; + uint32_t u32DivLClockFreq = 0U; + uint32_t u32FoscDivEn = 0U; + + DEV_ASSERT(NULL_PTR != pFoscConfig); + + /* Check DIV clock frequency is valid or not */ + if(pFoscConfig->eDivH != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivHClockFreq = (uint32_t)FOSC_FREQUENCY >> ((uint32_t)pFoscConfig->eDivH - 1U); + u32FoscDivEn |= (uint32_t)SCG_CLOCK_DIV_H; + } + if(pFoscConfig->eDivM != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivMClockFreq = (uint32_t)FOSC_FREQUENCY >> ((uint32_t)pFoscConfig->eDivM - 1U); + u32FoscDivEn |= (uint32_t)SCG_CLOCK_DIV_M; + } + if(pFoscConfig->eDivL != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivLClockFreq = (uint32_t)FOSC_FREQUENCY >> ((uint32_t)pFoscConfig->eDivL - 1U); + u32FoscDivEn |= (uint32_t)SCG_CLOCK_DIV_L; + } + + if ((u32DivHClockFreq > FOSC_DIVH_MAX_CLOCK) || (u32DivMClockFreq > FOSC_DIVM_MAX_CLOCK) || (u32DivLClockFreq > FOSC_DIVL_MAX_CLOCK)) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Unlock CSR register */ + SCG_HWA_UnlockFoscCsrReg(); + + /* COMP_EN is setting to 1 COMP_EN must be 1 when using an external crystal */ + /* Configure GM to the max value, GM_SEL: 15U */ + u32TempVal = SCG_FOSCCFG_BYPASS(pFoscConfig->bBypass) | SCG_FOSCCFG_COMP_EN(!pFoscConfig->bBypass) | + SCG_FOSCCFG_EOCV(50U) | SCG_FOSCCFG_GM_SEL(15U) | + SCG_FOSCCFG_ALC_D(1U) | SCG_FOSCCFG_HYST_D(0U); + SCG_HWA_SetFoscCfg(u32TempVal); + + /* Configure CSR register */ + u32TempVal = SCG_HWA_GetFoscCsr(); + u32TempVal &= ~(uint32_t)(SCG_FOSCCSR_STEN_MASK | SCG_FOSCCSR_CM_MASK | SCG_FOSCCSR_CMRE_MASK); + u32TempVal |= SCG_FOSCCSR_STEN(pFoscConfig->bSten); + SCG_HWA_SetFoscCsr(u32TempVal); + + /* Configure DIV value */ + SCG_HWA_DiableFoscDiv(SCG_CLOCK_DIV_ALL); + u32TempVal = SCG_HWA_GetClockDiv(SCG_FOSC_CLOCK_SYMBOL); + u32TempVal &= ~(uint32_t)(SCG_FOSCDIV_DIVL_MASK | SCG_FOSCDIV_DIVM_MASK | SCG_FOSCDIV_DIVH_MASK); + u32TempVal |= (SCG_FOSCDIV_DIVH(pFoscConfig->eDivH) | SCG_FOSCDIV_DIVM(pFoscConfig->eDivM) | SCG_FOSCDIV_DIVL( + pFoscConfig->eDivL)); + SCG_HWA_SetFoscDiv(u32TempVal) ; + + /* Enable FOSC */ + SCG_HWA_EnableFosc(); + + /* Wait FOSC vaild */ + u32TempVal = FOSC_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((false == SCG_HWA_GetClockVliad(SCG_FOSC_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Enable DIV */ + SCG_HWA_EnableFoscDiv((SCG_DivEnableType)u32FoscDivEn); + + if (pFoscConfig->bCm) + { + SCG_HWA_EnableFoscClockMonitor(); + } + + if (pFoscConfig->bCmre) + { + SCG_HWA_EnableFoscClockMonitorReset(); + } + + if (pFoscConfig->bLock) + { + /* Lock FOSC CSR register */ + SCG_HWA_LockFoscCsrReg(); + } + + /* Wait DIV[ACK] change to 1 */ + u32TempVal = CLOCK_DIV_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((SCG_HWA_GetFoscDivAck((SCG_DivEnableType)u32FoscDivEn) != true), u32TempVal, eStatusVal) + + /* if OSC >= 40M ,set 5, if OSC = 32M,set 10, if OSC = 24M, set 15, if OSC = 16M, set 20, if OSC = 8M, set 25*/ + /* This is the protection measure during low power wake up, if SCG register not valid after the setting time, the chip will reset + * and will set clock error flag in RGM register */ + u32FoscFreq = FOSC_FREQUENCY; + u8MSBVal = ((u32FoscFreq / 8000000U) >= 5U) ? (uint8_t)5U : (uint8_t)((6U - (FOSC_FREQUENCY / 8000000U)) * 5U); + SCG_HWA_SetWKPWDG(u8MSBVal); + } + else + { + /* Clear CSR configuration */ + SCG_HWA_SetFoscCsr(0U); + + /* Clear CFG configuration*/ + SCG_HWA_SetFoscCfg(0U); + + /* Clear DIV configuration*/ + SCG_HWA_SetFoscDiv(0U); + } + } + return eStatusVal; +} + +/** + * @brief Disable FOSC + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_DisableFOSC(void) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal; + uint8_t u8ClkSrc; + + u8ClkSrc = SCG_HWA_GetSysClkSrc(); + if ((uint8_t)SCG_CLOCK_SRC_FOSC == u8ClkSrc) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else if ((SCG_HWA_GetPllSrc(SCG_PLL0_CLOCK_SYMBOL) == (uint8_t)SCG_PLLSOURCE_FOSC) && ((uint8_t)SCG_CLOCK_SRC_PLL0 == u8ClkSrc)) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else + { + /* do nothing */ + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Unlock CSR register */ + SCG_HWA_UnlockFoscCsrReg(); + + /* Clear FOSC[EN] bit */ + SCG_HWA_DisableFosc(); + + u32TempVal = CLOCK_OFF_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((true == SCG_HWA_GetClockVliad(SCG_FOSC_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Clear CSR register */ + SCG_HWA_SetFoscCsr(0U); + + /* In order to avoid the DIV register value not cleared, Clear FOSC DIV register twice */ + SCG_HWA_SetFoscDiv(0U); + SCG_HWA_SetFoscDiv(0U); + } + } + + return eStatusVal; +} + +/** + * @brief Set SIRC configuration and configure SIRC DIV + * + * @param pSircConfig SIRC configuration + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_SetSIRC(const SCG_SircType *const pSircConfig) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal; + uint32_t u32SircDivEn = 0U; + uint16_t u16TrimDiv = 0U; + + DEV_ASSERT(NULL_PTR != pSircConfig); + DEV_ASSERT(pSircConfig->eDivH <= (uint32_t)SCG_ASYNCCLOCKDIV_BY64); + DEV_ASSERT(pSircConfig->eDivM <= (uint32_t)SCG_ASYNCCLOCKDIV_BY64); + DEV_ASSERT(pSircConfig->eDivL <= (uint32_t)SCG_ASYNCCLOCKDIV_BY64); + + /* Unlock SIRC CSR register */ + SCG_HWA_UnlockSircCsrReg(); + + /* Configure CSR register */ + u32TempVal = SCG_HWA_GetSircCsr(); + u32TempVal &= ~(uint32_t)(SCG_SIRCCSR_STEN_MASK | SCG_SIRCCSR_LPEN_MASK | SCG_SIRCCSR_TREN_MASK | SCG_SIRCCSR_TRUP_MASK | SCG_SIRCCSR_CM_MASK); + u32TempVal |= (uint32_t)(SCG_SIRCCSR_TRUP(pSircConfig->bTrEn) | SCG_SIRCCSR_TREN(pSircConfig->bTrEn) | SCG_SIRCCSR_LPEN(pSircConfig->bLpen) | SCG_SIRCCSR_STEN(pSircConfig->bSten)); + SCG_HWA_SetSircCsr(u32TempVal); + + /* Disable SIRC DIV[EN] bit */ + SCG_HWA_DiableSircDiv(SCG_CLOCK_DIV_ALL); + + if (pSircConfig->bCm) + { + SCG_HWA_EnableSircClockMonitor(); + } + + if (pSircConfig->bLock) + { + /* lock CSR */ + SCG_HWA_LockSircCsrReg(); + } + + /* Configure SIRC DIV */ + u32TempVal = SCG_HWA_GetClockDiv(SCG_SIRC_CLOCK_SYMBOL); + u32TempVal &= ~(uint32_t)(SCG_SIRCDIV_DIVL_MASK | SCG_SIRCDIV_DIVM_MASK | SCG_SIRCDIV_DIVH_MASK); + u32TempVal |= (uint32_t)(SCG_SIRCDIV_DIVL(pSircConfig->eDivL) | SCG_SIRCDIV_DIVM(pSircConfig->eDivM) | SCG_SIRCDIV_DIVH( + pSircConfig->eDivH)); + SCG_HWA_SetSircDiv(u32TempVal); + + /* Enable SIRC DIV */ + u32SircDivEn |= (pSircConfig->eDivH != SCG_ASYNC_CLOCK_DISABLE) ? (uint32_t)SCG_CLOCK_DIV_H : 0U; + u32SircDivEn |= (pSircConfig->eDivM != SCG_ASYNC_CLOCK_DISABLE) ? (uint32_t)SCG_CLOCK_DIV_M : 0U; + u32SircDivEn |= (pSircConfig->eDivL != SCG_ASYNC_CLOCK_DISABLE) ? (uint32_t)SCG_CLOCK_DIV_L : 0U; + SCG_HWA_EnableSircDiv((SCG_DivEnableType)u32SircDivEn); + u32TempVal = CLOCK_DIV_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((SCG_HWA_GetSircDivAck((SCG_DivEnableType)u32SircDivEn) != true), u32TempVal, eStatusVal) + + if (SCG_STATUS_SUCCESS != eStatusVal) + { + /* Clear SIRC DIV register */ + SCG_HWA_SetSircDiv(0U); + } + + /* Set SIRCTCFG register */ + if (pSircConfig->bTrEn == true) + { + /* set SIRCTCFG trim configuration */ + if (pSircConfig->u8TrimSrc == (uint8_t)SCG_IRC_TRIMSRC_FOSC) + { + /* Trim clock source choose FOSC */ + u16TrimDiv = (uint16_t)(FOSC_FREQUENCY / 250000U - 1U); + } + else if (pSircConfig->u8TrimSrc == (uint8_t)SCG_IRC_TRIMSRC_SOSC) + { + /* Trim clock source choose SOSC */ + u16TrimDiv = 0U; + } + else + { + /* Do nothing */ + } + u32TempVal = (uint32_t)(SCG_SIRCTCFG_TRIMSRC(pSircConfig->u8TrimSrc) | SCG_SIRCTCFG_TRIMDIV(u16TrimDiv)); + SCG_HWA_SetSircTcfg(u32TempVal); + } + + return eStatusVal; +} + +/** + * @brief Disable SIRC DIV and clear DIV configuration + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_ClearSIRC(void) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + + /* check SIRC is invalid, if invalid, do not configure SIRC */ + if (true != SCG_HWA_GetClockVliad(SCG_SIRC_CLOCK_SYMBOL)) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Unlock SIRC CSR register */ + SCG_HWA_UnlockSircCsrReg(); + + /* Disable SIRC DIV[EN] bit */ + SCG_HWA_DiableSircDiv(SCG_CLOCK_DIV_ALL); + + /* Clear SIRC DIV register */ + SCG_HWA_SetSircDiv(0U); + } + + return eStatusVal; +} + +/** + * @brief Enable SIRC32K + * + * @param pSirc32kConfig SIRC32K configuration + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_EnableSIRC32K(const SCG_Sirc32kType *const pSirc32kConfig) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal; + + DEV_ASSERT(NULL_PTR != pSirc32kConfig); + + /* Unlock SIRC32K CSR register */ + SCG_HWA_UnlockSirc32kCsrReg(); + + /* Enable SIRC32K */ + SCG_HWA_EnableSirc32kCsr(); + + /* Wait SIRC32K valid */ + u32TempVal = SIRC_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((false == SCG_HWA_GetClockVliad(SCG_SIRC32K_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + if (pSirc32kConfig->bLock) + { + /* Lock SIRC32K CSR register */ + SCG_HWA_LockSirc32kCsrReg(); + } + } + + return eStatusVal; +} + +/** + * @brief Disable SIRC32K + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_DisableSIRC32K(void) +{ + SCG_StatusType eStatusVal; + uint32_t u32TempVal; + + /* Unlock SIRC32K CSR register */ + SCG_HWA_UnlockSirc32kCsrReg(); + + /* Disable SIRC32K */ + SCG_HWA_DisableSirc32kCsr(); + + /* Wait SIRC32K not valid */ + u32TempVal = SIRC_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((true == SCG_HWA_GetClockVliad(SCG_SIRC32K_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + return eStatusVal; +} + +/** + * @brief Enable FIRC + * + * @param pFircConfig FIRC configuration + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_EnableFIRC(const SCG_FircType *const pFircConfig) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal, u32DivLClockFreq = 0U; + uint32_t u32FircDivEn = 0U; + uint16_t u16TrimDiv = 0U; + + DEV_ASSERT(NULL_PTR != pFircConfig); + DEV_ASSERT(pFircConfig->eDivH <= (uint32_t)SCG_ASYNCCLOCKDIV_BY64); + DEV_ASSERT(pFircConfig->eDivM <= (uint32_t)SCG_ASYNCCLOCKDIV_BY64); + DEV_ASSERT(pFircConfig->eDivL <= (uint32_t)SCG_ASYNCCLOCKDIV_BY64); + + /* Check DIV clock frequency is valid or not */ + if(pFircConfig->eDivL != SCG_ASYNC_CLOCK_DISABLE) + { + u32DivLClockFreq = (uint32_t)(FIRC_CLOCK >> (pFircConfig->eDivL - 1)); + u32FircDivEn |= (uint32_t)SCG_CLOCK_DIV_L; + } + if (u32DivLClockFreq > FIRC_DIVL_MAX_CLOCK) + { + eStatusVal = SCG_STATUS_PARAM_ERROR; + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Unlock CSR register */ + SCG_HWA_UnlockFircCsrReg(); + + /* Configure recommend value */ + SCG_HWA_SetFircCfg(SCG_FIRCCFG_CLKEN(3U)); + + /* Configure CSR register */ + u32TempVal = SCG_HWA_GetFircCsr(); + u32TempVal &= ~(uint32_t)(SCG_FIRCCSR_STEN_MASK | SCG_FIRCCSR_TREN_MASK | SCG_FIRCCSR_TRUP_MASK | SCG_FIRCCSR_CM_MASK); + u32TempVal |= (uint32_t)(SCG_FIRCCSR_TRUP(pFircConfig->bTrEn) | /* configure TRUP and EN together with TREN setting */ + SCG_FIRCCSR_TREN(pFircConfig->bTrEn) | + SCG_FIRCCSR_STEN(pFircConfig->bSten)); + SCG_HWA_SetFircCsr(u32TempVal); + + /* Configure DIV value */ + SCG_HWA_DiableFircDiv(SCG_CLOCK_DIV_ALL); + u32TempVal = SCG_HWA_GetClockDiv(SCG_FIRC_CLOCK_SYMBOL); + u32TempVal &= ~(uint32_t)(SCG_FIRCDIV_DIVL_MASK | SCG_FIRCDIV_DIVM_MASK | SCG_FIRCDIV_DIVH_MASK); + u32TempVal |= (SCG_FIRCDIV_DIVH(pFircConfig->eDivH) | SCG_FIRCDIV_DIVM(pFircConfig->eDivM) | SCG_FIRCDIV_DIVL( + pFircConfig->eDivL)); + SCG_HWA_SetFircDiv(u32TempVal) ; + + /* Set CSR[EN] bit to 1 */ + SCG_HWA_EnableFirc(); + + /* Wait FIRC valid */ + u32TempVal = FIRC_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((false == SCG_HWA_GetClockVliad(SCG_FIRC_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + if (pFircConfig->bCm) + { + SCG_HWA_EnableFircClockMonitor(); + } + + if (pFircConfig->bLock) + { + /* lock CSR register */ + SCG_HWA_LockFircCsrReg(); + } + + /* Enable DIV */ + u32FircDivEn |= (pFircConfig->eDivH != SCG_ASYNC_CLOCK_DISABLE) ? (uint32_t)SCG_CLOCK_DIV_H : 0U; + u32FircDivEn |= (pFircConfig->eDivM != SCG_ASYNC_CLOCK_DISABLE) ? (uint32_t)SCG_CLOCK_DIV_M : 0U; + SCG_HWA_EnableFircDiv((SCG_DivEnableType)u32FircDivEn); + + /* Wait DIV[ACK] change to 1 */ + u32TempVal = CLOCK_DIV_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((SCG_HWA_GetSircDivAck((SCG_DivEnableType)u32FircDivEn) != true), u32TempVal, eStatusVal) + + /* For clock auto trim, set TREN to True together with TRUP to True */ + if (pFircConfig->bTrEn == true) + { + /* set FIRCTCFG trim configuration */ + if (pFircConfig->u8TrimSrc == (uint8_t)SCG_IRC_TRIMSRC_FOSC) + { + /* Trim clock source choose FOSC */ + u16TrimDiv = (uint16_t)(FOSC_FREQUENCY / 250000U - 1U); + } + else if (pFircConfig->u8TrimSrc == (uint8_t)SCG_IRC_TRIMSRC_SOSC) + { + /* Trim clock source choose SOSC */ + u16TrimDiv = 0U; + } + else + { + /* do nothing */ + } + u32TempVal = (uint32_t)(SCG_FIRCTCFG_TRIMSRC(pFircConfig->u8TrimSrc) | SCG_FIRCTCFG_TRIMDIV(u16TrimDiv)); + SCG_HWA_SetFircTcfg(u32TempVal); + } + else + { + /* Trim disabled, just using IC internal IRC trim value */ + } + + } + else + { + /* Clear CSR configuration */ + SCG_HWA_SetFircCsr(0U); + + /* Clear DIV configuration*/ + SCG_HWA_SetFircDiv(0U); + } + } + return eStatusVal; +} + +/** + * @brief Disable FIRC + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_DisableFIRC(void) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32TempVal; + uint8_t u8ClkSrc; + + u8ClkSrc = SCG_HWA_GetSysClkSrc(); + if ((uint8_t)SCG_CLOCK_SRC_FIRC == u8ClkSrc) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else if ((SCG_HWA_GetPllSrc(SCG_PLL0_CLOCK_SYMBOL) == (uint8_t)SCG_PLLSOURCE_FIRC) && ((uint8_t)SCG_CLOCK_SRC_PLL0 == u8ClkSrc)) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else + { + /* do nothing */ + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Unlock CSR register */ + SCG_HWA_UnlockFircCsrReg(); + + /* Disable FIRC */ + SCG_HWA_DisableFirc(); + + /* Wait FIRC not valid */ + u32TempVal = FIRC_STABILIZATION_TIMEOUT; + SCG_CheckClockAckStatus((true == SCG_HWA_GetClockVliad(SCG_FIRC_CLOCK_SYMBOL)), u32TempVal, eStatusVal) + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + /* Clear CSR register */ + SCG_HWA_SetFircCsr(0U); + + /* In order to avoid the DIV register value not cleared, Clear FIRC DIV register twice */ + SCG_HWA_SetFircDiv(0U); + SCG_HWA_SetFircDiv(0U); + } + } + return eStatusVal; +} + + +/** + * @brief Enable PLL + * + * @param ePLL PLL instance + * @param pPllConfig PLL configuration + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_EnablePLL(const SCG_PllClkType ePll, const SCG_PllType *const pPllConfig) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + + DEV_ASSERT(NULL_PTR != pPllConfig); + DEV_ASSERT(((ePll == SCG_PLL0) || (ePll == SCG_PLL1))); + DEV_ASSERT(((pPllConfig->eSrc == SCG_PLLSOURCE_FOSC) || (pPllConfig->eSrc == SCG_PLLSOURCE_FIRC))); + DEV_ASSERT((pPllConfig->u16Mult > 95U) && (pPllConfig->u16Mult < 512U)); + DEV_ASSERT(pPllConfig->u8Prediv < 32U); + DEV_ASSERT(pPllConfig->u8Prediv != 2U); + DEV_ASSERT((pPllConfig->ePstDiv == SCG_PLLPSTDIV_BY2) || + (pPllConfig->ePstDiv == SCG_PLLPSTDIV_BY4) || + (pPllConfig->ePstDiv == SCG_PLLPSTDIV_BY8)); + DEV_ASSERT(pPllConfig->eDivH <= (uint32_t)SCG_ASYNCCLOCKDIV_BY64); + DEV_ASSERT(pPllConfig->eDivM <= (uint32_t)SCG_ASYNCCLOCKDIV_BY64); + DEV_ASSERT(pPllConfig->eDivL <= (uint32_t)SCG_ASYNCCLOCKDIV_BY64); + + + if ((true != SCG_HWA_GetClockVliad(SCG_FOSC_CLOCK_SYMBOL)) && (SCG_PLLSOURCE_FOSC == pPllConfig->eSrc)) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else if ((true != SCG_HWA_GetClockVliad(SCG_FIRC_CLOCK_SYMBOL)) && (SCG_PLLSOURCE_FIRC == pPllConfig->eSrc)) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else + { + /* do nothing */ + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + if (SCG_PLL0 == ePll) + { + eStatusVal = SCG_EnablePLL0(pPllConfig); + } + else if (SCG_PLL1 == ePll) + { + eStatusVal = SCG_EnablePLL1(pPllConfig); + } + else + { + /* do nothing */ + } + } + + return eStatusVal; +} + +/** + * @brief Disable PLL + * + * @param ePll PLL instance + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_DisablePLL(const SCG_PllClkType ePll) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + + if (SCG_PLL0 == ePll) + { + if (SCG_HWA_GetSysClkSrc() == (uint8_t)SCG_CLOCK_SRC_PLL0) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + else + { + eStatusVal = SCG_DisablePLL0(); + } + } + else + { + /* (SCG_PLL1 == ePll) */ + eStatusVal = SCG_DisablePLL1(); + } + + return eStatusVal; +} + +/** + * @brief Set system run time clock and related CORE/BUS/SLOW clock. + * + * @param pSysClkConfig pointer to the clockCtrlType structure data instance,which defined for system clock selection. + * @return SCG_StatusType function status + * SCG_STATUS_SUCCESS : clock source and dividers are valid,and switch system clock successfully + * SCG_STATUS_SEQUENCE_ERROR: new clock source is not enabled + * SCG_STATUS_PARAM_ERROR: the core bus slow divider are invalid + * SCG_STATUS_TIMEOUT: switch system clock procedure time out + */ +SCG_StatusType SCG_SetClkCtrl(const SCG_ClockCtrlType *const pSysClkConfig) +{ + DEV_ASSERT(NULL_PTR != pSysClkConfig); + + return SCG_SwitchSystemClockWithConfig(pSysClkConfig->eSrc,pSysClkConfig); +} + +/** + * @brief Get clock frequency + * + * @param eScgClockName Clock source type + * @return uint32_t frequency value + */ +uint32_t SCG_GetScgClockFreq(const SCG_ClkSrcType eScgClockName) +{ + uint32_t u32Freq; + DEV_ASSERT(eScgClockName < SCG_END_OF_CLOCKS); + + if ((SCG_CORE_CLK == eScgClockName) || + (SCG_BUS_CLK == eScgClockName) || + (SCG_SLOW_CLK == eScgClockName)) + { + u32Freq = SCG_CalculateSystemFreq(eScgClockName); + } + else if ((SCG_SIRC_CLK == eScgClockName) || + (SCG_SIRCDIVH_CLK == eScgClockName) || + (SCG_SIRCDIVM_CLK == eScgClockName) || + (SCG_SIRCDIVL_CLK == eScgClockName)) + { + u32Freq = SCG_CalculateSircFreq(eScgClockName); + } + else if ((SCG_FIRC_CLK == eScgClockName) || + (SCG_FIRCDIVH_CLK == eScgClockName) || + (SCG_FIRCDIVM_CLK == eScgClockName) || + (SCG_FIRCDIVL_CLK == eScgClockName)) + { + u32Freq = SCG_CalculateFircFreq(eScgClockName); + } + else if ((SCG_FOSC_CLK == eScgClockName) || + (SCG_FOSCDIVH_CLK == eScgClockName) || + (SCG_FOSCDIVM_CLK == eScgClockName) || + (SCG_FOSCDIVL_CLK == eScgClockName)) + { + u32Freq = SCG_CalculateFoscFreq(eScgClockName); + } + else if ((SCG_PLL0_CLK == eScgClockName) || + (SCG_PLL0DIVH_CLK == eScgClockName) || + (SCG_PLL0DIVM_CLK == eScgClockName) || + (SCG_PLL0DIVL_CLK == eScgClockName)) + { + u32Freq = SCG_CalculatePll0Freq(eScgClockName); + } + else if ((SCG_PLL1_CLK == eScgClockName) || + (SCG_PLL1DIVH_CLK == eScgClockName) || + (SCG_PLL1DIVM_CLK == eScgClockName) || + (SCG_PLL1DIVL_CLK == eScgClockName)) + { + u32Freq = SCG_CalculatePll1Freq(eScgClockName); + } + else if (SCG_SIRC32K_CLK == eScgClockName) + { + u32Freq = SIRC32K_CLOCK; + } + else if (SCG_SOSC_CLK == eScgClockName) + { + u32Freq = SOSC_FREQUENCY; + } + else if (SCG_SCG_CLKOUT_CLK == eScgClockName) + { + u32Freq = SCG_CalculateClkOutFreq(); + } + else if(SCG_NVMINIT_CLK == eScgClockName) + { + u32Freq = NVM_CLOCK; + } + else if(SCG_CMU4REF_CLK == eScgClockName) + { + u32Freq = SCG_CalculateCMU4RefFreq(); + } + else + { + u32Freq = UNKNOWN_CLOCK; + } + + if (UNKNOWN_CLOCK == u32Freq) + { + u32Freq = 0U; + } + + return u32Freq; +} + +/** + * @brief Select clock out source + * + * @param eClkoutSel clock out source + */ +void SCG_SetClkOut(const SCG_ClockoutSrcType eClkoutSel) +{ + DEV_ASSERT(eClkoutSel <= SCG_CLOCKOUT_SRC_SIRC32K); + + SCG_HWA_SetClkOutSel((uint8_t)eClkoutSel); +} + +/** + * @brief Select NVM clock source + * + * @param eNvmClkSrc NVM clock source + * @return uint32_t function status + */ +SCG_StatusType SCG_SetNvmClk(const SCG_NvmClkSrcType eNvmClkSrc) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + DEV_ASSERT((eNvmClkSrc == SCG_NVMCLK_SRC_SIRC) || (eNvmClkSrc == SCG_NVMCLK_SRC_FIRC)); + + if ((true != SCG_HWA_GetClockVliad(SCG_FIRC_CLOCK_SYMBOL)) && (eNvmClkSrc == SCG_NVMCLK_SRC_FIRC)) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + SCG_HWA_SetNvmClk(((uint32_t)1U << eNvmClkSrc)); + } + + return eStatusVal; +} + +/** + * @brief Select CMU4 clock source + * + * @param eCmu4ClkSrc CMU4 clock source + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_SetCmu4Clk(const SCG_Cmu4ClkSrcType eCmu4ClkSrc) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + DEV_ASSERT((eCmu4ClkSrc == SCG_CMU4CLK_SRC_SIRC) || (eCmu4ClkSrc == SCG_CMU4CLK_SRC_FOSC)); + + if ((true != SCG_HWA_GetClockVliad(SCG_FOSC_CLOCK_SYMBOL)) && (eCmu4ClkSrc == SCG_CMU4CLK_SRC_FOSC)) + { + eStatusVal = SCG_STATUS_SEQUENCE_ERROR; + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + SCG_HWA_SetCmu4Clk(((uint32_t)1U << eCmu4ClkSrc)); + } + return eStatusVal; +} + +/** + * @brief Generate the origion SCG register CRC result, and configure the SCG register CRC option. + * + * @param eMode The SCG register CRC trigger mode + * @return CRC configure status + * SCG_STATUS_SUCCESS : CRC configure successfully + * SCG_STATUS_TIMEOUT : CRC configure time out + */ +SCG_StatusType SCG_RegCrcConfig(SCG_CrcModeType eMode) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + uint32_t u32Timeout = 0xFFFFU; + + DEV_ASSERT((eMode == SCG_CRC_SW_MODE) || (eMode == SCG_CRC_TRIGGER_MODE)); + + /* Deinit CRC register */ + SCG_HWA_DisableCrcCheck(); + SCG_HWA_DisableCrcTriggerMode(); + SCG_HWA_DisableCrcErrorOutput(); + SCG_HWA_ClearCrcErrorFlag(); + + /* Generate original CRC result */ + SCG_HWA_GenCrcVal(); + while (SCG_HWA_GetCrcBusyStatus() == true) + { + u32Timeout--; + if (u32Timeout == 0U) + { + eStatusVal = SCG_STATUS_TIMEOUT; + break; + } + } + + if (eStatusVal == SCG_STATUS_SUCCESS) + { + if (eMode == SCG_CRC_TRIGGER_MODE) + { + SCG_HWA_EnableCrcTriggerMode(); + } + + /* Enable SCG CRC error to FCSMU in CSC0_SMU_CTRL4[SCG_CRC] */ + CSC0_HWA_CTRL4_EnableReqToSMU(CSC_SMU_SCG_CRC); + /* Generate CRC error output */ + SCG_HWA_EnableCrcErrorOutput(); + /* Generate CRC check */ + SCG_HWA_EnableCrcCheck(); + } + return eStatusVal; +} + +/** + * @brief Trigger the SCG register CRC generation by software + * + */ +void SCG_RegCrcGenerate(void) +{ + SCG_HWA_GenCrcVal(); +} + +/** + * @brief Trigger the SCG register CRC generation by software,and wait the CRC check result + * + * @return CRC check result + */ +SCG_CrcCheckResType SCG_RegCrcGenerateWaitResult(void) +{ + SCG_CrcCheckResType eStatusVal = SCG_CRC_CHECK_SUCCESS; + uint32_t u32Timeout = 0xFFFFU; + + SCG_HWA_GenCrcVal(); + while (SCG_HWA_GetCrcBusyStatus() == true) + { + u32Timeout--; + if (u32Timeout == 0U) + { + eStatusVal = SCG_CRC_GEN_TIMEOUT; + break; + } + } + + /* Check CRC is success or not */ + if (SCG_HWA_GetCrcErrorStatus()) + { + eStatusVal = SCG_CRC_CHECK_FAILED; + } + + return eStatusVal; +} + +/** + * @brief Clock source De-init + * + * @return SCG_StatusType function status + */ +SCG_StatusType SCG_Deinit(void) +{ + SCG_StatusType eStatusVal = SCG_STATUS_SUCCESS; + SCG_FircType tFircCfg = + { + .bLock = false, + .bCm = false, + .bTrEn = false, + .bSten = false, + .u8TrimSrc = 0U, + .eDivL = SCG_ASYNCCLOCKDIV_BY4, + .eDivM = SCG_ASYNCCLOCKDIV_BY2, + .eDivH = SCG_ASYNCCLOCKDIV_BY1 + }; + + if (SCG_HWA_GetSysClkSrc() != (uint8_t)SCG_CLOCK_SRC_FIRC) + { + eStatusVal = SCG_SwitchSystemClockWithConfig(SCG_CLOCK_SRC_FIRC,NULL_PTR); + if (SCG_STATUS_SEQUENCE_ERROR == eStatusVal) + { + eStatusVal = SCG_EnableFIRC(&tFircCfg); + if (SCG_STATUS_TIMEOUT != eStatusVal) + { + eStatusVal = SCG_SwitchSystemClockWithConfig(SCG_CLOCK_SRC_FIRC,NULL_PTR); + } + } + } + + if (SCG_STATUS_SUCCESS == eStatusVal) + { + /* Disable all clock source */ + (void)SCG_DisablePLL(SCG_PLL1); + (void)SCG_DisablePLL(SCG_PLL0); + (void)SCG_DisableFOSC(); + (void)SCG_DisableSOSC(); + (void)SCG_DisableSIRC32K(); + } + + return eStatusVal; +} + diff --git a/Src/fc7xxx_driver_scm.c b/Src/fc7xxx_driver_scm.c new file mode 100644 index 0000000..2b0edfa --- /dev/null +++ b/Src/fc7xxx_driver_scm.c @@ -0,0 +1,482 @@ +/** + * @file fc7xxx_driver_scm.h + * @author Flagchip + * @brief FC7xxx csc driver type definition and API + * @version 0.1.0 + * @date 2024-01-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ + +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_scm.h" + +/** + * @brief Get unique identification for the chip, loaded from NVR. + * + * @param pUid Pointer to UID + * + */ +void SCM_GetChip_UID(uint32 *pUid) +{ + DEV_ASSERT(NULL_PTR != pUid); + + pUid[0] = SCM_HWA_GetData_UIDL(); + pUid[1] = SCM_HWA_GetData_UIDML(); + pUid[2] = SCM_HWA_GetData_UIDMH(); + pUid[3] = SCM_HWA_GetData_UIDH(); +} + +/** + * @brief Get CCMx status. + * + * @param eCCMType CCM type + * @param u32Value selection to get + * + */ +uint32_t SCM_GetStatus_CCMx(SCM_CCM_Type eCCMType, uint32_t u32Value) +{ + uint32_t u32Temp; + + DEV_ASSERT(eCCMType == SCM_CCM0); + DEV_ASSERT((u32Value & SCM_CCM0_STATUS_MASK) == 0U); + + if (SCM_CCM0 == eCCMType) + { + u32Temp = SCM_HWA_GetStatus_CCM0(); + } + + return (u32Temp & u32Value); +} + +/** + * @brief Get matrix status. + * + * @param eMatrixType Matrix type + * @param u32Value selection to get + * + */ +uint32_t SCM_GetStatus_Matrix(SCM_MatrixStatusType eMatrixType, uint32_t u32Value) +{ + uint32_t u32Temp; + DEV_ASSERT((uint32_t)eMatrixType <= (uint32_t)SCM_MatrixStatus_ID); + + if (SCM_MatrixStatus_0 == eMatrixType) + { + u32Temp = SCM_HWA_GetStatus_MATRIX_STATUS0(); + } + else if (SCM_MatrixStatus_1 == eMatrixType) + { + u32Temp = SCM_HWA_GetStatus_MATRIX_STATUS1(); + } + else if (SCM_MatrixStatus_2 == eMatrixType) + { + u32Temp = SCM_HWA_GetStatus_MATRIX_STATUS2(); + } + else if (SCM_MatrixStatus_5 == eMatrixType) + { + u32Temp = SCM_HWA_GetStatus_MATRIX_STATUS5(); + } + else if (SCM_MatrixStatus_6 == eMatrixType) + { + u32Temp = SCM_HWA_GetStatus_MATRIX_STATUS6(); + } + else if (SCM_MatrixStatus_7 == eMatrixType) + { + u32Temp = SCM_HWA_GetStatus_MATRIX_STATUS7(); + } + else + { + u32Temp = SCM_HWA_GetStatus_MATRIX_ID_STATUS0(); + } + + return (u32Temp & u32Value); +} + +/** + * @brief Set cpu to control MAM ECC enable register 0. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_MAMECCR0(const SCM_WPB_CpuType eCpuType, bool bLockStatus) +{ + SCM_RetStatusType eRetVal; + DEV_ASSERT((uint32_t)eCpuType < (uint32_t)SCM_WP_CPU_NONE); + + if (0U == SCM_HWA_MAMECCEN0_GetWPBLockStatus()) + { + SCM_HWA_MAMECCEN0_SetCpuWritePermit(eCpuType); + + if (true == bLockStatus) + { + /* Lock the cpu to control settings until reset */ + SCM_HWA_MAMECCEN0_LockWritePermit(); + } + + eRetVal = SCM_E_OK; + } + else + { + eRetVal = SCM_E_LOCK; + } + + return eRetVal; +} + +/** + * @brief Set cpu to control MAM ECC enable register 1. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_MAMECCR1(const SCM_WPB_CpuType eCpuType, bool bLockStatus) +{ + SCM_RetStatusType eRetVal; + DEV_ASSERT((uint32_t)eCpuType < (uint32_t)SCM_WP_CPU_NONE); + + if (0U == SCM_HWA_MAMECCEN1_GetWPBLockStatus()) + { + SCM_HWA_MAMECCEN1_SetCpuWritePermit(eCpuType); + + if (true == bLockStatus) + { + /* Lock the cpu to control settings until reset */ + SCM_HWA_MAMECCEN1_LockWritePermit(); + } + + eRetVal = SCM_E_OK; + } + else + { + eRetVal = SCM_E_LOCK; + } + + return eRetVal; +} + +/** + * @brief Set cpu to control CPU0 ECC enable register. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_CPU0ECCEN(const SCM_WPB_CpuType eCpuType, bool bLockStatus) +{ + SCM_RetStatusType eRetVal; + DEV_ASSERT((uint32_t)eCpuType < (uint32_t)SCM_WP_CPU_NONE); + + if (0U == SCM_HWA_CPU0ECCEN_GetWPBLockStatus()) + { + SCM_HWA_CPU0ECCEN_SetCpuWritePermit(eCpuType); + + if (true == bLockStatus) + { + /* Lock the cpu to control settings until reset */ + SCM_HWA_CPU0ECCEN_LockWritePermit(); + } + + eRetVal = SCM_E_OK; + } + else + { + eRetVal = SCM_E_LOCK; + } + + return eRetVal; +} + +/** + * @brief Set cpu to control SOCMISC register. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_SOCMISC(const SCM_WPB_CpuType eCpuType, bool bLockStatus) +{ + SCM_RetStatusType eRetVal; + + if (0U == SCM_HWA_SOCMISC_GetWPBLockStatus()) + { + SCM_HWA_SOCMISC_SetCpuWritePermit(eCpuType); + + if (true == bLockStatus) + { + /* Lock the cpu to control settings until reset */ + SCM_HWA_SOCMISC_LockWritePermit(); + } + + eRetVal = SCM_E_OK; + } + else + { + eRetVal = SCM_E_LOCK; + } + + return eRetVal; +} + +/** + * @brief Set cpu to control Subsystem pcc register. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_SUBSYS_PCC(const SCM_WPB_CpuType eCpuType, bool bLockStatus) +{ + SCM_RetStatusType eRetVal; + + if (0U == SCM_HWA_SUBSYS_PCC_GetWPBLockStatus()) + { + SCM_HWA_SUBSYS_PCC_SetCpuWritePermit(eCpuType); + + if (true == bLockStatus) + { + /* Lock the cpu to control settings until reset */ + SCM_HWA_SUBSYS_PCC_LockWritePermit(); + } + + eRetVal = SCM_E_OK; + } + else + { + eRetVal = SCM_E_LOCK; + } + + return eRetVal; +} + +/** + * @brief Set cpu to control master halt request register. + * + * @param eCpuType Cpu to use + * @param bLockStatus Lock the cpu control settings + * + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetCpuCtrl_MASTER_HALT_REQ(const SCM_WPB_CpuType eCpuType, bool bLockStatus) +{ + SCM_RetStatusType eRetVal; + + if (0U == SCM_HWA_MASTER_HALT_REQ_GetWPBLockStatus()) + { + SCM_HWA_MASTER_HALT_REQ_SetCpuWritePermit(eCpuType); + + if (true == bLockStatus) + { + /* Lock the cpu to control settings until reset */ + SCM_HWA_MASTER_HALT_REQ_LockWritePermit(); + } + + eRetVal = SCM_E_OK; + } + else + { + eRetVal = SCM_E_LOCK; + } + + return eRetVal; +} + +/** + * @brief Set lock FTU_ROUTING register. + * + */ +void SCM_SetLock_FTU_ROUTING(void) +{ + if (0U == SCM_HWA_FTU_ROUTING_GetLockStatus()) + { + SCM_HWA_LockFTU_ROUTING(); + } +} + +/** + * @brief Set lock FTU_GTB register. + * + */ +void SCM_SetLock_FTU_GTB(void) +{ + if (0U == SCM_HWA_FTU_GTB_GetLockStatus()) + { + SCM_HWA_LockFTU_GTB(); + } +} + +/** + * @brief Set lock DEBUG_TRACE register. + * + */ +void SCM_SetLock_DEBUG_TRACE(void) +{ + if (0U == SCM_HWA_DEBUG_TRACE_GetLockStatus()) + { + SCM_HWA_LockDEBUG_TRACE(); + } +} + +/** + * @brief Set lock FLEXCAN_ROUTING register. + * + */ +void SCM_SetLock_FLEXCAN_ROUTING(void) +{ + if (0U == SCM_HWA_FLEXCAN_ROUTING_GetLockStatus()) + { + SCM_HWA_LockFLEXCAN_ROUTING(); + } +} + +/** + * @brief Set lock MSC0_ROUTING register. + * + */ +void SCM_SetLock_MSC0_ROUTING(void) +{ + if (0U == SCM_HWA_MSC0_ROUTING_GetLockStatus()) + { + SCM_HWA_LockMSC0_ROUTING(); + } +} + +/** + * @brief Set lock INT_ROUTER_NMI register. + * + */ +void SCM_SetLock_INT_ROUTER_NMI(void) +{ + if (0U == SCM_HWA_INT_ROUTER_NMI_GetLockStatus()) + { + SCM_HWA_LockINT_ROUTER_NMI(); + } +} + +/** + * @brief Set NMI interrupt router . + * + * @param eCpuType Cpu to use + * @param bEnable Enable/Disable + * @return Set operation success/failed + */ +SCM_RetStatusType SCM_SetEnable_NMIIntRouter(const SCM_WPB_CpuType eCpuType, bool bEnable) +{ + SCM_RetStatusType eRetVal; + + if (SCM_WP_CPU_0 == eCpuType) + { + SCM_HWA_SetEnable_Cpu0NMIIrqRouter(bEnable); + eRetVal = SCM_E_OK; + } + else + { + eRetVal = SCM_E_PARAM; + } + + return eRetVal; +} + +/** + * @brief Generate the origion SCM register CRC result, and configure the SCM register CRC option. + * + * @param eMode The SCM register CRC trigger mode + * @return CRC configure status + * SCM_E_OK : CRC configure successfully + * SCM_E_TIMEOUT : CRC configure time out + */ +SCM_RetStatusType SCM_RegCrcConfig(SCM_CrcModeType eMode) +{ + SCM_RetStatusType eStatusVal = SCM_E_OK; + uint32_t u32Timeout = 0xFFFFU; + + DEV_ASSERT((eMode == SCM_CRC_SW_MODE) || (eMode == SCM_CRC_TRIGGER_MODE)); + + /* Deinit CRC register */ + SCM_HWA_SetEnable_CrcCheck(false); + SCM_HWA_SetEnable_CrcTrigger(false); + SCM_HWA_SetEnable_CrcErrOut(false); + SCM_HWA_ClearCrcErrorFlag(); + + /* Generate original CRC result */ + SCM_HWA_SetEnable_CrcSwGen(true); + while (SCM_HWA_GetStatus_CrcBusyFlag() != 0U) + { + u32Timeout--; + if (u32Timeout == 0U) + { + eStatusVal = SCM_E_TIMEOUT; + break; + } + } + + if (eStatusVal == SCM_E_OK) + { + if (eMode == SCM_CRC_TRIGGER_MODE) + { + SCM_HWA_SetEnable_CrcTrigger(true); + } + + /* Enable SCM CRC error to FCSMU in CSC0_SMU_CTRL4[SCM_CRC] */ + CSC0_HWA_CTRL4_EnableReqToSMU(CSC_SMU_SCM_CRC); + /* Generate CRC error output */ + SCM_HWA_SetEnable_CrcErrOut(true); + /* Generate CRC check */ + SCM_HWA_SetEnable_CrcCheck(true); + } + return eStatusVal; +} + +/** + * @brief Trigger the SCM register CRC generation by software + * + */ +void SCM_RegCrcGenerate(void) +{ + SCM_HWA_SetEnable_CrcSwGen(true); +} + +/** + * @brief Trigger the SCM register CRC generation by software,and wait the CRC check result + * + * @return CRC check result + */ +SCM_RetStatusType SCM_RegCrcGenerateWaitResult(void) +{ + SCM_RetStatusType eStatusVal = SCM_E_OK; + uint32_t u32Timeout = 0xFFFFU; + + SCM_HWA_SetEnable_CrcSwGen(true); + while (SCM_HWA_GetStatus_CrcBusyFlag() != 0U) + { + u32Timeout--; + if (u32Timeout == 0U) + { + eStatusVal = SCM_E_TIMEOUT; + break; + } + } + + /* Check CRC is success or not */ + if (0U != SCM_HWA_GetStatus_CrcErrFlag()) + { + eStatusVal = SCM_E_CRC; + } + + return eStatusVal; +} diff --git a/Src/fc7xxx_driver_scst.c b/Src/fc7xxx_driver_scst.c new file mode 100644 index 0000000..e6388b9 --- /dev/null +++ b/Src/fc7xxx_driver_scst.c @@ -0,0 +1,230 @@ +/** + * @file fc7xxx_driver_scst.c + * @author Flagchip + * @brief FC7xxx scst driver source code + * @version 0.1.0 + * @date 2023-12-29 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/********************************************************************************* +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2023-12-29 qxw074 N/A First version for FC7240 +******************************************************************************** */ + +#include "fc7xxx_driver_scst.h" + +/** + * @brief The address of the specific implementation of the M7ST API + * + */ +#define M7ST_ROM_BASE 0x04812800 + +/** + * @brief The SCST Atomic Test function prototype + * + */ +typedef Type_M7ST_AtomicStatus (*Type_M7ST_RegressionTest) (uint32_t TestStart, uint32_t TestEnd, uint32_t InjectEnable, uint32_t RamBase); + +/** + * @brief The SCST Run selected tests function prototype + * + */ +typedef Type_M7ST_AtomicStatus (*Type_M7ST_AtomicTest) (uint32_t TestID, uint32_t InjectEnable, uint32_t RamBase); + +/** + * @brief M7ST API structure + * + */ +typedef struct Struct_M7ST_RomTable +{ + Type_M7ST_RegressionTest RegressionTest; + Type_M7ST_AtomicTest AluTest; + Type_M7ST_AtomicTest AluMLATest; + Type_M7ST_AtomicTest AluSHIFTTest; + Type_M7ST_AtomicTest AluTest1; + Type_M7ST_AtomicTest AluTest2; + Type_M7ST_AtomicTest AluTest3; + Type_M7ST_AtomicTest AluTest4; + Type_M7ST_AtomicTest AluTest5; + Type_M7ST_AtomicTest AluTest6; + Type_M7ST_AtomicTest RegbankTest1; + Type_M7ST_AtomicTest RegbankTest2; + Type_M7ST_AtomicTest RegbankTest3; + Type_M7ST_AtomicTest RegbankTest4; + Type_M7ST_AtomicTest RegbankTest5; + Type_M7ST_AtomicTest RegbankTest6; + Type_M7ST_AtomicTest LoadStoreTest1; + Type_M7ST_AtomicTest LoadStoreTest2; + Type_M7ST_AtomicTest LoadStoreTest3; + Type_M7ST_AtomicTest LoadStoreTest4; + Type_M7ST_AtomicTest LoadStoreTest5; + Type_M7ST_AtomicTest LoadStoreTest6; + Type_M7ST_AtomicTest SimdSatTest1; + Type_M7ST_AtomicTest SimdSatTest2; + Type_M7ST_AtomicTest SimdSatTest3; + Type_M7ST_AtomicTest SimdSatTest4; + Type_M7ST_AtomicTest MacTest1; + Type_M7ST_AtomicTest MacTest2; + Type_M7ST_AtomicTest FetchTest; + Type_M7ST_AtomicTest StatusTest1; + Type_M7ST_AtomicTest StatusTest2; + Type_M7ST_AtomicTest BranchTest1; + Type_M7ST_AtomicTest BranchTest2; +} Type_M7ST_RomTable; + +/** + * @brief This function is used to get the result of the executed test + * + * @param test_index is test number,0U..32U + * @param s_u32RamBase The first address of the 1k memory that the program needs to run + * @return M7ST_ErrorM7ST_TestPass is ok, others are not ok + */ +Type_M7ST_AtomicStatus SCST_ExecuteTest(SCST_TestIndexType test_index,uint32_t *s_u32RamBase) +{ + Type_M7ST_AtomicStatus Status = M7ST_FaultInjectError; + Type_M7ST_RomTable *M7ST_RomEntry = (Type_M7ST_RomTable *)M7ST_ROM_BASE; + switch(test_index) + { + case M7ST_AluTest: + Status = M7ST_RomEntry->AluTest(0,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_AluMLATest: + Status = M7ST_RomEntry->AluMLATest(1,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_AluSHIFTTest: + Status = M7ST_RomEntry->AluSHIFTTest(2,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_AluTes1t: + Status = M7ST_RomEntry->AluTest1(3,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_AluTest2: + Status = M7ST_RomEntry->AluTest2(4,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_AluTest3: + Status = M7ST_RomEntry->AluTest3(5,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_AluTest4: + Status = M7ST_RomEntry->AluTest4(6,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_AluTest5: + Status = M7ST_RomEntry->AluTest5(7,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_AluTest6: + Status = M7ST_RomEntry->AluTest6(8,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_RegbankTest1: + Status = M7ST_RomEntry->RegbankTest1(9,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_RegbankTest2: + Status = M7ST_RomEntry->RegbankTest2(10,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_RegbankTest3: + Status = M7ST_RomEntry->RegbankTest3(11,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_RegbankTest4: + Status = M7ST_RomEntry->RegbankTest4(12,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_RegbankTest5: + Status = M7ST_RomEntry->RegbankTest5(13,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_RegbankTest6: + Status = M7ST_RomEntry->RegbankTest6(14,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_LoadStoreTest1: + Status = M7ST_RomEntry->LoadStoreTest1(15,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_LoadStoreTest2: + Status = M7ST_RomEntry->LoadStoreTest2(16,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_LoadStoreTest3: + Status = M7ST_RomEntry->LoadStoreTest3(17,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_LoadStoreTest4: + Status = M7ST_RomEntry->LoadStoreTest4(18,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_LoadStoreTest5: + Status = M7ST_RomEntry->LoadStoreTest5(19,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_LoadStoreTest6: + Status = M7ST_RomEntry->LoadStoreTest6(20,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_SimdSatTest1: + Status = M7ST_RomEntry->SimdSatTest1(21,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_SimdSatTest2: + Status = M7ST_RomEntry->SimdSatTest2(22,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_SimdSatTest3: + Status = M7ST_RomEntry->SimdSatTest3(23,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_SimdSatTest4: + Status = M7ST_RomEntry->SimdSatTest4(24,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_MacTest1: + Status = M7ST_RomEntry->MacTest1(25,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_MacTest2: + Status = M7ST_RomEntry->MacTest2(26,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_FetchTest: + Status = M7ST_RomEntry->FetchTest(27,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_StatusTest1: + Status = M7ST_RomEntry->StatusTest1(28,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_StatusTest2: + Status = M7ST_RomEntry->StatusTest2(29,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_BranchTest1: + Status = M7ST_RomEntry->BranchTest1(30,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_BranchTest2: + Status = M7ST_RomEntry->BranchTest2(31,0,(uint32_t)&s_u32RamBase[0]); + break; + + case M7ST_RegressionTest: + Status = M7ST_RomEntry->RegressionTest(0,31,0,(uint32_t)&s_u32RamBase[0]); + break; + + default: + break; + } + return Status; +} + diff --git a/Src/fc7xxx_driver_sec.c b/Src/fc7xxx_driver_sec.c new file mode 100644 index 0000000..a8d20de --- /dev/null +++ b/Src/fc7xxx_driver_sec.c @@ -0,0 +1,424 @@ +/** + * @file fc7xxx_driver_sec.c + * @author FlagchipXXX + * @brief FC7xxx SEC driver type definition and API + * @version 0.1.0 + * @date 2024-1-12 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-1-12 Flagchip113 N/A First version for FC7240 +********************************************************************************/ +#include "fc7xxx_driver_sec.h" + + + + +/** + * @brief This function can be used to enable the Debug mode. + * @return true means enable debug success ,false means enable debug failed. + * */ +bool SEC_EnDebugMode(void) +{ + bool ret = false; + if (SEC_HWA_GetWritePer()) + { + SEC_HWA_EnDebug(); + ret = true; + } + return ret; +} + +/** + * @brief This function can be used to re-enable the Debug mode by the re-enable keys. + * @param keys The Debug mode re-enable keys. + * @return true means re-enable success,false means re-enable failed. + * */ +bool SEC_ReEnDebugMode(ReEnDebug_Keys keys) +{ + bool ret = false; + if (SEC_HWA_GetReEnDebug()) + { + SEC_HWA_ChangeDBK(0u, keys.Re_key0); + SEC_HWA_ChangeDBK(1u, keys.Re_key1); + SEC_HWA_ChangeDBK(2u, keys.Re_key2); + SEC_HWA_ChangeDBK(3u, keys.Re_key3); + ret = true; + } + return ret; +} + +/** + * @brief This function can get the system state (secured or no secured). + * */ +Systemstate SEC_SystemSecureState(void) +{ + Systemstate ret = Securedstate ; + uint16_t sskey0 = SEC_HWA_GetSScontrol0(); + uint16_t sskey1 = SEC_HWA_GetSScontrol1(); + if ((sskey0 == 0xC35AU) && (sskey1 == 0xFFFFU)) + { + ret = UnSecuredstate; + } + return ret ; +} + + +/** + * @brief This function can enable the test mode. + * @return true means enable test mode success,false means enable test mode failed. + * */ +bool SEC_EnTestMode(void) +{ + + bool ret = false; + if (SEC_HWA_GetWritePer()) + { + SEC_HWA_EnTest(); + ret = true; + } + return ret; +} + + + +/** + *@brief This function can Re-enable the test mode by the re-enable key. + *@param key The test mode re-enable key.The key is up to the user to decide in advance. + *@return true means re-enable success,false means re-enable failed. + * */ +bool SEC_ReEnTestMode(uint32_t key) +{ + bool ret = false; + + bool writeper = SEC_HWA_GetWritePer(); + bool reentest = SEC_HWA_GetReEnTest(); + if ((true == writeper) && (true == reentest)) + { + SEC_HWA_ReEnTestKey(key); + ret = true; + } + return ret; +} + + + +/** + * @brief This function can used to set the NVR write and read permission. + * @return true means setPer success,false means setPer failed. + * */ +bool SEC_SetNvrPer(NVR_Per per) +{ + bool ret = false; + if (SEC_HWA_GetWritePer()) + { + + if (per.ReadEn == true) + { + SEC_HWA_EnReadB0NVR(); + } + else + { + SEC_HWA_DisReadB0NVR(); + } + if (per.WritEn == true) + { + SEC_HWA_EnWriteB0NVR(); + } + else + { + SEC_HWA_DisWriteB0NVR(); + } + + if (per.EraseEn == true) + { + SEC_HWA_EnEraseB0NVR(); + } + else + { + SEC_HWA_DisEraseB0NVR(); + } + + ret = true; + } + return ret; +} + + +/** + * @brief Get Secure Boot Enable Status + * + * @return true is enable and false is disable + */ +bool SEC_GetSecureStatus(void) +{ + return SEC_HWA_GetSB(); +} + +/** + * @brief Get ISP Status + * + * @return true is active and false is inactive + */ +bool SEC_GetISPModeStatus(void) +{ + return SEC_HWA_GetIspStatus(); +} + +/** + * @brief Get User setting bootloader address + * + * @return bootloader address + */ +uint32_t SEC_GetBootAddress(void) +{ + return SEC_HWA_GetBLAddr(); +} + + +///** +// * @brief Get the HSM Firmware Address +// * +// * @return the HSM Firmware address +// */ +//uint32_t SEC_GetHsmFwAddress(void) +//{ +// return SEC_HWA_GetHsmAddr(); +//} + + +/** + * @brief Get the lifecycle. + * + * @return the lifecycle. + */ + +SC_LifeCycle SEC_GetLifeCycle(void) +{ + SC_LifeCycle lifecycle = LIFECYCLE_INVALID; + + uint8_t lifecycle_status; + lifecycle_status = SEC_HWA_GetLCStaus(); + + switch (lifecycle_status) + { + case 1u: + lifecycle = LIFECYCLE_OEM_DEV; + break; + case 2u: + lifecycle = LIFECYCLE_OEM_PDT; + break; + case 4u: + lifecycle = LIFECYCLE_INFIELD; + break; + case 8u: + lifecycle = LIFECYCLE_PREFA; + break; + case 16u: + lifecycle = LIFECYCLE_FA; + break; + default: + break; + + } + return lifecycle; +} + + + +/** + * @brief User Key Access Enable. Only valid under non-secure boot + * @return true means User key can be read/programmed/erased by host CPU + * */ +bool SEC_HostUKAccess(void) +{ + return SEC_HWA_GetUKAS(); +} + +/** + * @brief get the Bootloader Verification Algorithm + * @return the Bootloader Verification Algorithm + * */ +BL_VerifyAlgorithm SEC_GetBLVerifyAlgorithm(void) +{ + + return (BL_VerifyAlgorithm)(uint8_t)(SEC_HWA_GetBLVer()); +} + + +/** + * @brief get the Debug/ISP/PREFA Authentication and USRK decryption algorithm + * @return decryption algorithm + * */ +Decryption_Algorithm SEC_GetDecryptAlgorithm(void) +{ + return (Decryption_Algorithm)(uint8_t)(SEC_HWA_GetDecrypt()); + + +} + + +/** + * @brief Indicate the Host User Key Read/Write/Erase Protection + * @param PHostUKAccess the structure for information + * + * */ +void SEC_GetHostUKAccess(HostUKPermission *const PHostUKAccess) +{ + PHostUKAccess->HostUKEraseEn = SEC_HWA_GetHUKErase(); + PHostUKAccess->HostUKReadEn = SEC_HWA_GetHUKRead(); + PHostUKAccess->HostUKWriteEn = SEC_HWA_GetHUKWrite(); +} + +/** + * @brief Indicate the Host NVR Read/Write/Erase Protection + *@param PHostNvrAccess the structure to initialize + * */ +void SEC_GetHostNVRAccess(HostNVRPermission *const PHostNVRAccess) +{ + PHostNVRAccess->HostNVREraseEn = SEC_HWA_GetHostNvrErase(); + PHostNVRAccess->HostNVRReadEn = SEC_HWA_GetHostNvrRead(); + PHostNVRAccess->HostNVRWriteEn = SEC_HWA_GetHostNvrWrite(); + +} + + + +/** + * @brief Get the HSM User Key Erase Protection + * @return true - HSM erase access to User Key region is enabled + * false -HSM erase access to User Key region is disabled + * */ +bool SEC_GethsmUKEraseAccess(void) +{ + return SEC_HWA_GetHsmUKErase(); + +} + + +/** + * @brief Get the HSM NVR Erase Protection + * @return true - HSM erase access to NVR region is enabled + * false -HSM erase access to NVR region is disabled + * */ +bool SEC_GethsmNVREraseAccess(void) +{ + return SEC_HWA_GetHsmNvrErase(); +} + +/** + * @brief Get Bootloader Verification Mask + * @return Bootloader Verification Mask. + * */ +uint32_t SEC_GetBLVerMask(void) +{ + return SEC_HWA_GetBLMask(); +} + +/** + * @brief Get whether Debug Backdoor Key Input Enable. + * @return + * 0011b - User can input DBK through debug mailbox, ISP is not valid. + * 1100b - User can input DBK through ISP, debug mailbox is not valid. + * 1111b - User can input DBK through both debug mailbox and ISP. + * Other Values - User cannot input DBK through both debug mailbox andISP. + * */ +uint32_t SEC_GetDMBDkeyEn(void) +{ + return SEC_HWA_GetMBBKEN(); +} + + +/** + * @brief Host Debug Auth Enable. Only valid in secure boot. (Value loaded from NVR sector) + * @return true means Host debug authentication enable. false means Host debug authentication disable. + */ +bool SEC_GetDebugAuthEn(void) +{ + return SEC_HWA_GetDEAUEn(); +} + + +/** + * @brief Get the isp information. + * @param pIspInfo the structure to information + * @return Get whether operation is success. + * + * */ +SEC_RetType SEC_GetIspInfo(SEC_IspInfo *const pIspInfo) +{ + + SEC_RetType eRet ; + + if (NULL == pIspInfo) + { + eRet = SEC_STATUS_FAILED; + } + else + { + bool ispen = SEC_HWA_GetIspStatus(); + if (!ispen) + { + eRet = SEC_STATUS_FAILED; + } + else + { + pIspInfo->IspModeEn = SEC_HWA_GetIspStatus(); + pIspInfo->IspPinEn = SEC_HWA_GetIspEn(); + pIspInfo->IspAuthEn = SEC_HWA_GetISPAU(); + Isp_Instance ispins = (Isp_Instance)(uint8_t)(SEC_HWA_GetIspIns()); + if ((ispins == ISP_FCUART1) || (ispins == ISP_FCUART3)) + { + pIspInfo->Ispfcuartbaudrate = (FCUART_ISP_BAUDRATE)(uint8_t)(SEC_HWA_GetUartBR()); + pIspInfo->Ispflexcanbaudrate = ISP_FLEXCAN_INVALID; + } + else if ((ispins == ISP_FLEXCAN1) || (ispins == ISP_FLEXCAN5)) + { + pIspInfo->Ispfcuartbaudrate = ISP_FCUART_INVALID; + pIspInfo->Ispflexcanbaudrate = (FLEXCAN_ISP_BAUDRATE)(uint8_t)(SEC_HWA_GetCanBR()); + } + else + { + /*do nothing*/ + } + eRet = SEC_STATUS_SUCCESS; + } + } + return eRet; +} + +/** + * @brief Get the boot information. + * @param pBootInfo the structure for information + * @return Get whether operation is success. + * + * */ +SEC_RetType SEC_GetBootInfo(SEC_BootInfo *const pBootInfo) +{ + + SEC_RetType eRet ; + if (NULL == pBootInfo) + { + eRet = SEC_STATUS_FAILED; + } + else + { + pBootInfo->BootRom = SEC_HWA_GetBootRom(); + pBootInfo->NmiPinEn = SEC_HWA_GetNmiPin(); + pBootInfo->SecBootEn = SEC_HWA_GetSB(); + pBootInfo->OscEn = SEC_HWA_GetOSCAvail(); + pBootInfo->OscFreq = (Osc_FreqInfo)(uint8_t)(SEC_HWA_GetOSCFre()); + pBootInfo->FastBootSpeed = (FastBoot_Speed)(uint8_t)(SEC_HWA_GetFastBootClock()); + eRet = SEC_STATUS_SUCCESS; + } + return eRet; +} + + diff --git a/Src/fc7xxx_driver_sent.c b/Src/fc7xxx_driver_sent.c new file mode 100644 index 0000000..2111c29 --- /dev/null +++ b/Src/fc7xxx_driver_sent.c @@ -0,0 +1,896 @@ +/** + * @file fc7xxx_driver_sent.c + * @author Flagchip + * @brief FC7xxx SENT driver source code + * @version 0.2.0 + * @date 2022-12-30 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Author CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2022-12-14 Flagchip N/A First version for FC7300 SENT + * 0.2.0 2022-12-30 Flagchip N/A Support SPC mode for SENT + ******************************************************************************** */ + +#include "fc7xxx_driver_sent.h" +#include "interrupt_manager.h" +#include "HwA_sent.h" + +#define SENT_GLBL_CTL_PRESCALER_MAX 255U +#define SENT_GLBL_CTL_WATERMARK_MAX 16U + +static SENT_Type* const aSent_Base[] = SENT_BASE_PTRS; +static bool aSentInit[SENT_INSTANCE_COUNT] = {0u}; +static SENT_GBISRCallbackType aGBISRCallback[SENT_INSTANCE_MAX] = {NULL}; +static SENT_CHISRCallbackType aCHISRCallback[SENT_INSTANCE_MAX] = {NULL}; + +void SENT0_IRQHandler(void); +void SENT1_IRQHandler(void); + +static void SENT_IRQ_Handler(const Sent_InstanceType eInstance) +{ + uint8_t u8Channel; + uint32_t u32ChannelStatus; + SENT_Type *pSent = aSent_Base[eInstance]; + + + for(u8Channel = 0U; u8Channel < SENT_CHANNEL_COUNT; u8Channel++) + { + if(true == SENT_HWA_GetChannelReceive(pSent, u8Channel)) + { + if(true == SENT_HWA_GetSLowMessageUnderflowFlag(pSent, u8Channel)) + { + if(NULL != aGBISRCallback[eInstance]) + { + SENT_HWA_ClearSLowMessageUnderflowFlag(pSent, u8Channel); + aGBISRCallback[eInstance]((Sent_ChannelType)u8Channel, SENT_SLOW_MSG_DMA_UF_IT); + } + } + if(true == SENT_HWA_GetFastMessageReadyFlag(pSent, u8Channel)) + { + if(NULL != aGBISRCallback[eInstance]) + { + SENT_HWA_ClearFastMessageReadyFlag(pSent, u8Channel); + aGBISRCallback[eInstance]((Sent_ChannelType)u8Channel, SENT_FAST_MSG_READY_IT); + } + } + if(true == SENT_HWA_GetSlowMessageReadyFlag(pSent, u8Channel)) + { + if(NULL != aGBISRCallback[eInstance]) + { + SENT_HWA_ClearSlowMessageReadyFlag(pSent, u8Channel); + aGBISRCallback[eInstance]((Sent_ChannelType)u8Channel, SENT_SLOW_MSG_READY_IT); + } + } + if(true == SENT_HWA_GetFastMessageFIFOOverflowFlag(pSent, u8Channel)) + { + if(NULL != aGBISRCallback[eInstance]) + { + SENT_HWA_ClearFastMessageFIFOOverflowFlag(pSent, u8Channel); + aGBISRCallback[eInstance]((Sent_ChannelType)u8Channel, SENT_FAST_MSG_FIFO_OF_IT); + } + } + if(true == SENT_HWA_GetFastMessageDMAUnderflowFlag(pSent, u8Channel)) + { + if(NULL != aGBISRCallback[eInstance]) + { + SENT_HWA_ClearFastMessageDMAUnderflowFlag(pSent, u8Channel); + aGBISRCallback[eInstance]((Sent_ChannelType)u8Channel, SENT_FAST_MSG_DMA_DF_IT); + } + } + u32ChannelStatus = SENT_HWA_GetChannelStatus(pSent, u8Channel); + if(0U != u32ChannelStatus) + { + if(NULL != aCHISRCallback[eInstance]) + { + SENT_HWA_ClearChannelStatus(pSent, u8Channel, u32ChannelStatus); + aCHISRCallback[eInstance]((Sent_ChannelType)u8Channel, u32ChannelStatus); + } + } + } + } +} + +Sent_ReturnType SENT_Init(const Sent_InstanceType eInstance, const Sent_ConfigType *pCfg) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(false == aSentInit[eInstance]) + { + if((NULL != pCfg) && (eInstance < SENT_INSTANCE_MAX) && \ + (pCfg->u8DmaWaterMark <= SENT_GLBL_CTL_WATERMARK_MAX) && \ + (pCfg->u8PreScaler < SENT_GLBL_CTL_PRESCALER_MAX)) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_SetGlobalPreScaler(pSent, pCfg->u8PreScaler); + SENT_HWA_SetDMAWaterMark(pSent, pCfg->u8DmaWaterMark); + if(true == pCfg->bDebugModeEn) + { + SENT_HWA_EnableDebugMode(pSent); + } + else + { + SENT_HWA_DisableDebugMode(pSent); + } + if(true == pCfg->bAutoClearReadyFlag) + { + SENT_HWA_EnableDataOverflowFlagFastClear(pSent); + } + else + { + SENT_HWA_DisableDataOverflowFlagFastClear(pSent); + } + aGBISRCallback[eInstance] = pCfg->pGBCallback; + aCHISRCallback[eInstance] = pCfg->pCHCallback; + SENT_HWA_EnableGlobal(pSent); + aSentInit[eInstance] = true; + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_ALREADY_INIT; + } + + return eRet; +} + +Sent_ReturnType SENT_SetChannelConfig(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, const Sent_ChannelConfigType *pCfg) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((NULL != pCfg) && (eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + if(true == pCfg->bChannelEn) + { + if((pCfg->u8DataNibbleNumber > 0U) && (pCfg->u8DataNibbleNumber < 6U)) + { + SENT_HWA_DisableChannelReceive(pSent, (uint8_t)eChannel); + + SENT_HWA_SetChannelIdleCount(pSent, (uint8_t)eChannel, (uint8_t)pCfg->eIdleCount); + SENT_HWA_SetChannelDigitalFilterCount(pSent, (uint8_t)eChannel, pCfg->u8DigitalFilterCount); + SENT_HWA_SetChannelNibbleNumber(pSent, (uint8_t)eChannel, pCfg->u8DataNibbleNumber); + SENT_HWA_SetChannelPreScaler(pSent, (uint8_t)eChannel, (uint16_t)pCfg->u16TickScaler); + SENT_HWA_SetChannelNibbleDataMode(pSent, (uint8_t)eChannel, (SENT_NibbleDataModeType)(pCfg->eDataNibbleMode)); + + if(SENT_CALIBRATION_PULSE_DIAG_OPTION1 != pCfg->eCalDiagOption) + { + SENT_HWA_DisableChannelSPCOption1(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_EnableChannelSPCOption1(pSent, (uint8_t)eChannel); + } + if(true == pCfg->bPausePulseEn) + { + SENT_HWA_EnableChannelPausePulse(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelPausePulse(pSent, (uint8_t)eChannel); + } + if(true == pCfg->bTickCompensateEn) + { + SENT_HWA_EnableChannelCompensate(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelCompensate(pSent, (uint8_t)eChannel); + } + + if(true == pCfg->bFastMessageFifoEn) + { + SENT_HWA_EnableChannelFIFO(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelFIFO(pSent, (uint8_t)eChannel); + } + + if(true == pCfg->bFastMsgCRCAugEn) + { + SENT_HWA_EnableChannelFastMessageAugmentation(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelFastMessageAugmentation(pSent, (uint8_t)eChannel); + } + + if(true == pCfg->bFastMsgCRCCheckEn) + { + SENT_HWA_EnableChannelFastMessageCRCCheck(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelFastMessageCRCCheck(pSent, (uint8_t)eChannel); + } + + if(true == pCfg->bFastMsgCRCWithSCEn) + { + SENT_HWA_EnableChannelFastMessageCRCWithSC(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelFastMessageCRCWithSC(pSent, (uint8_t)eChannel); + } + + if(true == pCfg->bFastMsgDataChangeEn) + { + SENT_HWA_EnableChannelFastMessageDataChange(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelFastMessageDataChange(pSent, (uint8_t)eChannel); + } + + + if(true == pCfg->bSlowMsgCRCAugEn) + { + SENT_HWA_EnableChannelSlowMessageAugmentation(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelSlowMessageAugmentation(pSent, (uint8_t)eChannel); + } + + if(true == pCfg->bUseAlternativeCrc) + { + SENT_HWA_EnableChannelAltCRC(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelAltCRC(pSent, (uint8_t)eChannel); + } + + if(SENT_CALIBRATION_VALID_WITHIN_20 == pCfg->eCalValid) + { + SENT_HWA_DisableChannelCalValid20To25(pSent, (uint8_t)eChannel); + SENT_HWA_EnableChannelCalValidDiagnostic(pSent, (uint8_t)eChannel); + } + else if(SENT_CALIBRATION_VALID_FROM_20_TO_25 == pCfg->eCalValid) + { + SENT_HWA_EnableChannelCalValid20To25(pSent, (uint8_t)eChannel); + SENT_HWA_EnableChannelCalValidDiagnostic(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelCalValid20To25(pSent, (uint8_t)eChannel); + SENT_HWA_DisableChannelCalValidDiagnostic(pSent, (uint8_t)eChannel); + } + SENT_HWA_EnableChannelReceive(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + SENT_HWA_DisableChannelReceive(pSent, (uint8_t)eChannel); + } + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_SetDMAConfig(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, Sent_DMAConfigType *pCfg) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((NULL != pCfg) && (eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + if(true == pCfg->bFastMsgDmaEn) + { + SENT_HWA_EnableChannelFastMessageDmaRequest(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelFastMessageDmaRequest(pSent, (uint8_t)eChannel); + } + + if(true == pCfg->bSlowMsgDmaEn) + { + SENT_HWA_EnableChannelSlowMessageDmaRequest(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelSlowMessageDmaRequest(pSent, (uint8_t)eChannel); + } + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_SetSPCConfig(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, const Sent_SpcConfigType *pCfg) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((NULL != pCfg) && (eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_DisableChannelSPCMode(pSent, (uint8_t)eChannel); + SENT_HWA_SetChannelSPCTickBase(pSent, (uint8_t)eChannel, (SENT_SPCTickType)(pCfg->eSpcTickBase)); + SENT_HWA_SetChannelSPCTriggerMethod(pSent, (uint8_t)eChannel, (SENT_SPCTriggerType)(pCfg->eSpcTrigger)); + SENT_HWA_SetChannelSPCPulseDelay(pSent, (uint8_t)eChannel, pCfg->u8PulseDelay); + SENT_HWA_SetChannelSPCPulseWidth(pSent, (uint8_t)eChannel, pCfg->u8PulseWidth); + if(true == pCfg->bCalDiagEn) + { + SENT_HWA_EnableChannelCalibrationDiag(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelCalibrationDiag(pSent, (uint8_t)eChannel); + } + if(true == pCfg->bSpcModeEn) + { + SENT_HWA_EnableChannelSPCMode(pSent, (uint8_t)eChannel); + } + else + { + SENT_HWA_DisableChannelSPCMode(pSent, (uint8_t)eChannel); + } + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_GetFastMessageData(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, Sent_FastMessageDataType *pMsg) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + uint8_t u8DataShift; + + if(true == aSentInit[eInstance]) + { + if((NULL != pMsg) && (eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + pMsg->u8CRC = SENT_HWA_GetChannelFastMessageCRCNibble(pSent, (uint8_t)eChannel); + pMsg->u8SC = SENT_HWA_GetChannelFastMessageStatusNibble(pSent, (uint8_t)eChannel); + pMsg->u32Timestamp = SENT_HWA_GetChannelFastMessageTimeStamp(pSent, (uint8_t)eChannel); + u8DataShift = (5U - SENT_HWA_GetChannelNibbleNumber(pSent, (uint8_t)eChannel)) << 2U; + pMsg->u32Data = SENT_HWA_GetChannelDataNibble(pSent, (uint8_t)eChannel) >> (SENT_CHN_FDATA_DATA6_SHIFT + u8DataShift); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_GetSlowMessageData(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, Sent_SlowMessageDataType *pMsg) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((NULL != pMsg) && (eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + pMsg->eMsgType = (Sent_SerialMessageType)SENT_HWA_GetChannelSLowMessageType(pSent, (uint8_t)eChannel); + pMsg->u32Timestamp = SENT_HWA_GetChannelSlowMessageTimeStamp(pSent, (uint8_t)eChannel); + if(SENT_SERIAL_MESSAGE_SHORT == pMsg->eMsgType) + { + pMsg->u8CRC = SENT_HWA_GetChannelBit2CRC(pSent, (uint8_t)eChannel) & 0xFU; + pMsg->u16Data = (uint16_t)SENT_HWA_GetChannelBit2DATA(pSent, (uint8_t)eChannel) & 0xFFU; + pMsg->u8ID = SENT_HWA_GetChannelBit2DATA(pSent, (uint8_t)eChannel) >> 8U; + } + else if(SENT_SERIAL_MESSAGE_ENHANCE_12DATA_8ID == pMsg->eMsgType) + { + pMsg->u8CRC = SENT_HWA_GetChannelBit2CRC(pSent, (uint8_t)eChannel); + pMsg->u16Data = SENT_HWA_GetChannelBit2DATA(pSent, (uint8_t)eChannel); + pMsg->u8ID = (SENT_HWA_GetChannelBit3EnhancedID7_4_OR_ID3_0(pSent, (uint8_t)eChannel) << 4U) | SENT_HWA_GetChannelBit3EnhancedID3_0_OR_DATA15_12(pSent, (uint8_t)eChannel); + } + else if(SENT_SERIAL_MESSAGE_ENHANCE_16DATA_4ID == pMsg->eMsgType) + { + pMsg->u8CRC = SENT_HWA_GetChannelBit2CRC(pSent, (uint8_t)eChannel); + pMsg->u16Data = ((uint16_t)SENT_HWA_GetChannelBit3EnhancedID3_0_OR_DATA15_12(pSent, (uint8_t)eChannel) << 12U) | (uint16_t)SENT_HWA_GetChannelBit2DATA(pSent, (uint8_t)eChannel); + pMsg->u8ID = SENT_HWA_GetChannelBit3EnhancedID7_4_OR_ID3_0(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_NOT_OK; + } + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_DecodeFastMessageWithDMABuffer(uint32_t *pDmaBuffer, uint32_t u32BufferLength, Sent_FastMessageDataType *pMsg) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + + if((NULL != pMsg) && (NULL != pDmaBuffer) && (12U == u32BufferLength)) + { + pMsg->u8CRC = (uint8_t)((pDmaBuffer[1] & SENT_CHN_FCRC_CRC_DATA_MASK) >> SENT_CHN_FCRC_CRC_DATA_SHIFT); + pMsg->u8SC = (uint8_t)((pDmaBuffer[1] & SENT_CHN_FCRC_SC_NB_MASK) >> SENT_CHN_FCRC_SC_NB_SHIFT); + pMsg->u32Timestamp = ((pDmaBuffer[2] & SENT_CHN_FTS_TIMESTAMP_VAL_MASK) >> SENT_CHN_FTS_TIMESTAMP_VAL_SHIFT); + pMsg->u32Data = (pDmaBuffer[0] >> SENT_CHN_FDATA_DATA6_SHIFT); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + + return eRet; +} + +Sent_ReturnType SENT_DecodeSlowMessageWithDMABuffer(uint32_t *pDmaBuffer, uint32_t u32BufferLength, Sent_SlowMessageDataType *pMsg) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + + if((NULL != pMsg) && (NULL != pDmaBuffer) && (12U == u32BufferLength)) + { + if(SENT_CHN_SBIT3__MSG_TYPE_MASK == (pDmaBuffer[0] & SENT_CHN_SBIT3__MSG_TYPE_MASK)) + { + if(SENT_CHN_SBIT3__CFG_MASK == (pDmaBuffer[0] & SENT_CHN_SBIT3__CFG_MASK)) + { + pMsg->eMsgType = (Sent_SerialMessageType)SENT_SLOW_MESSAGE_ENHANCE_16DATA_4ID; + } + else + { + pMsg->eMsgType = (Sent_SerialMessageType)SENT_SLOW_MESSAGE_ENHANCE_12DATA_8ID; + } + } + else + { + pMsg->eMsgType = (Sent_SerialMessageType)SENT_SLOW_MESSAGE_SHORT; + } + pMsg->u32Timestamp = ((pDmaBuffer[2] & SENT_CHN_STS_SMSG_TIMESTAMP_MASK) >> SENT_CHN_STS_SMSG_TIMESTAMP_SHIFT); + if(SENT_SERIAL_MESSAGE_SHORT == pMsg->eMsgType) + { + pMsg->u8CRC =(uint8_t)(((pDmaBuffer[1] & SENT_CHN_SBIT2__SMSG_CRC_MASK) >> SENT_CHN_SBIT2__SMSG_CRC_SHIFT) & 0xFU); + pMsg->u16Data = (uint16_t)(((pDmaBuffer[1] & SENT_CHN_SBIT2__SMSG_DATA_MASK) >> SENT_CHN_SBIT2__SMSG_DATA_SHIFT) & 0xFFU); + pMsg->u8ID = (uint8_t)(((pDmaBuffer[1] & SENT_CHN_SBIT2__SMSG_DATA_MASK) >> SENT_CHN_SBIT2__SMSG_DATA_SHIFT) >> 8U); + } + else if(SENT_SERIAL_MESSAGE_ENHANCE_12DATA_8ID == pMsg->eMsgType) + { + pMsg->u8CRC = (uint8_t)((pDmaBuffer[1] & SENT_CHN_SBIT2__SMSG_CRC_MASK) >> SENT_CHN_SBIT2__SMSG_CRC_SHIFT); + pMsg->u16Data = (uint16_t)((pDmaBuffer[1] & SENT_CHN_SBIT2__SMSG_DATA_MASK) >> SENT_CHN_SBIT2__SMSG_DATA_SHIFT); + pMsg->u8ID = (uint8_t)((((pDmaBuffer[0] & SENT_CHN_SBIT3__ID7_4_OR_ID3_0_MASK) >> SENT_CHN_SBIT3__ID7_4_OR_ID3_0_SHIFT) << 4U) |\ + ((pDmaBuffer[0] & SENT_CHN_SBIT3__ID3_0_OR_DATA15_12_MASK) >> SENT_CHN_SBIT3__ID3_0_OR_DATA15_12_SHIFT)); + } + else if(SENT_SERIAL_MESSAGE_ENHANCE_16DATA_4ID == pMsg->eMsgType) + { + pMsg->u8CRC = (uint8_t)((pDmaBuffer[1] & SENT_CHN_SBIT2__SMSG_CRC_MASK) >> SENT_CHN_SBIT2__SMSG_CRC_SHIFT); + pMsg->u16Data = (uint16_t)((((pDmaBuffer[0] & SENT_CHN_SBIT3__ID3_0_OR_DATA15_12_MASK) >> SENT_CHN_SBIT3__ID3_0_OR_DATA15_12_SHIFT) << 12U) |\ + ((pDmaBuffer[1] & SENT_CHN_SBIT2__SMSG_DATA_MASK) >> SENT_CHN_SBIT2__SMSG_DATA_SHIFT)); + pMsg->u8ID = (uint8_t)((pDmaBuffer[0] & SENT_CHN_SBIT3__ID7_4_OR_ID3_0_MASK) >> SENT_CHN_SBIT3__ID7_4_OR_ID3_0_SHIFT); + } + else + { + eRet = SENT_RETURN_E_NOT_OK; + } + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + + return eRet; +} + +Sent_ReturnType SENT_EnableGlobalFastMsgNotification(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_EnableChannelFastMessageInterrupt(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_DisableGlobalFastMsgNotification(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_DisableChannelFastMessageInterrupt(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_EnableGlobalSlowMsgNotification(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_EnableChannelSlowMessageInterrupt(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_DisableGlobalSlowMsgNotification(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_DisableChannelSlowMessageInterrupt(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_EnableGlobalFastFifoMsgNotification(const Sent_InstanceType eInstance) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if(eInstance < SENT_INSTANCE_MAX) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_EnableFastMessageFIFOOverflowInterrupt(pSent); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_DisableGlobalFastFifoMsgNotification(const Sent_InstanceType eInstance) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if(eInstance < SENT_INSTANCE_MAX) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_DisableFastMessageFIFOOverflowInterrupt(pSent); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_ConfigChannelStatusNotification(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, const Sent_ChannelInterruptType *sInterruptEn) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_EnableChannelBusIdleInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bBusIdleITEn); + SENT_HWA_EnableChannelSPCOverRunInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bSpcOverrunITEn); + SENT_HWA_EnableChannelCALDiagInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bCalDiagErrITEn); + SENT_HWA_EnableChannelCalFailInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bCalFailITEn); + SENT_HWA_EnableChannelCalResyncInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bCalResyncErrITEn); + SENT_HWA_EnableChannelEdgeERRInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bFallingEdgeNumErrITEn); + SENT_HWA_EnableChannelFCRCInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bFastMsgCrcErrITEn); + SENT_HWA_EnableChannelFOVFLInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bFastMsgOFITEn); + SENT_HWA_EnableChannelNibbleErrorInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bNibbleValueErrITEn); + SENT_HWA_EnableChannelPPDiagInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bPrePulseDiagErrITEn); + SENT_HWA_EnableChannelSCRCInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bSlowMsgCrcErrITEn); + SENT_HWA_EnableChannelSOVFLInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bSlowMsgOFITEn); + SENT_HWA_EnableChannelCalERRInterrupt(pSent, (uint8_t)eChannel, sInterruptEn->bCalErrITEn); + //SENT_HWA_EnableChannelAllErrorInterrupt(pSent, eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_RequestSPCPulse(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_StartChannelSPC(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_GetFastMsgReadyFlag(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, bool *pFlag) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + *pFlag = SENT_HWA_GetFastMessageReadyFlag(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_GetSlowMsgReadyFlag(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, bool *pFlag) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + *pFlag = SENT_HWA_GetSlowMessageReadyFlag(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_GetChannelStatus(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, uint32_t *pStatus) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + *pStatus = SENT_HWA_GetChannelStatus(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_ClearChannelStatus(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, uint32_t Status) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + SENT_HWA_ClearChannelStatus(pSent, (uint8_t)eChannel, Status); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +Sent_ReturnType SENT_GetChannelSPCBusyFlag(const Sent_InstanceType eInstance, const Sent_ChannelType eChannel, bool *pflag) +{ + Sent_ReturnType eRet = SENT_RETURN_OK; + SENT_Type *pSent; + + if(true == aSentInit[eInstance]) + { + if((eInstance < SENT_INSTANCE_MAX) && (eChannel < SENT_CHANNEL_MAX)) + { + pSent = aSent_Base[eInstance]; + + *pflag = SENT_HWA_GetChanneSPCBusyFlag(pSent, (uint8_t)eChannel); + } + else + { + eRet = SENT_RETURN_E_PARAM; + } + } + else + { + eRet = SENT_RETURN_E_UNINIT; + } + + return eRet; +} + +void SENT0_IRQHandler(void) +{ + SENT_IRQ_Handler(SENT_INSTANCE_0); +} + +void SENT1_IRQHandler(void) +{ + SENT_IRQ_Handler(SENT_INSTANCE_1); +} diff --git a/Src/fc7xxx_driver_smc.c b/Src/fc7xxx_driver_smc.c new file mode 100644 index 0000000..cdb4ec0 --- /dev/null +++ b/Src/fc7xxx_driver_smc.c @@ -0,0 +1,122 @@ +/** + * @file fc7xxx_driver_smc.c + * @author Flagchip0105 + * @brief FC7xxx SMC driver type definition and API + * @version 0.1.0 + * @date 2024-01-08 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-08 Flagchip0105 N/A FC7240 First version +********************************************************************************/ +#include "fc7xxx_driver_smc.h" + +/** + * @brief Set system mode + * + * @param eMode MCU low power mode + * @return Smc return type + */ +SMC_StatusType SMC_SetSystemMode(const SMC_ModeType eMode) +{ + SMC_StatusType eRet = SMC_STATUS_SUCCESS; + + DEV_ASSERT(eMode <= SMC_MODE_STANBY_3); + + switch (eMode) + { + case SMC_MODE_RUN: + /* Clear the SLEEPDEEP bit to disable deep sleep mode */ + CM7_HWA_DisableDeepSleep(); + + break; + case SMC_MODE_STOP: + /* switch smc mode to stop mode */ + SMC_HWA_SetStopModeCtrl(SMC_STOP_MODE); + /* Set the SLEEPDEEP bit to enable deep sleep mode (STOP)*/ + CM7_HWA_EnableDeepSleep(); + + /* Cpu is going into deep sleep state */ + STANDBY(); + + break; + + case SMC_MODE_WAIT: + /* Clear the SLEEPDEEP bit to disable deep sleep mode */ + CM7_HWA_DisableDeepSleep(); + + /* Cpu is going into sleep state */ + STANDBY(); + + break; + + case SMC_MODE_STANBY_0: + /* select standby mode*/ + SMC_HWA_SetStandbyMode(SMC_CFG_STANDBY_0); + + /* switch smc mode to standby mode */ + SMC_HWA_SetStopModeCtrl(SMC_STANDBY_MODE); + /* Set the SLEEPDEEP bit to enable deep sleep mode */ + CM7_HWA_EnableDeepSleep(); + + /* Cpu is going into deep sleep state */ + STANDBY(); + + break; + + case SMC_MODE_STANBY_1: + /* select standby mode*/ + SMC_HWA_SetStandbyMode(SMC_CFG_STANDBY_1); + + /* switch smc mode to standby mode */ + SMC_HWA_SetStopModeCtrl(SMC_STANDBY_MODE); + + /* Set the SLEEPDEEP bit to enable deep sleep mode */ + CM7_HWA_EnableDeepSleep(); + + /* Cpu is going into deep sleep state */ + STANDBY(); + break; + + case SMC_MODE_STANBY_2: + /* select standby mode*/ + SMC_HWA_SetStandbyMode(SMC_CFG_STANDBY_2); + + /* switch smc mode to standby mode */ + SMC_HWA_SetStopModeCtrl(SMC_STANDBY_MODE); + + /* Set the SLEEPDEEP bit to enable deep sleep mode */ + CM7_HWA_EnableDeepSleep(); + + /* Cpu is going into deep sleep state */ + STANDBY(); + break; + + case SMC_MODE_STANBY_3: + /* select standby mode*/ + SMC_HWA_SetStandbyMode(SMC_CFG_STANDBY_3); + + /* switch smc mode to standby mode */ + SMC_HWA_SetStopModeCtrl(SMC_STANDBY_MODE); + + /* Set the SLEEPDEEP bit to enable deep sleep mode */ + CM7_HWA_EnableDeepSleep(); + + /* Cpu is going into deep sleep state */ + STANDBY(); + break; + default: + /* do nothing */ + break; + + } + + return eRet; +} diff --git a/Src/fc7xxx_driver_stcu.c b/Src/fc7xxx_driver_stcu.c new file mode 100644 index 0000000..30e5385 --- /dev/null +++ b/Src/fc7xxx_driver_stcu.c @@ -0,0 +1,202 @@ +/** + * @file fc7xxx_driver_stcu.c + * @author Flagchip + * @brief FC4xxx stcu driver type definition and API + * @version 0.1.0 + * @date 2023-02-15 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + */ + +/* ******************************************************************************** + * Revision History: + * + * Version Date Author CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 1/10/2024 Flagchip0095 N/A First version for FC7240 + ******************************************************************************** */ +#include "HwA_stcu.h" +#include "fc7xxx_driver_stcu.h" + + + +/* ################################################################################## */ +/* ##################################### Macros ##################################### */ +#define STCU_SAFETY_KEY (0xBB40E64DU) +#define STCU_RECOMMENDED_PATTERN (0xBUL) + + +/* ################################################################################## */ +/* ################################# Local Variables ################################ */ + +/* ################################################################################## */ +/* ########################### Local Functions Prototype ############################ */ + +/* ################################################################################## */ +/* ######################### Global Functions prototype ############################ */ +void STCU0_IRQHandler(void); + +/* ################################################################################## */ +/* ################################# Local Functions ############################### */ +static Stcu_IRQCallback sIRQCallback = NULL; + +/* ################################################################################## */ +/* ################################# Global Functions ############################### */ + +/** + * \brief Init the STCU module + * + * \param pConfig the configuration structure + */ +void STCU_Init(STCU_ConfigType *pConfig) +{ + uint32_t u32Reg; + + STCU_HWA_MbistSelect(pConfig->u32MbistSel); + + STCU_HWA_SetMBISTSWAlg(pConfig->bMbistFullTest, pConfig->bMbistSramInit); + + pConfig->bInterruptEn?STCU_HWA_EnableInterrupt():STCU_HWA_DisableInterrupt(); + + sIRQCallback = pConfig->pIrqCallback; + + u32Reg = STCU_SELF_TEST_CTRL_LBIST_CLKDIV((uint32_t)(pConfig->eLbistClkDivider)) | + STCU_SELF_TEST_CTRL_LBIST_EN(pConfig->bLbistEn?1UL:0UL) | + STCU_SELF_TEST_CTRL_MBIST_LP(pConfig->bMbistLPC?1UL:0UL) | + STCU_SELF_TEST_CTRL_MBIST_EN(pConfig->bMbistEn?1UL:0UL) | + STCU_SELF_TEST_CTRL_CLK_SEL((uint32_t)(pConfig->eClkSource)) | + STCU_SELF_TEST_CTRL_MT(pConfig->u16MaxTime) | + STCU_SELF_TEST_CTRL_PE(STCU_PORT_PULL_DISABLE == pConfig->ePortPullMode?0UL:1UL) | + STCU_SELF_TEST_CTRL_PS(STCU_PORT_PULL_UP == pConfig->ePortPullMode?1UL:0UL) | + STCU_SELF_TEST_CTRL_FCSMU_TRIG(0U) | /* FCSMU reset will trigger self-test */ + STCU_SELF_TEST_CTRL_LBIST_TD(1U) | /* enable LBIST at-speed test */ + STCU_SELF_TEST_CTRL_SCHK_EN(1U) | /* self check enable */ + STCU_SELF_TEST_CTRL_STEST_BYPASS(0U);/* self-test will be not bypassed */ + + STCU_HWA_SetSelfTestCTRL(u32Reg); +} + +/** + * \brief Set the LBIST Pattern value and expected misr value. + * The two value should be load from NVR, but also can reconfigure by this API. + * The expected misr value is calculated from pattern, so please make sure this two value is right, or the LBST would fail. + * + * \param u16Pattern the LBIST Pattern value + * \param u16Pattern the LBIST expected misr value + */ +void STCU_LBIST_Set_Pattern_Misr(uint16_t u16Pattern, uint32_t u32ExpectedMisr) +{ + STCU_HWA_SetLBISTPatternAmount(u16Pattern); + STCU_HWA_SetExpectedMisr(u32ExpectedMisr); +} + +/** + * \brief Trigger to start Software self test + * + */ +void STCU_StartSelfTest(void) +{ + /* clear STCU_SELF_TEST_STATUS. */ + STCU_HWA_ClearSelfTestStatus(); + + STCU_HWA_SetSafetyKey(STCU_SAFETY_KEY); /* enable STCU_SELF_TEST_CTRL A/B access */ + + /* set the TRIG bits in both STCU_SELF_TEST_TRIG_A and STCU_SELF_TEST_TRIG_B. */ + STCU_HWA_SwTriggerA(); + STCU_HWA_SwTriggerB(); +} + +/** + * \brief Check Software Trigger Self-test result. If the LBIST is done, could call "STCU_GetLbistFailResult" to check the test result. + * If the MBIST is done, could call "STCU_GetMbistFailResult" to check the test result. + * + * \return refer to "STCU_SelfTestStatusType" enum. + */ +uint32_t STCU_CheckTriggerResult(void) +{ + return STCU_HWA_GetSelfTestStatus(); +} + +/** + * \brief Get each MBIST Fail result + * + * \return refer to "STCU_MbistFailedType" enum. + */ +uint32_t STCU_GetMbistFailResult(void) +{ + uint32_t u32Done, u32Fail; + + u32Done = STCU_GetMbistDone(); + u32Fail = STCU_GetMbistFail(); + + return (u32Done & u32Fail); +} + +/** + * \brief Get if the LBIST test result is Fail + * + * \return true means LBIST fail. false means LBIST pass. + */ +bool STCU_GetLbistFailResult(void) +{ + uint32_t u32status; + + u32status = STCU_HWA_CheckLbistStatus(); + + u32status = (u32status >> STCU_LBIST_STATUS_FAIL_SHIFT) & (u32status & STCU_LBIST_STATUS_DONE_MASK); + + return (0UL == u32status?false:true); +} + +/** + * \brief Initial DTCM with hardware + */ +void STCU_StartRamInit(STCU_InitRamConfigType *pInitCfg) +{ + STCU_HWA_SetRamInitType( pInitCfg->u32InitRamType); + STCU_HWA_StartRamInit(pInitCfg->eInitMode,pInitCfg->bLockAfterEn); +} + +/** + * \brief Get status of RAM initialize action, for more detail, could call "STCU_GetRamInitDoneStatus" + * to get more info for each SRAM + * \return the status of ram initialize action, refer to "STCU_HardwareInitRamStatusType" + */ +uint32_t STCU_GetRamInitStatus(void) +{ + return STCU_HWA_GetRamInitStatus(); +} + +/** + * \brief Get each done status of SRAM initialize + * + * \return the done status of SRAM initialize action, refer to "STCU_InitRamDoneType" + */ +uint32_t STCU_GetRamInitDoneStatus(void) +{ + return STCU_HWA_GetRamInitDone(); +} + +/** + * \brief Get LBIST actual MISR value, the value should be read and use DFT tool to decode it, if LBIST test resault is fail. + * + * \return the LBIST actual MISR value + */ +uint32_t STCU_GetLbistAcutalMisr(void) +{ + return STCU_HWA_GetActualMisr(); +} + + +void STCU0_IRQHandler(void) +{ + uint32_t u32Flag; + + u32Flag = STCU_HWA_GetInterruptFlag(); + STCU_HWA_ClearInterruptFlag(); + if(NULL != sIRQCallback) + { + sIRQCallback(u32Flag); + } +} diff --git a/Src/fc7xxx_driver_systick.c b/Src/fc7xxx_driver_systick.c new file mode 100644 index 0000000..3136b49 --- /dev/null +++ b/Src/fc7xxx_driver_systick.c @@ -0,0 +1,60 @@ +#include "fc7xxx_driver_systick.h" + + + +/** + * \brief Config system tick + * + * \param u32ReloadVal reload value, val is decrease from reload value + * \return 0 is ok, and others are not ok + */ +uint8_t Core_SysTick_Config(uint32_t u32ReloadVal) +{ + uint8_t u8Retval; + + if (u32ReloadVal > SysTick_LOAD_RELOAD_Msk) + { + u8Retval = 1U; + } + else + { + SysTick->LOAD = u32ReloadVal; /* set reload register */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk; /* Processor clock */ + u8Retval = 0U; + } + + return u8Retval; +} + +void Core_SysTick_DeConfig(void) +{ + SysTick->CTRL = 0U; + SysTick->LOAD = 0U; + SysTick->VAL = 0U; +} + +void Core_SysTick_ClearValue(void) +{ + SysTick->VAL = 0U; +} + +void Core_SysTick_SetValue(uint32_t u32Value) +{ + SysTick->VAL = u32Value; +} + +uint32_t Core_SysTick_GetValue(void) +{ + return SysTick->VAL; +} + +void Core_SysTick_Enable(void) +{ + SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ +} + +void Core_SysTick_Disable(void) +{ + SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk); +} diff --git a/Src/fc7xxx_driver_tmu.c b/Src/fc7xxx_driver_tmu.c new file mode 100644 index 0000000..c1cc487 --- /dev/null +++ b/Src/fc7xxx_driver_tmu.c @@ -0,0 +1,312 @@ +/** + * @file fc7xxx_driver_tmu.c + * @author Flagchip + * @brief FC7xxx TMU driver source code + * @version 0.1.0 + * @date 2023-12-29 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/********************************************************************************* +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2023-12-29 qxw074 N/A First version for FC7240 +******************************************************************************** */ + +#include "fc7xxx_driver_tmu.h" +#include "fc7xxx_driver_pcc.h" +#include "interrupt_manager.h" + +/********* Local Variables ************/ +/** @brief TMU peripheral base pointers */ +static TMU_Type *const s_apTmuBase = TMU_BASE_PTRS; +/** @brief Temperature over 150 Celsius notify callback function point */ +static TMU_TempOver150InterruptCallbackType s_apTmuOver150Notify = NULL; +/** @brief Temperature over 125 Celsius notify callback function point */ +static TMU_TempOver125InterruptCallbackType s_apTmuOver125Notify = NULL; +/** @brief The Flag-based temperature sensor ready notify callback function point */ +static TMU_TempFlagReadyInterruptCallbackType s_apTmuFlagReadyNotify = NULL; +/** @brief The Voltage-based temperature sensor ready notify callback function point */ +static TMU_TempVoltageReadyInterruptCallbackType s_apTmuVoltgeReadyNotify = NULL; + +/***************TMU IRQ Functions*****************/ +/** @brief TMU interrupt entry */ +void TMU_IRQHandler(void); +/** + * @brief TMU irq handler + * + */ +void TMU_IRQHandler(void) +{ + TMU_Type *const pTmu = s_apTmuBase; + if (TMU_HWA_GetFlagTemperature150InterruptFlag(pTmu) == true) + { + if (TMU_HWA_Get150Flag(pTmu) == true) + { + if (s_apTmuOver150Notify != NULL) + { + s_apTmuOver150Notify(); + } + TMU_HWA_Clear150Flag(pTmu); + } + } + if (TMU_HWA_GetFlagTemperature125InterruptFlag(pTmu) == true) + { + if (TMU_HWA_Get125Flag(pTmu) == true) + { + if (s_apTmuOver125Notify != NULL) + { + s_apTmuOver125Notify(); + } + TMU_HWA_Clear125Flag(pTmu); + } + } + if (TMU_HWA_GetFlagTemperatureReadyInterruptFlag(pTmu) == true) + { + if (TMU_HWA_GetFlagTemperatureReady(pTmu) == true) + { + if (s_apTmuFlagReadyNotify != NULL) + { + s_apTmuFlagReadyNotify(); + } + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK); + TMU_HWA_SetFlagTemperatureReadyInterruptFlag(pTmu, false); + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK); + } + } + if (TMU_HWA_GetVoltageTemperatureReadyInterruptFlag(pTmu) == true) + { + if (TMU_HWA_GetVoltageTemperatureReady(pTmu) == true) + { + if (s_apTmuVoltgeReadyNotify != NULL) + { + s_apTmuVoltgeReadyNotify(); + } + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK); + TMU_HWA_SetVoltageTemperatureReadyInterruptFlag(pTmu, false); + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK); + } + } +} + +/** + * @brief Initialize the TMU instance + * + * @param pInitCfg the configurations of the TMU instance + */ +void TMU_Init(const TMU_InitType *const pInitCfg) +{ + DEV_ASSERT(pInitCfg != NULL); + + TMU_Type *const pTmu = s_apTmuBase; + uint32_t u32FlagCtrl; + uint32_t u32VoltageCtrl; + uint8_t u8FlagStartupCnt; + uint8_t u8VoltageStartupCnt; + + PCC_ClkSrcType eAdcClkName = PCC_CLK_TMU0; + uint32_t u32TmuClk; + u32TmuClk = PCC_GetPccFunctionClock(eAdcClkName); + + u8FlagStartupCnt = (uint8_t)((u32TmuClk * 11U) / 127000000U + 1U); + u8VoltageStartupCnt = (uint8_t)((u32TmuClk * 5U) / 127000000U + 1U); + if (u8FlagStartupCnt > 15U) + { + u8FlagStartupCnt = 15U; + } + if (u8VoltageStartupCnt > 7U) + { + u8VoltageStartupCnt = 7U; + } + + u32FlagCtrl = TMU_TF_CTRL_TF_150F_IE(pInitCfg->bTemperatureOver150IntEn) | + TMU_TF_CTRL_TF_125F_IE(pInitCfg->bTemperatureOver125IntEn) | + TMU_TF_CTRL_TF_RDYF_IE(pInitCfg->bFlagTempReadyIntEn) | + TMU_TF_CTRL_TF_HYSOFF(pInitCfg->eFlagTempHysteresisCon) | + TMU_TF_CTRL_TF_START_CNT(u8FlagStartupCnt) | + TMU_TF_CTRL_TF_FILT_BYP(pInitCfg->eFlagTempFilterBypassCon); + TMU_HWA_SetFlagTempCtrl(pTmu, u32FlagCtrl); + + u32VoltageCtrl = TMU_TV_CTRL_TV_RDYF_IE(pInitCfg->bVoltageTempReadyIntEn) | + TMU_TV_CTRL_TV_START_CNT(u8VoltageStartupCnt); + TMU_HWA_SetVoltageTempCtrl(pTmu, u32VoltageCtrl); + + TMU_HWA_SetStopAck(pInitCfg->bSmicsStopAckEn); + + /* interrupt callback function */ + s_apTmuOver150Notify = pInitCfg->pTemp150Notify; + s_apTmuOver125Notify = pInitCfg->pTemp125Notify; + s_apTmuFlagReadyNotify = pInitCfg->pFlagReadyNotify; + s_apTmuVoltgeReadyNotify = pInitCfg->pVoltagReadyNotify; + + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK); +} + +/** + * @brief Enable the Flag-based temperature sensor + * + * @return TMU_StatusType TMU_STATUS_SUCCESS when enable successfully, others fail + */ +TMU_StatusType TMU_FlagTempEnable(void) +{ + TMU_StatusType eRet; + uint32_t u32TimeOut = 15000000U; + TMU_Type *const pTmu = s_apTmuBase; + + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK); + TMU_HWA_SetFlagTemperatureEnableStatus(pTmu, true); + while ((TMU_HWA_GetFlagTemperatureReady(pTmu) != true) && (u32TimeOut != 0U)) + { + u32TimeOut--; + } + if (u32TimeOut != 0U) + { + eRet = TMU_STATUS_SUCCESS; + TMU_HWA_ClearFlagTemperatureReady(pTmu); + } + else + { + eRet = TMU_STATUS_TIMEOUT; + } + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK); + return eRet; +} + +/** + * @brief Disable the Flag-based temperature sensor + * + * @return TMU_StatusType TMU_STATUS_SUCCESS when disable successfully, others fail + */ +TMU_StatusType TMU_FlagTempDisable(void) +{ + TMU_StatusType eRet; + uint32_t u32TimeOut = 15000000U; + TMU_Type *const pTmu = s_apTmuBase; + + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK); + TMU_HWA_SetFlagTemperatureEnableStatus(pTmu, false); + TMU_HWA_ClearFlagTemperatureReady(pTmu); + while ((TMU_HWA_GetFlagTemperatureEnableStatus(pTmu) == true) && (u32TimeOut != 0U)) + { + u32TimeOut--; + } + if (u32TimeOut != 0U) + { + eRet = TMU_STATUS_SUCCESS; + } + else + { + eRet = TMU_STATUS_TIMEOUT; + } + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK); + return eRet; +} + +/** + * @brief Enable the Voltage-based temperature sensor + * + * @return TMU_StatusType TMU_STATUS_SUCCESS when enable successfully, others fail + */ +TMU_StatusType TMU_VoltageTempEnable(void) +{ + TMU_StatusType eRet; + uint32_t u32TimeOut = 15000000U; + TMU_Type *const pTmu = s_apTmuBase; + + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK); + TMU_HWA_SetVoltageTemperatureEnableStatus(pTmu, true); + while ((TMU_HWA_GetVoltageTemperatureReady(pTmu) != true) && (u32TimeOut != 0U)) + { + u32TimeOut--; + } + if (u32TimeOut != 0U) + { + eRet = TMU_STATUS_SUCCESS; + TMU_HWA_ClearVoltageTemperatureReady(pTmu); + } + else + { + eRet = TMU_STATUS_TIMEOUT; + } + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK); + return eRet; +} + +/** + * @brief Disable the Voltage-based temperature sensor + * + * @return TMU_StatusType TMU_STATUS_SUCCESS when disable successfully, others fail + */ +TMU_StatusType TMU_VoltageTempDisable(void) +{ + TMU_StatusType eRet; + uint32_t u32TimeOut = 15000000U; + TMU_Type *const pTmu = s_apTmuBase; + + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK); + TMU_HWA_SetVoltageTemperatureEnableStatus(pTmu, false); + TMU_HWA_ClearVoltageTemperatureReady(pTmu); + while ((TMU_HWA_GetVoltageTemperatureEnableStatus(pTmu) == true) && (u32TimeOut != 0U)) + { + u32TimeOut--; + } + if (u32TimeOut != 0U) + { + eRet = TMU_STATUS_SUCCESS; + } + else + { + eRet = TMU_STATUS_TIMEOUT; + } + TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK); + return eRet; +} + +/** + * @brief Check if cleaning flag is required + * + */ +void TMU_TempOverClear(void) +{ + TMU_Type *const pTmu = s_apTmuBase; + if (TMU_HWA_Get150Flag(pTmu)) + { + if (!TMU_HWA_Get150Status(pTmu)) + { + TMU_HWA_Clear150Flag(pTmu); + } + } + if (TMU_HWA_Get125Flag(pTmu)) + { + if (!TMU_HWA_Get125Status(pTmu)) + { + TMU_HWA_Clear125Flag(pTmu); + } + } +} + +/** + * @brief Get the temperature code from ADC + * + * @return uint32_t the value records the ADC conversion results for voltage-based temperature sensor result in 135 Celsius + */ +uint32_t TMU_GetTcode(void) +{ + TMU_Type *const pTmu = s_apTmuBase; + return TMU_HWA_GetTemperatureCode(pTmu); +} + +/** + * @brief Get the slope factor + * + * @return uint32_t the value records the slope factor for voltage-based temperature sensor + */ +uint32_t TMU_GetTslope(void) +{ + TMU_Type *const pTmu = s_apTmuBase; + return TMU_HWA_GetSlopeFactor(pTmu); +} diff --git a/Src/fc7xxx_driver_tpu.c b/Src/fc7xxx_driver_tpu.c new file mode 100644 index 0000000..c8d72c1 --- /dev/null +++ b/Src/fc7xxx_driver_tpu.c @@ -0,0 +1,596 @@ + +/** + * @file module_driver_tpu.c + * @author Flagchip099 + * @brief FC7xxx TPU driver source code + * @version 0.1.0 + * @date 2024-1-12 + * + * @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2024-1-12 Flagchip099 N/A First version for FC7240 + ******************************************************************************** */ + +#include "fc7xxx_driver_tpu.h" + +static uint32_t u32PwmLastFrame[TPU_E_CH_COUNT]; +static uint32_t u32PwmNextEdge[TPU_E_CH_COUNT]; +static bool bMeasActivePeriodComplete[TPU_E_CH_COUNT] = {(bool)false}; +static TPU_HSACallbackType s_TpuHSANotify[TPU_E_CH_COUNT] = {NULL}; +static TPU_EventCallbackType s_TpuEventNotify[TPU_E_CH_COUNT] = {NULL}; +static TPU_TCR1OverflowCallbackType s_TpuTCR1OverflowNotify = NULL; +static TPU_TCR2OverflowCallbackType s_TpuTCR2OverflowNotify = NULL; + + +void TPU0_CH0_7_IRQHandler(void); +void TPU0_CH8_15_IRQHandler(void); +void TPU0_CH16_23_IRQHandler(void); +void TPU0_CH24_31_IRQHandler(void); + +/** + * @brief TPU_Overflow_IRQHandler + * + */ +static inline void TPU_Overflow_IRQHandler(void) +{ + TPU_E_Type *const pTpuE = TPU_E_BASE_PTRS; + if (TPU_E_HWA_GetTCR1Overflow(pTpuE)) + { + TPU_E_HWA_ClearTCR1Overflow(pTpuE); + if (s_TpuTCR1OverflowNotify != NULL) + { + s_TpuTCR1OverflowNotify(); + } + } + if (TPU_E_HWA_GetTCR2Overflow(pTpuE)) + { + TPU_E_HWA_ClearTCR2Overflow(pTpuE); + if (s_TpuTCR2OverflowNotify != NULL) + { + s_TpuTCR2OverflowNotify(); + } + } +} + +/** + * @brief TPU_Event_IRQHandler + * + */ +static inline void TPU_Event_IRQHandler(uint8_t u8MinChannel, uint8_t u8MaxChannel) +{ + TPU_H_Type *const pTpuH = TPU_H_BASE_PTRS; + uint8_t u8Channel; + + for (u8Channel = (uint8_t)u8MinChannel; u8Channel < ((uint8_t)u8MaxChannel + 1u); u8Channel++) + { + if (TPU_H_HWA_GetChEventTrigISRStatus(pTpuH, u8Channel) == true) + { + if (s_TpuEventNotify[u8Channel] != NULL) + { + s_TpuEventNotify[u8Channel](); + } + } + if (TPU_H_HWA_GetChHSAReqStatus(pTpuH, u8Channel) == true) + { + TPU_H_HWA_ClearChHSA(pTpuH, u8Channel); + s_TpuHSANotify[u8Channel](); + } + } +} + +/** + * @brief TPU_InitOverflowInterrupt + * + */ +static void TPU_InitOverflowInterrupt(const TPU_InterruptCfgType *const pInterruptCfg) +{ + DEV_ASSERT(pInterruptCfg != NULL); + + TPU_E_Type *const pTPUE = TPU_E_BASE_PTRS; + + if (pInterruptCfg->bTCR1OverFlowEventIntEn) + { + s_TpuTCR1OverflowNotify = pInterruptCfg->pTCR1OverflowNotify; + TPU_E_HWA_EnableTCR1OVFIRQ(pTPUE, (bool)true); + } + else + { + TPU_E_HWA_EnableTCR1OVFIRQ(pTPUE, (bool)false); + s_TpuTCR1OverflowNotify = NULL; + } + + if (pInterruptCfg->bTCR2OverFlowEventIntEn) + { + s_TpuTCR2OverflowNotify = pInterruptCfg->pTCR2OverflowNotify; + TPU_E_HWA_EnableTCR2OVFIRQ(pTPUE, (bool)true); + } + else + { + TPU_E_HWA_EnableTCR2OVFIRQ(pTPUE, (bool)false); + s_TpuTCR2OverflowNotify = NULL; + } +} + +/** + * @brief TPU0_CH0_7_IRQHandler + * + */ +void TPU0_CH0_7_IRQHandler(void) +{ + TPU_Event_IRQHandler(TPU_CHANNEL_0, TPU_CHANNEL_7); +} + +/** + * @brief TPU0_CH8_15_IRQHandler + * + */ +void TPU0_CH8_15_IRQHandler(void) +{ + TPU_Event_IRQHandler(TPU_CHANNEL_8, TPU_CHANNEL_15); +} + +/** + * @brief TPU0_CH16_23_IRQHandler + * + */ +void TPU0_CH16_23_IRQHandler(void) +{ + TPU_Event_IRQHandler(TPU_CHANNEL_16, TPU_CHANNEL_23); +} + +/** + * @brief TPU0_CH24_31_IRQHandler + * + */ +void TPU0_CH24_31_IRQHandler(void) +{ + TPU_Overflow_IRQHandler(); + TPU_Event_IRQHandler(TPU_CHANNEL_24, TPU_CHANNEL_31); +} + +/** + * @brief TPU_InitChannelInterrupt + * + */ +void TPU_InitChannelInterrupt(uint8_t u8Channel, const TPU_InterruptCfgType *const pInterruptCfg) +{ + DEV_ASSERT(u8Channel < TPU_E_CH_COUNT); + DEV_ASSERT(pInterruptCfg != NULL); + + TPU_E_Type *const pTPUE = TPU_E_BASE_PTRS; + TPU_H_Type *const pTPUH = TPU_H_BASE_PTRS; + + if (pInterruptCfg->bEventIntEn) + { + s_TpuEventNotify[u8Channel] = pInterruptCfg->pEventNotify; + TPU_E_HWA_EnableChEventInt(pTPUE, u8Channel, (bool)true); + TPU_E_HWA_EnableSrvReq(pTPUE, u8Channel, (bool)true); + TPU_H_HWA_SetChTrig(pTPUH, u8Channel, pInterruptCfg->eChTrigType); + } + else + { + s_TpuEventNotify[u8Channel] = NULL; + } + TPU_InitOverflowInterrupt(pInterruptCfg); +} + +/** + * @brief TPU_Init + * + */ +void TPU_Init(void) +{ + TPU_E_Type *const pTPUE = TPU_E_BASE_PTRS; + + SCM_HWA_SUBSYS_PCC_SetEnable_TPUClock((bool)true); + TPU_E_HWA_SetTimeBaseCntStopInStopMode(pTPUE, (bool)true); +} + +/** + * @brief TPU_DeInit + * + */ +void TPU_DeInit(void) +{ + TPU_E_Type *const pTPUE = TPU_E_BASE_PTRS; + + TPU_E_HWA_TrigReset(pTPUE); +} + +/** + * @brief TPU_StartChannel + * + */ +void TPU_StartChannel(void) +{ + SCM_HWA_ConfigTpuGTBSelect((bool)true); +} + +/** + * @brief TPU_SetHSR + * + */ +void TPU_SetHSR(uint8_t u8channel, uint8_t u8HSRIdx) +{ + TPU_H_Type *const pTPUH = TPU_H_BASE_PTRS; + + TPU_H_HWA_SetChHSA(pTPUH, u8channel, true); + TPU_H_HWA_SetChHSRIdx(pTPUH, u8channel, u8HSRIdx); + TPU_H_HWA_SetChHSRISR(pTPUH, u8channel, (bool)true); + TPU_H_HWA_SetChSyncISR(pTPUH, u8channel, (bool)false); +} + +/** + * @brief TPU_SendHSR + * + */ +void TPU_SendHSR(uint8_t u8channel) +{ + TPU_H_Type *const pTPUH = TPU_H_BASE_PTRS; + + TPU_H_HWA_ClearChHSR(pTPUH, u8channel); +} + +/** + * @brief TPU_GetHSA + * + */ +uint8_t TPU_GetHSA(uint8_t u8Channel) +{ + TPU_H_Type *const pTPUH = TPU_H_BASE_PTRS; + + return TPU_H_HWA_GetChHSAIdx(pTPUH, (uint8_t)u8Channel); +} + +/** + * @brief TPU_InitChannelInterrupt + * + */ +void TPU_InitChannelHSAInterrupt(uint8_t u8Channel, const TPU_InterruptCfgType *const pInterruptCfg) +{ + s_TpuHSANotify[u8Channel] = pInterruptCfg->pHSANotify; +} + +/** + * @brief TPU_InitChannelOverflowInterrupt + * + */ +void TPU_InitChannelOverflowInterrupt(const TPU_InterruptCfgType *const pInterruptCfg) +{ + s_TpuTCR1OverflowNotify = pInterruptCfg->pTCR1OverflowNotify; + s_TpuTCR2OverflowNotify = pInterruptCfg->pTCR2OverflowNotify; +} + +/** + * @brief TPU_EnableSubSystem + * + */ +void TPU_EnableSubSystem(void) +{ + SCM_HWA_SUBSYS_PCC_SetEnable_SubSystemClock((bool)true); +} + +/** + * @brief TPU_EnableEventTrigDma + * + */ +void TPU_EnableEventTrigDma(uint8_t u8Channel) +{ + TPU_H_Type *const pTPUH = TPU_H_BASE_PTRS; + + TPU_H_HWA_SetChEventDMAEnable(pTPUH, (uint8_t)u8Channel, (bool)true); +} + +void TPU_EnableEventTrigTrgSel(uint8_t u8Channel, const TPU_InterruptCfgType *const pInterruptCfg) +{ + TPU_H_Type *const pTPUH = TPU_H_BASE_PTRS; + + TPU_H_HWA_SetChTrig(pTPUH, u8Channel, pInterruptCfg->eChTrigType); +} + +/** + * @brief TPU_EnableFlexcoreTrigDma + * + */ +void TPU_EnableFlexcoreTrigDma(uint8_t u8Channel) +{ + TPU_H_Type *const pTPUH = TPU_H_BASE_PTRS; + + TPU_H_HWA_SetChReqDMAEnable(pTPUH, (uint8_t)u8Channel, (bool)true); +} + +/** + * @brief TPU_PwmModeInit + * + */ +void TPU_PwmModeInit(uint8_t u8channel, const TPU_PwmCfgType *const p_etpu_config) +{ + TPU_E_Type *const pTPUE = TPU_E_BASE_PTRS; + uint32_t u32ER1_Val; + + TPU_E_HWA_ClearMatch1CFGFlg(pTPUE, u8channel); + TPU_E_HWA_ClearMatch1Event(pTPUE, u8channel); + TPU_E_HWA_ClearTransDetect1Event(pTPUE, u8channel); + TPU_E_HWA_ClearMatch2CFGFlg(pTPUE, u8channel); + TPU_E_HWA_ClearMatch2Event(pTPUE, u8channel); + TPU_E_HWA_ClearTransDetect2Event(pTPUE, u8channel); + TPU_E_HWA_SetOPAC1(pTPUE, u8channel, TPUE_NO_CHANGE_OUTPUT); + TPU_E_HWA_SetOPAC2(pTPUE, u8channel, TPUE_NO_CHANGE_OUTPUT); + TPU_E_HWA_SetTCR1ClkControl(pTPUE, TPUE_TCR1CLK_CLK_SRC_TPUCLKDIV2); + TPU_E_HWA_SetPDCM(pTPUE, u8channel, TPUE_EM_NB_ST); + TPU_E_HWA_SetTCR1MaxCnt(pTPUE, TPU_TCR1_MAXVALUE); + TPU_E_HWA_SetTCR2MaxCnt(pTPUE, TPU_TCR1_MAXVALUE); + + if (p_etpu_config->bPwmUseTCR1) + { + TPU_E_HWA_SetMatchER1(pTPUE, u8channel, (TPU_E_HWA_GetTCR1CntVal(pTPUE) + 1U)); + u32ER1_Val = TPU_E_HWA_GetER1Val(pTPUE, u8channel); + TPU_E_HWA_SetER2(pTPUE, u8channel, (p_etpu_config->u32ActiveTime + u32ER1_Val)); + } + + u32PwmNextEdge[u8channel] = TPU_E_HWA_GetER2Val(pTPUE, u8channel); + + TPU_E_HWA_SetChOutputActiveHigh(pTPUE, u8channel, p_etpu_config->bActiveHigh); + if (p_etpu_config->bActiveHigh) + { + TPU_E_HWA_SetOPAC1(pTPUE, u8channel, TPUE_MATCH_SET_OUTPUT_HIGH); + TPU_E_HWA_SetOPAC2(pTPUE, u8channel, TPUE_MATCH_SET_OUTPUT_LOW); + TPU_E_HWA_SetChTBS1(pTPUE, u8channel, p_etpu_config->eTBS1); + TPU_E_HWA_SetChTBS2(pTPUE, u8channel, p_etpu_config->eTBS2); + TPU_E_HWA_SetChEntryTblflag1(pTPUE, u8channel, (bool)true); + } + else + { + TPU_E_HWA_SetOPAC1(pTPUE, u8channel, TPUE_MATCH_SET_OUTPUT_LOW); + TPU_E_HWA_SetOPAC2(pTPUE, u8channel, TPUE_MATCH_SET_OUTPUT_HIGH); + TPU_E_HWA_SetChTBS1(pTPUE, u8channel, p_etpu_config->eTBS1); + TPU_E_HWA_SetChTBS2(pTPUE, u8channel, p_etpu_config->eTBS2); + TPU_E_HWA_SetChEntryTblflag1(pTPUE, u8channel, (bool)false); + } + /* Set channel priority */ + + /* Here do not enable NVIC */ + + TPU_E_HWA_SetOutputSelOPAC1(pTPUE, u8channel, (bool)true); + TPU_E_HWA_SetOutputSelOPAC2(pTPUE, u8channel, (bool)true); + TPU_E_HWA_EnableChOutputBuf(pTPUE, u8channel, (bool)true); + TPU_E_HWA_EnableMatch(pTPUE, u8channel, (bool)true); + TPU_E_HWA_EnableSrvReq(pTPUE, u8channel, (bool)true); + + return; +} + +/** + * @brief TPU_PwmServiceReq + * + */ +void TPU_PwmServiceReq(uint8_t u8channel, uint32_t u32ActiveTime, uint32_t u32Period) +{ + TPU_E_Type *const pTPUE = TPU_E_BASE_PTRS; + + if (TPU_E_HWA_GetChMatchRecLatch1Status(pTPUE, u8channel) == (bool)true) + { + /* in match1 */ + TPU_E_HWA_ClearMatch1Event(pTPUE, u8channel); + TPU_E_HWA_SetChEntryTblflag0(pTPUE, u8channel, (bool)false); + u32PwmLastFrame[u8channel] = TPU_E_HWA_GetER1Val(pTPUE, u8channel); + /* Next ER1 */ + if ((u32PwmLastFrame[u8channel] + u32Period) > TPU_TCR1_MAXVALUE) + { + TPU_E_HWA_SetMatchER1(pTPUE, u8channel, (u32PwmLastFrame[u8channel] + u32Period - TPU_TCR1_MAXVALUE - 1U)); + } + else + { + TPU_E_HWA_SetMatchER1(pTPUE, u8channel, (u32PwmLastFrame[u8channel] + u32Period)); + } + + if ((TPU_E_HWA_GetER1Val(pTPUE, u8channel) + u32ActiveTime) > TPU_TCR1_MAXVALUE) + { + u32PwmNextEdge[u8channel] = TPU_E_HWA_GetER1Val(pTPUE, u8channel) + u32ActiveTime - TPU_TCR1_MAXVALUE - 1U; + } + else + { + u32PwmNextEdge[u8channel] = TPU_E_HWA_GetER1Val(pTPUE, u8channel) + u32ActiveTime; + } + TPU_E_HWA_EnableMatch(pTPUE, u8channel, (bool)true); + } + else if (TPU_E_HWA_GetChMatchRecLatch2Status(pTPUE, u8channel) == (bool)true) + { + /* in match2 */ + TPU_E_HWA_ClearMatch2Event(pTPUE, u8channel); + TPU_E_HWA_SetChEntryTblflag0(pTPUE, u8channel, (bool)true); + /* Next ER2 */ + TPU_E_HWA_SetER2(pTPUE, u8channel, u32PwmNextEdge[u8channel]); + TPU_E_HWA_EnableMatch(pTPUE, u8channel, (bool)true); + } + TPU_E_HWA_ClearChEventISRFlg(pTPUE, (uint8_t)u8channel); +} + +/** + * @brief TPU_CaptureModeInit + * + */ +void TPU_CaptureModeInit(uint8_t u8channel, const TPU_CaptureCfgType *const p_etpu_config) +{ + TPU_E_Type *const pTPUE = TPU_E_BASE_PTRS; + + TPU_E_HWA_ClearMatchEn1(pTPUE, u8channel); + TPU_E_HWA_ClearMatch1CFGFlg(pTPUE, u8channel); + TPU_E_HWA_ClearMatch1Event(pTPUE, u8channel); + TPU_E_HWA_ClearTransDetect1Event(pTPUE, u8channel); + TPU_E_HWA_ClearMatch2CFGFlg(pTPUE, u8channel); + TPU_E_HWA_ClearMatch2Event(pTPUE, u8channel); + TPU_E_HWA_ClearTransDetect2Event(pTPUE, u8channel); + TPU_E_HWA_SetTCR1ClkControl(pTPUE, TPUE_TCR1CLK_CLK_SRC_TPUCLKDIV2); + TPU_E_HWA_SetChTBS1(pTPUE, u8channel, TPUE_GREATER_OR_EQUAL_CAPBASE_TCR1_MATCHBASE_TCR1); + TPU_E_HWA_SetChTBS2(pTPUE, u8channel, TPUE_GREATER_OR_EQUAL_CAPBASE_TCR1_MATCHBASE_TCR1); + TPU_E_HWA_SetOPAC1(pTPUE, u8channel, TPUE_NO_CHANGE_OUTPUT); + TPU_E_HWA_SetOPAC2(pTPUE, u8channel, TPUE_NO_CHANGE_OUTPUT); + TPU_E_HWA_SetChEntryTblflag1(pTPUE, u8channel, (bool)false); + TPU_E_HWA_SetChEntryTblflag0(pTPUE, u8channel, (bool)false); + TPU_E_HWA_SetTCR1MaxCnt(pTPUE, TPU_TCR1_MAXVALUE); + TPU_E_HWA_SetTCR2MaxCnt(pTPUE, TPU_TCR1_MAXVALUE); + + if (p_etpu_config->eMeasureMode == TPU_DutyMeasurementActiveHigh) + { + TPU_E_HWA_SetPDCM(pTPUE, u8channel, TPUE_SM_DT); + TPU_E_HWA_SetIPAC1(pTPUE, u8channel, TPUE_DETECT_RISING_EDGE_ONLY); + TPU_E_HWA_SetIPAC2(pTPUE, u8channel, TPUE_DETECT_FALLING_EDGE_ONLY); + } + else if (p_etpu_config->eMeasureMode == TPU_DutyMeasurementActiveLow) + { + TPU_E_HWA_SetPDCM(pTPUE, u8channel, TPUE_SM_DT); + TPU_E_HWA_SetIPAC1(pTPUE, u8channel, TPUE_DETECT_FALLING_EDGE_ONLY); + TPU_E_HWA_SetIPAC2(pTPUE, u8channel, TPUE_DETECT_RISING_EDGE_ONLY); + } + else if (p_etpu_config->eMeasureMode == TPU_PeriodMeasurement) + { + TPU_E_HWA_SetPDCM(pTPUE, u8channel, TPUE_SM_ST); + TPU_E_HWA_SetIPAC1(pTPUE, u8channel, p_etpu_config->eInputType); + TPU_E_HWA_SetIPAC2(pTPUE, u8channel, TPUE_NO_TRANSITIONS); + } + else + { + /* do nothing */ + } + + TPU_E_HWA_SetMatchER1(pTPUE, u8channel, (TPU_E_HWA_GetTCR1CntVal(pTPUE) + p_etpu_config->u32SampleTime)); + TPU_E_HWA_EnableTransContinue(pTPUE, u8channel, (bool)true); + + /* Here not set channel priority */ + + /* Here not enable NVIC */ + + TPU_E_HWA_EnableChEventInt(pTPUE, u8channel, (bool)true); + TPU_E_HWA_EnableMatch(pTPUE, u8channel, (bool)true); + TPU_E_HWA_EnableSrvReq(pTPUE, u8channel, (bool)true); + + return; +} + +/** + * @brief TPU_CaptureMeasPeriodServiceReq + * + */ +void TPU_CaptureMeasPeriodServiceReq(uint8_t u8channel, TPU_CaptureCfgType *p_etpu_config) +{ + TPU_E_Type *const pTPUE = TPU_E_BASE_PTRS; + volatile bool bMeasurement = TPU_E_HWA_GetChEntryTblflag1(pTPUE, u8channel); + + if (TPU_E_HWA_GetChMatchRecLatch1Status(pTPUE, u8channel) == (bool)true) + { + TPU_E_HWA_ClearMatch1Event(pTPUE, u8channel); + TPU_E_HWA_ClearTransDetect1Event(pTPUE, u8channel); + TPU_E_HWA_ClearTransDetect2Event(pTPUE, u8channel); + p_etpu_config->LastTime = TPU_E_HWA_GetER1Val(pTPUE, u8channel); + TPU_E_HWA_SetMatchER1(pTPUE, u8channel, (p_etpu_config->LastTime + p_etpu_config->u32SampleTime)); + TPU_E_HWA_EnableMatch(pTPUE, u8channel, (bool)true); + TPU_E_HWA_ClearChEventISRFlg(pTPUE, (uint8_t)u8channel); + TPU_E_HWA_SetChEntryTblflag1(pTPUE, u8channel, (bool)false); + p_etpu_config->u32PeriodTime = 0; + } + else if (TPU_E_HWA_GetChTransDetectLatch1Status(pTPUE, u8channel) == (bool)true) + { + TPU_E_HWA_ClearTransDetect1Event(pTPUE, u8channel); + TPU_E_HWA_ClearChEventISRFlg(pTPUE, (uint8_t)u8channel); + /* transition happened */ + if (bMeasurement) + { + /* Complete once normal measurement */ + if (TPU_E_HWA_GetCaptureER1Val(pTPUE, u8channel) >= p_etpu_config->LastTime) + { + p_etpu_config->u32PeriodTime = (TPU_E_HWA_GetCaptureER1Val(pTPUE, u8channel) - p_etpu_config->LastTime); + } + else + { + p_etpu_config->u32PeriodTime = (TPU_E_HWA_GetCaptureER1Val(pTPUE, u8channel) + TPU_TCR1_MAXVALUE - p_etpu_config->LastTime + 1U); + } + + TPU_E_HWA_SetChEntryTblflag1(pTPUE, u8channel, (bool)false); + } + /* Start normal measurement */ + p_etpu_config->LastTime = TPU_E_HWA_GetCaptureER1Val(pTPUE, u8channel); + TPU_E_HWA_SetMatchER1(pTPUE, u8channel, (p_etpu_config->LastTime + p_etpu_config->u32SampleTime)); + + /* bMeasurement = active */ + TPU_E_HWA_EnableMatch(pTPUE, u8channel, (bool)true); + TPU_E_HWA_SetChEntryTblflag1(pTPUE, u8channel, (bool)true); + } +} + +/** + * @brief TPU_CaptureMeasActiveLowServiceReq + * + */ +void TPU_CaptureMeasActivePeriodServiceReq(uint8_t u8channel, TPU_CaptureCfgType *p_etpu_config) +{ + TPU_E_Type *const pTPUE = TPU_E_BASE_PTRS; + + if (TPU_E_HWA_GetChMatchRecLatch1Status(pTPUE, u8channel) == (bool)true) + { + TPU_E_HWA_ClearMatch1Event(pTPUE, u8channel); + TPU_E_HWA_ClearTransDetect1Event(pTPUE, u8channel); + TPU_E_HWA_ClearTransDetect2Event(pTPUE, u8channel); + p_etpu_config->LastTime = TPU_E_HWA_GetER1Val(pTPUE, u8channel); + TPU_E_HWA_SetMatchER1(pTPUE, u8channel, (p_etpu_config->LastTime + p_etpu_config->u32SampleTime)); + TPU_E_HWA_EnableMatch(pTPUE, u8channel, (bool)true); + TPU_E_HWA_ClearChEventISRFlg(pTPUE, (uint8_t)u8channel); + p_etpu_config->u32PeriodTime = 0; + p_etpu_config->u32ActiveTime = 0; + bMeasActivePeriodComplete[u8channel] = (bool)false; + } + else if ((TPU_E_HWA_GetChTransDetectLatch1Status(pTPUE, u8channel) == (bool)true) || (TPU_E_HWA_GetChTransDetectLatch2Status(pTPUE, u8channel) == (bool)true)) + { + /* transition1 or 2 happened */ + TPU_E_HWA_ClearTransDetect1Event(pTPUE, u8channel); + TPU_E_HWA_ClearTransDetect2Event(pTPUE, u8channel); + TPU_E_HWA_ClearChEventISRFlg(pTPUE, (uint8_t)u8channel); + + /* ER1 stores TCR1 in IPAC1 edge */ + /* Here calculate period */ + if (bMeasActivePeriodComplete[u8channel]) + { + /* Complete once normal measurement */ + if (TPU_E_HWA_GetCaptureER1Val(pTPUE, u8channel) >= p_etpu_config->StartTime) + { + p_etpu_config->u32PeriodTime = (TPU_E_HWA_GetCaptureER1Val(pTPUE, u8channel) - p_etpu_config->StartTime); + } + else + { + p_etpu_config->u32PeriodTime = (TPU_E_HWA_GetCaptureER1Val(pTPUE, u8channel) + TPU_TCR1_MAXVALUE - p_etpu_config->StartTime + 1); + } + + /* MeasurementComplete = inactive */ + bMeasActivePeriodComplete[u8channel] = (bool)false; + } + + /* Start normal low measurement */ + p_etpu_config->LastTime = TPU_E_HWA_GetCaptureER1Val(pTPUE, u8channel); + p_etpu_config->StartTime = p_etpu_config->LastTime; + + /* ER2 stores TCR1 in IPAC2 edge */ + /* Complete once normal measurement */ + if (TPU_E_HWA_GetCaptureER2Val(pTPUE, u8channel) >= p_etpu_config->LastTime) + { + p_etpu_config->u32ActiveTime = (TPU_E_HWA_GetCaptureER2Val(pTPUE, u8channel) - p_etpu_config->LastTime); + } + else + { + p_etpu_config->u32ActiveTime = (TPU_E_HWA_GetCaptureER2Val(pTPUE, u8channel) + TPU_TCR1_MAXVALUE - p_etpu_config->LastTime + 1); + } + + /* MeasurementComplete = active */ + bMeasActivePeriodComplete[u8channel] = (bool)true; + + /* Waiting for first IPAC1 edge */ + p_etpu_config->LastTime = TPU_E_HWA_GetCaptureER2Val(pTPUE, u8channel); + TPU_E_HWA_SetMatchER1(pTPUE, u8channel, (p_etpu_config->LastTime + p_etpu_config->u32SampleTime)); + TPU_E_HWA_EnableMatch(pTPUE, u8channel, (bool)true); + } +} diff --git a/Src/fc7xxx_driver_trgsel.c b/Src/fc7xxx_driver_trgsel.c new file mode 100644 index 0000000..2043fe6 --- /dev/null +++ b/Src/fc7xxx_driver_trgsel.c @@ -0,0 +1,314 @@ +/** + * @file fc7xxx_driver_trgsel.c + * @author Flagchip0103 + * @brief FC7xxx TRGSEL driver source code + * @version 0.1.0 + * @date 2023-12-19 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + */ +/* ******************************************************************************** + * Revision History: + * + * Version Date Initials CR# Descriptions + * --------- ---------- ------------ ---------- --------------- + * 0.1.0 2023-12-19 Flagchip0103 N/A First version for FC7240 + ******************************************************************************** */ + +#include + +#include "fc7xxx_driver_trgsel.h" +#include "HwA_trgsel.h" +#include "HwA_scm.h" + +/** + * @brief Number of target outputs of TrgSel 0 + * + */ +#define TRGSEL0_NUM_OUTPUTS 38U + +/** + * @brief Number of target outputs of TrgSel 1 + * + */ +#define TRGSEL1_NUM_OUTPUTS 28U + +/** + * @brief Number of target outputs of TrgSel 2 + * + */ +#define TRGSEL2_NUM_OUTPUTS 30U + +/** + * @brief Number of target outputs of TrgSel 3 + * + */ +#define TRGSEL3_NUM_OUTPUTS 16U + +/** + * @brief Number of target outputs of TrgSel 4 + * + */ +#define TRGSEL4_NUM_OUTPUTS 10U + +/** + * @brief Number of target outputs of TrgSel 5 + * + */ +#define TRGSEL5_NUM_OUTPUTS 13U + +/** + * @brief Number of input sources of TrgSel 0 + * + */ +#define TRGSEL0_NUM_SOURCES 128U + +/** + * @brief Number of input sources of TrgSel 1 + * + */ +#define TRGSEL1_NUM_SOURCES 94U + +/** + * @brief Number of input sources of TrgSel 2 + * + */ +#define TRGSEL2_NUM_SOURCES 32U + +/** + * @brief Number of input sources of TrgSel 3 + * + */ +#define TRGSEL3_NUM_SOURCES 62U + +/** + * @brief Number of input sources of TrgSel 4 + * + */ +#define TRGSEL4_NUM_SOURCES 112U + +/** + * @brief Number of input sources of TrgSel 5 + * + */ +#define TRGSEL5_NUM_SOURCES 64U + +#define TRGSEL_NUM_SW_TRG_CHANNELS 8U + +static TRGSEL_Type *const s_trgselBase[TRGSEL_INSTANCE_COUNT] = TRGSEL_BASE_PTRS; + +#ifndef NDEBUG +/** + * @brief Check whether the TRGSEL target is valid for the TRGSEL instance + * + * @param eInstance the selected TRGSEL instance + * @param eTarget the target value to check + * @return true the TRGSEL target is valid + * @return false the TRGSEL target is invalid + */ +static inline bool TRGSEL_IsValidTarget(const TRGSEL_InstanceType eInstance, const TRGSEL_TargetType eTarget); + +/** + * @brief Check whether the TRGSEL source is valid for the TRGSEL instance + * + * @param eInstance the selected TRGSEL instance + * @param eSource the source value to check + * @return true the TRGSEL source is valid + * @return false the TRGSEL source is invalid + */ +static inline bool TRGSEL_IsValidSource(const TRGSEL_InstanceType eInstance, const TRGSEL_SourceType eSource); + +static inline bool TRGSEL_IsValidTarget(const TRGSEL_InstanceType eInstance, const TRGSEL_TargetType eTarget) +{ + bool bRet = false; + switch (eInstance) + { + case TRGSEL_INSTANCE_0: + { + bRet = (bool)((eTarget < TRGSEL0_NUM_OUTPUTS) ? true : false); + break; + } + + case TRGSEL_INSTANCE_1: + { + bRet = (bool)((eTarget < TRGSEL1_NUM_OUTPUTS) ? true : false); + break; + } + + case TRGSEL_INSTANCE_2: + { + bRet = (bool)((eTarget < TRGSEL2_NUM_OUTPUTS) ? true : false); + break; + } + + case TRGSEL_INSTANCE_3: + { + bRet = (bool)((eTarget < TRGSEL3_NUM_OUTPUTS) ? true : false); + break; + } + + case TRGSEL_INSTANCE_4: + { + bRet = (bool)((eTarget < TRGSEL4_NUM_OUTPUTS) ? true : false); + break; + } + + case TRGSEL_INSTANCE_5: + { + bRet = (bool)((eTarget < TRGSEL5_NUM_OUTPUTS) ? true : false); + break; + } + + default: + break; + } + return bRet; +} + +static inline bool TRGSEL_IsValidSource(const TRGSEL_InstanceType eInstance, const TRGSEL_SourceType eSource) +{ + bool bRet = false; + switch (eInstance) + { + case TRGSEL_INSTANCE_0: + { + bRet = (bool)((eSource < TRGSEL0_NUM_SOURCES) ? true : false); + break; + } + + case TRGSEL_INSTANCE_1: + { + bRet = (bool)((eSource < TRGSEL1_NUM_SOURCES) ? true : false); + break; + } + + case TRGSEL_INSTANCE_2: + { + bRet = (bool)((eSource < TRGSEL2_NUM_SOURCES) ? true : false); + break; + } + + case TRGSEL_INSTANCE_3: + { + bRet = (bool)((eSource < TRGSEL3_NUM_SOURCES) ? true : false); + break; + } + + case TRGSEL_INSTANCE_4: + { + bRet = (bool)((eSource < TRGSEL4_NUM_SOURCES) ? true : false); + break; + } + + case TRGSEL_INSTANCE_5: + { + bRet = (bool)((eSource < TRGSEL5_NUM_SOURCES) ? true : false); + break; + } + + default: + break; + } + return bRet; +} +#endif + +TRGSEL_SourceType TRGSEL_GetTargetTriggerSource(const TRGSEL_InstanceType eInstance, const TRGSEL_TargetType eTarget) +{ + DEV_ASSERT(eInstance < TRGSEL_INSTANCE_COUNT); + DEV_ASSERT(TRGSEL_IsValidTarget(eInstance, eTarget)); + + const TRGSEL_Type *const pTrgsel = s_trgselBase[eInstance]; + + uint32_t u32Tmp = TRGSEL_HWA_GetTargetTriggerSource(pTrgsel, eTarget); + + return (TRGSEL_SourceType)u32Tmp; +} + +void TRGSEL_SetTargetTriggerSource(const TRGSEL_InstanceType eInstance, const TRGSEL_TargetType eTarget, + const TRGSEL_SourceType eSource) +{ + DEV_ASSERT(eInstance < TRGSEL_INSTANCE_COUNT); + DEV_ASSERT(TRGSEL_IsValidTarget(eInstance, eTarget)); + DEV_ASSERT(TRGSEL_IsValidSource(eInstance, eSource)); + DEV_ASSERT(TRGSEL_GetTargetLockStatus(eInstance, eTarget) != true); + + TRGSEL_Type *const pTrgsel = s_trgselBase[eInstance]; + + TRGSEL_HWA_SetTargetTriggerSource(pTrgsel, eTarget, eSource); +} + +bool TRGSEL_GetTargetLockStatus(const TRGSEL_InstanceType eInstance, const TRGSEL_TargetType eTarget) +{ + DEV_ASSERT(eInstance < TRGSEL_INSTANCE_COUNT); + DEV_ASSERT(TRGSEL_IsValidTarget(eInstance, eTarget)); + + const TRGSEL_Type *const pTrgsel = s_trgselBase[eInstance]; + + return TRGSEL_HWA_GetTargetLockStatus(pTrgsel, eTarget); +} + +void TRGSEL_LockTargetTriggerSource(const TRGSEL_InstanceType eInstance, const TRGSEL_TargetType eTarget) +{ + DEV_ASSERT(eInstance < TRGSEL_INSTANCE_COUNT); + DEV_ASSERT(TRGSEL_IsValidTarget(eInstance, eTarget)); + + TRGSEL_Type *const pTrgsel = s_trgselBase[eInstance]; + + if (TRGSEL_GetTargetLockStatus(eInstance, eTarget) != true) + { + TRGSEL_HWA_LockTargetTriggerSource(pTrgsel, eTarget); + } +} + +void TRGSEL_GenerateSwTrigger(const TRGSEL_SwTriggerChannelType eChannel) +{ + DEV_ASSERT(eChannel < TRGSEL_NUM_SW_TRG_CHANNELS); + + switch (eChannel) + { + case TRGSEL_SW_TRIGGER_CHANNEL_0: + { + SCM_HWA_SetSwTrigx_Trgsel04(SCM_SW_TRIG_0); + break; + } + case TRGSEL_SW_TRIGGER_CHANNEL_1: + { + SCM_HWA_SetSwTrigx_Trgsel04(SCM_SW_TRIG_1); + break; + } + case TRGSEL_SW_TRIGGER_CHANNEL_2: + { + SCM_HWA_SetSwTrigx_Trgsel04(SCM_SW_TRIG_2); + break; + } + case TRGSEL_SW_TRIGGER_CHANNEL_3: + { + SCM_HWA_SetSwTrigx_Trgsel04(SCM_SW_TRIG_3); + break; + } + case TRGSEL_SW_TRIGGER_CHANNEL_4: + { + SCM_HWA_SetSwTrigx_Trgsel15(SCM_SW_TRIG_4); + break; + } + case TRGSEL_SW_TRIGGER_CHANNEL_5: + { + SCM_HWA_SetSwTrigx_Trgsel15(SCM_SW_TRIG_5); + break; + } + case TRGSEL_SW_TRIGGER_CHANNEL_6: + { + SCM_HWA_SetSwTrigx_Trgsel15(SCM_SW_TRIG_6); + break; + } + case TRGSEL_SW_TRIGGER_CHANNEL_7: + { + SCM_HWA_SetSwTrigx_Trgsel15(SCM_SW_TRIG_7); + break; + } + default: + break; + } +} diff --git a/Src/fc7xxx_driver_tstmp.c b/Src/fc7xxx_driver_tstmp.c new file mode 100644 index 0000000..0856be5 --- /dev/null +++ b/Src/fc7xxx_driver_tstmp.c @@ -0,0 +1,420 @@ +/** + * @file fc7xxx_driver_tstmp.c + * @author Flagchip + * @brief FC7xxx TSTMP driver source code + * @version 0.1.0 + * @date 2024-01-14 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-14 Flagchip0122 N/A FC7xxx internal release version +********************************************************************************/ + +#include "fc7xxx_driver_tstmp.h" +#include "interrupt_manager.h" + +/** @brief Tstmp instance list */ +static TSTMP_Type *s_pTstmpPtrs[TSTMP_INSTANCE_COUNT] = TSTMP_BASE_PTRS; +/** @brief Tstmp user defined interrupt function */ +static TSTMP_InterruptCallBackType s_pTstmpModulateNotifyPtr[TSTMP_INSTANCE_COUNT][MAX_MOD_NUMBER] = {NULL}; + +/** @brief TSTMP0 interrupt entry */ +void TSTMP0_IRQHandler(void); +/** @brief TSTMP1 interrupt entry */ +void TSTMP1_IRQHandler(void); + +/** @brief TSTMP common interrupt function */ +static void Tstmp_CommonProcessInterrupt(const TSTMP_InstanceType eInstance, const TSTMP_ModulateType eIntModulate); + +/** + * @brief Initialize TSTMP instance + * + * @param eInstance TSTMP instance + * @param pInitStruct TSTMP initialization structure + * @return TSTMP_StatusType TSTMP return type + * @note TSTMP0 clock source is 1MHZ and TSTMP1,TSTMP2,TSTMP3 clock source is bus clock + */ +TSTMP_StatusType TSTMP_Init(const TSTMP_InstanceType eInstance, const TSTMP_InitType *const pInitStruct) +{ + TSTMP_Type *pTstmp; + TSTMP_StatusType eRet = TSTMP_STATUS_SUCCESS; + if ((NULL == pInitStruct) || (eInstance >= TSTMP_INSTANCE_MAX)) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + else + { + pTstmp = s_pTstmpPtrs[eInstance]; + /* clear MOD(n) match flag */ + TSTMP_HWA_ClearMod0MatchFlag(pTstmp); + TSTMP_HWA_ClearAllMod123MatchFlag(pTstmp); + + for(uint8_t i = 0; i < MAX_MOD_NUMBER; i++) + { + TSTMP_HWA_SelectClkSource(pTstmp, (TSTMP_ModulateType)i, pInitStruct->pClk[i]); + } + /* set MOD0 match value */ + TSTMP_HWA_SetModMatchValue(pTstmp, TSTMP_MOD0, pInitStruct->u32Modulate0Value); + /* set MOD1 match value */ + TSTMP_HWA_SetModMatchValue(pTstmp, TSTMP_MOD1, pInitStruct->u32Modulate1Value); + /* set MOD2 match value */ + TSTMP_HWA_SetModMatchValue(pTstmp, TSTMP_MOD2, pInitStruct->u32Modulate2Value); + /* set MOD3 match value */ + TSTMP_HWA_SetModMatchValue(pTstmp, TSTMP_MOD3, pInitStruct->u32Modulate3Value); + } + + return eRet; +} + +/** + * @brief Set the Counting mode of modulate timer counter0,1,2,3 + * + * @param eInstance TSTMP instance + * @param eCounter0Mode Counting mode of counter0 + * @param eCounter1Mode Counting mode of counter1 + * @param eCounter2Mode Counting mode of counter2 + * @param eCounter3Mode Counting mode of counter3 + * @return TSTMP_StatusType TSTMP return type + */ +TSTMP_StatusType TSTMP_SetCounterRunningMode(const TSTMP_InstanceType eInstance, const TSTMP_ModeCounterRunningMode eCounter0Mode, + const TSTMP_ModeCounterRunningMode eCounter1Mode,const TSTMP_ModeCounterRunningMode eCounter2Mode, + const TSTMP_ModeCounterRunningMode eCounter3Mode) +{ + TSTMP_Type *pTstmp; + TSTMP_StatusType eRet = TSTMP_STATUS_SUCCESS; + if (eInstance >= TSTMP_INSTANCE_MAX) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + if( (eCounter0Mode > TSTMP_MODE_PERIOD_RUNNING) || (eCounter1Mode > TSTMP_MODE_PERIOD_RUNNING) || + (eCounter2Mode > TSTMP_MODE_PERIOD_RUNNING) || (eCounter3Mode > TSTMP_MODE_PERIOD_RUNNING)) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + if(eRet == TSTMP_STATUS_SUCCESS) + { + pTstmp = s_pTstmpPtrs[eInstance]; + TSTMP_HWA_SetModCounterMode(pTstmp,TSTMP_MOD0, eCounter0Mode); + TSTMP_HWA_SetModCounterMode(pTstmp,TSTMP_MOD1, eCounter1Mode); + TSTMP_HWA_SetModCounterMode(pTstmp,TSTMP_MOD2, eCounter2Mode); + TSTMP_HWA_SetModCounterMode(pTstmp,TSTMP_MOD3, eCounter3Mode); + } + return eRet; +} +/** + * @brief De-initialize TSTMP instance + * + * @param eInstance TSTMP instance + * @return TSTMP_StatusType TSTMP return type + */ +TSTMP_StatusType TSTMP_Deinit(const TSTMP_InstanceType eInstance) +{ + TSTMP_Type *pTstmp; + TSTMP_StatusType eRet = TSTMP_STATUS_SUCCESS; + uint8_t u8Index; + if (eInstance >= TSTMP_INSTANCE_MAX) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + else + { + pTstmp = s_pTstmpPtrs[eInstance]; + for (u8Index = 0U; u8Index < MAX_MOD_NUMBER; u8Index++) + { + /* Disable TSTMP MOD(n) match interrupt */ + TSTMP_HWA_DisableModMatchInterrupt(pTstmp, (TSTMP_ModulateType)u8Index); + /* Disable TSTMP MOD(n) counter */ + TSTMP_HWA_DisableModCounter(pTstmp, (TSTMP_ModulateType)u8Index); + /* Clear TSTMP MOD(n) match value set*/ + TSTMP_HWA_SetModMatchValue(pTstmp, (TSTMP_ModulateType)u8Index, (uint32_t)0U); + s_pTstmpModulateNotifyPtr[eInstance][u8Index] = NULL; + } + /* clear MOD(n) match flag */ + TSTMP_HWA_ClearMod0MatchFlag(pTstmp); + TSTMP_HWA_ClearAllMod123MatchFlag(pTstmp); + } + return eRet; +} + +/** + * @brief Initialize TSTMP interrupt functionality + * + * @param eInstance TSTMP instance + * @param pIntStruct TSTMP interrupt structure + * @return TSTMP_StatusType TSTMP return type + */ +TSTMP_StatusType TSTMP_InitInterrupt(const TSTMP_InstanceType eInstance, const TSTMP_IntType *const pIntStruct) +{ + TSTMP_StatusType eRet = TSTMP_STATUS_SUCCESS; + TSTMP_Type *pTstmp; + uint8_t u8Index; + if ((NULL == pIntStruct) || (eInstance >= TSTMP_INSTANCE_MAX)) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + else + { + pTstmp = s_pTstmpPtrs[eInstance]; + for (u8Index = 0U; u8Index < MAX_MOD_NUMBER; u8Index++) + { + if (pIntStruct->bModulateIntEn[u8Index] == true) + { + /* Enable TSTMP MOD(n) match interrupt */ + TSTMP_HWA_EnableModMatchInterrupt(pTstmp, (TSTMP_ModulateType)u8Index); + s_pTstmpModulateNotifyPtr[eInstance][u8Index] = pIntStruct->pIsrModNotify[u8Index]; + } + else + { + /* Disable TSTMP MOD(n) match interrupt */ + TSTMP_HWA_DisableModMatchInterrupt(pTstmp, (TSTMP_ModulateType)u8Index); + s_pTstmpModulateNotifyPtr[eInstance][u8Index] = NULL; + } + } + } + return eRet; +} + +/** + * @brief Enable TSTMP interrupt function + * + * @param eInstance TSTMP instance + * @param eMod TSTMP modulate enumeration + * @return TSTMP_StatusType TSTMP return type + */ +TSTMP_StatusType TSTMP_EnableInterrupt(const TSTMP_InstanceType eInstance, const TSTMP_ModulateType eMod) +{ + TSTMP_StatusType eRet = TSTMP_STATUS_SUCCESS; + TSTMP_Type *pTstmp; + if (((uint8_t)eMod >= MAX_MOD_NUMBER) || (eInstance >= TSTMP_INSTANCE_MAX)) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + else + { + pTstmp = s_pTstmpPtrs[eInstance]; + /* Enable TSTMP MOD(n) match interrupt */ + TSTMP_HWA_EnableModMatchInterrupt(pTstmp, eMod); + } + + return eRet; +} + +/** + * @brief Disable TSTMP interrupt function + * + * @param eInstance TSTMP instance + * @param eMod TSTMP modulate enumeration + * @return TSTMP_StatusType TSTMP return type + */ +TSTMP_StatusType TSTMP_DisableInterrupt(const TSTMP_InstanceType eInstance, const TSTMP_ModulateType eMod) +{ + TSTMP_StatusType eRet = TSTMP_STATUS_SUCCESS; + TSTMP_Type *pTstmp; + if (((uint8_t)eMod >= MAX_MOD_NUMBER) || (eInstance >= TSTMP_INSTANCE_MAX)) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + else + { + pTstmp = s_pTstmpPtrs[eInstance]; + /* Disable TSTMP MOD(n) match interrupt */ + TSTMP_HWA_DisableModMatchInterrupt(pTstmp, eMod); + } + + return eRet; +} + +/** + * @brief Get TSTMP count value + * + * @param eInstance TSTMP instance + * @param u64TstmpValue in/out value + * @return TSTMP_StatusType TSTMP return type + */ +TSTMP_StatusType TSTMP_GetTstmpValue(const TSTMP_InstanceType eInstance, uint64_t *const u64TstmpValue) +{ + TSTMP_StatusType eRet = TSTMP_STATUS_SUCCESS; + TSTMP_Type *pTstmp; + if ((NULL == u64TstmpValue) || (eInstance >= TSTMP_INSTANCE_MAX)) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + else + { + pTstmp = s_pTstmpPtrs[eInstance]; + *u64TstmpValue = TSTMP_HWA_ReadTstmpValue(pTstmp); + } + return eRet; +} + +/** + * @brief Update Modulate configuration + * + * @param eInstance TSTMP instance + * @param pUpdateStruct TSTMP update structure pointer + * @return TSTMP_StatusType TSTMP return type + */ +TSTMP_StatusType TSTMP_UpdateMod(const TSTMP_InstanceType eInstance, const TSTMP_UpdateType *const pUpdateStruct) +{ + TSTMP_StatusType eRet = TSTMP_STATUS_SUCCESS; + TSTMP_Type *pTstmp; + bool bIntEnStatus; + if ((NULL == pUpdateStruct) || (eInstance >= TSTMP_INSTANCE_MAX)) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + else + { + pTstmp = s_pTstmpPtrs[eInstance]; + /* Clear MOD(n) interrupt flag */ + if (TSTMP_MOD0 == pUpdateStruct->eMod) + { + TSTMP_HWA_ClearMod0MatchFlag(pTstmp); + } + else + { + TSTMP_HWA_ClearSingleMod123MatchFlag(pTstmp, pUpdateStruct->eMod); + } + bIntEnStatus = (bool)(((uint32_t)0U == (TSTMP_HWA_ReadTstmpInterruptEnable(pTstmp) & + TSTMP_MOD_INTEN_MOD0_INTEN_MASK << (pUpdateStruct->eMod))) ? true : false); + if ((pUpdateStruct->bIntEn) == true) + { + if(bIntEnStatus == true) + { + /* Enable TSTMP MOD(n) match interrupt */ + TSTMP_HWA_EnableModMatchInterrupt(pTstmp, pUpdateStruct->eMod); + if (NULL != pUpdateStruct->pIsrModNotify) + { + s_pTstmpModulateNotifyPtr[eInstance][pUpdateStruct->eMod] = pUpdateStruct->pIsrModNotify; + } + } + }else + { + if(bIntEnStatus == false) + { + /* Disable TSTMP MOD(n) match interrupt */ + TSTMP_HWA_DisableModMatchInterrupt(pTstmp, pUpdateStruct->eMod); + } + } + /* set MOD(n) match value */ + TSTMP_HWA_SetModMatchValue(pTstmp, pUpdateStruct->eMod, pUpdateStruct->u32ModValue); + } + return eRet; +} + +/** + * @brief Set counter MOD(n) counting on or off + * + * @param eInstance TSTMP instance + * @param eMod MOD number + * @param bCounterEn Whether enable the selected Modulate Timer Counter + * @return TSTMP_StatusType TSTMP return type + */ +TSTMP_StatusType TSTMP_SetModCountConfig(const TSTMP_InstanceType eInstance, const TSTMP_ModulateType eMod, const bool bCounterEn) +{ + TSTMP_StatusType eRet = TSTMP_STATUS_SUCCESS; + TSTMP_Type *pTstmp; + if (eInstance >= TSTMP_INSTANCE_MAX || eMod > TSTMP_MOD3) + { + eRet = TSTMP_STATUS_PARAM_INVALID; + } + else + { + pTstmp = s_pTstmpPtrs[eInstance]; + if(bCounterEn) + { + TSTMP_HWA_EnableModCounter(pTstmp, eMod); + }else + { + TSTMP_HWA_DisableModCounter(pTstmp, eMod); + } + } + return eRet; +} + +/** + * @brief TSTMP common interrupt function + * + * @param eInstance TSTMP instance + * @param eIntModulate TSTMP modulate + */ +static void Tstmp_CommonProcessInterrupt(const TSTMP_InstanceType eInstance, const TSTMP_ModulateType eIntModulate) +{ + if (NULL != s_pTstmpModulateNotifyPtr[eInstance][eIntModulate]) + { + s_pTstmpModulateNotifyPtr[eInstance][eIntModulate](); + } +} + +/** + * @brief TSTMP0 interrupt handler entry + * + */ +void TSTMP0_IRQHandler(void) +{ + uint32_t u32TstmpStatus = TSTMP_HWA_ReadModMatchFlag(TSTMP0); + if ((u32TstmpStatus & TSTMP_MOD_STATUS_MOD0_MATCH_MASK)>>TSTMP_MOD_STATUS_MOD0_MATCH_SHIFT == 1U) + { + Tstmp_CommonProcessInterrupt(TSTMP_INSTANCE_0, TSTMP_MOD0); + /* Clear MOD0 interrupt flag */ + TSTMP_HWA_ClearMod0MatchFlag(TSTMP0); + } + if ((u32TstmpStatus & TSTMP_MOD_STATUS_MOD1_MATCH_MASK)>>TSTMP_MOD_STATUS_MOD1_MATCH_SHIFT == 1U) + { + Tstmp_CommonProcessInterrupt(TSTMP_INSTANCE_0, TSTMP_MOD1); + /* Clear MOD1 interrupt flag */ + TSTMP_HWA_ClearSingleMod123MatchFlag(TSTMP0, TSTMP_MOD1); + } + if ((u32TstmpStatus & TSTMP_MOD_STATUS_MOD2_MATCH_MASK)>>TSTMP_MOD_STATUS_MOD2_MATCH_SHIFT == 1U) + { + Tstmp_CommonProcessInterrupt(TSTMP_INSTANCE_0, TSTMP_MOD2); + /* Clear MOD2 interrupt flag */ + TSTMP_HWA_ClearSingleMod123MatchFlag(TSTMP0, TSTMP_MOD2); + } + if ((u32TstmpStatus & TSTMP_MOD_STATUS_MOD3_MATCH_MASK)>>TSTMP_MOD_STATUS_MOD3_MATCH_SHIFT == 1U) + { + Tstmp_CommonProcessInterrupt(TSTMP_INSTANCE_0, TSTMP_MOD3); + /* Clear MOD3 interrupt flag */ + TSTMP_HWA_ClearSingleMod123MatchFlag(TSTMP0, TSTMP_MOD3); + } +} + +/** + * @brief TSTMP1 interrupt handler entry + * + */ +void TSTMP1_IRQHandler(void) +{ + uint32_t u32TstmpStatus = TSTMP_HWA_ReadModMatchFlag(TSTMP1); + if ((u32TstmpStatus & TSTMP_MOD_STATUS_MOD0_MATCH_MASK)>>TSTMP_MOD_STATUS_MOD0_MATCH_SHIFT == 1U) + { + Tstmp_CommonProcessInterrupt(TSTMP_INSTANCE_1, TSTMP_MOD0); + /* Clear MOD0 interrupt flag */ + TSTMP_HWA_ClearMod0MatchFlag(TSTMP1); + } + if ((u32TstmpStatus & TSTMP_MOD_STATUS_MOD1_MATCH_MASK)>>TSTMP_MOD_STATUS_MOD1_MATCH_SHIFT == 1U) + { + Tstmp_CommonProcessInterrupt(TSTMP_INSTANCE_1, TSTMP_MOD1); + /* Clear MOD1 interrupt flag */ + TSTMP_HWA_ClearSingleMod123MatchFlag(TSTMP1, TSTMP_MOD1); + } + if ((u32TstmpStatus & TSTMP_MOD_STATUS_MOD2_MATCH_MASK)>>TSTMP_MOD_STATUS_MOD2_MATCH_SHIFT == 1U) + { + Tstmp_CommonProcessInterrupt(TSTMP_INSTANCE_1, TSTMP_MOD2); + /* Clear MOD2 interrupt flag */ + TSTMP_HWA_ClearSingleMod123MatchFlag(TSTMP1, TSTMP_MOD2); + } + if ((u32TstmpStatus & TSTMP_MOD_STATUS_MOD3_MATCH_MASK)>>TSTMP_MOD_STATUS_MOD3_MATCH_SHIFT == 1U) + { + Tstmp_CommonProcessInterrupt(TSTMP_INSTANCE_1, TSTMP_MOD3); + /* Clear MOD3 interrupt flag */ + TSTMP_HWA_ClearSingleMod123MatchFlag(TSTMP1, TSTMP_MOD3); + } +} diff --git a/Src/fc7xxx_driver_wdog.c b/Src/fc7xxx_driver_wdog.c new file mode 100644 index 0000000..36b04b3 --- /dev/null +++ b/Src/fc7xxx_driver_wdog.c @@ -0,0 +1,131 @@ +/** + * @file fc7xxx_driver_wdog.c + * @author Flagchip + * @brief FC7xxx WDOG driver source code + * @version 0.1.0 + * @date 2023-12-29 + * + * @copyright Copyright (c) 2022 Flagchip Semiconductors Co., Ltd. + * + */ + +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2023-12-29 qxw0074 N/A First version for FC7240 +********************************************************************************/ + +#include "fc7xxx_driver_wdog.h" + +/** + * @brief UNLOCK and REFRESH CMD For MPW FC100. this may not match with FC4150 user manual + */ +#define WDOG_UNLOCK_CMD (uint32_t)(0x08181982U) +#define WDOG_REFRESH_CMD (uint32_t)(0x20CFFC20U) + +static WDOG_Type *const s_apWdogBase[WDOG_INSTANCE_COUNT] = WDOG_BASE_PTRS; + +static WDOG_IRQ_Callback aIRQCallback[WDOG_INSTANCE_MAX] = {0U}; + +void WDOG0_IRQHandler(void); +void WDOG1_IRQHandler(void); +/** + * @brief unlock the wdog before Watch dog reconfigure set. + * @param instance: WDOG module instance: WDOG0/WDOG1 defined in FC4150. + */ +void WDOG_Unlock(WDOG_InstanceType eInstance) +{ + WDOG_Type *pWdog = s_apWdogBase[eInstance]; + WDOG_HWA_SetCounter(pWdog,WDOG_UNLOCK_CMD); +} + +/** + * @brief feed the watch dog by writing typical cmd to counter. + * @param instance: WDOG module instance: WDOG0/WDOG1 defined in FC4150. + */ +void WDOG_Refresh(WDOG_InstanceType eInstance) +{ + WDOG_Type *pWdog = s_apWdogBase[eInstance]; + WDOG_HWA_SetCounter(pWdog,WDOG_REFRESH_CMD); +} + +/** + * @brief Initialize the WDOG configuration setting. * + * @param pWdogCfg: point to WDOG init module type. + */ +void WDOG_Init(WDOG_InstanceType eInstance,WDOG_CfgType* pWdogCfg) +{ + WDOG_Type *pWdog = s_apWdogBase[eInstance]; + uint32_t u32Temp = 0U; + + /* Disable the global interrupt */ + __disable_irq(); + + u32Temp = WDOG_CS_WIN(pWdogCfg->bWinEnable) | WDOG_CS_PRESCALER(pWdogCfg->bPrescalerEnable) | + WDOG_CS_CLK_SEL(pWdogCfg->eClkSource) | WDOG_CS_TST(pWdogCfg->eTesttype) | + WDOG_CS_DBG(pWdogCfg->bEnableInDebug) | WDOG_CS_UPDATE_MASK | WDOG_CS_ENABLE_MASK | + WDOG_CS_WAIT(pWdogCfg->bEnableInWait) | WDOG_CS_STOP(pWdogCfg->bEnableInStop); + if(WDOG_REACTION_NO_INT != pWdogCfg->eTimeoutReaction) + { + u32Temp |= (WDOG_CS_INT_MASK | WDOG_CS_DLY_CNT_MSB(pWdogCfg->eTimeoutReaction)); + } + else + { + //Do nothing. Keep disabling the wdog interrupt and no reset dealy. + } + + WDOG_Unlock(eInstance); + + while (WDOG_HWA_GetUnlockStatus(pWdog) == false) + { + /* 0 indicate WDOG locked. Wait until registers are unlocked */ + } + + WDOG_HWA_SetCs(pWdog,u32Temp); + + WDOG_Unlock(eInstance); + + while (WDOG_HWA_GetUnlockStatus(pWdog) == false) + { + /* 0 indicate WDOG locked. Wait until registers are unlocked */ + } + + /* configure the timeout value */ + WDOG_HWA_SetTimeout(pWdog,pWdogCfg->u16TimeoutValue); + + WDOG_Unlock(eInstance); + + while (WDOG_HWA_GetUnlockStatus(pWdog) == false) + { + /* 0 indicate WDOG locked. Wait until registers are unlocked */ + } + /* configure window value */ + WDOG_HWA_SetWindow(pWdog,pWdogCfg->u16WindowValue); + + aIRQCallback[eInstance] = pWdogCfg->pISRCallback; + + /* Enable the global interrupt */ + __enable_irq(); + + +} + +void WDOG0_IRQHandler(void) +{ + WDOG_HWA_ClearInterruptFlag(WDOG0); + if(NULL != aIRQCallback[WDOG_INSTANCE_0]) + { + (aIRQCallback[WDOG_INSTANCE_0])(); + } +} + +void WDOG1_IRQHandler(void) +{ + WDOG_HWA_ClearInterruptFlag(WDOG1); + if(NULL != aIRQCallback[WDOG_INSTANCE_1]) + { + (aIRQCallback[WDOG_INSTANCE_1])(); + } +} diff --git a/Src/fc7xxx_driver_wku.c b/Src/fc7xxx_driver_wku.c new file mode 100644 index 0000000..ec16de6 --- /dev/null +++ b/Src/fc7xxx_driver_wku.c @@ -0,0 +1,97 @@ +/** + * @file fc7xxx_driver_wku.c + * @author Flagchip + * @brief FC7xxx WKU driver type definition and API + * @version 0.1.0 + * @date 2023-02-13 + * + * @copyright Copyright (c) 2023 Flagchip Semiconductors Co., Ltd. + * + * @details + */ +/******************************************************************************** +* Revision History: +* +* Version Date Initials CR# Descriptions +* --------- ---------- ------------ ---------- --------------- +* 0.1.0 2024-01-05 Flagchip055 N/A FC7240 First version +********************************************************************************/ +#include "fc7xxx_driver_wku.h" + +/** + * @brief WKU Enable wakeup source for single input + * + * @param u32Input Number of input, WKU_WakeupInputType type is wakeup source definition + * @return WKU return type + */ +WKU_StatusType WKU_EnableWakeupSource(const uint32_t u32Input) +{ + uint32_t u32TempValue = 0U; + uint8_t u8Index = 0U; + WKU_StatusType eRet = WKU_STATUS_SUCCESS; + + DEV_ASSERT(((u32Input & ~(uint32_t)WKU_INPUT_ALL_MASK) == 0U)); + + u32TempValue = u32Input; + while (u32TempValue) + { + if (1U == (u32TempValue & ((uint32_t)1))) + { + WKU_HWA_EnableWakeupSource((WKU_WakeupInputType)((uint32_t)1 << u8Index)); + } + u32TempValue >>= 1U; + u8Index++; + } + + return eRet; +} + +/** + * @brief WKU Disable wakeup source for single input + * + * @param u32Input Number of input, WKU_WakeupInputType type is wakeup source definition + * @return WKU return type + */ +WKU_StatusType WKU_DisableWakeupSource(const uint32_t u32Input) +{ + uint32_t u32TempValue = 0U; + uint8_t u8Index = 0U; + WKU_StatusType eRet = WKU_STATUS_SUCCESS; + + DEV_ASSERT(((u32Input & ~(uint32_t)WKU_INPUT_ALL_MASK) == 0U)); + + u32TempValue = u32Input; + while (u32TempValue) + { + if (u32TempValue & ((uint32_t)1 << u8Index)) + { + WKU_HWA_DisableWakeupSource((WKU_WakeupInputType)((uint32_t)1 << u8Index)); + } + u32TempValue &= (uint32_t)~((uint32_t)1 << u8Index); + u8Index++; + } + + return eRet; +} + +/** + * @brief WKU get wakeup source + * + * @return output wakeup source + */ +uint32_t WKU_GetWakeupSources(void) +{ + return WKU_HWA_ReadWakeupSource(); +} + +/** + * @brief WKU set wake up delay time + * + * @param u8Delaytime The delay time is 2^(u8Delaytime+3) AON_CLK cycles + */ +void WKU_SetWakeupDelay(uint8_t u8Delaytime) +{ + WKU_HWA_DisableDelayCounter(); + WKU_HWA_SetDelayTime(u8Delaytime); + WKU_HWA_EnableDelayCounter(); +} diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..701bbe8 --- /dev/null +++ b/modular.json @@ -0,0 +1,13 @@ +{ + "dep": [ + ], + "cmake": { + "inc_dirs": [ + "Inc", + "Inc_src" + ], + "srcs": [ + "Src/**.c" + ] + } +} \ No newline at end of file